001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.geronimo.jetty6; 019 020 import java.net.URL; 021 import java.util.ArrayList; 022 import java.util.Collection; 023 import java.util.EventListener; 024 import java.util.HashMap; 025 import java.util.HashSet; 026 import java.util.Hashtable; 027 import java.util.Map; 028 import java.util.Set; 029 030 import javax.management.MalformedObjectNameException; 031 import javax.management.ObjectName; 032 import javax.naming.Context; 033 import javax.security.auth.Subject; 034 import javax.security.auth.login.LoginException; 035 import javax.transaction.TransactionManager; 036 037 import org.apache.commons.logging.Log; 038 import org.apache.commons.logging.LogFactory; 039 import org.apache.geronimo.connector.outbound.connectiontracking.TrackedConnectionAssociator; 040 import org.apache.geronimo.gbean.GBeanInfo; 041 import org.apache.geronimo.gbean.GBeanInfoBuilder; 042 import org.apache.geronimo.gbean.GBeanLifecycle; 043 import org.apache.geronimo.j2ee.RuntimeCustomizer; 044 import org.apache.geronimo.j2ee.annotation.Holder; 045 import org.apache.geronimo.j2ee.annotation.LifecycleMethod; 046 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 047 import org.apache.geronimo.j2ee.management.impl.InvalidObjectNameException; 048 import org.apache.geronimo.jetty6.handler.AbstractImmutableHandler; 049 import org.apache.geronimo.jetty6.handler.ComponentContextHandler; 050 import org.apache.geronimo.jetty6.handler.InstanceContextHandler; 051 import org.apache.geronimo.jetty6.handler.JettySecurityHandler; 052 import org.apache.geronimo.jetty6.handler.LifecycleCommand; 053 import org.apache.geronimo.jetty6.handler.ThreadClassloaderHandler; 054 import org.apache.geronimo.jetty6.handler.TwistyWebAppContext; 055 import org.apache.geronimo.jetty6.handler.UserTransactionHandler; 056 import org.apache.geronimo.kernel.Kernel; 057 import org.apache.geronimo.kernel.ObjectNameUtil; 058 import org.apache.geronimo.management.J2EEApplication; 059 import org.apache.geronimo.management.J2EEServer; 060 import org.apache.geronimo.management.geronimo.WebContainer; 061 import org.apache.geronimo.management.geronimo.WebModule; 062 import org.apache.geronimo.naming.enc.EnterpriseNamingContext; 063 import org.apache.geronimo.security.jacc.RunAsSource; 064 import org.apache.geronimo.transaction.GeronimoUserTransaction; 065 import org.mortbay.jetty.Handler; 066 import org.mortbay.jetty.MimeTypes; 067 import org.mortbay.jetty.security.Authenticator; 068 import org.mortbay.jetty.servlet.ErrorPageErrorHandler; 069 import org.mortbay.jetty.servlet.ServletHandler; 070 import org.mortbay.jetty.servlet.ServletHolder; 071 import org.mortbay.jetty.servlet.ServletMapping; 072 import org.mortbay.jetty.servlet.SessionHandler; 073 074 /** 075 * Wrapper for a WebApplicationContext that sets up its J2EE environment. 076 * 077 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 078 */ 079 public class JettyWebAppContext implements GBeanLifecycle, JettyServletRegistration, WebModule { 080 private static Log log = LogFactory.getLog(JettyWebAppContext.class); 081 082 private final String originalSpecDD; 083 private final J2EEServer server; 084 private final J2EEApplication application; 085 086 private final ClassLoader webClassLoader; 087 private final JettyContainer jettyContainer; 088 089 private final String webAppRoot; 090 private final URL configurationBaseURL; 091 private String displayName; 092 093 private final String objectName; 094 private final TwistyWebAppContext webAppContext;//delegate 095 private final AbstractImmutableHandler lifecycleChain; 096 private final Context componentContext; 097 private final Holder holder; 098 private final RunAsSource runAsSource; 099 100 private final Set<String> servletNames = new HashSet<String>(); 101 102 public JettyWebAppContext(String objectName, 103 String originalSpecDD, 104 Map<String, Object> componentContext, 105 ClassLoader classLoader, 106 URL configurationBaseUrl, 107 Set unshareableResources, 108 Set applicationManagedSecurityResources, 109 String displayName, 110 Map contextParamMap, 111 Collection<String> listenerClassNames, 112 boolean distributable, 113 Map mimeMap, 114 String[] welcomeFiles, 115 Map<String, String> localeEncodingMapping, 116 Map errorPages, 117 Authenticator authenticator, 118 String realmName, 119 Map<String, String> tagLibMap, 120 boolean compactPath, 121 122 int sessionTimeoutSeconds, 123 SessionHandlerFactory handlerFactory, 124 PreHandlerFactory preHandlerFactory, 125 126 String policyContextID, 127 String securityRealmName, 128 129 RunAsSource runAsSource, Holder holder, 130 131 Host host, 132 TransactionManager transactionManager, 133 TrackedConnectionAssociator trackedConnectionAssociator, 134 JettyContainer jettyContainer, 135 RuntimeCustomizer contextCustomizer, 136 137 J2EEServer server, 138 J2EEApplication application, 139 Kernel kernel) throws Exception { 140 141 assert componentContext != null; 142 assert classLoader != null; 143 assert configurationBaseUrl != null; 144 assert transactionManager != null; 145 assert trackedConnectionAssociator != null; 146 assert jettyContainer != null; 147 148 this.holder = holder == null ? Holder.EMPTY : holder; 149 150 this.runAsSource = runAsSource == null? RunAsSource.NULL: runAsSource; 151 152 SessionHandler sessionHandler; 153 if (null != handlerFactory) { 154 if (null == preHandlerFactory) { 155 throw new IllegalStateException("A preHandlerFactory must be set if an handler factory is set."); 156 } 157 PreHandler preHandler = preHandlerFactory.createHandler(); 158 sessionHandler = handlerFactory.createHandler(preHandler); 159 } else { 160 sessionHandler = new SessionHandler(); 161 } 162 JettySecurityHandler securityHandler = null; 163 if (securityRealmName != null) { 164 InternalJAASJettyRealm internalJAASJettyRealm = jettyContainer.addRealm(securityRealmName); 165 //wrap jetty realm with something that knows the dumb realmName 166 JAASJettyRealm realm = new JAASJettyRealm(realmName, internalJAASJettyRealm); 167 Subject defaultSubject = this.runAsSource.getDefaultSubject(); 168 securityHandler = new JettySecurityHandler(authenticator, realm, policyContextID, defaultSubject); 169 } 170 171 ServletHandler servletHandler = new ServletHandler(); 172 173 webAppContext = new TwistyWebAppContext(securityHandler, sessionHandler, servletHandler, null); 174 //See Jetty-386. Setting this to true can expose secured content. 175 webAppContext.setCompactPath(compactPath); 176 177 //wrap the web app context with the jndi handler 178 GeronimoUserTransaction userTransaction = new GeronimoUserTransaction(transactionManager); 179 this.componentContext = EnterpriseNamingContext.createEnterpriseNamingContext(componentContext, userTransaction, kernel, classLoader); 180 181 //install jasper injection support if required 182 if (contextCustomizer != null) { 183 Map<String, Object> servletContext = new HashMap<String, Object>(); 184 Map<Class, Object> customizerContext = new HashMap<Class, Object>(); 185 customizerContext.put(Map.class, servletContext); 186 customizerContext.put(Context.class, JettyWebAppContext.this.componentContext); 187 contextCustomizer.customize(customizerContext); 188 for (Map.Entry<String, Object> entry: servletContext.entrySet()) { 189 webAppContext.setAttribute(entry.getKey(), entry.getValue()); 190 } 191 } 192 193 // localize access to next 194 { 195 //install the other handlers inside the web app context 196 Handler next = webAppContext.newTwistyHandler(); 197 next = new ThreadClassloaderHandler(next, classLoader); 198 199 next = new InstanceContextHandler(next, unshareableResources, applicationManagedSecurityResources, trackedConnectionAssociator); 200 next = new UserTransactionHandler(next, userTransaction); 201 next = new ComponentContextHandler(next, this.componentContext); 202 webAppContext.setTwistyHandler(next); 203 204 lifecycleChain = (AbstractImmutableHandler) next; 205 } 206 MimeTypes mimeTypes = new MimeTypes(); 207 mimeTypes.setMimeMap(mimeMap); 208 webAppContext.setMimeTypes(mimeTypes); 209 210 this.server = server; 211 this.application = application; 212 this.objectName = objectName; 213 if (objectName != null) { 214 ObjectName myObjectName = ObjectNameUtil.getObjectName(objectName); 215 verifyObjectName(myObjectName); 216 } 217 this.configurationBaseURL = configurationBaseUrl; 218 this.jettyContainer = jettyContainer; 219 this.originalSpecDD = originalSpecDD; 220 221 //DONT install the jetty TLD configuration as we find and create all the listeners ourselves 222 webAppContext.setConfigurationClasses(new String[]{}); 223 224 webAppRoot = configurationBaseUrl.toString(); 225 webClassLoader = classLoader; 226 webAppContext.setClassLoader(webClassLoader); 227 228 if (host != null) { 229 webAppContext.setConnectorNames(host.getHosts()); 230 webAppContext.setVirtualHosts(host.getVirtualHosts()); 231 } 232 233 //stuff from spec dd 234 webAppContext.setDisplayName(displayName); 235 webAppContext.setInitParams(contextParamMap); 236 setListenerClassNames(listenerClassNames); 237 webAppContext.setDistributable(distributable); 238 webAppContext.setWelcomeFiles(welcomeFiles); 239 setLocaleEncodingMapping(localeEncodingMapping); 240 setErrorPages(errorPages); 241 setTagLibMap(tagLibMap); 242 243 if (!distributable) { 244 setSessionTimeoutSeconds(sessionTimeoutSeconds); 245 } 246 247 } 248 249 250 public String getObjectName() { 251 return objectName; 252 } 253 254 public boolean isStateManageable() { 255 return true; 256 } 257 258 public boolean isStatisticsProvider() { 259 return false; 260 } 261 262 public boolean isEventProvider() { 263 return true; 264 } 265 266 public URL getWARDirectory() { 267 return configurationBaseURL; 268 } 269 270 public String getWARName() { 271 //todo: make this return something more consistent 272 try { 273 return ObjectName.getInstance(objectName).getKeyProperty(NameFactory.J2EE_NAME); 274 } catch (MalformedObjectNameException e) { 275 return null; 276 } 277 } 278 279 public WebContainer getContainer() { 280 return jettyContainer; 281 } 282 283 public void setContextPath(String path) { 284 if (path == null || !path.startsWith("/")) { 285 throw new IllegalArgumentException("context path must be non-null and start with '/', not " + path); 286 } 287 this.webAppContext.setContextPath(path); 288 } 289 290 public String getContextPath() { 291 return this.webAppContext.getContextPath(); 292 } 293 294 public void setWorkDir(String workDir) { 295 if(workDir == null) { 296 return; 297 } 298 this.webAppContext.setTempDirectory(jettyContainer.resolveToJettyHome(workDir)); 299 } 300 301 public ClassLoader getWebClassLoader() { 302 return webClassLoader; 303 } 304 305 public AbstractImmutableHandler getLifecycleChain() { 306 return lifecycleChain; 307 } 308 309 public Subject getSubjectForRole(String role) throws LoginException { 310 return runAsSource.getSubjectForRole(role); 311 } 312 313 public Object newInstance(String className) throws InstantiationException, IllegalAccessException { 314 if (className == null) { 315 throw new InstantiationException("no class loaded"); 316 } 317 return holder.newInstance(className, webClassLoader, componentContext); 318 } 319 320 public void destroyInstance(Object o) throws Exception { 321 Class clazz = o.getClass(); 322 if (holder != null) { 323 Map<String, LifecycleMethod> preDestroy = holder.getPreDestroy(); 324 if (preDestroy != null) { 325 Holder.apply(o, clazz, preDestroy); 326 } 327 } 328 } 329 330 public void doStart() throws Exception { 331 // reset the classsloader... jetty likes to set it to null when stopping 332 this.webAppContext.setClassLoader(webClassLoader); 333 this.webAppContext.setWar(webAppRoot); 334 335 getLifecycleChain().lifecycleCommand(new StartCommand()); 336 } 337 338 public void doStop() throws Exception { 339 getLifecycleChain().lifecycleCommand(new StopCommand()); 340 341 // No more logging will occur for this ClassLoader. Inform the LogFactory to avoid a memory leak. 342 LogFactory.release(webClassLoader); 343 344 // need to release the JSF factories. Otherwise, we'll leak ClassLoaders. 345 //should be done in a myfaces gbean 346 // FactoryFinder.releaseFactories(); 347 348 log.debug("JettyWebAppContext stopped"); 349 } 350 351 public void doFail() { 352 try { 353 doStop(); 354 } catch (Exception e) { 355 //ignore 356 } 357 358 log.warn("JettyWebAppContext failed"); 359 } 360 361 public class StartCommand implements LifecycleCommand { 362 363 public void lifecycleMethod() throws Exception { 364 //order seems backwards... .maybe container is calling start itself??? 365 jettyContainer.addContext(webAppContext); 366 webAppContext.start(); 367 } 368 } 369 370 public class StopCommand implements LifecycleCommand { 371 372 public void lifecycleMethod() throws Exception { 373 webAppContext.stop(); 374 //TODO is this order correct? 375 for (EventListener listener : webAppContext.getEventListeners()) { 376 destroyInstance(listener); 377 } 378 jettyContainer.removeContext(webAppContext); 379 } 380 } 381 //pass through attributes. They should be constructor params 382 383 public void setLocaleEncodingMapping(Map<String, String> localeEncodingMap) { 384 if (localeEncodingMap != null) { 385 for (Map.Entry<String, String> entry : localeEncodingMap.entrySet()) { 386 this.webAppContext.addLocaleEncoding(entry.getKey(), entry.getValue()); 387 } 388 } 389 } 390 391 public void setListenerClassNames(Collection<String> eventListeners) throws ClassNotFoundException, IllegalAccessException, InstantiationException { 392 if (eventListeners != null) { 393 Collection<EventListener> listeners = new ArrayList<EventListener>(); 394 for (String listenerClassName : eventListeners) { 395 EventListener listener = (EventListener) newInstance(listenerClassName); 396 listeners.add(listener); 397 } 398 webAppContext.setEventListeners(listeners.toArray(new EventListener[listeners.size()])); 399 } 400 } 401 402 public void setErrorPages(Map errorPageMap) { 403 if (errorPageMap != null) { 404 ((ErrorPageErrorHandler) this.webAppContext.getErrorHandler()).setErrorPages(errorPageMap); 405 } 406 } 407 408 public void setTagLibMap(Map<String, String> tagLibMap) { 409 if (tagLibMap != null) { 410 for (Map.Entry<String, String> entry : tagLibMap.entrySet()) { 411 this.webAppContext.setResourceAlias(entry.getKey(), entry.getValue()); 412 } 413 } 414 } 415 416 public void setSessionTimeoutSeconds(int seconds) { 417 this.webAppContext.getSessionHandler().getSessionManager().setMaxInactiveInterval(seconds); 418 } 419 420 421 //TODO this is really dumb, but jetty5 liked to set the displayname to null frequently. 422 //we need to re-check for jetty6 423 public String getDisplayName() { 424 return displayName; 425 } 426 427 public void setDisplayName(String displayName) { 428 this.displayName = displayName; 429 this.webAppContext.setDisplayName(displayName); 430 } 431 432 public String getDeploymentDescriptor() { 433 return originalSpecDD; 434 } 435 436 public String getServer() { 437 return server.getObjectName(); 438 } 439 440 public String getApplication() { 441 if (application == null) { 442 return null; 443 } 444 return application.getObjectName(); 445 } 446 447 public String[] getJavaVMs() { 448 return server.getJavaVMs(); 449 } 450 451 public String[] getServlets() { 452 synchronized (servletNames) { 453 return servletNames.toArray(new String[servletNames.size()]); 454 } 455 } 456 457 public ServletHandler getServletHandler() { 458 return this.webAppContext.getServletHandler(); 459 } 460 461 /** 462 * ObjectName must match this pattern: 463 * <p/> 464 * domain:j2eeType=WebModule,name=MyName,J2EEServer=MyServer,J2EEApplication=MyApplication 465 * 466 * @param objectName ObjectName to verify 467 */ 468 private void verifyObjectName(ObjectName objectName) { 469 if (objectName.isPattern()) { 470 throw new InvalidObjectNameException("ObjectName can not be a pattern", objectName); 471 } 472 Hashtable keyPropertyList = objectName.getKeyPropertyList(); 473 if (!NameFactory.WEB_MODULE.equals(keyPropertyList.get("j2eeType"))) { 474 throw new InvalidObjectNameException("WebModule object name j2eeType property must be 'WebModule'", objectName); 475 } 476 if (!keyPropertyList.containsKey(NameFactory.J2EE_NAME)) { 477 throw new InvalidObjectNameException("WebModule object must contain a name property", objectName); 478 } 479 if (!keyPropertyList.containsKey(NameFactory.J2EE_SERVER)) { 480 throw new InvalidObjectNameException("WebModule object name must contain a J2EEServer property", objectName); 481 } 482 if (!keyPropertyList.containsKey(NameFactory.J2EE_APPLICATION)) { 483 throw new InvalidObjectNameException("WebModule object name must contain a J2EEApplication property", objectName); 484 } 485 if (keyPropertyList.size() != 4) { 486 throw new InvalidObjectNameException("WebModule object name can only have j2eeType, name, J2EEApplication, and J2EEServer properties", objectName); 487 } 488 } 489 490 public void registerServletHolder(ServletHolder servletHolder, String servletName, Set<String> servletMappings, String objectName) throws Exception { 491 webAppContext.getServletHandler().addServlet(servletHolder); 492 if (servletMappings != null) { 493 for (String urlPattern : servletMappings) { 494 ServletMapping servletMapping = new ServletMapping(); 495 servletMapping.setPathSpec(urlPattern); 496 servletMapping.setServletName(servletName); 497 this.webAppContext.getServletHandler().addServletMapping(servletMapping); 498 } 499 } 500 // LifecycleCommand lifecycleCommand = new LifecycleCommand.StartCommand(servletHolder); 501 // lifecycleChain.lifecycleCommand(lifecycleCommand); 502 if (objectName != null) { 503 synchronized (servletNames) { 504 servletNames.add(objectName); 505 } 506 } 507 } 508 509 public void unregisterServletHolder(ServletHolder servletHolder, String servletName, Set<String> servletMappings, String objectName) throws Exception { 510 //no way to remove servlets 511 // webAppContext.getServletHandler().removeServlet(servletHolder); 512 // if (servletMappings != null) { 513 // for (Iterator iterator = servletMappings.iterator(); iterator.hasNext();) { 514 // String urlPattern = (String) iterator.next(); 515 // ServletMapping servletMapping = new ServletMapping(); 516 // servletMapping.setPathSpec(urlPattern); 517 // servletMapping.setServletName(servletName); 518 // webAppContext.getServletHandler().removeServletMapping(servletMapping); 519 // } 520 // } 521 // LifecycleCommand lifecycleCommand = new LifecycleCommand.StopCommand(servletHolder); 522 // lifecycleChain.lifecycleCommand(lifecycleCommand); 523 if (objectName != null) { 524 synchronized (servletNames) { 525 servletNames.remove(objectName); 526 } 527 } 528 } 529 530 public static final GBeanInfo GBEAN_INFO; 531 532 public static final String GBEAN_ATTR_SESSION_TIMEOUT = "sessionTimeoutSeconds"; 533 534 public static final String GBEAN_REF_SESSION_HANDLER_FACTORY = "SessionHandlerFactory"; 535 public static final String GBEAN_REF_PRE_HANDLER_FACTORY = "PreHandlerFactory"; 536 537 static { 538 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic("Jetty WebApplication Context", JettyWebAppContext.class, NameFactory.WEB_MODULE); 539 infoBuilder.addAttribute("deploymentDescriptor", String.class, true); 540 //from jetty6's webapp context 541 542 infoBuilder.addAttribute("displayName", String.class, true); 543 infoBuilder.addAttribute("contextParamMap", Map.class, true); 544 infoBuilder.addAttribute("listenerClassNames", Collection.class, true); 545 infoBuilder.addAttribute("distributable", boolean.class, true); 546 547 infoBuilder.addAttribute("mimeMap", Map.class, true); 548 infoBuilder.addAttribute("welcomeFiles", String[].class, true); 549 infoBuilder.addAttribute("localeEncodingMapping", Map.class, true); 550 infoBuilder.addAttribute("errorPages", Map.class, true); 551 infoBuilder.addAttribute("authenticator", Authenticator.class, true); 552 infoBuilder.addAttribute("realmName", String.class, true); 553 infoBuilder.addAttribute("tagLibMap", Map.class, true); 554 infoBuilder.addAttribute(GBEAN_ATTR_SESSION_TIMEOUT, int.class, true); 555 infoBuilder.addReference(GBEAN_REF_SESSION_HANDLER_FACTORY, SessionHandlerFactory.class, 556 NameFactory.GERONIMO_SERVICE); 557 infoBuilder.addReference(GBEAN_REF_PRE_HANDLER_FACTORY, PreHandlerFactory.class, NameFactory.GERONIMO_SERVICE); 558 559 infoBuilder.addAttribute("componentContext", Map.class, true); 560 infoBuilder.addAttribute("classLoader", ClassLoader.class, false); 561 infoBuilder.addAttribute("configurationBaseUrl", URL.class, true); 562 infoBuilder.addAttribute("unshareableResources", Set.class, true); 563 infoBuilder.addAttribute("applicationManagedSecurityResources", Set.class, true); 564 565 infoBuilder.addAttribute("contextPath", String.class, true); 566 infoBuilder.addAttribute("compactPath", boolean.class, true); 567 568 infoBuilder.addAttribute("workDir", String.class, true); 569 infoBuilder.addReference("Host", Host.class, "Host"); 570 infoBuilder.addReference("TransactionManager", TransactionManager.class, NameFactory.JTA_RESOURCE); 571 infoBuilder.addReference("TrackedConnectionAssociator", TrackedConnectionAssociator.class, NameFactory.JCA_CONNECTION_TRACKER); 572 infoBuilder.addReference("JettyContainer", JettyContainer.class, NameFactory.GERONIMO_SERVICE); 573 infoBuilder.addReference("ContextCustomizer", RuntimeCustomizer.class, NameFactory.GERONIMO_SERVICE); 574 575 infoBuilder.addInterface(JettyServletRegistration.class); 576 577 infoBuilder.addAttribute("policyContextID", String.class, true); 578 infoBuilder.addAttribute("securityRealmName", String.class, true); 579 infoBuilder.addReference("RunAsSource", RunAsSource.class, NameFactory.JACC_MANAGER); 580 581 infoBuilder.addAttribute("holder", Holder.class, true); 582 583 infoBuilder.addReference("J2EEServer", J2EEServer.class); 584 infoBuilder.addReference("J2EEApplication", J2EEApplication.class); 585 586 infoBuilder.addAttribute("kernel", Kernel.class, false); 587 infoBuilder.addAttribute("objectName", String.class, false); 588 infoBuilder.addAttribute("application", String.class, false); 589 infoBuilder.addAttribute("javaVMs", String[].class, false); 590 infoBuilder.addAttribute("servlets", String[].class, false); 591 592 infoBuilder.addInterface(WebModule.class); 593 594 infoBuilder.setConstructor(new String[]{ 595 "objectName", 596 "deploymentDescriptor", 597 "componentContext", 598 "classLoader", 599 "configurationBaseUrl", 600 "unshareableResources", 601 "applicationManagedSecurityResources", 602 603 "displayName", 604 "contextParamMap", 605 "listenerClassNames", 606 "distributable", 607 "mimeMap", 608 "welcomeFiles", 609 "localeEncodingMapping", 610 "errorPages", 611 "authenticator", 612 "realmName", 613 "tagLibMap", 614 "compactPath", 615 GBEAN_ATTR_SESSION_TIMEOUT, 616 GBEAN_REF_SESSION_HANDLER_FACTORY, 617 GBEAN_REF_PRE_HANDLER_FACTORY, 618 619 "policyContextID", 620 "securityRealmName", 621 "RunAsSource", 622 623 "holder", 624 625 "Host", 626 "TransactionManager", 627 "TrackedConnectionAssociator", 628 "JettyContainer", 629 "ContextCustomizer", 630 631 "J2EEServer", 632 "J2EEApplication", 633 "kernel" 634 }); 635 636 GBEAN_INFO = infoBuilder.getBeanInfo(); 637 } 638 639 public static GBeanInfo getGBeanInfo() { 640 return GBEAN_INFO; 641 } 642 643 }