View Javadoc

1   /**
2    *
3    *  Licensed to the Apache Software Foundation (ASF) under one or more
4    *  contributor license agreements.  See the NOTICE file distributed with
5    *  this work for additional information regarding copyright ownership.
6    *  The ASF licenses this file to You under the Apache License, Version 2.0
7    *  (the "License"); you may not use this file except in compliance with
8    *  the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing, software
13   *  distributed under the License is distributed on an "AS IS" BASIS,
14   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *  See the License for the specific language governing permissions and
16   *  limitations under the License.
17   */
18  
19  package org.apache.geronimo.jetty;
20  
21  import java.io.IOException;
22  import java.net.MalformedURLException;
23  import java.net.URL;
24  import java.security.PermissionCollection;
25  import java.util.Collection;
26  import java.util.EventListener;
27  import java.util.HashMap;
28  import java.util.HashSet;
29  import java.util.Hashtable;
30  import java.util.Iterator;
31  import java.util.Map;
32  import java.util.Set;
33  
34  import javax.management.MalformedObjectNameException;
35  import javax.management.ObjectName;
36  import javax.naming.Context;
37  import javax.transaction.TransactionManager;
38  
39  import org.apache.commons.logging.Log;
40  import org.apache.commons.logging.LogFactory;
41  import org.apache.geronimo.connector.outbound.connectiontracking.TrackedConnectionAssociator;
42  import org.apache.geronimo.gbean.GBeanInfo;
43  import org.apache.geronimo.gbean.GBeanInfoBuilder;
44  import org.apache.geronimo.gbean.GBeanLifecycle;
45  import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
46  import org.apache.geronimo.j2ee.management.impl.InvalidObjectNameException;
47  import org.apache.geronimo.jetty.interceptor.BeforeAfter;
48  import org.apache.geronimo.jetty.interceptor.ComponentContextBeforeAfter;
49  import org.apache.geronimo.jetty.interceptor.InstanceContextBeforeAfter;
50  import org.apache.geronimo.jetty.interceptor.SecurityContextBeforeAfter;
51  import org.apache.geronimo.jetty.interceptor.ThreadClassloaderBeforeAfter;
52  import org.apache.geronimo.jetty.interceptor.WebApplicationContextBeforeAfter;
53  import org.apache.geronimo.kernel.Kernel;
54  import org.apache.geronimo.kernel.ObjectNameUtil;
55  import org.apache.geronimo.management.J2EEApplication;
56  import org.apache.geronimo.management.J2EEServer;
57  import org.apache.geronimo.management.geronimo.WebConnector;
58  import org.apache.geronimo.management.geronimo.WebContainer;
59  import org.apache.geronimo.management.geronimo.WebModule;
60  import org.apache.geronimo.naming.enc.EnterpriseNamingContext;
61  import org.apache.geronimo.security.deploy.DefaultPrincipal;
62  import org.apache.geronimo.transaction.GeronimoUserTransaction;
63  import org.mortbay.http.Authenticator;
64  import org.mortbay.http.HttpException;
65  import org.mortbay.http.HttpRequest;
66  import org.mortbay.http.HttpResponse;
67  import org.mortbay.jetty.servlet.AbstractSessionManager;
68  import org.mortbay.jetty.servlet.Dispatcher;
69  import org.mortbay.jetty.servlet.FilterHolder;
70  import org.mortbay.jetty.servlet.JSR154Filter;
71  import org.mortbay.jetty.servlet.ServletHolder;
72  import org.mortbay.jetty.servlet.ServletHttpRequest;
73  import org.mortbay.jetty.servlet.ServletHttpResponse;
74  import org.mortbay.jetty.servlet.WebApplicationContext;
75  import org.mortbay.jetty.servlet.WebApplicationHandler;
76  
77  /**
78   * Wrapper for a WebApplicationContext that sets up its J2EE environment.
79   *
80   * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
81   */
82  public class JettyWebAppContext extends WebApplicationContext implements GBeanLifecycle, JettyServletRegistration, WebModule {
83      private static Log log = LogFactory.getLog(JettyWebAppContext.class);
84  
85      private final String originalSpecDD;
86      private final J2EEServer server;
87      private final J2EEApplication application;
88  
89      private final ClassLoader webClassLoader;
90      private final JettyContainer jettyContainer;
91  
92      private final String webAppRoot;
93      private final URL configurationBaseURL;
94      private final WebApplicationHandler handler;
95      private final HandleInterceptor handleInterceptor;
96      private String displayName;
97      private final String[] welcomeFiles;
98  
99      private final BeforeAfter chain;
100     private final int contextLength;
101     private final SecurityContextBeforeAfter securityInterceptor;
102 
103     private final String objectName;
104 
105     private final Set servletNames = new HashSet();
106 
107     /**
108      * @deprecated never use this... this is only here because Jetty WebApplicationContext is externalizable
109      */
110     public JettyWebAppContext() {
111         server = null;
112         application = null;
113         originalSpecDD = null;
114         webClassLoader = null;
115         jettyContainer = null;
116         webAppRoot = null;
117         handler = null;
118         handleInterceptor = null; 
119         chain = null;
120         contextLength = 0;
121         securityInterceptor = null;
122         welcomeFiles = null;
123         objectName = null;
124         configurationBaseURL = null;
125     }
126 
127     public JettyWebAppContext(String objectName,
128                               String originalSpecDD,
129                               Map componentContext,
130                               ClassLoader classLoader,
131                               URL configurationBaseUrl,
132                               Set unshareableResources,
133                               Set applicationManagedSecurityResources,
134             String displayName,
135             Map contextParamMap,
136             Collection listenerClassNames,
137             boolean distributable,
138             Map mimeMap,
139             String[] welcomeFiles,
140             Map localeEncodingMapping,
141             Map errorPages,
142             Authenticator authenticator,
143             String realmName,
144             Map tagLibMap,
145             int sessionTimeoutSeconds,
146                               WebApplicationHandlerFactory handlerFactory,
147                               HandleInterceptor handleInterceptor,
148 
149             String policyContextID,
150             String securityRealmName,
151             DefaultPrincipal defaultPrincipal,
152             PermissionCollection checkedPermissions,
153             PermissionCollection excludedPermissions,
154 
155             Host host,
156             TransactionManager transactionManager,
157             TrackedConnectionAssociator trackedConnectionAssociator,
158             JettyContainer jettyContainer,
159             J2EEServer server,
160             J2EEApplication application,
161             Kernel kernel) throws Exception, IllegalAccessException, InstantiationException, ClassNotFoundException {
162 
163         assert componentContext != null;
164         assert classLoader != null;
165         assert configurationBaseUrl != null;
166         assert transactionManager != null;
167         assert trackedConnectionAssociator != null;
168         assert jettyContainer != null;
169 
170         this.server = server;
171         this.application = application;
172         this.objectName = objectName;
173         if (objectName != null) {
174             ObjectName myObjectName = ObjectNameUtil.getObjectName(objectName);
175             verifyObjectName(myObjectName);
176         }
177         this.configurationBaseURL = configurationBaseUrl;
178         this.jettyContainer = jettyContainer;
179         this.originalSpecDD = originalSpecDD;
180         this.handleInterceptor = handleInterceptor;
181         
182         setConfigurationClassNames(new String[]{});
183 
184         webAppRoot = configurationBaseUrl.toString();
185         this.webClassLoader = classLoader;
186         setClassLoader(this.webClassLoader);
187 
188         if (host != null) {
189             setHosts(host.getHosts());
190             setVirtualHosts(host.getVirtualHosts());
191         }
192 
193         handler = handlerFactory.createHandler();
194         addHandler(handler);
195 
196         //stuff from spec dd
197         setDisplayName(displayName);
198         setContextParamMap(contextParamMap);
199         setListenerClassNames(listenerClassNames);
200         setDistributable(distributable);
201         setMimeMap(mimeMap);
202         this.welcomeFiles = welcomeFiles;
203         setLocaleEncodingMapping(localeEncodingMapping);
204         setErrorPages(errorPages);
205         setAuthenticator(authenticator);
206         setRealmName(realmName);
207         setTagLibMap(tagLibMap);
208 
209         if (false == distributable) {
210             setSessionTimeoutSeconds(sessionTimeoutSeconds);
211         }
212 
213         GeronimoUserTransaction userTransaction = new GeronimoUserTransaction(transactionManager);
214         Context enc = EnterpriseNamingContext.createEnterpriseNamingContext(componentContext, userTransaction, kernel, webClassLoader);
215 
216         int index = 0;
217         BeforeAfter interceptor = new InstanceContextBeforeAfter(null, index++, unshareableResources, applicationManagedSecurityResources, trackedConnectionAssociator);
218         interceptor = new ComponentContextBeforeAfter(interceptor, index++, enc);
219         interceptor = new ThreadClassloaderBeforeAfter(interceptor, index++, index++, this.webClassLoader);
220         interceptor = new WebApplicationContextBeforeAfter(interceptor, index++, this);
221 //JACC
222 
223         if (securityRealmName != null) {
224             InternalJAASJettyRealm internalJAASJettyRealm = jettyContainer.addRealm(securityRealmName);
225             //wrap jetty realm with something that knows the dumb realmName
226             JAASJettyRealm realm = new JAASJettyRealm(realmName, internalJAASJettyRealm);
227             setRealm(realm);
228             this.securityInterceptor = new SecurityContextBeforeAfter(interceptor, index++, index++, policyContextID, defaultPrincipal, authenticator, checkedPermissions, excludedPermissions, realm, classLoader);
229             interceptor = this.securityInterceptor;
230         } else {
231             securityInterceptor = null;
232         }
233 //      end JACC
234         chain = interceptor;
235         contextLength = index;
236 
237         //cheat -- add jsr154 filter not as a gbean
238         FilterHolder jsr154FilterHolder = new FilterHolder(handler, "jsr154", JSR154Filter.class.getName());
239         handler.addFilterHolder(jsr154FilterHolder);
240         jsr154FilterHolder.setInitParameter("unwrappedDispatch", "true");
241         handler.addFilterPathMapping("/*", "jsr154", Dispatcher.__REQUEST | Dispatcher.__FORWARD | Dispatcher.__INCLUDE | Dispatcher.__ERROR);
242     }
243 
244 
245     public String getObjectName() {
246         return objectName;
247     }
248 
249     public boolean isStateManageable() {
250         return true;
251     }
252 
253     public boolean isStatisticsProvider() {
254         return false;
255     }
256 
257     public boolean isEventProvider() {
258         return true;
259     }
260 
261     public URL getWARDirectory() {
262         return configurationBaseURL;
263     }
264 
265     public String getWARName() {
266         //todo: make this return something more consistent
267         try {
268             return ObjectName.getInstance(objectName).getKeyProperty(NameFactory.J2EE_NAME);
269         } catch (MalformedObjectNameException e) {
270             return null;
271         }
272     }
273 
274     public WebContainer getContainer() {
275         return jettyContainer;
276     }
277 
278     public URL getURLFor() {
279         WebConnector[] connectors = (WebConnector[]) jettyContainer.getConnectors();
280         Map map = new HashMap();
281         for (int i = 0; i < connectors.length; i++) {
282             WebConnector connector = connectors[i];
283             map.put(connector.getProtocol(), connector.getConnectUrl());
284         }
285         String urlPrefix;
286         if((urlPrefix = (String) map.get("HTTP")) == null) {
287             if((urlPrefix = (String) map.get("HTTPS")) == null) {
288                 urlPrefix = (String) map.get("AJP");
289             }
290         }
291         if(urlPrefix == null) {
292             return null;
293         }
294         try {
295             return new URL(urlPrefix + getContextPath());
296         } catch (MalformedURLException e) {
297             log.error("Bad URL to connect to web app", e);
298             return null;
299         }
300     }
301 
302     public Object enterContextScope(HttpRequest httpRequest, HttpResponse httpResponse) {
303         Object[] context = new Object[contextLength];
304         chain.before(context, httpRequest, httpResponse);
305         return context;
306     }
307 
308     public void leaveContextScope(HttpRequest httpRequest, HttpResponse httpResponse, Object oldScope) {
309         Object[] context = (Object[]) oldScope;
310         chain.after(context, httpRequest, httpResponse);
311     }
312 
313     public void handle(HttpRequest httpRequest, HttpResponse httpResponse) throws HttpException, IOException {
314         super.handle(httpRequest, httpResponse);
315     }
316     
317     public void handle(String pathInContext, String pathParams, HttpRequest httpRequest, HttpResponse httpResponse)
318             throws HttpException, IOException {
319         ServletHttpRequest request = (ServletHttpRequest) httpRequest.getWrapper();
320         if (null == request) {
321             request = new GeronimoServletHttpRequest(handler, null, httpRequest);
322             ServletHttpResponse response = new ServletHttpResponse(request, httpResponse);
323             httpRequest.setWrapper(request);
324             httpResponse.setWrapper(response);
325         }
326         ((GeronimoServletHttpRequest) request).setRequestedSessionId(pathParams);
327         if (null != handleInterceptor) {
328             handleInterceptor.handle(pathInContext, pathParams, httpRequest, httpResponse, new EndHandleInterceptor());   
329         } else {
330             super.handle(pathInContext, pathParams, httpRequest, httpResponse);
331         }
332     }
333     
334     public ClassLoader getWebClassLoader() {
335         return webClassLoader;
336     }
337 
338     public void doStart() throws Exception {
339         // reset the classsloader... jetty likes to set it to null when stopping
340         setClassLoader(webClassLoader);
341 
342         // merge Geronimo and Jetty Lifecycles
343         if (!isStarting()) {
344             super.start();
345             return;
346         }
347 
348         ((AbstractSessionManager) getServletHandler().getSessionManager()).setUseRequestedId(true);
349 
350         setWAR(webAppRoot);
351 
352         jettyContainer.addContext(this);
353 
354         Object context = enterContextScope(null, null);
355         try {
356             super.doStart();
357         } finally {
358             leaveContextScope(null, null, context);
359         }
360         //super.doStart sets welcomefiles to null!!
361         setWelcomeFiles(welcomeFiles);
362 
363         log.debug("JettyWebAppContext started");
364     }
365 
366     public void doStop() throws Exception {
367         // merge Geronimo and Jetty Lifecycles
368         if (!isStopping()) {
369             super.stop();
370             return;
371         }
372 
373         if (securityInterceptor != null) {
374             securityInterceptor.stop(jettyContainer);
375         }
376         Object context = enterContextScope(null, null);
377         try {
378             super.doStop();
379         } finally {
380             leaveContextScope(null, null, context);
381             jettyContainer.removeContext(this);
382         }
383 
384         // No more logging will occur for this ClassLoader. Inform the LogFactory to avoid a memory leak.
385         LogFactory.release(webClassLoader);
386 
387         log.debug("JettyWebAppContext stopped");
388     }
389 
390     public void doFail() {
391         try {
392             //this will call doStop
393             super.stop();
394         } catch (InterruptedException e) {
395         }
396 
397         log.warn("JettyWebAppContext failed");
398     }
399 
400     //pass through attributes.  They should be constructor params
401 
402     //TODO encourage jetty to improve their naming convention.
403     public void setContextParamMap(Map initParameters) {
404         if (initParameters != null) {
405             for (Iterator iterator = initParameters.entrySet().iterator(); iterator.hasNext();) {
406                 Map.Entry entry = (Map.Entry) iterator.next();
407                 setInitParameter((String) entry.getKey(), (String) entry.getValue());
408             }
409         }
410     }
411 
412     public void setLocaleEncodingMapping(Map localeEncodingMap) {
413         if (localeEncodingMap != null) {
414             for (Iterator iterator = localeEncodingMap.entrySet().iterator(); iterator.hasNext();) {
415                 Map.Entry entry = (Map.Entry) iterator.next();
416                 addLocaleEncoding((String) entry.getKey(), (String) entry.getValue());
417             }
418         }
419     }
420 
421     public void setListenerClassNames(Collection eventListeners) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
422         if (eventListeners != null) {
423             for (Iterator iterator = eventListeners.iterator(); iterator.hasNext();) {
424                 String listenerClassName = (String) iterator.next();
425                 Class clazz = loadClass(listenerClassName);
426                 EventListener listener = (EventListener) clazz.newInstance();
427                 addEventListener(listener);
428                 handler.addEventListener(listener);
429             }
430         }
431     }
432 
433     public void setErrorPages(Map errorPageMap) {
434         if (errorPageMap != null) {
435             for (Iterator iterator = errorPageMap.entrySet().iterator(); iterator.hasNext();) {
436                 Map.Entry entry = (Map.Entry) iterator.next();
437                 setErrorPage((String) entry.getKey(), (String) entry.getValue());
438             }
439         }
440     }
441 
442     public void setTagLibMap(Map tagLibMap) {
443         if (tagLibMap != null) {
444             for (Iterator iterator = tagLibMap.entrySet().iterator(); iterator.hasNext();) {
445                 Map.Entry entry = (Map.Entry) iterator.next();
446                 setResourceAlias((String) entry.getKey(), (String) entry.getValue());
447             }
448         }
449     }
450 
451     public void setSessionTimeoutSeconds(int seconds) {
452         handler.setSessionInactiveInterval(seconds);
453     }
454 
455 
456     //TODO this is really dumb, but jetty likes to set the displayname to null frequently.
457     public String getDisplayName() {
458         return displayName;
459     }
460 
461     public void setDisplayName(String displayName) {
462         this.displayName = displayName;
463         super.setDisplayName(displayName);
464     }
465 
466     public String getDeploymentDescriptor() {
467         return originalSpecDD;
468     }
469 
470     public String getServer() {
471         return server.getObjectName();
472     }
473 
474     public String getApplication() {
475         if (application == null) {
476             return null;
477         }
478         return application.getObjectName();
479     }
480 
481     public String[] getJavaVMs() {
482         return server.getJavaVMs();
483     }
484 
485     public String[] getServlets() {
486         synchronized(servletNames) {
487             return (String[]) servletNames.toArray(new String[servletNames.size()]);
488         }
489     }
490 
491     /**
492      * ObjectName must match this pattern:
493      * <p/>
494      * domain:j2eeType=WebModule,name=MyName,J2EEServer=MyServer,J2EEApplication=MyApplication
495      */
496     private void verifyObjectName(ObjectName objectName) {
497         if (objectName.isPattern()) {
498             throw new InvalidObjectNameException("ObjectName can not be a pattern", objectName);
499         }
500         Hashtable keyPropertyList = objectName.getKeyPropertyList();
501         if (!NameFactory.WEB_MODULE.equals(keyPropertyList.get("j2eeType"))) {
502             throw new InvalidObjectNameException("WebModule object name j2eeType property must be 'WebModule'", objectName);
503         }
504         if (!keyPropertyList.containsKey(NameFactory.J2EE_NAME)) {
505             throw new InvalidObjectNameException("WebModule object must contain a name property", objectName);
506         }
507         if (!keyPropertyList.containsKey(NameFactory.J2EE_SERVER)) {
508             throw new InvalidObjectNameException("WebModule object name must contain a J2EEServer property", objectName);
509         }
510         if (!keyPropertyList.containsKey(NameFactory.J2EE_APPLICATION)) {
511             throw new InvalidObjectNameException("WebModule object name must contain a J2EEApplication property", objectName);
512         }
513         if (keyPropertyList.size() != 4) {
514             throw new InvalidObjectNameException("WebModule object name can only have j2eeType, name, J2EEApplication, and J2EEServer properties", objectName);
515         }
516     }
517 
518     public void registerServletHolder(ServletHolder servletHolder, String servletName, Set servletMappings, String objectName) throws Exception {
519         //TODO filters
520         handler.addServletHolder(servletHolder);
521         if (servletMappings != null) {
522             for (Iterator iterator = servletMappings.iterator(); iterator.hasNext();) {
523                 String urlPattern = (String) iterator.next();
524                 handler.mapPathToServlet(urlPattern, servletName);
525             }
526         }
527         Object context = enterContextScope(null, null);
528         try {
529             servletHolder.start();
530         } finally {
531             leaveContextScope(null, null, context);
532         }
533         if (objectName != null) {
534             synchronized(servletNames) {
535                 servletNames.add(objectName);
536             }
537         }
538     }
539 
540     public boolean checkSecurityConstraints(String pathInContext, HttpRequest request, HttpResponse response) throws HttpException, IOException {
541         if (securityInterceptor != null) {
542             return securityInterceptor.checkSecurityConstraints(pathInContext, request, response);
543         }
544         return super.checkSecurityConstraints(pathInContext, request, response);
545     }
546 
547     private void doHandle(String pathInContext, String pathParams, HttpRequest httpRequest, HttpResponse httpResponse)
548             throws HttpException, IOException {
549         super.handle(pathInContext, pathParams, httpRequest, httpResponse);
550     }
551     
552     private class EndHandleInterceptor implements HandleInterceptor {
553 
554         public void handle(String pathInContext, String pathParams, HttpRequest httpRequest, HttpResponse httpResponse,
555                 HandleInterceptor end) throws HttpException, IOException {
556             doHandle(pathInContext, pathParams, httpRequest, httpResponse);
557         }
558     }
559     
560     public static final GBeanInfo GBEAN_INFO;
561     
562     public static final String GBEAN_ATTR_SESSION_TIMEOUT = "sessionTimeoutSeconds";
563     
564     public static final String GBEAN_REF_WEB_APPLICATION_HANDLER_FACTORY = "WebApplicationHandlerFactory";
565     public static final String GBEAN_REF_HANDLE_INTERCEPTOR = "HandleInterceptor";
566 
567     static {
568         GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic("Jetty WebApplication Context", JettyWebAppContext.class, NameFactory.WEB_MODULE);
569         infoBuilder.addAttribute("deploymentDescriptor", String.class, true);
570         //from jetty's webapp context
571 
572         infoBuilder.addAttribute("displayName", String.class, true);
573         infoBuilder.addAttribute("contextParamMap", Map.class, true);
574         infoBuilder.addAttribute("listenerClassNames", Collection.class, true);
575         infoBuilder.addAttribute("distributable", boolean.class, true);
576 
577         infoBuilder.addAttribute("mimeMap", Map.class, true);
578         infoBuilder.addAttribute("welcomeFiles", String[].class, true);
579         infoBuilder.addAttribute("localeEncodingMapping", Map.class, true);
580         infoBuilder.addAttribute("errorPages", Map.class, true);
581         infoBuilder.addAttribute("authenticator", Authenticator.class, true);
582         infoBuilder.addAttribute("realmName", String.class, true);
583         infoBuilder.addAttribute("tagLibMap", Map.class, true);
584         infoBuilder.addAttribute(GBEAN_ATTR_SESSION_TIMEOUT, int.class, true);
585         infoBuilder.addReference(GBEAN_REF_WEB_APPLICATION_HANDLER_FACTORY, WebApplicationHandlerFactory.class,
586                 NameFactory.GERONIMO_SERVICE);
587         infoBuilder.addReference(GBEAN_REF_HANDLE_INTERCEPTOR, HandleInterceptor.class, NameFactory.GERONIMO_SERVICE);
588         
589         infoBuilder.addAttribute("componentContext", Map.class, true);
590         infoBuilder.addAttribute("classLoader", ClassLoader.class, false);
591         infoBuilder.addAttribute("configurationBaseUrl", URL.class, true);
592         infoBuilder.addAttribute("unshareableResources", Set.class, true);
593         infoBuilder.addAttribute("applicationManagedSecurityResources", Set.class, true);
594 
595         infoBuilder.addAttribute("contextPath", String.class, true);
596 
597         infoBuilder.addReference("Host", Host.class, "Host");
598         infoBuilder.addReference("TransactionManager", TransactionManager.class, NameFactory.TRANSACTION_MANAGER);
599         infoBuilder.addReference("TrackedConnectionAssociator", TrackedConnectionAssociator.class, NameFactory.JCA_CONNECTION_TRACKER);
600         infoBuilder.addReference("JettyContainer", JettyContainer.class, NameFactory.GERONIMO_SERVICE);
601 
602         infoBuilder.addInterface(JettyServletRegistration.class);
603 
604         infoBuilder.addAttribute("policyContextID", String.class, true);
605         infoBuilder.addAttribute("securityRealmName", String.class, true);
606         infoBuilder.addAttribute("defaultPrincipal", DefaultPrincipal.class, true);
607 
608         infoBuilder.addAttribute("checkedPermissions", PermissionCollection.class, true);
609         infoBuilder.addAttribute("excludedPermissions", PermissionCollection.class, true);
610 
611         infoBuilder.addReference("J2EEServer", J2EEServer.class);
612         infoBuilder.addReference("J2EEApplication", J2EEApplication.class);
613 
614         infoBuilder.addAttribute("kernel", Kernel.class, false);
615         infoBuilder.addAttribute("objectName", String.class, false);
616         infoBuilder.addAttribute("server", String.class, false);
617         infoBuilder.addAttribute("application", String.class, false);
618         infoBuilder.addAttribute("javaVMs", String[].class, false);
619         infoBuilder.addAttribute("servlets", String[].class, false);
620 
621         infoBuilder.addInterface(WebModule.class);
622 
623         infoBuilder.setConstructor(new String[]{
624                 "objectName",
625                 "deploymentDescriptor",
626                 "componentContext",
627                 "classLoader",
628                 "configurationBaseUrl",
629                 "unshareableResources",
630                 "applicationManagedSecurityResources",
631 
632                 "displayName",
633                 "contextParamMap",
634                 "listenerClassNames",
635                 "distributable",
636                 "mimeMap",
637                 "welcomeFiles",
638                 "localeEncodingMapping",
639                 "errorPages",
640                 "authenticator",
641                 "realmName",
642                 "tagLibMap",
643                 GBEAN_ATTR_SESSION_TIMEOUT,
644                 GBEAN_REF_WEB_APPLICATION_HANDLER_FACTORY,
645                 GBEAN_REF_HANDLE_INTERCEPTOR,
646 
647                 "policyContextID",
648                 "securityRealmName",
649                 "defaultPrincipal",
650 
651                 "checkedPermissions",
652                 "excludedPermissions",
653 
654                 "Host",
655                 "TransactionManager",
656                 "TrackedConnectionAssociator",
657                 "JettyContainer",
658 
659                 "J2EEServer",
660                 "J2EEApplication",
661                 "kernel"
662         });
663 
664         GBEAN_INFO = infoBuilder.getBeanInfo();
665     }
666 
667     public static GBeanInfo getGBeanInfo() {
668         return GBEAN_INFO;
669     }
670 
671 }