1 17 18 package org.apache.geronimo.jetty6; 19 20 import java.net.MalformedURLException ; 21 import java.net.URL ; 22 import java.security.PermissionCollection ; 23 import java.util.Collection ; 24 import java.util.EventListener ; 25 import java.util.HashMap ; 26 import java.util.HashSet ; 27 import java.util.Hashtable ; 28 import java.util.Iterator ; 29 import java.util.Map ; 30 import java.util.Set ; 31 32 import javax.management.MalformedObjectNameException ; 33 import javax.management.ObjectName ; 34 import javax.naming.Context ; 35 import javax.transaction.TransactionManager ; 36 37 import org.apache.commons.logging.Log; 38 import org.apache.commons.logging.LogFactory; 39 import org.apache.geronimo.connector.outbound.connectiontracking.TrackedConnectionAssociator; 40 import org.apache.geronimo.gbean.GBeanInfo; 41 import org.apache.geronimo.gbean.GBeanInfoBuilder; 42 import org.apache.geronimo.gbean.GBeanLifecycle; 43 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 44 import org.apache.geronimo.j2ee.management.impl.InvalidObjectNameException; 45 import org.apache.geronimo.jetty6.handler.AbstractImmutableHandler; 46 import org.apache.geronimo.jetty6.handler.ComponentContextHandler; 47 import org.apache.geronimo.jetty6.handler.InstanceContextHandler; 48 import org.apache.geronimo.jetty6.handler.JettySecurityHandler; 49 import org.apache.geronimo.jetty6.handler.LifecycleCommand; 50 import org.apache.geronimo.jetty6.handler.ThreadClassloaderHandler; 51 import org.apache.geronimo.kernel.Kernel; 52 import org.apache.geronimo.kernel.ObjectNameUtil; 53 import org.apache.geronimo.management.J2EEApplication; 54 import org.apache.geronimo.management.J2EEServer; 55 import org.apache.geronimo.management.geronimo.WebConnector; 56 import org.apache.geronimo.management.geronimo.WebContainer; 57 import org.apache.geronimo.management.geronimo.WebModule; 58 import org.apache.geronimo.naming.enc.EnterpriseNamingContext; 59 import org.apache.geronimo.security.deploy.DefaultPrincipal; 60 import org.apache.geronimo.transaction.GeronimoUserTransaction; 61 import org.mortbay.jetty.handler.AbstractHandler; 62 import org.mortbay.jetty.security.Authenticator; 63 import org.mortbay.jetty.servlet.ErrorPageErrorHandler; 64 import org.mortbay.jetty.servlet.ServletHandler; 65 import org.mortbay.jetty.servlet.ServletHolder; 66 import org.mortbay.jetty.servlet.ServletMapping; 67 import org.mortbay.jetty.servlet.SessionHandler; 68 import org.mortbay.jetty.webapp.WebAppContext; 69 import org.mortbay.jetty.MimeTypes; 70 71 76 public class JettyWebAppContext implements GBeanLifecycle, JettyServletRegistration, WebModule { 77 private static Log log = LogFactory.getLog(JettyWebAppContext.class); 78 79 private final String originalSpecDD; 80 private final J2EEServer server; 81 private final J2EEApplication application; 82 83 private final ClassLoader webClassLoader; 84 private final JettyContainer jettyContainer; 85 86 private final String webAppRoot; 87 private final URL configurationBaseURL; 88 private String displayName; 90 private final String [] welcomeFiles; 91 92 private final String objectName; 93 private final WebAppContext webAppContext; private final AbstractImmutableHandler lifecycleChain; 95 96 private final Set servletNames = new HashSet (); 97 98 101 public JettyWebAppContext() { 102 server = null; 103 application = null; 104 originalSpecDD = null; 105 webClassLoader = null; 106 jettyContainer = null; 107 webAppRoot = null; 108 welcomeFiles = null; 110 objectName = null; 111 configurationBaseURL = null; 112 webAppContext = null; 113 lifecycleChain = null; 114 } 115 116 public JettyWebAppContext(String objectName, 117 String originalSpecDD, 118 Map componentContext, 119 ClassLoader classLoader, 120 URL configurationBaseUrl, 121 Set unshareableResources, 122 Set applicationManagedSecurityResources, 123 String displayName, 124 Map contextParamMap, 125 Collection listenerClassNames, 126 boolean distributable, 127 Map mimeMap, 128 String [] welcomeFiles, 129 Map localeEncodingMapping, 130 Map errorPages, 131 Authenticator authenticator, 132 String realmName, 133 Map tagLibMap, 134 int sessionTimeoutSeconds, 135 SessionHandlerFactory handlerFactory, 136 PreHandlerFactory preHandlerFactory, 137 138 String policyContextID, 139 String securityRealmName, 140 DefaultPrincipal defaultPrincipal, 141 PermissionCollection checkedPermissions, 142 PermissionCollection excludedPermissions, 143 144 Host host, 145 TransactionManager transactionManager, 146 TrackedConnectionAssociator trackedConnectionAssociator, 147 JettyContainer jettyContainer, 148 J2EEServer server, 149 J2EEApplication application, 150 Kernel kernel) throws Exception , IllegalAccessException , InstantiationException , ClassNotFoundException { 151 152 assert componentContext != null; 153 assert classLoader != null; 154 assert configurationBaseUrl != null; 155 assert transactionManager != null; 156 assert trackedConnectionAssociator != null; 157 assert jettyContainer != null; 158 SessionHandler sessionHandler = handlerFactory == null ? new SessionHandler() : handlerFactory.createHandler(); 159 JettySecurityHandler securityHandler = null; 161 if (securityRealmName != null) { 162 securityHandler = new JettySecurityHandler(); 163 InternalJAASJettyRealm internalJAASJettyRealm = jettyContainer.addRealm(securityRealmName); 164 JAASJettyRealm realm = new JAASJettyRealm(realmName, internalJAASJettyRealm); 166 securityHandler.setUserRealm(realm); 167 168 securityHandler.init(policyContextID, defaultPrincipal, checkedPermissions, excludedPermissions, classLoader); 169 } 170 171 PreHandler preHandler = null == preHandlerFactory ? null : preHandlerFactory.createHandler(); 172 ServletHandler servletHandler = new JettyServletHandler(preHandler); 173 174 webAppContext = new WebAppContext(securityHandler, sessionHandler, servletHandler, null); 175 AbstractHandler next = sessionHandler; 176 next = new ThreadClassloaderHandler(next, classLoader); 177 178 GeronimoUserTransaction userTransaction = new GeronimoUserTransaction(transactionManager); 179 Context enc = EnterpriseNamingContext.createEnterpriseNamingContext(componentContext, userTransaction, kernel, classLoader); 180 next = new ComponentContextHandler(next, enc); 181 next = new InstanceContextHandler(next, unshareableResources, applicationManagedSecurityResources, trackedConnectionAssociator); 182 lifecycleChain = (AbstractImmutableHandler) next; 183 webAppContext.setHandler(next); 184 185 MimeTypes mimeTypes = new MimeTypes(); 186 mimeTypes.setMimeMap(mimeMap); 187 webAppContext.setMimeTypes(mimeTypes); 188 189 this.server = server; 190 this.application = application; 191 this.objectName = objectName; 192 if (objectName != null) { 193 ObjectName myObjectName = ObjectNameUtil.getObjectName(objectName); 194 verifyObjectName(myObjectName); 195 } 196 this.configurationBaseURL = configurationBaseUrl; 197 this.jettyContainer = jettyContainer; 198 this.originalSpecDD = originalSpecDD; 199 201 this.webAppContext.setConfigurationClasses(new String []{}); 202 203 webAppRoot = configurationBaseUrl.toString(); 204 this.webClassLoader = classLoader; 205 this.webAppContext.setClassLoader(this.webClassLoader); 206 207 if (host != null) { 208 this.webAppContext.setConnectorNames(host.getHosts()); 209 this.webAppContext.setVirtualHosts(host.getVirtualHosts()); 210 } 211 212 this.webAppContext.setDisplayName(displayName); 214 this.webAppContext.setInitParams(contextParamMap); 215 setListenerClassNames(listenerClassNames); 216 this.webAppContext.setDistributable(distributable); 217 this.welcomeFiles = welcomeFiles; 220 setLocaleEncodingMapping(localeEncodingMapping); 221 setErrorPages(errorPages); 222 this.webAppContext.getSecurityHandler().setAuthenticator(authenticator); 223 setTagLibMap(tagLibMap); 224 225 if (!distributable) { 226 setSessionTimeoutSeconds(sessionTimeoutSeconds); 227 } 228 229 } 230 231 232 public String getObjectName() { 233 return objectName; 234 } 235 236 public boolean isStateManageable() { 237 return true; 238 } 239 240 public boolean isStatisticsProvider() { 241 return false; 242 } 243 244 public boolean isEventProvider() { 245 return true; 246 } 247 248 public URL getWARDirectory() { 249 return configurationBaseURL; 250 } 251 252 public String getWARName() { 253 try { 255 return ObjectName.getInstance(objectName).getKeyProperty(NameFactory.J2EE_NAME); 256 } catch (MalformedObjectNameException e) { 257 return null; 258 } 259 } 260 261 public WebContainer getContainer() { 262 return jettyContainer; 263 } 264 265 public URL getURLFor() { 266 WebConnector[] connectors = (WebConnector[]) jettyContainer.getConnectors(); 267 Map map = new HashMap (); 268 for (int i = 0; i < connectors.length; i++) { 269 WebConnector connector = connectors[i]; 270 map.put(connector.getProtocol(), connector.getConnectUrl()); 271 } 272 String urlPrefix; 273 if ((urlPrefix = (String ) map.get("HTTP")) == null) { 274 if ((urlPrefix = (String ) map.get("HTTPS")) == null) { 275 urlPrefix = (String ) map.get("AJP"); 276 } 277 } 278 if (urlPrefix == null) { 279 return null; 280 } 281 StringBuffer buf = new StringBuffer (urlPrefix); 282 String contextPath = getContextPath(); 283 if (!contextPath.startsWith("/")) { 284 buf.append("/"); 285 } 286 buf.append(contextPath); 287 try { 288 return new URL (buf.toString()); 289 } catch (MalformedURLException e) { 290 log.error("Bad URL to connect to web app", e); 291 return null; 292 } 293 } 294 295 public void setContextPath(String path) { 296 if (path == null || !path.startsWith("/")) { 297 throw new IllegalArgumentException ("context path must be non-null and start with '/', not " + path); 298 } 299 this.webAppContext.setContextPath(path); 300 } 301 302 public String getContextPath() { 303 return this.webAppContext.getContextPath(); 304 } 305 306 public ClassLoader getWebClassLoader() { 307 return webClassLoader; 308 } 309 310 public AbstractImmutableHandler getLifecycleChain() { 311 return lifecycleChain; 312 } 313 314 public void doStart() throws Exception { 315 this.webAppContext.setClassLoader(webClassLoader); 317 this.webAppContext.setWar(webAppRoot); 318 319 getLifecycleChain().lifecycleCommand(new StartCommand()); 320 } 321 322 public void doStop() throws Exception { 323 getLifecycleChain().lifecycleCommand(new StopCommand()); 324 325 LogFactory.release(webClassLoader); 327 328 log.debug("JettyWebAppContext stopped"); 329 } 330 331 public void doFail() { 332 try { 333 doStop(); 334 } catch (Exception e) { 335 } 337 338 log.warn("JettyWebAppContext failed"); 339 } 340 341 public class StartCommand implements LifecycleCommand { 342 343 public void lifecycleMethod() throws Exception { 344 jettyContainer.addContext(webAppContext); 346 webAppContext.start(); 347 } 348 } 349 350 public class StopCommand implements LifecycleCommand { 351 352 public void lifecycleMethod() throws Exception { 353 webAppContext.stop(); 354 jettyContainer.removeContext(webAppContext); 355 } 356 } 357 359 public void setLocaleEncodingMapping(Map localeEncodingMap) { 360 if (localeEncodingMap != null) { 361 for (Iterator iterator = localeEncodingMap.entrySet().iterator(); iterator.hasNext();) { 362 Map.Entry entry = (Map.Entry ) iterator.next(); 363 this.webAppContext.addLocaleEncoding((String ) entry.getKey(), (String ) entry.getValue()); 364 } 365 } 366 } 367 368 public void setListenerClassNames(Collection eventListeners) throws ClassNotFoundException , IllegalAccessException , InstantiationException { 369 if (eventListeners != null) { 370 for (Iterator iterator = eventListeners.iterator(); iterator.hasNext();) { 371 String listenerClassName = (String ) iterator.next(); 372 Class clazz = this.webAppContext.loadClass(listenerClassName); 373 EventListener listener = (EventListener ) clazz.newInstance(); 374 this.webAppContext.addEventListener(listener); 375 } 376 } 377 } 378 379 public void setErrorPages(Map errorPageMap) { 380 if (errorPageMap != null) { 381 ((ErrorPageErrorHandler) this.webAppContext.getErrorHandler()).setErrorPages(errorPageMap); 382 } 383 } 384 385 public void setTagLibMap(Map tagLibMap) { 386 if (tagLibMap != null) { 387 for (Iterator iterator = tagLibMap.entrySet().iterator(); iterator.hasNext();) { 388 Map.Entry entry = (Map.Entry ) iterator.next(); 389 this.webAppContext.setResourceAlias((String ) entry.getKey(), (String ) entry.getValue()); 390 } 391 } 392 } 393 394 public void setSessionTimeoutSeconds(int seconds) { 395 this.webAppContext.getSessionHandler().getSessionManager().setMaxInactiveInterval(seconds); 396 } 397 398 399 public String getDisplayName() { 401 return displayName; 402 } 403 404 public void setDisplayName(String displayName) { 405 this.displayName = displayName; 406 this.webAppContext.setDisplayName(displayName); 407 } 408 409 public String getDeploymentDescriptor() { 410 return originalSpecDD; 411 } 412 413 public String getServer() { 414 return server.getObjectName(); 415 } 416 417 public String getApplication() { 418 if (application == null) { 419 return null; 420 } 421 return application.getObjectName(); 422 } 423 424 public String [] getJavaVMs() { 425 return server.getJavaVMs(); 426 } 427 428 public String [] getServlets() { 429 synchronized (servletNames) { 430 return (String []) servletNames.toArray(new String [servletNames.size()]); 431 } 432 } 433 434 public ServletHandler getServletHandler() { 435 return this.webAppContext.getServletHandler(); 436 } 437 438 443 private void verifyObjectName(ObjectName objectName) { 444 if (objectName.isPattern()) { 445 throw new InvalidObjectNameException("ObjectName can not be a pattern", objectName); 446 } 447 Hashtable keyPropertyList = objectName.getKeyPropertyList(); 448 if (!NameFactory.WEB_MODULE.equals(keyPropertyList.get("j2eeType"))) { 449 throw new InvalidObjectNameException("WebModule object name j2eeType property must be 'WebModule'", objectName); 450 } 451 if (!keyPropertyList.containsKey(NameFactory.J2EE_NAME)) { 452 throw new InvalidObjectNameException("WebModule object must contain a name property", objectName); 453 } 454 if (!keyPropertyList.containsKey(NameFactory.J2EE_SERVER)) { 455 throw new InvalidObjectNameException("WebModule object name must contain a J2EEServer property", objectName); 456 } 457 if (!keyPropertyList.containsKey(NameFactory.J2EE_APPLICATION)) { 458 throw new InvalidObjectNameException("WebModule object name must contain a J2EEApplication property", objectName); 459 } 460 if (keyPropertyList.size() != 4) { 461 throw new InvalidObjectNameException("WebModule object name can only have j2eeType, name, J2EEApplication, and J2EEServer properties", objectName); 462 } 463 } 464 465 public void registerServletHolder(ServletHolder servletHolder, String servletName, Set servletMappings, String objectName) throws Exception { 466 webAppContext.getServletHandler().addServlet(servletHolder); 468 if (servletMappings != null) { 469 for (Iterator iterator = servletMappings.iterator(); iterator.hasNext();) { 470 String urlPattern = (String ) iterator.next(); 471 ServletMapping servletMapping = new ServletMapping(); 472 servletMapping.setPathSpec(urlPattern); 473 servletMapping.setServletName(servletName); 474 this.webAppContext.getServletHandler().addServletMapping(servletMapping); 475 } 476 } 477 if (objectName != null) { 480 synchronized (servletNames) { 481 servletNames.add(objectName); 482 } 483 } 484 } 485 486 public void unregisterServletHolder(ServletHolder servletHolder, String servletName, Set servletMappings, String objectName) throws Exception { 487 if (objectName != null) { 501 synchronized (servletNames) { 502 servletNames.remove(objectName); 503 } 504 } 505 } 506 507 public static final GBeanInfo GBEAN_INFO; 508 509 public static final String GBEAN_ATTR_SESSION_TIMEOUT = "sessionTimeoutSeconds"; 510 511 public static final String GBEAN_REF_SESSION_HANDLER_FACTORY = "SessionHandlerFactory"; 512 public static final String GBEAN_REF_PRE_HANDLER_FACTORY = "PreHandlerFactory"; 513 514 static { 515 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic("Jetty WebApplication Context", JettyWebAppContext.class, NameFactory.WEB_MODULE); 516 infoBuilder.addAttribute("deploymentDescriptor", String .class, true); 517 519 infoBuilder.addAttribute("displayName", String .class, true); 520 infoBuilder.addAttribute("contextParamMap", Map .class, true); 521 infoBuilder.addAttribute("listenerClassNames", Collection .class, true); 522 infoBuilder.addAttribute("distributable", boolean.class, true); 523 524 infoBuilder.addAttribute("mimeMap", Map .class, true); 525 infoBuilder.addAttribute("welcomeFiles", String [].class, true); 526 infoBuilder.addAttribute("localeEncodingMapping", Map .class, true); 527 infoBuilder.addAttribute("errorPages", Map .class, true); 528 infoBuilder.addAttribute("authenticator", Authenticator.class, true); 529 infoBuilder.addAttribute("realmName", String .class, true); 530 infoBuilder.addAttribute("tagLibMap", Map .class, true); 531 infoBuilder.addAttribute(GBEAN_ATTR_SESSION_TIMEOUT, int.class, true); 532 infoBuilder.addReference(GBEAN_REF_SESSION_HANDLER_FACTORY, SessionHandlerFactory.class, 533 NameFactory.GERONIMO_SERVICE); 534 infoBuilder.addReference(GBEAN_REF_PRE_HANDLER_FACTORY, PreHandlerFactory.class, NameFactory.GERONIMO_SERVICE); 535 536 infoBuilder.addAttribute("componentContext", Map .class, true); 537 infoBuilder.addAttribute("classLoader", ClassLoader .class, false); 538 infoBuilder.addAttribute("configurationBaseUrl", URL .class, true); 539 infoBuilder.addAttribute("unshareableResources", Set .class, true); 540 infoBuilder.addAttribute("applicationManagedSecurityResources", Set .class, true); 541 542 infoBuilder.addAttribute("contextPath", String .class, true); 543 544 infoBuilder.addReference("Host", Host.class, "Host"); 545 infoBuilder.addReference("TransactionManager", TransactionManager .class, NameFactory.TRANSACTION_MANAGER); 546 infoBuilder.addReference("TrackedConnectionAssociator", TrackedConnectionAssociator.class, NameFactory.JCA_CONNECTION_TRACKER); 547 infoBuilder.addReference("JettyContainer", JettyContainer.class, NameFactory.GERONIMO_SERVICE); 548 549 infoBuilder.addInterface(JettyServletRegistration.class); 550 551 infoBuilder.addAttribute("policyContextID", String .class, true); 552 infoBuilder.addAttribute("securityRealmName", String .class, true); 553 infoBuilder.addAttribute("defaultPrincipal", DefaultPrincipal.class, true); 554 555 infoBuilder.addAttribute("checkedPermissions", PermissionCollection .class, true); 556 infoBuilder.addAttribute("excludedPermissions", PermissionCollection .class, true); 557 558 infoBuilder.addReference("J2EEServer", J2EEServer.class); 559 infoBuilder.addReference("J2EEApplication", J2EEApplication.class); 560 561 infoBuilder.addAttribute("kernel", Kernel.class, false); 562 infoBuilder.addAttribute("objectName", String .class, false); 563 infoBuilder.addAttribute("application", String .class, false); 564 infoBuilder.addAttribute("javaVMs", String [].class, false); 565 infoBuilder.addAttribute("servlets", String [].class, false); 566 567 infoBuilder.addInterface(WebModule.class); 568 569 infoBuilder.setConstructor(new String []{ 570 "objectName", 571 "deploymentDescriptor", 572 "componentContext", 573 "classLoader", 574 "configurationBaseUrl", 575 "unshareableResources", 576 "applicationManagedSecurityResources", 577 578 "displayName", 579 "contextParamMap", 580 "listenerClassNames", 581 "distributable", 582 "mimeMap", 583 "welcomeFiles", 584 "localeEncodingMapping", 585 "errorPages", 586 "authenticator", 587 "realmName", 588 "tagLibMap", 589 GBEAN_ATTR_SESSION_TIMEOUT, 590 GBEAN_REF_SESSION_HANDLER_FACTORY, 591 GBEAN_REF_PRE_HANDLER_FACTORY, 592 593 "policyContextID", 594 "securityRealmName", 595 "defaultPrincipal", 596 597 "checkedPermissions", 598 "excludedPermissions", 599 600 "Host", 601 "TransactionManager", 602 "TrackedConnectionAssociator", 603 "JettyContainer", 604 605 "J2EEServer", 606 "J2EEApplication", 607 "kernel" 608 }); 609 610 GBEAN_INFO = infoBuilder.getBeanInfo(); 611 } 612 613 public static GBeanInfo getGBeanInfo() { 614 return GBEAN_INFO; 615 } 616 617 } 618 | Popular Tags |