| 1 25 26 package org.objectweb.jonas.web.catalina55; 27 28 import java.io.File ; 29 import java.io.FileInputStream ; 30 import java.io.FileNotFoundException ; 31 import java.io.InputStream ; 32 import java.lang.reflect.Method ; 33 import java.net.URL ; 34 import java.rmi.RemoteException ; 35 import java.util.ArrayList ; 36 import java.util.Iterator ; 37 import java.util.List ; 38 import java.util.StringTokenizer ; 39 import java.util.Vector ; 40 41 import javax.management.InstanceAlreadyExistsException ; 42 import javax.management.MBeanRegistrationException ; 43 import javax.management.MBeanServer ; 44 import javax.management.MalformedObjectNameException ; 45 import javax.management.NotCompliantMBeanException ; 46 import javax.management.ObjectName ; 47 import javax.naming.LinkRef ; 48 import javax.naming.NamingException ; 49 import javax.naming.Reference ; 50 import javax.naming.StringRefAddr ; 51 52 import org.xml.sax.InputSource ; 53 54 import org.apache.catalina.Container; 55 import org.apache.catalina.Context; 56 import org.apache.catalina.Engine; 57 import org.apache.catalina.Host; 58 import org.apache.catalina.Lifecycle; 59 import org.apache.catalina.LifecycleException; 60 import org.apache.catalina.Realm; 61 import org.apache.catalina.Server; 62 import org.apache.catalina.Service; 63 import org.apache.catalina.connector.Connector; 64 import org.apache.catalina.core.StandardContext; 65 import org.apache.catalina.core.StandardEngine; 66 import org.apache.catalina.core.StandardServer; 67 import org.apache.catalina.deploy.ContextResource; 68 import org.apache.catalina.deploy.NamingResources; 69 import org.apache.catalina.startup.ContextConfig; 70 import org.apache.commons.modeler.Registry; 71 import org.apache.tomcat.util.digester.Digester; 72 73 import org.objectweb.jonas_lib.I18n; 74 75 import org.objectweb.jonas.jmx.J2eeObjectName; 76 import org.objectweb.jonas.jmx.JonasObjectName; 77 import org.objectweb.jonas.security.realm.web.catalina55.JACC; 78 import org.objectweb.jonas.server.LoaderManager; 79 import org.objectweb.jonas.service.ServiceException; 80 import org.objectweb.jonas.web.AbsJWebContainerServiceImpl; 81 import org.objectweb.jonas.web.JWebContainerServiceException; 82 import org.objectweb.jonas.web.lib.PermissionManager; 83 import org.objectweb.jonas.web.wrapper.CatalinaJWebContainerService; 84 85 import org.objectweb.util.monolog.api.BasicLevel; 86 87 93 public class CatalinaJWebContainerServiceImpl 94 extends AbsJWebContainerServiceImpl 95 implements CatalinaJWebContainerService { 96 97 100 protected static final String CONFIG_FILE = "conf/server.xml"; 101 102 105 private static I18n i18n = null; 106 107 110 private Server server = null; 111 112 115 private ClassLoader parentClassLoader = null; 116 117 120 private ClassLoader catalinaLoader = null; 121 122 125 private boolean tomcatStarted = false; 126 127 128 133 protected void doInit(javax.naming.Context ctx) throws ServiceException { 134 super.doInit(ctx); 135 136 initCatalinaEnvironment(); 138 139 LoaderManager lm = LoaderManager.getInstance(); 141 try { 142 parentClassLoader = lm.getAppsLoader(); 143 catalinaLoader = lm.getCatalinaLoader(); 144 } catch (Exception e1) { 145 throw new ServiceException("Cannot get Application/Catalina ClassLoader", e1); 146 } 147 148 i18n = I18n.getInstance(CatalinaJWebContainerServiceImpl.class, catalinaLoader); 150 151 if (getLogger().isLoggable(BasicLevel.DEBUG)) { 153 getLogger().log(BasicLevel.DEBUG, "Add mbeans descriptions to the JMX Registry"); 154 } 155 InputStream stream = this.getClass().getResourceAsStream("/org/objectweb/jonas/web/catalina55/mbeans-descriptors.xml"); 156 try { 157 Registry.loadRegistry(stream); 158 stream.close(); 159 } catch (Exception e) { 160 getLogger().log(BasicLevel.ERROR, "Can't add the mbeans description into Tomcat" + e.getMessage()); 161 } 162 163 CatalinaConnectorFactory cf = new CatalinaConnectorFactory(); 165 MBeanServer mbeanServer = getMbeanServer(); 166 cf.setMyServer(mbeanServer); 167 if (mbeanServer != null) { 168 ObjectName on = null; 169 try { 170 on = JonasObjectName.catalinaConnectorFactory(getDomainName()); 171 mbeanServer.registerMBean(cf, on); 172 } catch (MalformedObjectNameException e1) { 173 getLogger().log(BasicLevel.WARN, "Can't create Objectname for CatalinaConnectorFactory MBean"); 174 } catch (InstanceAlreadyExistsException e2) { 175 getLogger().log(BasicLevel.WARN, "MBean named " + on.toString() + "already registered in the MBean server"); 176 } catch (MBeanRegistrationException e2) { 177 getLogger().log(BasicLevel.WARN, "Can't register MBean " + on.toString()); 178 e2.printStackTrace(); 179 } catch (NotCompliantMBeanException e2) { 180 getLogger().log(BasicLevel.WARN, "Can't register MBean " + on.toString()); 181 e2.printStackTrace(); 182 } 183 } 184 185 WebModuleProxy px = new WebModuleProxy(); 187 px.setMyServer(mbeanServer); 188 if (mbeanServer != null) { 189 ObjectName on = null; 190 try { 191 on = JonasObjectName.webModuleProxy(getDomainName()); 192 mbeanServer.registerMBean(px, on); 193 } catch (MalformedObjectNameException e1) { 194 getLogger().log(BasicLevel.WARN, "Can't create Objectname for WebModuleProxy MBean"); 195 } catch (InstanceAlreadyExistsException e2) { 196 getLogger().log(BasicLevel.WARN, "MBean named " + on.toString() + "already registered in the MBean server"); 197 } catch (MBeanRegistrationException e2) { 198 getLogger().log(BasicLevel.WARN, "Can't register MBean " + on.toString()); 199 e2.printStackTrace(); 200 } catch (NotCompliantMBeanException e2) { 201 getLogger().log(BasicLevel.WARN, "Can't register MBean " + on.toString()); 202 e2.printStackTrace(); 203 } 204 } 205 } 206 207 208 213 protected void initCatalinaEnvironment() throws ServiceException { 214 215 String catalinaHome = System.getProperty("catalina.home"); 218 if (catalinaHome != null) { 219 if (System.getProperty("catalina.base") == null) { 220 System.setProperty("catalina.base", catalinaHome); 221 } 222 } else { 223 throw new ServiceException("catalina.home property is not set"); 224 } 225 226 System.setProperty("catalina.useNaming", "false"); 228 } 229 230 231 235 public void doStart() throws ServiceException { 236 237 Digester digester = createServerDigester(); 239 240 File configFile = null; 243 244 try { 245 configFile = getConfigFile(); 246 } catch (FileNotFoundException e) { 247 String err = i18n.getMessage("CatJWebServ.doStart.fileNotFound", configFile, e.getMessage()); 248 getLogger().log(BasicLevel.ERROR, err); 249 throw new ServiceException(err, e); 250 } 251 252 try { 253 InputSource is = new InputSource ("file://" + configFile.getAbsolutePath()); 254 FileInputStream fis = new FileInputStream (configFile); 255 is.setByteStream(fis); 256 digester.push(this); 257 digester.parse(is); 258 fis.close(); 259 } catch (Exception e) { 260 String err = i18n.getMessage("CatJWebServ.doStart.readfileError", configFile, e.getMessage()); 261 getLogger().log(BasicLevel.ERROR, err); 262 throw new ServiceException(err, e); 263 } 264 265 javax.naming.Context ctxOld = setGlobalNamingResources(); 266 267 Iterator it = getEngines().iterator(); 269 while (it.hasNext()) { 270 StandardEngine oSE = (StandardEngine) it.next(); 271 oSE.setDomain(getDomainName()); 277 oSE.setName(getDomainName()); 278 } 279 280 if (server instanceof Lifecycle) { 282 try { 283 server.initialize(); 284 ((Lifecycle) server).start(); 285 } catch (Exception e) { 286 String err = i18n.getMessage("CatJWebServ.doStart.startCatalinaError"); 287 getLogger().log(BasicLevel.ERROR, err); 288 throw new ServiceException(e.getMessage(), e); 289 } 290 } 291 getNaming().setComponentContext(ctxOld); 293 294 tomcatStarted = true; 296 297 super.doStart(); 299 } 300 301 308 protected javax.naming.Context setGlobalNamingResources() throws ServiceException { 309 NamingResources namingResources = server.getGlobalNamingResources(); 311 javax.naming.Context globalCtx = null; 312 javax.naming.Context ctxold = null; 313 try { 314 globalCtx = getNaming().createEnvironmentContext("catalina_global"); 315 ctxold = getNaming().setComponentContext(globalCtx); 316 317 int i; 318 ContextResource[] resources = namingResources.findResources(); 320 for (i = 0; i < resources.length; i++) { 321 addResource(globalCtx, resources[i]); 322 } 323 } catch (NamingException e) { 324 String err = i18n.getMessage("CatJWebServ.doStart.populateEnvError", e.getMessage()); 325 getLogger().log(BasicLevel.ERROR, err); 326 throw new ServiceException(err, e); 327 } 328 ((StandardServer) server).setGlobalNamingContext(globalCtx); 330 return ctxold; 331 } 332 333 334 338 protected void doStop() throws ServiceException { 339 super.doStop(); 341 342 if (server instanceof Lifecycle) { 344 try { 345 ((Lifecycle) server).stop(); 346 } catch (Exception e) { 347 String err = i18n.getMessage("CatJWebServ.doStop.stopCatalinaError"); 348 getLogger().log(BasicLevel.ERROR, err); 349 throw new ServiceException(e.getMessage(), e); 350 } 351 } 352 353 } 354 355 356 363 protected void doRegisterWar(javax.naming.Context ctx) 364 throws JWebContainerServiceException { 365 378 URL warURL = null; 379 URL earURL = null; 380 URL unpackedWarURL = null; 381 String contextRoot = null; 382 boolean java2DelegationModel = true; 383 PermissionManager permissionManager = null; 384 boolean inEarCase = true; 385 String earAppName = null; 386 String jonasDD = null; 387 try { 388 warURL = (URL ) ctx.lookup("warURL"); 389 unpackedWarURL = (URL ) ctx.lookup("unpackedWarURL"); 390 contextRoot = (String ) ctx.lookup("contextRoot"); 391 Boolean bool = (Boolean ) ctx.lookup("java2DelegationModel"); 392 java2DelegationModel = bool.booleanValue(); 393 jonasDD = (String ) ctx.lookup("jonasDD"); 394 permissionManager = (PermissionManager) ctx.lookup("permissionManager"); 395 } catch (NamingException e) { 396 String err = i18n.getMessage("CatJWebServ.doRegisterWar.gettingParamError"); 397 getLogger().log(BasicLevel.ERROR, err + e.getMessage()); 398 throw new JWebContainerServiceException(err, e); 399 } 400 401 try { 402 earAppName = (String ) ctx.lookup("earAppName"); 403 earURL = (URL ) ctx.lookup("earURL"); 404 } catch (NamingException e) { 405 inEarCase = false; 407 earURL = warURL; 409 } 410 411 ClassLoader webClassLoader = null; 412 413 try { 414 webClassLoader = (ClassLoader ) ctx.lookup("parentCL"); 415 } catch (NamingException e) { 416 String err = i18n.getMessage("CatJWebServ.doRegisterWar.gettingParamError"); 417 getLogger().log(BasicLevel.ERROR, err + e.getMessage()); 418 throw new JWebContainerServiceException(err, e); 419 } 420 421 String hostName = null; 422 try { 423 hostName = (String ) ctx.lookup("hostName"); 424 } catch (NamingException e) { 425 hostName = ""; 426 } 427 428 435 if (contextRoot.equals("/")) { 436 contextRoot = ""; 437 } else { 438 contextRoot = "/" + contextRoot; 439 } 440 441 File fWar = new File (warURL.getFile()); 443 445 String destDir = null; 447 if (fWar.isDirectory()) { 448 destDir = warURL.getPath(); 449 } else { 450 destDir = unpackedWarURL.getPath(); 451 } 452 453 File contextXmlFile = new File (destDir + File.separator + "META-INF" + File.separator + "context.xml"); 455 456 457 List jonasContexts = getConfiguredMatchingJonasContexts(contextRoot, fWar, destDir); 459 460 Host deployer = null; 461 if (jonasContexts.isEmpty()) { 463 deployer = findHost(hostName); 465 466 JOnASStandardContext context = new JOnASStandardContext(false, java2DelegationModel, inEarCase); 468 context.setDocBase(destDir); 469 context.setPath(contextRoot); 470 ContextConfig config = new ContextConfig(); 471 472 ((Lifecycle) context).addLifecycleListener(config); 474 jonasContexts.add(context); 475 } 476 477 Iterator it = jonasContexts.iterator(); 479 while (it.hasNext()) { 480 JOnASStandardContext jStdCtx = (JOnASStandardContext) it.next(); 481 482 jStdCtx.setParentClassLoader(webClassLoader); 484 485 jStdCtx.setDelegate(java2DelegationModel); 487 if (getLogger().isLoggable(BasicLevel.DEBUG)) { 488 getLogger().log(BasicLevel.DEBUG, "Webapp class loader java 2 delegation model set to " + java2DelegationModel); 489 } 490 491 if (contextXmlFile.exists()) { 493 jStdCtx.setConfigFile(contextXmlFile.getAbsolutePath()); 494 } 495 496 jStdCtx.setJ2EEServer(getJonasServerName()); 498 jStdCtx.setServer(J2eeObjectName.J2EEServer(getDomainName(), getJonasServerName()).toString()); 499 if (getMbeanServer() != null) { 500 try { 501 String [] as = (String []) getMbeanServer().getAttribute(J2eeObjectName.J2EEServer(getDomainName() 502 , getJonasServerName()), "javaVMs"); 503 jStdCtx.setJavaVMs(as); 504 } catch (Exception e) { 505 getLogger().log(BasicLevel.WARN, "Set MBean JVM error : " + e.getClass().getName() + " " + e.getMessage()); 508 } 509 } 510 if (earAppName != null) { 511 jStdCtx.setJ2EEApplication(earAppName); 512 } 513 jStdCtx.setJonasDeploymentDescriptor(jonasDD); 514 515 Realm ctxRealm = jStdCtx.getRealm(); 517 518 if (ctxRealm == null) { 520 ctxRealm = deployer.getRealm(); 521 } 522 523 524 if (ctxRealm != null && ctxRealm instanceof JACC) { 525 JACC jaccRealm = null; 526 try { 527 jaccRealm = (JACC) ((JACC) ctxRealm).clone(); 528 } catch (CloneNotSupportedException cnse) { 529 String err = "Cannot clone the realm used by the existing context or its parent realm"; 530 getLogger().log(BasicLevel.ERROR, err + cnse.getMessage()); 531 throw new JWebContainerServiceException(err, cnse); 532 } 533 if (getLogger().isLoggable(BasicLevel.DEBUG)) { 534 getLogger().log(BasicLevel.DEBUG, "Setting permission manager to " + permissionManager); 535 } 536 jaccRealm.setPermissionManager(permissionManager); 537 jaccRealm.setContext(jStdCtx); 538 jStdCtx.setRealm(jaccRealm); 540 } 541 542 jStdCtx.setWarURL(warURL); 546 if (inEarCase) { 547 jStdCtx.setEarURL(earURL); 548 } 549 550 if (jStdCtx.isInServerXml()) { 552 try { 553 jStdCtx.setLoader(null); 554 jStdCtx.start(); 555 } catch (LifecycleException lce) { 556 String err = i18n.getMessage("CatJWebServ.doRegisterWar.startContextError", jStdCtx); 557 getLogger().log(BasicLevel.ERROR, err + lce.getMessage()); 558 throw new JWebContainerServiceException(err, lce); 559 560 } 561 } else { 562 if (deployer == null) { 564 String err = i18n.getMessage("CatJWebServ.doRegisterWar.deployerIsNull", jStdCtx); 565 getLogger().log(BasicLevel.ERROR, err); 566 throw new JWebContainerServiceException(err); 567 } 568 deployer.addChild(jStdCtx); 569 } 570 571 checkStartedContext(jStdCtx, permissionManager); 573 574 try { 576 ctx.rebind("WebModule", jStdCtx.createObjectName(getDomainName(), jStdCtx.getParentName())); 577 } catch(Exception e) { 578 String err = "Cannot rebind WebModule ObjectName in Context"; 581 getLogger().log(BasicLevel.ERROR, err, e); 582 throw new JWebContainerServiceException(err, e); 583 } 584 } 585 } 586 587 588 596 protected List getConfiguredMatchingJonasContexts(String contextRoot, File fpackedWar, String destDir) { 597 ArrayList jonasContexts = new ArrayList (); 598 Iterator it = getContexts().iterator(); 602 while (it.hasNext()) { 603 Context ctx = (Context) it.next(); 604 if (!(ctx instanceof JOnASStandardContext)) { 606 continue; 607 } 608 JOnASStandardContext jStdCtx = (JOnASStandardContext) ctx; 609 if (jStdCtx != null) { 610 if (!jStdCtx.isInServerXml()) { 612 continue; 613 } 614 615 String serverCtxRoot = jStdCtx.getPath(); 617 if (!serverCtxRoot.equals(contextRoot)) { 618 continue; 619 } 620 if (jStdCtx.getPrivileged()) { 621 if (fpackedWar.isDirectory()) { 623 String err = i18n.getMessage("CatJWebServ.getConfiguredMatchingJonasContexts.privilegedContextError"); 624 getLogger().log(BasicLevel.ERROR, err); 625 } 626 jStdCtx.setDocBase(fpackedWar.getPath()); 627 } else { 628 jStdCtx.setDocBase(destDir); 629 } 630 jonasContexts.add(jStdCtx); 631 } 632 } 633 return jonasContexts; 634 } 635 636 637 643 protected void checkStartedContext(Context context, PermissionManager permissionManager) throws JWebContainerServiceException { 644 if (!context.getConfigured()) { 646 String err = i18n.getMessage("CatJWebServ.checkStartedContext.configuredFail", context.getName()); 647 getLogger().log(BasicLevel.ERROR, err); 648 throw new JWebContainerServiceException(err); 649 } 650 ((JOnASStandardContext) context).unsetAuthenticationCaching(); 651 652 Realm ctxRealm = context.getRealm(); 654 if (ctxRealm != null && ctxRealm instanceof JACC) { 655 JACC jaccRealm = (JACC) ctxRealm; 656 PermissionManager ctxPerm = jaccRealm.getPermissionManager(); 657 if (ctxPerm == null && permissionManager != null) { 658 jaccRealm.setPermissionManager(permissionManager); 659 } 660 } 661 if (getLogger().isLoggable(BasicLevel.DEBUG)) { 662 getLogger().log(BasicLevel.DEBUG, "context " + context + " started"); 663 } 664 665 } 666 667 672 protected synchronized List getEngines() throws JWebContainerServiceException { 673 List engines = new ArrayList (); 674 Service[] services = server.findServices(); 675 676 for (int s = 0; s < services.length; s++) { 678 Container cont = services[s].getContainer(); 679 if (!(cont instanceof Engine)) { 680 String err = "The container of the service must be an engine (server.xml)"; 681 throw new JWebContainerServiceException(err); 682 } 683 engines.add(cont); 684 } 685 return engines; 686 } 687 688 693 protected synchronized List getContexts() throws JWebContainerServiceException { 694 List contexts = new ArrayList (); 695 696 Iterator itEngines = getEngines().iterator(); 697 while (itEngines.hasNext()) { 698 Engine engine = (Engine) itEngines.next(); 699 Container[] hosts = engine.findChildren(); 700 701 for (int j = 0; j < hosts.length; j++) { 702 Container[] containers = hosts[j].findChildren(); 703 for (int k = 0; k < containers.length; k++) { 704 Container container = containers[k]; 705 if (container instanceof Context) { 706 contexts.add(container); 707 } 708 } 709 } 710 } 711 return contexts; 712 } 713 714 |