1 25 26 package org.objectweb.easybeans.client; 27 28 import static org.objectweb.easybeans.util.url.URLUtils.fileToURL2; 29 30 import java.io.File ; 31 import java.lang.reflect.InvocationTargetException ; 32 import java.lang.reflect.Method ; 33 import java.net.URL ; 34 import java.net.URLClassLoader ; 35 import java.util.ArrayList ; 36 import java.util.Arrays ; 37 import java.util.HashMap ; 38 import java.util.List ; 39 import java.util.Map ; 40 import java.util.StringTokenizer ; 41 import java.util.jar.Attributes ; 42 import java.util.jar.JarFile ; 43 import java.util.jar.Manifest ; 44 45 import javax.naming.Context ; 46 import javax.naming.InitialContext ; 47 import javax.naming.LinkRef ; 48 import javax.naming.NamingException ; 49 50 import org.objectweb.carol.util.configuration.ConfigurationRepository; 51 import org.objectweb.easybeans.api.EZBArchive; 52 import org.objectweb.easybeans.client.xml.ApplicationClient; 53 import org.objectweb.easybeans.client.xml.ApplicationClientLoader; 54 import org.objectweb.easybeans.container.archive.ArchiveManager; 55 import org.objectweb.easybeans.deployment.Deployment; 56 import org.objectweb.easybeans.deployment.resolver.JNDIResolver; 57 import org.objectweb.easybeans.deployment.xml.struct.common.EJBRef; 58 import org.objectweb.easybeans.enhancer.EnhancerException; 59 import org.objectweb.easybeans.loader.EasyBeansClassLoader; 60 import org.objectweb.easybeans.log.JLog; 61 import org.objectweb.easybeans.log.JLogFactory; 62 import org.objectweb.easybeans.naming.NamingManager; 63 import org.objectweb.easybeans.util.files.FileUtils; 64 import org.objectweb.easybeans.util.files.FileUtilsException; 65 import org.objectweb.easybeans.util.url.URLUtilsException; 66 67 72 public final class ClientContainer { 73 74 77 private static final String DEFAULT_FOLDER = "EasyBeans-Deployer"; 78 79 82 private String mainClass = null; 83 84 87 private String tmpDir = null; 88 89 92 private String classpath = null; 93 94 97 private String [] args = null; 98 99 102 private List <String > appArgs = null; 103 104 107 private URL [] extensionsURLs = null; 108 109 112 private JLog logger = JLogFactory.getLog(ClientContainer.class); 113 114 115 118 private JNDIResolver jndiResolver = null; 119 120 123 private String jarClient = null; 124 125 128 private ApplicationClient applicationClient = null; 129 130 134 private ClientContainer(final String [] args) { 135 this.args = args; 136 137 appArgs = new ArrayList <String >(); 138 } 139 140 144 public static void main(final String [] args) { 145 ClientContainer cc = new ClientContainer(args); 147 148 try { 149 cc.start(); 150 } catch (InvocationTargetException ite) { 151 Throwable t = ite.getTargetException(); 152 String message = t.getMessage(); 153 if (t instanceof Error ) { 154 System.err.println("There was the following error : " + message); 155 } else if (t instanceof Exception ) { 156 System.err.println("There was the following exception : " + message); 157 } 158 t.printStackTrace(System.err); 159 } catch (Exception e) { 160 System.err.println("There was the following exception : " + e.getMessage()); 161 e.printStackTrace(); 162 System.exit(-1); 163 } 164 } 165 166 170 private void start() throws Exception { 171 analyzeArgs(); 172 173 String userArg = null; 175 String fileName = null; 176 boolean fileMode = true; 177 178 try { 179 userArg = appArgs.get(0); 180 } catch (IndexOutOfBoundsException ioobe) { 181 usage(); 182 throw new ClientContainerException("You haven't specify a jar, an ear file or class name as argument." 183 + "See the Usage."); 184 } 185 186 String className = null; 187 if (!(userArg.toLowerCase().endsWith(".jar") || userArg.toLowerCase().endsWith(".ear"))) { 189 className = userArg; 190 fileMode = false; 191 } else { 192 fileMode = true; 193 fileName = userArg; 194 } 195 196 File clientJarFile = null; 198 if (fileMode) { 199 File argFile = new File (fileName); 200 201 if (fileName.toLowerCase().endsWith(".ear")) { 203 clientJarFile = extractAndAnalyzeEar(argFile); 204 } else { 205 clientJarFile = argFile; 207 } 208 } 209 210 ConfigurationRepository.init(); 212 System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.objectweb.carol.jndi.spi.MultiOrbInitialContextFactory"); 213 System.setProperty(InitialContext.URL_PKG_PREFIXES , "org.objectweb.easybeans.naming.pkg"); 214 215 if (fileMode) { 217 Manifest manifest = new JarFile (clientJarFile).getManifest(); 218 219 if (manifest == null) { 220 throw new ClientContainerException("No manifest was found inside the file" + clientJarFile); 221 } 222 223 Attributes attributes = manifest.getMainAttributes(); 225 226 if (attributes == null) { 227 throw new ClientContainerException("No attributes were found in the manifest of the file '" + clientJarFile 228 + "'."); 229 } 230 mainClass = attributes.getValue(Attributes.Name.MAIN_CLASS); 231 } else { 232 mainClass = className; 233 } 234 235 if (!fileMode) { 237 ClassLoader clientCL = new URLClassLoader (getUserClasspathUrls()); 238 Thread.currentThread().setContextClassLoader(clientCL); 239 invokeClient(); 240 return; 241 } 242 243 if (mainClass == null || mainClass.length() == 0) { 244 throw new ClientContainerException("No main class was found inside the Manifest of the file '" + clientJarFile 245 + "'. This attribute is required to launch the application client."); 246 } 247 248 logger.info("Using Main-Class : {0}", mainClass); 249 250 251 URL clientJarURL = null; 253 254 try { 255 clientJarURL = fileToURL2(clientJarFile); 256 } catch (URLUtilsException uue) { 257 throw new ClientContainerException("Error when building an URL with the file '" + clientJarFile + "'.", uue); 258 } 259 260 applicationClient = ApplicationClientLoader.loadApplicationClient(clientJarFile); 262 263 264 URL [] urlsClient = null; 266 267 if (extensionsURLs != null) { 269 urlsClient = new URL [extensionsURLs.length + 1]; 271 272 for (int i = 0; i < extensionsURLs.length; i++) { 273 urlsClient[i] = extensionsURLs[i]; 274 275 logger.debug("Adding " + extensionsURLs[i] + " to the urls of the client"); 276 } 277 278 urlsClient[extensionsURLs.length] = clientJarURL; 279 } else { 280 logger.debug("Only one url for urls of client"); 281 282 urlsClient = new URL [1]; 284 urlsClient[0] = clientJarURL; 285 } 286 287 logger.debug("Building classloader with urls {0}", Arrays.asList(urlsClient)); 289 EasyBeansClassLoader clientClassloader = new EasyBeansClassLoader(urlsClient, 290 Thread.currentThread().getContextClassLoader()); 291 Thread.currentThread().setContextClassLoader(clientClassloader); 292 293 294 buildENC(); 296 297 invokeClient(); 299 300 } 301 302 310 private void invokeClient() throws ClassNotFoundException , NoSuchMethodException , IllegalAccessException , 311 InvocationTargetException , EnhancerException { 312 ClassLoader clientClassloader = Thread.currentThread().getContextClassLoader(); 313 314 if (logger.isDebugEnabled()) { 315 if (clientClassloader instanceof URLClassLoader ) { 316 URLClassLoader urlClassLoader = (URLClassLoader ) clientClassloader; 317 URL [] urls = urlClassLoader.getURLs(); 318 logger.debug("URLs of the classloader :"); 319 for (int u = 0; u < urls.length; u++) { 320 logger.debug("URL[" + u + "] = " + urls[u]); 321 } 322 } 323 } 324 325 326 327 List <String > classesToEnhance = new ArrayList <String >(); 329 classesToEnhance.add(mainClass.replace(".", "/")); 330 Map <String , Object > map = new HashMap <String , Object >(); 331 map.put(JNDIResolver.NAME, jndiResolver); 332 ClientEnhancer.enhance(Thread.currentThread().getContextClassLoader(), classesToEnhance, map); 333 334 335 336 Class clazz = clientClassloader.loadClass(mainClass); 339 Class [] argList = new Class [] {args.getClass()}; 340 341 Method injectedMeth = clazz.getMethod("injectedByEasyBeans", new Class [] {}); 343 try { 344 injectedMeth.invoke(null, new Object [] {}); 345 } catch (Exception e) { 346 logger.error("Cannot perform injection on the client", e); 347 } 348 349 Method lifeCycleMeth = clazz.getMethod("easyBeansLifeCyclePostConstruct", new Class [] {}); 351 try { 352 lifeCycleMeth.invoke(null, new Object [] {}); 353 } catch (Exception e) { 354 logger.error("Cannot perform lifecycle init on the client", e); 355 } 356 357 358 Method meth = clazz.getMethod("main", argList); 359 360 String [] newArgs = new String [appArgs.size() - 1]; 362 String txtArgs = ""; 363 364 for (int i = 0; i < newArgs.length; i++) { 365 newArgs[i] = appArgs.get(i + 1); 366 txtArgs += (newArgs[i] + " "); 367 } 368 369 logger.info("Starting the application client with the arguments '" + txtArgs + "'."); 370 371 logger.info("Starting client..."); 372 373 meth.invoke(null, new Object [] {newArgs}); 374 375 logger.debug("End of main method"); 376 377 } 378 379 383 private void analyzeArgs() throws Exception { 384 for (int argn = 0; argn < args.length; argn++) { 385 String arg = args[argn]; 386 387 try { 388 if (arg.equals("-tmpDir")) { 389 tmpDir = args[++argn]; 390 391 continue; 392 } 393 394 if (arg.equals("-jarClient")) { 395 jarClient = args[++argn]; 396 397 continue; 398 } 399 400 if (arg.equals("-cp")) { 401 classpath = args[++argn]; 402 continue; 403 } 404 405 if (arg.equals("--help") || arg.equals("-help") || arg.equals("-h") || arg.equals("-?")) { 406 usage(); 407 System.exit(1); 408 } 409 410 appArgs.add(arg); 412 } catch (ArrayIndexOutOfBoundsException aioobe) { 413 throw new ClientContainerException("A required parameter was missing after the argument" + arg); 415 } 416 } 417 } 418 419 422 private void usage() { 423 System.out.println("Usage of this client :"); 424 System.out.println("-------------------------------------------------------------------"); 425 System.out.println("java -jar client.jar <client.jar|app.ear|className> [options]"); 426 System.out.println("-------------------------------------------------------------------"); 427 System.out.println(" -jarClient : Specify the client jar to use of the ear if many."); 428 System.out.println(" -tmpDir : Specify the temp directory where unpack the ear."); 429 System.out.println(" -cp : Specify the classpath to use for the jar client."); 430 System.out.println("-------------------------------------------------------------------"); 431 System.out.println(" --help : Display this help."); 432 System.out.println(" -help : Display this help."); 433 System.out.println(" -h : Display this help."); 434 System.out.println(" -? : Display this help."); 435 System.out.println("-------------------------------------------------------------------"); 436 } 437 438 444 private File extractAndAnalyzeEar(final File earFile) throws Exception { 445 446 URL earUrl = null; 447 448 try { 449 earUrl = fileToURL2(earFile); 450 } catch (URLUtilsException uue) { 451 throw new ClientContainerException("Can not build an url with the filename '" + earFile + "'.", uue); 452 } 453 454 URL [] arrURL = new URL [1]; 456 arrURL[0] = earUrl; 457 458 String tempDir = null; 460 461 if (tmpDir != null) { 462 tempDir = tmpDir; 464 logger.debug("Use your specified temp directory '" + tempDir + "'."); 465 } else { 466 tempDir = System.getProperty("java.io.tmpdir"); 468 } 469 470 logger.debug("Using temp directory {0}", tempDir); 471 472 File tmpFileDir = new File (tempDir); 474 475 if (!tmpFileDir.exists() || !tmpFileDir.isDirectory()) { 476 throw new ClientContainerException("The temp directory '" + tempDir + "' doesn't exist or is not a directory."); 477 } 478 479 if (!tmpFileDir.canWrite()) { 480 throw new ClientContainerException("Can not write to the temporary directory '" + tempDir + "'."); 481 } 482 483 logger.info("Ear file = {0}", earFile); 484 JarFile earJarFile = new JarFile (earFile); 486 File rootFolder = new File (System.getProperty("java.io.tmpdir") + File.separator + System.getProperty("user.name") 487 + File.separator + DEFAULT_FOLDER); 488 rootFolder.mkdirs(); 489 490 File tmpFolder = new File (rootFolder, "TMP"); 491 tmpFolder.mkdirs(); 492 File file = new File (tmpFolder, earFile.getName() + ".new"); 493 494 try { 495 FileUtils.unpack(earJarFile, file); 496 } catch (FileUtilsException e) { 497 throw new ClientContainerException("Cannot unpack '" + earJarFile + "'.", e); 498 } 499 500 File fClient = null; 501 502 jndiResolver = new JNDIResolver(); 503 504 File clientFile = null; 505 File [] files = file.listFiles(); 506 if (files != null) { 507 if (jarClient != null) { 508 int f = 0; 509 File ff = null; 510 boolean found = false; 511 512 while (f < files.length && !found) { 513 ff = files[f]; 514 515 if (ff.getPath().endsWith(jarClient)) { 516 found = true; 517 clientFile = ff; 518 logger.info("Found a matching client with the name {0}", ff); 519 } 520 521 f++; 522 } 523 524 if (!found) { 525 throw new ClientContainerException("No client with the name '" + jarClient 526 + "' was found in this Ear file"); 527 } 528 } 529 530 for (File f : files) { 531 if (f.getName().toLowerCase().endsWith("_client.jar") && clientFile == null) { 532 clientFile = f; 533 } else if (f.getName().toLowerCase().endsWith(".ear")) { 534 continue; 536 } else { 537 EZBArchive archive = ArchiveManager.getInstance().getArchive(f); 538 Deployment dep = new Deployment(archive); 539 dep.analyze(); 540 jndiResolver.addDeployment(dep); 541 } 542 } 543 } 544 545 logger.debug("Resolver =" + jndiResolver); 546 547 if (clientFile == null) { 548 throw new IllegalStateException ("No client found"); 549 } 550 551 fClient = clientFile; 553 554 logger.info("Use the application client '" + fClient + "' of the Ear '" + earUrl + "'."); 555 556 return fClient; 557 } 558 559 563 private URL [] getUserClasspathUrls() { 564 if (classpath == null) { 565 return new URL [0]; 566 } 567 String sep = File.pathSeparator; 568 List <URL > clUser = new ArrayList <URL >(); 569 StringTokenizer tokenizer = new StringTokenizer (classpath, sep); 570 while (tokenizer.hasMoreTokens()) { 571 File file = new File (tokenizer.nextToken()); 572 try { 573 clUser.add(fileToURL2(file)); 574 } catch (URLUtilsException uue) { 575 logger.warn("Cannot transform to URL the file : '" + file + "'", uue); 576 } 577 } 578 return clUser.toArray(new URL [0]); 579 } 580 581 585 private void buildENC() throws ClientContainerException { 586 587 NamingManager namingManager = null; 589 try { 590 namingManager = NamingManager.getInstance(); 591 } catch (NamingException e) { 592 throw new ClientContainerException("Cannot get a reference on the naming manager.", e); 593 } 594 595 Context javaCtx = null; 596 try { 598 javaCtx = namingManager.createEnvironmentContext("client"); 599 } catch (NamingException e) { 600 throw new ClientContainerException("Cannot build an environment context", e); 601 } 602 603 Context envCtx; 604 try { 605 envCtx = javaCtx.createSubcontext("comp/env"); 606 } catch (NamingException e) { 607 throw new ClientContainerException("Cannot create subcontext comp/env", e); 608 } 609 610 namingManager.setClientContainerComponentContext(javaCtx); 612 613 if (applicationClient != null) { 615 for (EJBRef ejbRef : applicationClient.getEJBRefs()) { 616 String ejbRefName = ejbRef.getEjbRefName(); 618 String ejbLink = ejbRef.getEjbLink(); 620 621 String itfName = ejbRef.getRemote(); 623 624 String jndiName = jndiResolver.getJndiNameInterface(itfName, ejbLink); 626 627 try { 629 logger.debug("Binding ejb-ref-name {0} with jndi-name {1}", ejbRefName, jndiName); 630 envCtx.bind(ejbRefName, new LinkRef (jndiName)); 631 } catch (NamingException e) { 632 throw new ClientContainerException("Cannot bind name '" + ejbRefName + "' in java:comp/env", e); 633 } 634 } 635 } 636 } 637 638 } 639 | Popular Tags |