| 1 25 package org.objectweb.jonas.client; 26 27 import java.io.File ; 28 import java.io.IOException ; 29 import java.lang.reflect.InvocationTargetException ; 30 import java.lang.reflect.Method ; 31 import java.net.MalformedURLException ; 32 import java.net.URL ; 33 import java.net.URLClassLoader ; 34 import java.util.ArrayList ; 35 import java.util.Iterator ; 36 import java.util.List ; 37 import java.util.Map ; 38 import java.util.StringTokenizer ; 39 import java.util.jar.Attributes ; 40 import java.util.jar.JarFile ; 41 import java.util.jar.Manifest ; 42 43 import javax.naming.Context ; 44 import javax.naming.LinkRef ; 45 import javax.naming.NamingException ; 46 import javax.naming.Reference ; 47 import javax.naming.StringRefAddr ; 48 import javax.security.auth.callback.CallbackHandler ; 49 import javax.security.auth.login.LoginContext ; 50 51 import org.objectweb.carol.util.configuration.CarolDefaultValues; 52 import org.objectweb.carol.util.configuration.ConfigurationRepository; 53 54 55 import org.objectweb.jonas_client.deployment.api.ClientContainerDeploymentDesc; 56 import org.objectweb.jonas_client.deployment.api.ClientContainerDeploymentDescException; 57 import org.objectweb.jonas_client.deployment.lib.ClientDeploymentDescManager; 58 59 import org.objectweb.jonas_ear.deployment.api.EarDeploymentDesc; 60 import org.objectweb.jonas_ear.deployment.api.EarDeploymentDescException; 61 import org.objectweb.jonas_ear.deployment.lib.EarDeploymentDescManager; 62 import org.objectweb.jonas_ear.deployment.xml.Web; 63 64 import org.objectweb.jonas_ejb.deployment.lib.EjbDeploymentDescManager; 65 66 import org.objectweb.jonas_lib.deployment.api.EjbRefDesc; 67 import org.objectweb.jonas_lib.deployment.api.EnvEntryDesc; 68 import org.objectweb.jonas_lib.deployment.api.MessageDestinationRefDesc; 69 import org.objectweb.jonas_lib.deployment.api.ResourceEnvRefDesc; 70 import org.objectweb.jonas_lib.deployment.api.ResourceRefDesc; 71 import org.objectweb.jonas_lib.deployment.work.EarFileManager; 72 import org.objectweb.jonas_lib.naming.ContainerNaming; 73 74 import org.objectweb.jonas_web.deployment.lib.WebDeploymentDescManager; 75 76 import org.objectweb.jonas_ws.deployment.api.ServiceRefDesc; 77 78 import org.objectweb.jonas.common.Log; 79 import org.objectweb.jonas.ear.lib.EarClassPathManager; 80 import org.objectweb.jonas.ear.lib.EarClassPathManagerException; 81 import org.objectweb.jonas.ear.lib.JarList; 82 import org.objectweb.jonas.ear.lib.JarListException; 83 import org.objectweb.jonas.naming.NamingManager; 84 import org.objectweb.jonas.security.auth.callback.NoInputCallbackHandler; 85 import org.objectweb.jonas.security.jacc.JPolicyUserRoleMapping; 86 import org.objectweb.jonas.ws.ClientJServiceFactoryFinder; 87 import org.objectweb.jonas.ws.JServiceFactory; 88 89 import org.objectweb.util.monolog.api.BasicLevel; 90 import org.objectweb.util.monolog.api.Logger; 91 92 97 public class ClientContainer { 98 99 102 private static final String CAROL_FILE = "carol.properties"; 103 104 107 private String mainClass = null; 108 109 112 private String tmpDir = null; 113 114 117 private String jarClient = null; 118 119 122 private String classpath = null; 123 124 127 private String clientTraceFile = null; 128 129 132 private ContainerNaming naming; 133 134 137 private String carolFile = null; 138 139 142 private String [] args = null; 143 144 147 private URLClassLoader earClassLoader = null; 148 149 152 private ArrayList appArgs = null; 153 154 157 private URL [] extensionsURLs = null; 158 159 162 private Logger logger = null; 163 164 168 private ClientContainer(String [] args) { 169 this.args = args; 170 171 appArgs = new ArrayList (); 172 } 173 174 177 private void initLogger() { 178 Log.configure(clientTraceFile); 180 this.logger = Log.getLogger(Log.JONAS_CLIENT_PREFIX); 182 } 183 184 188 public static void main(String [] args) { 189 ClientContainer cc = new ClientContainer(args); 191 192 try { 193 cc.start(); 194 } catch (InvocationTargetException ite) { 195 Throwable t = ite.getTargetException(); 196 String message = t.getMessage(); 197 if (t instanceof Error ) { 198 System.err.println("There was the following error : " + message); 199 } else if (t instanceof Exception ) { 200 System.err.println("There was the following exception : " + message); 201 } 202 t.printStackTrace(System.err); 203 } catch (Exception e) { 204 System.err.println("There was the following exception : " + e.getMessage()); 205 e.printStackTrace(); 206 System.exit(-1); 207 } 208 } 209 210 214 private void start() throws Exception { 215 analyzeArgs(); 216 217 if (clientTraceFile != null) { 219 File tClient = new File (clientTraceFile); 220 221 if (!tClient.exists()) { 222 throw new ClientContainerException("The file '" + clientTraceFile + "' was not found."); 223 } 224 225 if (!tClient.isFile()) { 226 throw new ClientContainerException("The file '" + clientTraceFile 227 + "' is not a valid file. Maybe a directory ?"); 228 } 229 230 System.setProperty("jonas.client.trace.file", clientTraceFile); 232 Log.reset(); 233 } else { 234 clientTraceFile = "traceclient"; 235 } 236 237 initLogger(); 238 239 String userArg = null; 241 String fileName = null; 242 boolean fileMode = true; 243 244 try { 245 userArg = (String ) appArgs.get(0); 246 } catch (IndexOutOfBoundsException ioobe) { 247 usage(); 248 throw new ClientContainerException( 249 "You haven't specify a jar, an ear file or class name as argument. See the Usage."); 250 } 251 252 String className = null; 253 if (!(userArg.toLowerCase().endsWith(".jar") || userArg.toLowerCase().endsWith(".ear"))) { 255 className = userArg; 256 fileMode = false; 257 } else { 258 fileMode = true; 259 fileName = userArg; 260 } 261 262 File clientJarFile = null; 264 if (fileMode) { 265 File argFile = new File (fileName); 266 267 if (!argFile.exists()) { 268 throw new ClientContainerException("The specified file '" + fileName + "' doesn't exists."); 269 } 270 271 if (fileName.toLowerCase().endsWith(".ear")) { 273 clientJarFile = extractAndAnalyzeEar(argFile); 274 } else { 275 clientJarFile = argFile; 277 } 278 } 279 280 System.setProperty("javax.rmi.CORBA.PortableRemoteObjectClass", 282 "org.objectweb.carol.rmi.multi.MultiPRODelegate"); 283 System.setProperty("java.naming.factory.initial", "org.objectweb.carol.jndi.spi.MultiOrbInitialContextFactory"); 284 System.setProperty("org.omg.PortableInterceptor.ORBInitializerClass.org.objectweb.jotm.ots.OTSORBInitializer", 285 ""); 286 System.setProperty("org.omg.PortableInterceptor.ORBInitializerClass.org.objectweb.jonas.security.interceptors.iiop.SecurityInitializer", 287 ""); 288 System.setProperty("org.omg.CORBA.ORBClass" , "org.jacorb.orb.ORB"); 289 System.setProperty("org.omg.CORBA.ORBSingletonClass", "org.jacorb.orb.ORBSingleton"); 290 System.setProperty("org.omg.PortableInterceptor.ORBInitializerClass.standard_init" , "org.jacorb.orb.standardInterceptors.IORInterceptorInitializer"); 291 System.setProperty("javax.rmi.CORBA.UtilClass" , "org.objectweb.carol.util.delegate.UtilDelegateImpl"); 292 293 System.setProperty("axis.jaxrpc11Compliance", "true"); 295 296 URL urlCarolFile = null; 302 303 if (carolFile != null) { 304 File fCarol = new File (carolFile); 305 306 if (!fCarol.exists()) { 307 throw new ClientContainerException("The file '" + carolFile + "' was not found."); 308 } 309 310 if (!fCarol.isFile()) { 311 throw new ClientContainerException("The file '" + carolFile 312 + "' is not a valid file. Maybe a directory ?"); 313 } 314 315 if (!fCarol.getName().equals(CAROL_FILE)) { 316 throw new ClientContainerException("The file '" + carolFile + "' must be named '" + CAROL_FILE + "'."); 317 } 318 319 try { 320 urlCarolFile = fCarol.toURL(); 321 if (logger.isLoggable(BasicLevel.DEBUG)) { 322 logger.log(BasicLevel.DEBUG, "Using carol.properties file specified by the user on command line"); 323 } 324 } catch (MalformedURLException mue) { 325 throw new ClientContainerException("Error when building an URL for the file '" + fCarol + "'.", mue); 326 } 327 } 328 329 if (urlCarolFile == null && fileMode) { 331 URL tmpUrl = null; 332 try { 333 tmpUrl = clientJarFile.toURL(); 334 } catch (MalformedURLException mue) { 335 throw new ClientContainerException("Error when building an URL for the file '" + clientJarFile + "'.", mue); 336 } 337 ClassLoader tmpCl = new URLClassLoader (new URL [] {tmpUrl}, null); 339 340 urlCarolFile = tmpCl.getResource(CarolDefaultValues.CAROL_CONFIGURATION_FILE); 341 if (urlCarolFile != null) { 342 if (logger.isLoggable(BasicLevel.DEBUG)) { 343 logger.log(BasicLevel.DEBUG, "Using carol.properties file of the '" + clientJarFile + "' file."); 344 } 345 } 346 } 347 348 349 350 if (urlCarolFile != null) { 351 if (logger.isLoggable(BasicLevel.DEBUG)) { 352 logger.log(BasicLevel.DEBUG, "Init carol with URL '" + urlCarolFile + "'."); 353 } 354 ConfigurationRepository.init(urlCarolFile); 355 } else { 356 ConfigurationRepository.init(); 357 } 358 ConfigurationRepository.addInterceptors("iiop", "org.objectweb.jonas.security.iiop.Csiv2Initializer"); 360 361 362 if (fileMode) { 365 Manifest manifest = new JarFile (clientJarFile).getManifest(); 366 367 if (manifest == null) { 368 throw new ClientContainerException("No manifest was found inside the file" + clientJarFile); 369 } 370 371 Attributes attributes = manifest.getMainAttributes(); 373 374 if (attributes == null) { 375 throw new ClientContainerException("No attributes were found in the manifest of the file '" 376 + clientJarFile + "'."); 377 } 378 mainClass = attributes.getValue(Attributes.Name.MAIN_CLASS); 379 } else { 380 mainClass = className; 381 } 382 383 if (!fileMode) { 385 ClassLoader clientCL = new URLClassLoader (getUserClasspathUrls()); 386 Thread.currentThread().setContextClassLoader(clientCL); 387 invokeClient(); 388 return; 389 } 390 391 if (mainClass == null || mainClass.length() == 0) { 392 throw new ClientContainerException("No main class was found inside the Manifest of the file '" 393 + clientJarFile + "'. This attribute is required to launch the application client."); 394 } 395 396 if (logger.isLoggable(BasicLevel.DEBUG)) { 397 logger.log(BasicLevel.DEBUG, "Using Main-Class :" + mainClass); 398 } 399 400 URL clientJarURL = null; 402 403 try { 404 clientJarURL = clientJarFile.toURL(); 405 } catch (MalformedURLException mue) { 406 throw new ClientContainerException("Error when building an URL with the file '" + clientJarFile + "'.", mue); 407 } 408 409 URL [] urlsClient = null; 411 412 if (extensionsURLs != null) { 414 urlsClient = new URL [extensionsURLs.length + 1]; 416 417 for (int i = 0; i < extensionsURLs.length; i++) { 418 urlsClient[i] = extensionsURLs[i]; 419 420 if (logger.isLoggable(BasicLevel.DEBUG)) { 421 logger.log(BasicLevel.DEBUG, "Adding " + extensionsURLs[i] + " to the urls of the client"); 422 } 423 } 424 425 urlsClient[extensionsURLs.length] = clientJarURL; 426 } else { 427 if (logger.isLoggable(BasicLevel.DEBUG)) { 428 logger.log(BasicLevel.DEBUG, "Only one url for urls of client"); 429 } 430 431 urlsClient = new URL [1]; 433 urlsClient[0] = clientJarURL; 434 } 435 436 URLClassLoader clientClassloader = new URLClassLoader (urlsClient, Thread.currentThread() 438 .getContextClassLoader()); 439 Thread.currentThread().setContextClassLoader(clientClassloader); 440 441 ClientContainerDeploymentDesc clientDD = null; 443 if (extensionsURLs != null) { 444 EjbDeploymentDescManager.getInstance().addClassLoaderUrlMapping(clientClassloader, extensionsURLs); 445 } 446 447 try { 448 clientDD = ClientDeploymentDescManager.getInstance().getDeploymentDesc(clientJarURL, clientClassloader, earClassLoader); 449 } catch (ClientContainerDeploymentDescException e) { 450 String err = "Cannot read the deployment descriptors '" + clientJarURL + "'"; 451 error(err); 452 throw new ClientContainerException(err, e); 453 } 454 455 try { 457 setClientEnvironment(clientDD); 458 } catch (Exception e) { 459 String err = "Error when populating "; 461 error(err); 462 throw new ClientContainerException(err, e); 463 } 464 465 String jaasFile = clientDD.getJaasFile(); 467 String jaasEntry = clientDD.getJaasEntry(); 468 String username = clientDD.getUsername(); 469 String password = clientDD.getPassword(); 470 471 if (logger.isLoggable(BasicLevel.DEBUG)) { 472 logger.log(BasicLevel.DEBUG, "Using jaas file = " + jaasFile); 473 } 474 475 String jaasConfigFile = null; 476 477 if (jaasFile != null) { 478 jaasConfigFile = "jar:" + clientJarURL.toExternalForm() + "!/" + jaasFile; 480 System.setProperty("java.security.auth.login.config", jaasConfigFile); 481 } 482 483 CallbackHandler ch = null; 484 485 if ((username != null) && (password != null)) { 486 ch = new NoInputCallbackHandler(username, password); 487 info("Using the login/password specified in the jonas-client.xml file with a specific CallbackHandler"); 488 } else { 489 String ddCallbackHandler = clientDD.getCallbackHandler(); 491 492 if (ddCallbackHandler != null) { 493 if (logger.isLoggable(BasicLevel.DEBUG)) { 494 logger.log(BasicLevel.DEBUG, "Using '" + ddCallbackHandler + "' class as CallbackHandler."); 495 } 496 497 Class clazz = null; 498 499 try { 501 clazz = clientClassloader.loadClass(ddCallbackHandler); 502 } catch (Exception e) { 503 throw new ClientContainerException("There was an error while trying to instantiate the class '" 504 + ddCallbackHandler 505 + "' which is specified in the application.xml as CallbackHandler class", e); 506 } 507 508 try { 509 ch = (CallbackHandler ) clazz.newInstance(); 510 } catch (Exception e) { 511 throw new ClientContainerException( 512 "Error while triyng to cast the class '" 513 + ddCallbackHandler 514 + "' to CallbackHandler interface, maybe the specified class doesn't implement this interface.", 515 e); 516 } 517 } 518 } 519 520 if (ch != null) { 522 if (jaasFile == null) { 523 throw new ClientContainerException( 524 "You have defined that you want use a CallbackHandler but you haven't specify the jaas file to use for the JAAS configuration."); 525 } 526 527 if (jaasEntry == null) { 528 throw new ClientContainerException( 529 "You have defined that you want use a CallbackHandler but you haven't specify the jaas entry to use from the jaas config file."); 530 } 531 532 info("Using JAAS loginContext '" + jaasEntry + "' from the file '" + jaasConfigFile + "'."); 533 534 try { 535 LoginContext lc = new LoginContext (jaasEntry, ch); 536 lc.login(); 537 } catch (Exception e) { 538 String err = "Can not use the JAAS authentication"; 539 error(err); 540 throw new ClientContainerException(err, e); 541 } 542 } 543 544 invokeClient(); 546 547 } 548 549 556 private void invokeClient() throws ClassNotFoundException , NoSuchMethodException , IllegalAccessException , 557 InvocationTargetException { 558 ClassLoader clientClassloader = Thread.currentThread().getContextClassLoader(); 559 560 if (logger.isLoggable(BasicLevel.DEBUG)) { 561 if (clientClassloader instanceof URLClassLoader ) { 562 URLClassLoader urlClassLoader = (URLClassLoader ) clientClassloader; 563 URL [] urls = urlClassLoader.getURLs(); 564 logger.log(BasicLevel.DEBUG, "URLs of the classloader :"); 565 for (int u = 0; u < urls.length; u++) { 566 logger.log(BasicLevel.DEBUG, "URL[" + u + "] = " + urls[u]); 567 } 568 } 569 } 570 571 Class clazz = clientClassloader.loadClass(mainClass); 574 Class [] argList = new Class [] {args.getClass()}; 575 Method meth = clazz.getMethod("main", argList); 576 577 String [] newArgs = new String [appArgs.size() - 1]; 579 String txtArgs = ""; 580 581 for (int i = 0; i < newArgs.length; i++) { 582 newArgs[i] = (String ) appArgs.get(i + 1); 583 txtArgs += (newArgs[i] + " "); 584 } 585 586 if (logger.isLoggable(BasicLevel.DEBUG)) { 587 logger.log(BasicLevel.DEBUG, "Starting the application client with the arguments '" + txtArgs + "'."); 588 } 589 590 info("Starting client..."); 591 592 meth.invoke(null, new Object [] {newArgs}); 593 594 if (logger.isLoggable(BasicLevel.DEBUG)) { 595 logger.log(BasicLevel.DEBUG, "End of main method"); 596 } 597 598 } 599 600 605 private void setClientEnvironment(ClientContainerDeploymentDesc clientDD) throws NamingException { 606 if (logger.isLoggable(BasicLevel.DEBUG)) { 607 logger.log(BasicLevel.DEBUG, ""); 608 } 609 610 try { 612 naming = NamingManager.getInstance(); 613 } catch (NamingException e) { 614 throw new ClientContainerException("Error when getting the reference to the Naming manager", e); 615 } 616 617 Context javaCtx = naming.createEnvironmentContext("ClientContainer"); 618 naming.setClientContainerComponentContext(javaCtx); 619 620 Context envCtx = javaCtx.createSubcontext("comp/env"); 621 622 EnvEntryDesc[] envt = clientDD.getEnvEntryDesc(); 624 625 for (int i = 0; i < envt.length; i++) { 626 String name = envt[i].getName(); 628 Object obj = envt[i].getValue(); 629 630 if (logger.isLoggable(BasicLevel.DEBUG)) { 632 logger.log(BasicLevel.DEBUG, "Binding object " + name + " -> " + obj); 633 } 634 635 envCtx.rebind(name, obj); 636 } 637 638 ResourceRefDesc[] resref = clientDD.getResourceRefDesc(); 640 641 for (int i = 0; i < resref.length; i++) { 642 String name = resref[i].getName(); 644 String resname = resref[i].getJndiName(); 645 String type = resref[i].getTypeName(); 646 647 if (logger.isLoggable(BasicLevel.DEBUG)) { 651 logger.log(BasicLevel.DEBUG, "Linking resource " + name + " -> " + resname); 652 } 653 654 if (type.equalsIgnoreCase("java.net.URL")) { 655 Reference ref = new Reference ("java.net.URL", "org.objectweb.jonas_lib.naming.factory.URLFactory", null); 657 StringRefAddr refAddr = new StringRefAddr ("url", resname); 658 ref.add(refAddr); 659 envCtx.rebind(name, ref); 660 } else { 661 LinkRef lref = new LinkRef (resname); 662 envCtx.rebind(name, lref); 663 } 664 } 665 666 ResourceEnvRefDesc[] resEnvref = clientDD.getResourceEnvRefDesc(); 668 669 for (int i = 0; i < resEnvref.length; i++) { 670 String name = resEnvref[i].getName(); 672 String resname = resEnvref[i].getJndiName(); 673 LinkRef lref = new LinkRef (resname); 674 675 if (logger.isLoggable(BasicLevel.DEBUG)) { 676 logger.log(BasicLevel.DEBUG, "Linking resource environment " + name + " -> " + resname); 677 } 678 679 envCtx.rebind(name, lref); 680 } 681 682 EjbRefDesc[] ejbref = clientDD.getEjbRefDesc(); 684 685 for (int i = 0; i < ejbref.length; i++) { 686 String name = ejbref[i].getEjbRefName(); 688 String ejbname = null; 689 ejbname = ejbref[i].getJndiName(); 690 691 LinkRef lref = new LinkRef (ejbname); 692 693 if (logger.isLoggable(BasicLevel.DEBUG)) { 694 logger.log(BasicLevel.DEBUG, "Linking ejb " + name + " -> " + ejbname); 695 } 696 697 envCtx.rebind(name, lref); 698 } 699 700 ServiceRefDesc[] serviceRefs = clientDD.getServiceRefDesc(); 702 if (serviceRefs.length != 0) { 703 704 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 706 707 JServiceFactory factory = ClientJServiceFactoryFinder.getJOnASServiceFactory(); 709 710 for (int i = 0; i < serviceRefs.length; i++) { 711 String refname = serviceRefs[i].getServiceRefName(); 713 714 Reference ref = factory.getServiceReference(serviceRefs[i], loader); 715 envCtx.rebind(refname, ref); 716 717 if (logger.isLoggable(BasicLevel.DEBUG)) { 718 logger.log(BasicLevel.DEBUG, "Adding service-ref 'java:comp/env/" + refname + "'"); 719 } 720 } 721 } 722 723 MessageDestinationRefDesc[] mdref = clientDD.getMessageDestinationRefDesc(); 725 726 for (int i = 0; i < mdref.length; i++) { 727 String name = mdref[i].getMessageDestinationRefName(); 729 String mdname = null; 730 mdname = mdref[i].getJndiName(); 731 732 LinkRef lref = new LinkRef  |