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