001    /**
002     *
003     *  Licensed to the Apache Software Foundation (ASF) under one or more
004     *  contributor license agreements.  See the NOTICE file distributed with
005     *  this work for additional information regarding copyright ownership.
006     *  The ASF licenses this file to You under the Apache License, Version 2.0
007     *  (the "License"); you may not use this file except in compliance with
008     *  the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     *  Unless required by applicable law or agreed to in writing, software
013     *  distributed under the License is distributed on an "AS IS" BASIS,
014     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     *  See the License for the specific language governing permissions and
016     *  limitations under the License.
017     */
018    
019    package org.apache.geronimo.tomcat.deployment;
020    
021    import java.io.File;
022    import java.io.FileNotFoundException;
023    import java.io.IOException;
024    import java.net.URL;
025    import java.security.Permission;
026    import java.security.PermissionCollection;
027    import java.security.Permissions;
028    import java.util.Collection;
029    import java.util.Enumeration;
030    import java.util.HashMap;
031    import java.util.Iterator;
032    import java.util.Map;
033    import java.util.Set;
034    import java.util.jar.JarFile;
035    
036    import javax.servlet.Servlet;
037    
038    import org.apache.commons.logging.Log;
039    import org.apache.commons.logging.LogFactory;
040    import org.apache.geronimo.common.DeploymentException;
041    import org.apache.geronimo.deployment.ModuleIDBuilder;
042    import org.apache.geronimo.deployment.NamespaceDrivenBuilder;
043    import org.apache.geronimo.deployment.service.EnvironmentBuilder;
044    import org.apache.geronimo.deployment.util.DeploymentUtil;
045    import org.apache.geronimo.deployment.xbeans.EnvironmentType;
046    import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
047    import org.apache.geronimo.gbean.AbstractName;
048    import org.apache.geronimo.gbean.AbstractNameQuery;
049    import org.apache.geronimo.gbean.GBeanData;
050    import org.apache.geronimo.gbean.GBeanInfo;
051    import org.apache.geronimo.gbean.GBeanInfoBuilder;
052    import org.apache.geronimo.gbean.SingleElementCollection;
053    import org.apache.geronimo.gbean.ReferencePatterns;
054    import org.apache.geronimo.j2ee.deployment.EARContext;
055    import org.apache.geronimo.j2ee.deployment.Module;
056    import org.apache.geronimo.j2ee.deployment.ModuleBuilder;
057    import org.apache.geronimo.j2ee.deployment.NamingBuilder;
058    import org.apache.geronimo.j2ee.deployment.WebModule;
059    import org.apache.geronimo.j2ee.deployment.WebServiceBuilder;
060    import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
061    import org.apache.geronimo.kernel.Kernel;
062    import org.apache.geronimo.kernel.Naming;
063    import org.apache.geronimo.kernel.config.Configuration;
064    import org.apache.geronimo.kernel.config.ConfigurationData;
065    import org.apache.geronimo.kernel.repository.Environment;
066    import org.apache.geronimo.naming.deployment.ENCConfigBuilder;
067    import org.apache.geronimo.naming.deployment.GBeanResourceEnvironmentBuilder;
068    import org.apache.geronimo.naming.deployment.ResourceEnvironmentSetter;
069    import org.apache.geronimo.security.deploy.DefaultPrincipal;
070    import org.apache.geronimo.security.deployment.SecurityConfiguration;
071    import org.apache.geronimo.security.jacc.ComponentPermissions;
072    import org.apache.geronimo.tomcat.ManagerGBean;
073    import org.apache.geronimo.tomcat.RealmGBean;
074    import org.apache.geronimo.tomcat.TomcatWebAppContext;
075    import org.apache.geronimo.tomcat.ValveGBean;
076    import org.apache.geronimo.tomcat.cluster.CatalinaClusterGBean;
077    import org.apache.geronimo.tomcat.util.SecurityHolder;
078    import org.apache.geronimo.web.deployment.AbstractWebModuleBuilder;
079    import org.apache.geronimo.web.deployment.GenericToSpecificPlanConverter;
080    import org.apache.geronimo.xbeans.geronimo.web.tomcat.TomcatWebAppDocument;
081    import org.apache.geronimo.xbeans.geronimo.web.tomcat.TomcatWebAppType;
082    import org.apache.geronimo.xbeans.geronimo.web.tomcat.config.GerTomcatDocument;
083    import org.apache.geronimo.xbeans.j2ee.ServletType;
084    import org.apache.geronimo.xbeans.j2ee.WebAppDocument;
085    import org.apache.geronimo.xbeans.j2ee.WebAppType;
086    import org.apache.xmlbeans.XmlException;
087    import org.apache.xmlbeans.XmlObject;
088    
089    
090    /**
091     * @version $Rev:385659 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
092     */
093    public class TomcatModuleBuilder extends AbstractWebModuleBuilder {
094    
095        private static final Log log = LogFactory.getLog(TomcatModuleBuilder.class);
096    
097        private final Environment defaultEnvironment;
098        private final AbstractNameQuery tomcatContainerName;
099    
100        private final SingleElementCollection webServiceBuilder;
101    
102        private static final String TOMCAT_NAMESPACE = TomcatWebAppDocument.type.getDocumentElementName().getNamespaceURI();
103    
104        public TomcatModuleBuilder(Environment defaultEnvironment,
105                AbstractNameQuery tomcatContainerName,
106                Collection webServiceBuilder,
107                Collection securityBuilders,
108                Collection serviceBuilders,
109                NamingBuilder namingBuilders,
110                ResourceEnvironmentSetter resourceEnvironmentSetter,
111                Kernel kernel) {
112            super(kernel, securityBuilders, serviceBuilders, namingBuilders, resourceEnvironmentSetter);
113            this.defaultEnvironment = defaultEnvironment;
114    
115            this.tomcatContainerName = tomcatContainerName;
116            this.webServiceBuilder = new SingleElementCollection(webServiceBuilder);
117        }
118    
119        private WebServiceBuilder getWebServiceBuilder() {
120            return (WebServiceBuilder) webServiceBuilder.getElement();
121        }
122    
123        protected Module createModule(Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, boolean standAlone, String contextRoot, AbstractName earName, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException {
124            assert moduleFile != null: "moduleFile is null";
125            assert targetPath != null: "targetPath is null";
126            assert !targetPath.endsWith("/"): "targetPath must not end with a '/'";
127    
128            // parse the spec dd
129            String specDD;
130            WebAppType webApp;
131            try {
132                if (specDDUrl == null) {
133                    specDDUrl = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/web.xml");
134                }
135    
136                // read in the entire specDD as a string, we need this for getDeploymentDescriptor
137                // on the J2ee management object
138                specDD = DeploymentUtil.readAll(specDDUrl);
139            } catch (Exception e) {
140                //no web.xml, not for us
141                return null;
142            }
143            //we found web.xml, if it won't parse that's an error.
144            try {
145                // parse it
146                XmlObject parsed = XmlBeansUtil.parse(specDD);
147                WebAppDocument webAppDoc = convertToServletSchema(parsed);
148                webApp = webAppDoc.getWebApp();
149            } catch (XmlException xmle) {
150                // Output the target path in the error to make it clearer to the user which webapp
151                // has the problem.  The targetPath is used, as moduleFile may have an unhelpful
152                // value such as C:\geronimo-1.1\var\temp\geronimo-deploymentUtil22826.tmpdir
153                throw new DeploymentException("Error parsing web.xml for " + targetPath, xmle);
154            }
155            check(webApp);
156    
157            // parse vendor dd
158            TomcatWebAppType tomcatWebApp = getTomcatWebApp(plan, moduleFile, standAlone, targetPath, webApp);
159    
160            if (contextRoot == null || contextRoot.trim().equals("")) {
161                if (tomcatWebApp.isSetContextRoot()) {
162                    contextRoot = tomcatWebApp.getContextRoot();
163                } else {
164                    contextRoot = determineDefaultContextRoot(webApp, standAlone, moduleFile, targetPath);
165                }
166            }
167    
168            contextRoot = contextRoot.trim();
169    
170            EnvironmentType environmentType = tomcatWebApp.getEnvironment();
171            Environment environment = EnvironmentBuilder.buildEnvironment(environmentType, defaultEnvironment);
172    
173            getNamingBuilders().buildEnvironment(webApp, tomcatWebApp, environment);
174    
175            // Note: logic elsewhere depends on the default artifact ID being the file name less extension (ConfigIDExtractor)
176            String warName = new File(moduleFile.getName()).getName();
177            if (warName.lastIndexOf('.') > -1) {
178                warName = warName.substring(0, warName.lastIndexOf('.'));
179            }
180            idBuilder.resolve(environment, warName, "war");
181    
182            Map servletNameToPathMap = buildServletNameToPathMap(webApp, contextRoot);
183    
184            Map portMap = getWebServiceBuilder().findWebServices(moduleFile, false, servletNameToPathMap, environment);
185            AbstractName moduleName;
186            if (earName == null) {
187                earName = naming.createRootName(environment.getConfigId(), NameFactory.NULL, NameFactory.J2EE_APPLICATION);
188                moduleName = naming.createChildName(earName, environment.getConfigId().toString(), NameFactory.WEB_MODULE);
189            } else {
190                moduleName = naming.createChildName(earName, targetPath, NameFactory.WEB_MODULE);
191            }
192    
193            return new WebModule(standAlone, moduleName, environment, moduleFile, targetPath, webApp, tomcatWebApp, specDD, contextRoot, portMap, TOMCAT_NAMESPACE);
194        }
195    
196    
197        TomcatWebAppType getTomcatWebApp(Object plan, JarFile moduleFile, boolean standAlone, String targetPath, WebAppType webApp) throws DeploymentException {
198            XmlObject rawPlan = null;
199            try {
200                // load the geronimo-web.xml from either the supplied plan or from the earFile
201                try {
202                    if (plan instanceof XmlObject) {
203                        rawPlan = (XmlObject) plan;
204                    } else {
205                        if (plan != null) {
206                            rawPlan = XmlBeansUtil.parse(((File) plan).toURL(), getClass().getClassLoader());
207                        } else {
208                            URL path = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/geronimo-web.xml");
209                            try {
210                                rawPlan = XmlBeansUtil.parse(path, getClass().getClassLoader());
211                            } catch (FileNotFoundException e) {
212                                path = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/geronimo-tomcat.xml");
213                                try {
214                                    rawPlan = XmlBeansUtil.parse(path, getClass().getClassLoader());
215                                } catch (FileNotFoundException e1) {
216                                    log.warn("Web application " + targetPath + " does not contain a WEB-INF/geronimo-web.xml deployment plan.  This may or may not be a problem, depending on whether you have things like resource references that need to be resolved.  You can also give the deployer a separate deployment plan file on the command line.");
217                                }
218                            }
219                        }
220                    }
221                } catch (IOException e) {
222                    log.warn(e);
223                }
224    
225                TomcatWebAppType tomcatWebApp;
226                if (rawPlan != null) {
227                    XmlObject webPlan = new GenericToSpecificPlanConverter(GerTomcatDocument.type.getDocumentElementName().getNamespaceURI(),
228                            TomcatWebAppDocument.type.getDocumentElementName().getNamespaceURI(), "tomcat").convertToSpecificPlan(rawPlan);
229                    tomcatWebApp = (TomcatWebAppType) webPlan.changeType(TomcatWebAppType.type);
230                    XmlBeansUtil.validateDD(tomcatWebApp);
231                } else {
232                    String defaultContextRoot = determineDefaultContextRoot(webApp, standAlone, moduleFile, targetPath);
233                    tomcatWebApp = createDefaultPlan(defaultContextRoot);
234                }
235                return tomcatWebApp;
236            } catch (XmlException e) {
237                throw new DeploymentException("xml problem for web app " + targetPath, e);
238            }
239        }
240    
241        private TomcatWebAppType createDefaultPlan(String path) {
242            TomcatWebAppType tomcatWebApp = TomcatWebAppType.Factory.newInstance();
243            tomcatWebApp.setContextRoot("/" + path);
244            return tomcatWebApp;
245        }
246    
247    
248        public void initContext(EARContext earContext, Module module, ClassLoader cl) throws DeploymentException {
249            WebAppType webApp = (WebAppType) module.getSpecDD();
250    //        MessageDestinationType[] messageDestinations = webApp.getMessageDestinationArray();
251            TomcatWebAppType gerWebApp = (TomcatWebAppType) module.getVendorDD();
252    //        GerMessageDestinationType[] gerMessageDestinations = gerWebApp.getMessageDestinationArray();
253    
254    //        ENCConfigBuilder.registerMessageDestinations(earContext, module.getName(), messageDestinations, gerMessageDestinations);
255            getNamingBuilders().initContext(webApp, gerWebApp, module.getEarContext().getConfiguration(), earContext.getConfiguration(), module);
256            if ((webApp.getSecurityConstraintArray().length > 0 || webApp.getSecurityRoleArray().length > 0) &&
257                    !gerWebApp.isSetSecurityRealmName()) {
258                throw new DeploymentException("web.xml for web app " + module.getName() + " includes security elements but Geronimo deployment plan is not provided or does not contain <security-realm-name> element necessary to configure security accordingly.");
259            }
260            boolean hasSecurityRealmName = gerWebApp.isSetSecurityRealmName();
261            buildSubstitutionGroups(gerWebApp, hasSecurityRealmName, module, earContext);
262        }
263    
264        public void addGBeans(EARContext earContext, Module module, ClassLoader cl, Collection repository) throws DeploymentException {
265            EARContext moduleContext = module.getEarContext();
266            ClassLoader webClassLoader = moduleContext.getClassLoader();
267            AbstractName moduleName = moduleContext.getModuleName();
268            WebModule webModule = (WebModule) module;
269    
270            WebAppType webApp = (WebAppType) webModule.getSpecDD();
271            TomcatWebAppType tomcatWebApp = (TomcatWebAppType) webModule.getVendorDD();
272    
273            GBeanData webModuleData = new GBeanData(moduleName, TomcatWebAppContext.GBEAN_INFO);
274            try {
275                webModuleData.setReferencePattern("J2EEServer", moduleContext.getServerName());
276                if (!module.isStandAlone()) {
277                    webModuleData.setReferencePattern("J2EEApplication", earContext.getModuleName());
278                }
279    
280                webModuleData.setAttribute("deploymentDescriptor", module.getOriginalSpecDD());
281                Set securityRoles = collectRoleNames(webApp);
282                Map rolePermissions = new HashMap();
283    
284                webModuleData.setAttribute("contextPath", webModule.getContextRoot());
285    
286                //Add dependencies on managed connection factories and ejbs in this app
287                //This is overkill, but allows for people not using java:comp context (even though we don't support it)
288                //and sidesteps the problem of circular references between ejbs.
289                Set dependencies = findGBeanDependencies(earContext);
290                webModuleData.addDependencies(dependencies);
291    
292                //N.B. we use the ear context which has all the gbeans we could possibly be looking up from this ear.
293                Map buildingContext = new HashMap();
294                buildingContext.put(NamingBuilder.JNDI_KEY, new HashMap());
295                buildingContext.put(NamingBuilder.GBEAN_NAME_KEY, moduleName);
296                Configuration earConfiguration = earContext.getConfiguration();
297                getNamingBuilders().buildNaming(webApp, tomcatWebApp, earConfiguration, earConfiguration, webModule, buildingContext);
298                Map compContext = (Map) buildingContext.get(NamingBuilder.JNDI_KEY);
299    
300                webModuleData.setAttribute("componentContext", compContext);
301                // unsharableResources, applicationManagedSecurityResources
302                GBeanResourceEnvironmentBuilder rebuilder = new GBeanResourceEnvironmentBuilder(webModuleData);
303                //N.B. use earContext not moduleContext
304                resourceEnvironmentSetter.setResourceEnvironment(rebuilder, webApp.getResourceRefArray(), tomcatWebApp.getResourceRefArray());
305    
306                webModuleData.setReferencePattern("TransactionManager", earContext.getTransactionManagerName());
307                webModuleData.setReferencePattern("TrackedConnectionAssociator", earContext.getConnectionTrackerName());
308    
309                if (tomcatWebApp.isSetWebContainer()) {
310                    AbstractNameQuery webContainerName = ENCConfigBuilder.getGBeanQuery(NameFactory.GERONIMO_SERVICE, tomcatWebApp.getWebContainer());
311                    webModuleData.setReferencePattern("Container", webContainerName);
312                } else {
313                    webModuleData.setReferencePattern("Container", tomcatContainerName);
314                }
315                // Process the Tomcat container-config elements
316                if (tomcatWebApp.isSetHost()) {
317                    String virtualServer = tomcatWebApp.getHost().trim();
318                    webModuleData.setAttribute("virtualServer", virtualServer);
319                }
320                if (tomcatWebApp.isSetCrossContext()) {
321                    webModuleData.setAttribute("crossContext", Boolean.TRUE);
322                }
323                if (tomcatWebApp.isSetDisableCookies()) {
324                    webModuleData.setAttribute("disableCookies", Boolean.TRUE);
325                }
326                if (tomcatWebApp.isSetTomcatRealm()) {
327                    String tomcatRealm = tomcatWebApp.getTomcatRealm().trim();
328                    AbstractName realmName = earContext.getNaming().createChildName(moduleName, tomcatRealm, RealmGBean.GBEAN_INFO.getJ2eeType());
329                    webModuleData.setReferencePattern("TomcatRealm", realmName);
330                }
331                if (tomcatWebApp.isSetValveChain()) {
332                    String valveChain = tomcatWebApp.getValveChain().trim();
333                    AbstractName valveName = earContext.getNaming().createChildName(moduleName, valveChain, ValveGBean.J2EE_TYPE);
334                    webModuleData.setReferencePattern("TomcatValveChain", valveName);
335                }
336    
337                if (tomcatWebApp.isSetCluster()) {
338                    String cluster = tomcatWebApp.getCluster().trim();
339                    AbstractName clusterName = earContext.getNaming().createChildName(moduleName, cluster, CatalinaClusterGBean.J2EE_TYPE);
340                    webModuleData.setReferencePattern("Cluster", clusterName);
341                }
342    
343                if (tomcatWebApp.isSetManager()) {
344                    String manager = tomcatWebApp.getManager().trim();
345                    AbstractName managerName = earContext.getNaming().createChildName(moduleName, manager, ManagerGBean.J2EE_TYPE);
346                    webModuleData.setReferencePattern("Manager", managerName);
347                }
348                Map portMap = webModule.getPortMap();
349    
350                //Handle the role permissions and webservices on the servlets.
351                ServletType[] servletTypes = webApp.getServletArray();
352                Map webServices = new HashMap();
353                Class baseServletClass;
354                try {
355                    baseServletClass = webClassLoader.loadClass(Servlet.class.getName());
356                } catch (ClassNotFoundException e) {
357                    throw new DeploymentException("Could not load javax.servlet.Servlet in web classloader", e); // TODO identify web app in message
358                }
359                for (int i = 0; i < servletTypes.length; i++) {
360                    ServletType servletType = servletTypes[i];
361    
362                    //Handle the Role Ref Permissions
363                    processRoleRefPermissions(servletType, securityRoles, rolePermissions);
364    
365                    if (servletType.isSetServletClass()) {
366                        String servletName = servletType.getServletName().getStringValue().trim();
367                        String servletClassName = servletType.getServletClass().getStringValue().trim();
368                        Class servletClass;
369                        try {
370                            servletClass = webClassLoader.loadClass(servletClassName);
371                        } catch (ClassNotFoundException e) {
372                            throw new DeploymentException("Could not load servlet class " + servletClassName, e); // TODO identify web app in message
373                        }
374                        if (!baseServletClass.isAssignableFrom(servletClass)) {
375                            //fake servletData
376                            AbstractName servletAbstractName = moduleContext.getNaming().createChildName(moduleName, servletName, NameFactory.SERVLET);
377                            GBeanData servletData = new GBeanData();
378                            servletData.setAbstractName(servletAbstractName);
379                            //let the web service builder deal with configuring the gbean with the web service stack
380                            //Here we just extract the factory reference
381                            Object portInfo = portMap.get(servletName);
382                            getWebServiceBuilder().configurePOJO(servletData, module, portInfo, servletClassName, moduleContext);
383                            ReferencePatterns patterns = servletData.getReferencePatterns("WebServiceContainerFactory");
384                            AbstractName wsContainerFactoryName = patterns.getAbstractName();
385                            webServices.put(servletName, wsContainerFactoryName);
386                            //force all the factories to start before the web app that needs them.
387                            webModuleData.addDependency(wsContainerFactoryName);
388                        }
389                    }
390                }
391    
392                // JACC v1.0 secion B.19
393                addUnmappedJSPPermissions(securityRoles, rolePermissions);
394    
395                webModuleData.setAttribute("webServices", webServices);
396    
397                if (tomcatWebApp.isSetSecurityRealmName()) {
398                    if (earContext.getSecurityConfiguration() == null) {
399                        throw new DeploymentException("You have specified a <security-realm-name> for the webapp " + moduleName + " but no <security> configuration (role mapping) is supplied in the Geronimo plan for the web application (or the Geronimo plan for the EAR if the web app is in an EAR)");
400                    }
401    
402                    SecurityHolder securityHolder = new SecurityHolder();
403                    securityHolder.setSecurityRealm(tomcatWebApp.getSecurityRealmName().trim());
404    
405                    /**
406                     * TODO - go back to commented version when possible.
407                     */
408                    String policyContextID = moduleName.toString().replaceAll("[, :]", "_");
409                    securityHolder.setPolicyContextID(policyContextID);
410    
411                    ComponentPermissions componentPermissions = buildSpecSecurityConfig(webApp, securityRoles, rolePermissions);
412                    securityHolder.setExcluded(componentPermissions.getExcludedPermissions());
413                    PermissionCollection checkedPermissions = new Permissions();
414                    for (Iterator iterator = rolePermissions.values().iterator(); iterator.hasNext();) {
415                        PermissionCollection permissionsForRole = (PermissionCollection) iterator.next();
416                        for (Enumeration iterator2 = permissionsForRole.elements(); iterator2.hasMoreElements();) {
417                            Permission permission = (Permission) iterator2.nextElement();
418                            checkedPermissions.add(permission);
419                        }
420                    }
421                    securityHolder.setChecked(checkedPermissions);
422                    earContext.addSecurityContext(policyContextID, componentPermissions);
423                    DefaultPrincipal defaultPrincipal = ((SecurityConfiguration) earContext.getSecurityConfiguration()).getDefaultPrincipal();
424                    securityHolder.setDefaultPrincipal(defaultPrincipal);
425                    if (defaultPrincipal != null) {
426                        securityHolder.setSecurity(true);
427                    }
428    
429                    webModuleData.setAttribute("securityHolder", securityHolder);
430                }
431    
432                moduleContext.addGBean(webModuleData);
433    
434                if (!module.isStandAlone()) {
435                    ConfigurationData moduleConfigurationData = moduleContext.getConfigurationData();
436                    earContext.addChildConfiguration(module.getTargetPath(), moduleConfigurationData);
437                }
438            } catch (DeploymentException de) {
439                throw de;
440            } catch (Exception e) {
441                throw new DeploymentException("Unable to initialize GBean for web app " + module.getName(), e);
442            }
443        }
444    
445        public String getSchemaNamespace() {
446            return TOMCAT_NAMESPACE;
447        }
448    
449    
450        public static final GBeanInfo GBEAN_INFO;
451    
452        static {
453            GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(TomcatModuleBuilder.class, NameFactory.MODULE_BUILDER);
454            infoBuilder.addAttribute("defaultEnvironment", Environment.class, true, true);
455            infoBuilder.addAttribute("tomcatContainerName", AbstractNameQuery.class, true, true);
456            infoBuilder.addReference("WebServiceBuilder", WebServiceBuilder.class, NameFactory.MODULE_BUILDER);
457            infoBuilder.addReference("SecurityBuilders", NamespaceDrivenBuilder.class, NameFactory.MODULE_BUILDER);
458            infoBuilder.addReference("ServiceBuilders", NamespaceDrivenBuilder.class, NameFactory.MODULE_BUILDER);
459            infoBuilder.addReference("NamingBuilders", NamingBuilder.class, NameFactory.MODULE_BUILDER);
460            infoBuilder.addReference("ResourceEnvironmentSetter", ResourceEnvironmentSetter.class, NameFactory.MODULE_BUILDER);
461            infoBuilder.addAttribute("kernel", Kernel.class, false);
462            infoBuilder.addInterface(ModuleBuilder.class);
463    
464            infoBuilder.setConstructor(new String[]{
465                    "defaultEnvironment",
466                    "tomcatContainerName",
467                    "WebServiceBuilder",
468                    "SecurityBuilders",
469                    "ServiceBuilders",
470                    "NamingBuilders",
471                    "ResourceEnvironmentSetter",
472                    "kernel"});
473            GBEAN_INFO = infoBuilder.getBeanInfo();
474        }
475    
476        public static GBeanInfo getGBeanInfo() {
477            return GBEAN_INFO;
478        }
479    
480    }