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    }