Home » geronimo-2.2-source-release » org.apache.geronimo.jetty6.deployment » [javadoc | source]

    1   /**
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   
   18   package org.apache.geronimo.jetty6.deployment;
   19   
   20   import java.io.File;
   21   import java.io.FileNotFoundException;
   22   import java.io.IOException;
   23   import static java.lang.Boolean.FALSE;
   24   import static java.lang.Boolean.TRUE;
   25   import java.net.URL;
   26   import java.util.ArrayList;
   27   import java.util.Arrays;
   28   import java.util.Collection;
   29   import java.util.Collections;
   30   import java.util.Comparator;
   31   import java.util.HashMap;
   32   import java.util.HashSet;
   33   import java.util.List;
   34   import java.util.Map;
   35   import java.util.Set;
   36   import java.util.TreeSet;
   37   import java.util.jar.JarFile;
   38   
   39   import javax.management.ObjectName;
   40   import javax.servlet.Servlet;
   41   
   42   import org.slf4j.Logger;
   43   import org.slf4j.LoggerFactory;
   44   import org.apache.geronimo.common.DeploymentException;
   45   import org.apache.geronimo.deployment.ModuleIDBuilder;
   46   import org.apache.geronimo.deployment.NamespaceDrivenBuilder;
   47   import org.apache.geronimo.deployment.NamespaceDrivenBuilderCollection;
   48   import org.apache.geronimo.deployment.service.EnvironmentBuilder;
   49   import org.apache.geronimo.deployment.util.DeploymentUtil;
   50   import org.apache.geronimo.deployment.xbeans.EnvironmentType;
   51   import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
   52   import org.apache.geronimo.gbean.AbstractName;
   53   import org.apache.geronimo.gbean.AbstractNameQuery;
   54   import org.apache.geronimo.gbean.GBeanData;
   55   import org.apache.geronimo.gbean.GBeanInfo;
   56   import org.apache.geronimo.gbean.GBeanInfoBuilder;
   57   import org.apache.geronimo.gbean.GBeanLifecycle;
   58   import org.apache.geronimo.j2ee.deployment.EARContext;
   59   import org.apache.geronimo.j2ee.deployment.Module;
   60   import org.apache.geronimo.j2ee.deployment.ModuleBuilder;
   61   import org.apache.geronimo.j2ee.deployment.ModuleBuilderExtension;
   62   import org.apache.geronimo.j2ee.deployment.NamingBuilder;
   63   import org.apache.geronimo.j2ee.deployment.WebModule;
   64   import org.apache.geronimo.j2ee.deployment.WebServiceBuilder;
   65   import org.apache.geronimo.j2ee.deployment.annotation.AnnotatedWebApp;
   66   import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
   67   import org.apache.geronimo.jetty6.Host;
   68   import org.apache.geronimo.jetty6.JettyDefaultServletHolder;
   69   import org.apache.geronimo.jetty6.JettyFilterHolder;
   70   import org.apache.geronimo.jetty6.JettyFilterMapping;
   71   import org.apache.geronimo.jetty6.JettyServletHolder;
   72   import org.apache.geronimo.jetty6.JettyWebAppContext;
   73   import org.apache.geronimo.jetty6.NonAuthenticator;
   74   import org.apache.geronimo.jetty6.JettyJspServletHolder;
   75   import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
   76   import org.apache.geronimo.kernel.GBeanNotFoundException;
   77   import org.apache.geronimo.kernel.Kernel;
   78   import org.apache.geronimo.kernel.Naming;
   79   import org.apache.geronimo.kernel.config.ConfigurationData;
   80   import org.apache.geronimo.kernel.repository.Environment;
   81   import org.apache.geronimo.naming.deployment.ENCConfigBuilder;
   82   import org.apache.geronimo.naming.deployment.GBeanResourceEnvironmentBuilder;
   83   import org.apache.geronimo.naming.deployment.ResourceEnvironmentSetter;
   84   import org.apache.geronimo.security.jacc.ComponentPermissions;
   85   import org.apache.geronimo.security.jaas.ConfigurationFactory;
   86   import org.apache.geronimo.web.deployment.GenericToSpecificPlanConverter;
   87   import org.apache.geronimo.web25.deployment.AbstractWebModuleBuilder;
   88   import org.apache.geronimo.xbeans.geronimo.web.jetty.JettyWebAppDocument;
   89   import org.apache.geronimo.xbeans.geronimo.web.jetty.JettyWebAppType;
   90   import org.apache.geronimo.xbeans.geronimo.web.jetty.config.GerJettyDocument;
   91   import org.apache.geronimo.xbeans.javaee.DispatcherType;
   92   import org.apache.geronimo.xbeans.javaee.ErrorPageType;
   93   import org.apache.geronimo.xbeans.javaee.FilterMappingType;
   94   import org.apache.geronimo.xbeans.javaee.FilterType;
   95   import org.apache.geronimo.xbeans.javaee.FormLoginConfigType;
   96   import org.apache.geronimo.xbeans.javaee.JspConfigType;
   97   import org.apache.geronimo.xbeans.javaee.ListenerType;
   98   import org.apache.geronimo.xbeans.javaee.LocaleEncodingMappingListType;
   99   import org.apache.geronimo.xbeans.javaee.LocaleEncodingMappingType;
  100   import org.apache.geronimo.xbeans.javaee.LoginConfigType;
  101   import org.apache.geronimo.xbeans.javaee.MimeMappingType;
  102   import org.apache.geronimo.xbeans.javaee.ParamValueType;
  103   import org.apache.geronimo.xbeans.javaee.ServletMappingType;
  104   import org.apache.geronimo.xbeans.javaee.ServletType;
  105   import org.apache.geronimo.xbeans.javaee.TaglibType;
  106   import org.apache.geronimo.xbeans.javaee.UrlPatternType;
  107   import org.apache.geronimo.xbeans.javaee.WebAppDocument;
  108   import org.apache.geronimo.xbeans.javaee.WebAppType;
  109   import org.apache.geronimo.xbeans.javaee.WelcomeFileListType;
  110   import org.apache.geronimo.xbeans.javaee.JspPropertyGroupType;
  111   import org.apache.xmlbeans.XmlException;
  112   import org.apache.xmlbeans.XmlObject;
  113   import org.mortbay.jetty.security.BasicAuthenticator;
  114   import org.mortbay.jetty.security.ClientCertAuthenticator;
  115   import org.mortbay.jetty.security.DigestAuthenticator;
  116   import org.mortbay.jetty.security.FormAuthenticator;
  117   
  118   
  119   /**
  120    * @version $Rev:385659 $ $Date: 2009-05-26 07:50:40 -0700 (Tue, 26 May 2009) $
  121    */
  122   public class JettyModuleBuilder extends AbstractWebModuleBuilder implements GBeanLifecycle {
  123       private static final Logger log = LoggerFactory.getLogger(JettyModuleBuilder.class);
  124       
  125       private static final String ROLE_MAPPER_DATA_NAME = "roleMapperDataName";
  126   
  127       private static final Map<String, String> NAMESPACE_UPDATES = new HashMap<String, String>();
  128       static {
  129           NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web", "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
  130           NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web-1.1", "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
  131           NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web-1.2", "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
  132           NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web-2.0", "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
  133           NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/jetty", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.1");
  134           NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/jetty-1.1", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.2");
  135           NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/jetty-1.2", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.2");
  136           NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.2");
  137           NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.1", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.2");
  138           NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/jetty/config", "http://geronimo.apache.org/xml/ns/web/jetty/config-1.0.1");
  139           NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/jetty/config-1.0", "http://geronimo.apache.org/xml/ns/web/jetty/config-1.0.1");
  140       }
  141   
  142       private final Environment defaultEnvironment;
  143       private final AbstractNameQuery jettyContainerObjectName;
  144       private final JettyJspServletHolder jspServlet;
  145       private final Collection defaultServlets;
  146       private final Collection defaultFilters;
  147       private final Collection defaultFilterMappings;
  148       private final GBeanData pojoWebServiceTemplate;
  149   
  150       protected final NamespaceDrivenBuilderCollection clusteringBuilders;
  151   
  152       private final List<String> defaultWelcomeFiles;
  153       private final Integer defaultSessionTimeoutSeconds;
  154       private final Map<String, String> defaultLocaleEncodingMappings;
  155       private final Map<String, String> defaultMimeTypeMappings;
  156   
  157       private static final String JETTY_NAMESPACE = JettyWebAppDocument.type.getDocumentElementName().getNamespaceURI();
  158   
  159       public JettyModuleBuilder(Environment defaultEnvironment,
  160                                 Integer defaultSessionTimeoutSeconds,
  161                                 List<String> defaultWelcomeFiles,
  162                                 AbstractNameQuery jettyContainerName,
  163                                 JettyJspServletHolder jspServlet,
  164                                 Collection defaultServlets,
  165                                 Collection defaultFilters,
  166                                 Collection defaultFilterMappings,
  167                                 Map<String, String> defaultLocaleEncodingMappings,
  168                                 Map<String, String> defaultMimeTypeMappings,
  169                                 Object pojoWebServiceTemplate,
  170                                 Collection<WebServiceBuilder> webServiceBuilder,
  171                                 Collection clusteringBuilders,
  172                                 Collection serviceBuilders,
  173                                 NamingBuilder namingBuilders,
  174                                 Collection<ModuleBuilderExtension> moduleBuilderExtensions,
  175                                 ResourceEnvironmentSetter resourceEnvironmentSetter,
  176                                 Kernel kernel) throws GBeanNotFoundException {
  177           super(kernel, serviceBuilders, namingBuilders, resourceEnvironmentSetter, webServiceBuilder, moduleBuilderExtensions);
  178           this.defaultEnvironment = defaultEnvironment;
  179           this.defaultSessionTimeoutSeconds = (defaultSessionTimeoutSeconds == null) ? 30 * 60 : defaultSessionTimeoutSeconds;
  180           this.jettyContainerObjectName = jettyContainerName;
  181           this.jspServlet = jspServlet;
  182           this.defaultServlets = defaultServlets;
  183           this.defaultFilters = defaultFilters;
  184           this.defaultFilterMappings = defaultFilterMappings;
  185           this.pojoWebServiceTemplate = getGBeanData(kernel, pojoWebServiceTemplate);
  186           this.clusteringBuilders = new NamespaceDrivenBuilderCollection(clusteringBuilders);
  187   
  188           this.defaultWelcomeFiles = defaultWelcomeFiles == null ? new ArrayList<String>() : defaultWelcomeFiles;
  189           this.defaultLocaleEncodingMappings = defaultLocaleEncodingMappings == null ? new HashMap<String, String>() : defaultLocaleEncodingMappings;
  190           this.defaultMimeTypeMappings = defaultMimeTypeMappings == null ? new HashMap<String, String>() : defaultMimeTypeMappings;
  191       }
  192   
  193       public void doStart() throws Exception {
  194           XmlBeansUtil.registerNamespaceUpdates(NAMESPACE_UPDATES);
  195       }
  196   
  197       public void doStop() {
  198           XmlBeansUtil.unregisterNamespaceUpdates(NAMESPACE_UPDATES);
  199       }
  200   
  201       public void doFail() {
  202           doStop();
  203       }
  204   
  205       private static GBeanData getGBeanData(Kernel kernel, Object template) throws GBeanNotFoundException {
  206           if (template == null) {
  207               return null;
  208           }
  209           AbstractName templateName = kernel.getAbstractNameFor(template);
  210           return kernel.getGBeanData(templateName);
  211       }
  212   
  213       protected Module createModule(Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, boolean standAlone, String contextRoot, AbstractName earName, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException {
  214           assert moduleFile != null : "moduleFile is null";
  215           assert targetPath != null : "targetPath is null";
  216           assert !targetPath.endsWith("/") : "targetPath must not end with a '/'";
  217   
  218           // parse the spec dd
  219           String specDD = null;
  220           WebAppType webApp = null;
  221           try {
  222               if (specDDUrl == null) {
  223                   specDDUrl = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/web.xml");
  224               }
  225   
  226               // read in the entire specDD as a string, we need this for getDeploymentDescriptor
  227               // on the J2ee management object
  228               specDD = DeploymentUtil.readAll(specDDUrl);
  229   
  230               // we found web.xml, if it won't parse that's an error.
  231               XmlObject parsed = XmlBeansUtil.parse(specDD);
  232               WebAppDocument webAppDoc = convertToServletSchema(parsed);
  233               webApp = webAppDoc.getWebApp();
  234               check(webApp);
  235           } catch (XmlException e) {
  236               // Output the target path in the error to make it clearer to the user which webapp
  237               // has the problem.  The targetPath is used, as moduleFile may have an unhelpful
  238               // value such as C:\geronimo-1.1\var\temp\geronimo-deploymentUtil22826.tmpdir
  239               throw new DeploymentException("Error parsing web.xml for " + targetPath, e);
  240           } catch (Exception e) {
  241               if (!moduleFile.getName().endsWith(".war")) {
  242                   //not for us
  243                   return null;
  244               }
  245               //else ignore as jee5 allows optional spec dd for .war's
  246           }
  247   
  248           if (webApp == null) {
  249               webApp = WebAppType.Factory.newInstance();
  250           }
  251   
  252           // parse vendor dd
  253           JettyWebAppType jettyWebApp = getJettyWebApp(plan, moduleFile, standAlone, targetPath, webApp);
  254           contextRoot = getContextRoot(jettyWebApp, contextRoot, webApp, standAlone, moduleFile, targetPath);
  255   
  256           EnvironmentType environmentType = jettyWebApp.getEnvironment();
  257           Environment environment = EnvironmentBuilder.buildEnvironment(environmentType, defaultEnvironment);
  258   
  259           Boolean distributable = webApp.getDistributableArray().length == 1 ? TRUE : FALSE;
  260           if (TRUE == distributable) {
  261               clusteringBuilders.buildEnvironment(jettyWebApp, environment);
  262           }
  263   
  264           // Note: logic elsewhere depends on the default artifact ID being the file name less extension (ConfigIDExtractor)
  265           String warName = new File(moduleFile.getName()).getName();
  266           if (warName.lastIndexOf('.') > -1) {
  267               warName = warName.substring(0, warName.lastIndexOf('.'));
  268           }
  269           idBuilder.resolve(environment, warName, "car");
  270   
  271           AbstractName moduleName;
  272           if (earName == null) {
  273               earName = naming.createRootName(environment.getConfigId(), NameFactory.NULL, NameFactory.J2EE_APPLICATION);
  274               moduleName = naming.createChildName(earName, environment.getConfigId().toString(), NameFactory.WEB_MODULE);
  275           } else {
  276               moduleName = naming.createChildName(earName, targetPath, NameFactory.WEB_MODULE);
  277           }
  278   
  279           // Create the AnnotatedApp interface for the WebModule
  280           AnnotatedWebApp annotatedWebApp = new AnnotatedWebApp(webApp);
  281   
  282           WebModule module = new WebModule(standAlone, moduleName, environment, moduleFile, targetPath, webApp, jettyWebApp, specDD, contextRoot, JETTY_NAMESPACE, annotatedWebApp);
  283   
  284           for (ModuleBuilderExtension mbe : moduleBuilderExtensions) {
  285               mbe.createModule(module, plan, moduleFile, targetPath, specDDUrl, environment, contextRoot, earName, naming, idBuilder);
  286           }
  287           return module;
  288       }
  289   
  290       String getContextRoot(JettyWebAppType jettyWebApp, String contextRoot, WebAppType webApp, boolean standAlone, JarFile moduleFile, String targetPath) {
  291           if (jettyWebApp.isSetContextRoot()) {
  292               contextRoot = jettyWebApp.getContextRoot();
  293           } else if (contextRoot == null || contextRoot.trim().equals("")) {
  294               contextRoot = determineDefaultContextRoot(webApp, standAlone, moduleFile, targetPath);
  295           }
  296   
  297           contextRoot = contextRoot.trim();
  298           return contextRoot;
  299       }
  300   
  301       JettyWebAppType getJettyWebApp(Object plan, JarFile moduleFile, boolean standAlone, String targetPath, WebAppType webApp) throws DeploymentException {
  302           XmlObject rawPlan = null;
  303           try {
  304               // load the geronimo-web.xml from either the supplied plan or from the earFile
  305               try {
  306                   if (plan instanceof XmlObject) {
  307                       rawPlan = (XmlObject) plan;
  308                   } else {
  309                       if (plan != null) {
  310                           rawPlan = XmlBeansUtil.parse(((File) plan).toURL(), getClass().getClassLoader());
  311                       } else {
  312                           URL path = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/geronimo-web.xml");
  313                           try {
  314                               rawPlan = XmlBeansUtil.parse(path, getClass().getClassLoader());
  315                           } catch (FileNotFoundException e) {
  316                               path = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/geronimo-jetty.xml");
  317                               try {
  318                                   rawPlan = XmlBeansUtil.parse(path, getClass().getClassLoader());
  319                               } catch (FileNotFoundException e1) {
  320                                   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.");
  321                               }
  322                           }
  323                       }
  324                   }
  325               } catch (IOException e) {
  326                   log.warn("Failed to load geronimo-web.xml", e);
  327               }
  328   
  329               JettyWebAppType jettyWebApp;
  330               if (rawPlan != null) {
  331                   XmlObject webPlan = new GenericToSpecificPlanConverter(GerJettyDocument.type.getDocumentElementName().getNamespaceURI(),
  332                           JettyWebAppDocument.type.getDocumentElementName().getNamespaceURI(), "jetty").convertToSpecificPlan(rawPlan);
  333                   jettyWebApp = (JettyWebAppType) webPlan.changeType(JettyWebAppType.type);
  334                   XmlBeansUtil.validateDD(jettyWebApp);
  335               } else {
  336                   jettyWebApp = createDefaultPlan();
  337               }
  338               return jettyWebApp;
  339           } catch (XmlException e) {
  340               throw new DeploymentException("xml problem for web app " + targetPath, e);
  341           }
  342       }
  343   
  344       private JettyWebAppType createDefaultPlan() {
  345           return JettyWebAppType.Factory.newInstance();
  346       }
  347   
  348       public void initContext(EARContext earContext, Module module, ClassLoader cl) throws DeploymentException {
  349           JettyWebAppType gerWebApp = (JettyWebAppType) module.getVendorDD();
  350           boolean hasSecurityRealmName = gerWebApp.isSetSecurityRealmName();
  351           basicInitContext(earContext, module, gerWebApp, hasSecurityRealmName);
  352           for (ModuleBuilderExtension mbe : moduleBuilderExtensions) {
  353               mbe.initContext(earContext, module, cl);
  354           }
  355       }
  356   
  357       public void addGBeans(EARContext earContext, Module module, ClassLoader cl, Collection repository) throws DeploymentException {
  358           EARContext moduleContext = module.getEarContext();
  359           AbstractName moduleName = moduleContext.getModuleName();
  360           WebModule webModule = (WebModule) module;
  361   
  362           WebAppType webApp = (WebAppType) webModule.getSpecDD();
  363           JettyWebAppType jettyWebApp = (JettyWebAppType) webModule.getVendorDD();
  364           GBeanData webModuleData = new GBeanData(moduleName, JettyWebAppContext.GBEAN_INFO);
  365   
  366           configureBasicWebModuleAttributes(webApp, jettyWebApp, moduleContext, earContext, webModule, webModuleData);
  367   
  368           // unsharableResources, applicationManagedSecurityResources
  369           GBeanResourceEnvironmentBuilder rebuilder = new GBeanResourceEnvironmentBuilder(webModuleData);
  370           //N.B. use earContext not moduleContext
  371           //TODO fix this for javaee 5 !!!
  372           resourceEnvironmentSetter.setResourceEnvironment(rebuilder, webApp.getResourceRefArray(), jettyWebApp.getResourceRefArray());
  373           try {
  374               moduleContext.addGBean(webModuleData);
  375   
  376               // configure hosts and virtual-hosts
  377               configureHosts(earContext, jettyWebApp, webModuleData);
  378   
  379   
  380               String contextPath = webModule.getContextRoot();
  381               if (contextPath == null) {
  382                   throw new DeploymentException("null contextPath");
  383               }
  384               if (!contextPath.startsWith("/")) {
  385                   contextPath = "/" + contextPath;
  386               }
  387               webModuleData.setAttribute("contextPath", contextPath);
  388   
  389               if (jettyWebApp.isSetWorkDir()) {
  390                   String workDir = jettyWebApp.getWorkDir();
  391                   webModuleData.setAttribute("workDir", workDir);
  392               }
  393   
  394               if (jettyWebApp.isSetWebContainer()) {
  395                   AbstractNameQuery webContainerName = ENCConfigBuilder.getGBeanQuery(GBeanInfoBuilder.DEFAULT_J2EE_TYPE, jettyWebApp.getWebContainer());
  396                   webModuleData.setReferencePattern("JettyContainer", webContainerName);
  397               } else {
  398                   webModuleData.setReferencePattern("JettyContainer", jettyContainerObjectName);
  399               }
  400               //stuff that jetty used to do
  401               if (webApp.getDisplayNameArray().length > 0) {
  402                   webModuleData.setAttribute("displayName", webApp.getDisplayNameArray()[0].getStringValue());
  403               }
  404   
  405               // configure context parameters.
  406               configureContextParams(webApp, webModuleData);
  407   
  408               // configure listeners.
  409               configureListeners(webApp, webModuleData);
  410   
  411               webModuleData.setAttribute(JettyWebAppContext.GBEAN_ATTR_SESSION_TIMEOUT,
  412                       (webApp.getSessionConfigArray().length == 1 && webApp.getSessionConfigArray(0).getSessionTimeout() != null) ?
  413                               webApp.getSessionConfigArray(0).getSessionTimeout().getBigIntegerValue().intValue() * 60 :
  414                               defaultSessionTimeoutSeconds);
  415   
  416               Boolean distributable = webApp.getDistributableArray().length == 1 ? TRUE : FALSE;
  417               webModuleData.setAttribute("distributable", distributable);
  418               if (TRUE == distributable) {
  419                   clusteringBuilders.build(jettyWebApp, earContext, moduleContext);
  420                   if (webModuleData.getReferencePatterns(JettyWebAppContext.GBEAN_REF_SESSION_HANDLER_FACTORY) == null) {
  421                       log.warn("No clustering builders configured: app will not be clustered");
  422                       configureNoClustering(moduleContext, webModuleData);
  423                   }
  424               } else {
  425                   configureNoClustering(moduleContext, webModuleData);
  426               }
  427   
  428               // configure mime mappings.
  429               configureMimeMappings(webApp, webModuleData);
  430   
  431               // configure welcome file lists.
  432               configureWelcomeFileLists(webApp, webModuleData);
  433   
  434               // configure local encoding mapping lists.
  435               configureLocaleEncodingMappingLists(webApp, webModuleData);
  436   
  437               // configure error pages.
  438               configureErrorPages(webApp, webModuleData);
  439   
  440               // configure tag libs.
  441               Set<String> knownServletMappings = new HashSet<String>();
  442               Map<String, Set<String>> servletMappings = new HashMap<String, Set<String>>();
  443               if (jspServlet != null) {
  444                   configureTagLibs(module, webApp, webModuleData, servletMappings, knownServletMappings, jspServlet.getServletName());
  445                   GBeanData jspServletData = configureDefaultServlet(jspServlet, earContext, moduleName, knownServletMappings, moduleContext);
  446                   Set<String> jspMappings = (Set<String>) jspServletData.getAttribute("servletMappings");
  447                   jspMappings.addAll(knownServletMappings);
  448                   jspServletData.setAttribute("servletMappings", jspMappings);
  449               }
  450   
  451               // configure login configs.
  452               configureLoginConfigs(module, webApp, jettyWebApp, webModuleData);
  453   
  454               // Make sure that servlet mappings point to available servlets and never add a duplicate pattern.
  455   
  456               buildServletMappings(module, webApp, servletMappings, knownServletMappings);
  457   
  458               //"previous" filter mapping for linked list to keep dd's ordering.
  459               AbstractName previous = null;
  460   
  461               //add default filters
  462               if (defaultFilters != null) {
  463                   previous = addDefaultFiltersGBeans(earContext, moduleContext, moduleName, previous);
  464               }
  465   
  466               //add default filtermappings
  467   //            if (defaultFilterMappings != null) {
  468   //                for (Iterator iterator = defaultFilterMappings.iterator(); iterator.hasNext();) {
  469   //                    Object defaultFilterMapping = iterator.next();
  470   //                    GBeanData filterMappingGBeanData = getGBeanData(kernel, defaultFilterMapping);
  471   //                    String filterName = (String) filterMappingGBeanData.getAttribute("filterName");
  472   //                    ObjectName defaultFilterMappingObjectName;
  473   //                    if (filterMappingGBeanData.getAttribute("urlPattern") != null) {
  474   //                        String urlPattern = (String) filterMappingGBeanData.getAttribute("urlPattern");
  475   //                        defaultFilterMappingObjectName = NameFactory.getWebFilterMappingName(null, null, null, null, filterName, null, urlPattern, moduleName);
  476   //                    } else {
  477   //                        Set servletNames = filterMappingGBeanData.getReferencePatterns("Servlet");
  478   //                        if (servletNames == null || servletNames.size() != 1) {
  479   //                            throw new DeploymentException("Exactly one servlet name must be supplied");
  480   //                        }
  481   //                        ObjectName servletObjectName = (ObjectName) servletNames.iterator().next();
  482   //                        String servletName = servletObjectName.getKeyProperty("name");
  483   //                        defaultFilterMappingObjectName = NameFactory.getWebFilterMappingName(null, null, null, null, filterName, servletName, null, moduleName);
  484   //                    }
  485   //                    filterMappingGBeanData.setName(defaultFilterMappingObjectName);
  486   //                    filterMappingGBeanData.setReferencePattern("JettyFilterMappingRegistration", webModuleName);
  487   //                    moduleContext.addGBean(filterMappingGBeanData);
  488   //                }
  489   //            }
  490   
  491               // add filter mapping GBeans.
  492               addFilterMappingsGBeans(earContext, moduleContext, moduleName, webApp, previous);
  493   
  494               // add filter GBeans.
  495               addFiltersGBeans(earContext, moduleContext, moduleName, webApp);
  496   
  497               //add default servlets
  498               if (defaultServlets != null) {
  499                   addDefaultServletsGBeans(earContext, moduleContext, moduleName, knownServletMappings);
  500               }
  501   
  502               //set up servlet gbeans.
  503               ServletType[] servletTypes = webApp.getServletArray();
  504               addServlets(moduleName, webModule, servletTypes, servletMappings, moduleContext);
  505   
  506               if (jettyWebApp.isSetSecurityRealmName()) {
  507                   configureSecurityRealm(earContext, webApp, jettyWebApp, webModuleData);
  508               }
  509   
  510               //See Jetty-386, GERONIMO-3738
  511               if (jettyWebApp.getCompactPath()) {
  512                   webModuleData.setAttribute("compactPath", Boolean.TRUE);
  513               }
  514   
  515               //TODO this may definitely not be the best place for this!
  516               for (ModuleBuilderExtension mbe : moduleBuilderExtensions) {
  517                   mbe.addGBeans(earContext, module, cl, repository);
  518               }
  519   
  520               //not truly metadata complete until MBEs have run
  521               if (!webApp.getMetadataComplete()) {
  522                   webApp.setMetadataComplete(true);
  523                   module.setOriginalSpecDD(module.getSpecDD().toString());
  524               }
  525               webModuleData.setAttribute("deploymentDescriptor", module.getOriginalSpecDD());
  526   
  527               if (!module.isStandAlone()) {
  528                   ConfigurationData moduleConfigurationData = moduleContext.getConfigurationData();
  529                   earContext.addChildConfiguration(module.getTargetPath(), moduleConfigurationData);
  530               }
  531           } catch (DeploymentException de) {
  532               throw de;
  533           } catch (Exception e) {
  534               throw new DeploymentException("Unable to initialize webapp GBean for " + module.getName(), e);
  535           }
  536   
  537       }
  538   
  539       private void configureNoClustering(EARContext moduleContext, GBeanData webModuleData) throws GBeanAlreadyExistsException {
  540   //        AbstractName name = moduleContext.getNaming().createChildName(moduleContext.getModuleName(),
  541   //                "DefaultWebApplicationHandlerFactory",
  542   //                GBeanInfoBuilder.DEFAULT_J2EE_TYPE);
  543   //        GBeanData beanData = new GBeanData(name, DefaultWebApplicationHandlerFactory.GBEAN_INFO);
  544   //        webModuleData.setReferencePattern(JettyWebAppContext.GBEAN_REF_WEB_APPLICATION_HANDLER_FACTORY, name);
  545   //        moduleContext.addGBean(beanData);
  546       }
  547   
  548       private void configureSecurityRealm(EARContext earContext, WebAppType webApp, JettyWebAppType jettyWebApp, GBeanData webModuleData) throws DeploymentException {
  549           AbstractName moduleName = webModuleData.getAbstractName();
  550           if (earContext.getSecurityConfiguration() == null) {
  551               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)");
  552           }
  553           String securityRealmName = jettyWebApp.getSecurityRealmName().trim();
  554           webModuleData.setReferencePattern("ConfigurationFactory", new AbstractNameQuery(null, Collections.singletonMap("name", securityRealmName), ConfigurationFactory.class.getName()));
  555           webModuleData.setReferencePattern("RunAsSource", (AbstractNameQuery)earContext.getGeneralData().get(ROLE_MAPPER_DATA_NAME));
  556   
  557           /**
  558            * TODO - go back to commented version when possible.
  559            */
  560           String policyContextID = moduleName.toString().replaceAll("[, :]", "_");
  561           //String policyContextID = webModuleName.getCanonicalName();
  562           webModuleData.setAttribute("policyContextID", policyContextID);
  563   
  564           ComponentPermissions componentPermissions = buildSpecSecurityConfig(webApp);
  565   
  566           earContext.addSecurityContext(policyContextID, componentPermissions);
  567       }
  568   
  569       private void addDefaultServletsGBeans(EARContext earContext, EARContext moduleContext, AbstractName moduleName, Set knownServletMappings) throws GBeanNotFoundException, GBeanAlreadyExistsException {
  570           for (Object defaultServlet : defaultServlets) {
  571               configureDefaultServlet(defaultServlet, earContext, moduleName, knownServletMappings, moduleContext);
  572           }
  573       }
  574   
  575       private GBeanData configureDefaultServlet(Object defaultServlet, EARContext earContext, AbstractName moduleName, Set knownServletMappings, EARContext moduleContext) throws GBeanNotFoundException, GBeanAlreadyExistsException {
  576           GBeanData servletGBeanData = getGBeanData(kernel, defaultServlet);
  577           AbstractName defaultServletObjectName = earContext.getNaming().createChildName(moduleName, (String) servletGBeanData.getAttribute("servletName"), NameFactory.SERVLET);
  578           servletGBeanData.setAbstractName(defaultServletObjectName);
  579           servletGBeanData.setReferencePattern("JettyServletRegistration", moduleName);
  580           Set<String> defaultServletMappings = new HashSet<String>((Collection<String>) servletGBeanData.getAttribute("servletMappings"));
  581           defaultServletMappings.removeAll(knownServletMappings);
  582           servletGBeanData.setAttribute("servletMappings", defaultServletMappings);
  583           moduleContext.addGBean(servletGBeanData);
  584           return servletGBeanData;
  585       }
  586   
  587       private void addFiltersGBeans(EARContext earContext, EARContext moduleContext, AbstractName moduleName, WebAppType webApp) throws GBeanAlreadyExistsException {
  588           FilterType[] filterArray = webApp.getFilterArray();
  589           for (FilterType filterType : filterArray) {
  590               String filterName = filterType.getFilterName().getStringValue().trim();
  591               AbstractName filterAbstractName = earContext.getNaming().createChildName(moduleName, filterName, NameFactory.WEB_FILTER);
  592               GBeanData filterData = new GBeanData(filterAbstractName, JettyFilterHolder.GBEAN_INFO);
  593               filterData.setAttribute("filterName", filterName);
  594               filterData.setAttribute("filterClass", filterType.getFilterClass().getStringValue().trim());
  595               Map<String, String> initParams = new HashMap<String, String>();
  596               ParamValueType[] initParamArray = filterType.getInitParamArray();
  597               for (ParamValueType paramValueType : initParamArray) {
  598                   initParams.put(paramValueType.getParamName().getStringValue().trim(), paramValueType.getParamValue().getStringValue().trim());
  599               }
  600               filterData.setAttribute("initParams", initParams);
  601               filterData.setReferencePattern("JettyServletRegistration", moduleName);
  602               moduleContext.addGBean(filterData);
  603           }
  604       }
  605   
  606       private void addFilterMappingsGBeans(EARContext earContext, EARContext moduleContext, AbstractName moduleName, WebAppType webApp, AbstractName previous) throws GBeanAlreadyExistsException {
  607           FilterMappingType[] filterMappingArray = webApp.getFilterMappingArray();
  608           for (FilterMappingType filterMappingType : filterMappingArray) {
  609               String filterName = filterMappingType.getFilterName().getStringValue().trim();
  610               GBeanData filterMappingData = new GBeanData(JettyFilterMapping.GBEAN_INFO);
  611               if (previous != null) {
  612                   filterMappingData.addDependency(previous);
  613               }
  614               filterMappingData.setReferencePattern("JettyServletRegistration", moduleName);
  615               AbstractName filterAbstractName = earContext.getNaming().createChildName(moduleName, filterName, NameFactory.WEB_FILTER);
  616   
  617               AbstractName filterMappingName = null;
  618               if (filterMappingType.sizeOfUrlPatternArray() > 0) {
  619                   String[] urlPatterns = new String[filterMappingType.sizeOfUrlPatternArray()];
  620                   for (int j = 0; j < urlPatterns.length; j++) {
  621                       urlPatterns[j] = filterMappingType.getUrlPatternArray(j).getStringValue().trim();
  622                   }
  623   
  624                   filterMappingData.setAttribute("urlPatterns", urlPatterns);
  625                   filterMappingName = earContext.getNaming().createChildName(filterAbstractName, ObjectName.quote(Arrays.deepToString(urlPatterns)), NameFactory.URL_WEB_FILTER_MAPPING);
  626               }
  627               if (filterMappingType.sizeOfServletNameArray() > 0) {
  628                   Set<AbstractName> servletNameSet = new HashSet<AbstractName>();
  629                   for (int j = 0; j < filterMappingType.sizeOfServletNameArray(); j++) {
  630                       String servletName = filterMappingType.getServletNameArray(j).getStringValue().trim();
  631                       AbstractName abstractServletName = earContext.getNaming().createChildName(moduleName, servletName, NameFactory.SERVLET);
  632                       servletNameSet.add(abstractServletName);
  633                       filterMappingData.addDependency(abstractServletName);
  634                   }
  635   
  636                   filterMappingData.setReferencePatterns("Servlets", servletNameSet);
  637                   filterMappingName = earContext.getNaming().createChildName(filterAbstractName, ObjectName.quote(Arrays.deepToString(servletNameSet.toArray())), NameFactory.SERVLET_WEB_FILTER_MAPPING);
  638   
  639               }
  640               filterMappingData.setAbstractName(filterMappingName);
  641               previous = filterMappingName;
  642   
  643               boolean request = filterMappingType.getDispatcherArray().length == 0;
  644               boolean forward = false;
  645               boolean include = false;
  646               boolean error = false;
  647               for (int j = 0; j < filterMappingType.getDispatcherArray().length; j++) {
  648                   DispatcherType dispatcherType = filterMappingType.getDispatcherArray()[j];
  649                   if (dispatcherType.getStringValue().equals("REQUEST")) {
  650                       request = true;
  651                   } else if (dispatcherType.getStringValue().equals("FORWARD")) {
  652                       forward = true;
  653                   } else if (dispatcherType.getStringValue().equals("INCLUDE")) {
  654                       include = true;
  655                   } else if (dispatcherType.getStringValue().equals("ERROR")) {
  656                       error = true;
  657                   }
  658               }
  659               filterMappingData.setAttribute("requestDispatch", request);
  660               filterMappingData.setAttribute("forwardDispatch", forward);
  661               filterMappingData.setAttribute("includeDispatch", include);
  662               filterMappingData.setAttribute("errorDispatch", error);
  663               filterMappingData.setReferencePattern("Filter", filterAbstractName);
  664               moduleContext.addGBean(filterMappingData);
  665           }
  666       }
  667   
  668       private AbstractName addDefaultFiltersGBeans(EARContext earContext, EARContext moduleContext, AbstractName moduleName, AbstractName previous) throws GBeanNotFoundException, GBeanAlreadyExistsException {
  669           for (Object defaultFilter : defaultFilters) {
  670               GBeanData filterGBeanData = getGBeanData(kernel, defaultFilter);
  671               String filterName = (String) filterGBeanData.getAttribute("filterName");
  672               AbstractName defaultFilterAbstractName = earContext.getNaming().createChildName(moduleName, filterName, NameFactory.WEB_FILTER);
  673               filterGBeanData.setAbstractName(defaultFilterAbstractName);
  674               filterGBeanData.setReferencePattern("JettyServletRegistration", moduleName);
  675               moduleContext.addGBean(filterGBeanData);
  676               //add a mapping to /*
  677   
  678               GBeanData filterMappingGBeanData = new GBeanData(JettyFilterMapping.GBEAN_INFO);
  679               if (previous != null) {
  680                   filterMappingGBeanData.addDependency(previous);
  681               }
  682               filterMappingGBeanData.setReferencePattern("JettyServletRegistration", moduleName);
  683               String urlPattern = "/*";
  684               filterMappingGBeanData.setAttribute("urlPattern", urlPattern);
  685               AbstractName filterMappingName = earContext.getNaming().createChildName(defaultFilterAbstractName, urlPattern, NameFactory.URL_WEB_FILTER_MAPPING);
  686               filterMappingGBeanData.setAbstractName(filterMappingName);
  687               previous = filterMappingName;
  688   
  689   
  690               filterMappingGBeanData.setAttribute("requestDispatch", TRUE);
  691               filterMappingGBeanData.setAttribute("forwardDispatch", TRUE);
  692               filterMappingGBeanData.setAttribute("includeDispatch", TRUE);
  693               filterMappingGBeanData.setAttribute("errorDispatch", FALSE);
  694               filterMappingGBeanData.setReferencePattern("Filter", defaultFilterAbstractName);
  695               moduleContext.addGBean(filterMappingGBeanData);
  696           }
  697           return previous;
  698       }
  699   
  700       private Map buildServletMappings(Module module, WebAppType webApp, Map<String, Set<String>> servletMappings, Set<String> knownServletMappings) throws DeploymentException {
  701           ServletType[] servletTypes = webApp.getServletArray();
  702           Set<String> knownServlets = new HashSet<String>();
  703           for (ServletType type : servletTypes) {
  704               knownServlets.add(type.getServletName().getStringValue().trim());
  705           }
  706   
  707           ServletMappingType[] servletMappingArray = webApp.getServletMappingArray();
  708           for (ServletMappingType servletMappingType : servletMappingArray) {
  709               String servletName = servletMappingType.getServletName().getStringValue().trim();
  710               if (!knownServlets.contains(servletName)) {
  711                   throw new DeploymentException("Web app " + module.getName() +
  712                           " contains a servlet mapping that refers to servlet '" + servletName +
  713                           "' but no such servlet was found!");
  714               }
  715               UrlPatternType[] urlPatterns = servletMappingType.getUrlPatternArray();
  716               addMappingsForServlet(servletName, urlPatterns, knownServletMappings, servletMappings);
  717           }
  718   
  719           return servletMappings;
  720       }
  721   
  722       private void addMappingsForServlet(String servletName, UrlPatternType[] urlPatterns, Set<String> knownServletMappings, Map<String, Set<String>> servletMappings) throws DeploymentException {
  723           for (UrlPatternType patternType : urlPatterns) {
  724               String urlPattern = patternType.getStringValue().trim();
  725               if (!urlPattern.startsWith("*") && !urlPattern.startsWith("/")) {
  726                   urlPattern = "/" + urlPattern;
  727               }
  728               if (!knownServletMappings.contains(urlPattern)) {
  729                   knownServletMappings.add(urlPattern);
  730                   checkString(urlPattern);
  731                   Set<String> urlsForServlet = servletMappings.get(servletName);
  732                   if (urlsForServlet == null) {
  733                       urlsForServlet = new HashSet<String>();
  734                       servletMappings.put(servletName, urlsForServlet);
  735                   }
  736                   urlsForServlet.add(urlPattern);
  737               }
  738           }
  739       }
  740   
  741       private void configureLoginConfigs(Module module, WebAppType webApp, JettyWebAppType jettyWebApp, GBeanData webModuleData) throws DeploymentException {
  742           LoginConfigType[] loginConfigArray = webApp.getLoginConfigArray();
  743           if (loginConfigArray.length > 1) {
  744               throw new DeploymentException("Web app " + module.getName() + " cannot have more than one login-config element.  Currently has " + loginConfigArray.length + " login-config elements.");
  745           }
  746           if (loginConfigArray.length == 1) {
  747               LoginConfigType loginConfig = loginConfigArray[0];
  748               if (loginConfig.isSetAuthMethod()) {
  749                   String authMethod = loginConfig.getAuthMethod().getStringValue();
  750                   if ("BASIC".equals(authMethod)) {
  751                       webModuleData.setAttribute("authenticator", new BasicAuthenticator());
  752                   } else if ("DIGEST".equals(authMethod)) {
  753                       webModuleData.setAttribute("authenticator", new DigestAuthenticator());
  754                   } else if ("FORM".equals(authMethod)) {
  755   
  756                       FormAuthenticator formAuthenticator = new FormAuthenticator();
  757                       webModuleData.setAttribute("authenticator", formAuthenticator);
  758                       if (loginConfig.isSetFormLoginConfig()) {
  759                           FormLoginConfigType formLoginConfig = loginConfig.getFormLoginConfig();
  760                           formAuthenticator.setLoginPage(formLoginConfig.getFormLoginPage().getStringValue());
  761                           formAuthenticator.setErrorPage(formLoginConfig.getFormErrorPage().getStringValue());
  762                       }
  763                   } else if ("CLIENT-CERT".equals(authMethod)) {
  764                       webModuleData.setAttribute("authenticator", new ClientCertAuthenticator());
  765                   }
  766               }
  767               if (loginConfig.isSetRealmName()) {
  768                   webModuleData.setAttribute("realmName", loginConfig.getRealmName().getStringValue());
  769               }
  770   
  771           } else if (jettyWebApp.isSetSecurityRealmName()) {
  772               webModuleData.setAttribute("authenticator", new NonAuthenticator());
  773           }
  774       }
  775   
  776       private void configureTagLibs(Module module, WebAppType webApp, GBeanData webModuleData, Map<String, Set<String>> servletMappings, Set<String> knownServletMappings, String jspServletName) throws DeploymentException {
  777           JspConfigType[] jspConfigArray = webApp.getJspConfigArray();
  778           if (jspConfigArray.length > 1) {
  779               throw new DeploymentException("Web app " + module.getName() + " cannot have more than one jsp-config element.  Currently has " + jspConfigArray.length + " jsp-config elements.");
  780           }
  781           Map<String, String> tagLibMap = new HashMap<String, String>();
  782           for (JspConfigType aJspConfigArray : jspConfigArray) {
  783               TaglibType[] tagLibArray = aJspConfigArray.getTaglibArray();
  784               for (TaglibType taglib : tagLibArray) {
  785                   tagLibMap.put(taglib.getTaglibUri().getStringValue().trim(), taglib.getTaglibLocation().getStringValue().trim());
  786               }
  787               for (JspPropertyGroupType propertyGroup: aJspConfigArray.getJspPropertyGroupArray()) {
  788                   UrlPatternType[] urlPatterns = propertyGroup.getUrlPatternArray();
  789                   addMappingsForServlet(jspServletName, urlPatterns, knownServletMappings, servletMappings);
  790               }
  791           }
  792           webModuleData.setAttribute("tagLibMap", tagLibMap);
  793       }
  794   
  795       private void configureErrorPages(WebAppType webApp, GBeanData webModuleData) {
  796           ErrorPageType[] errorPageArray = webApp.getErrorPageArray();
  797           Map<String, String> errorPageMap = new HashMap<String, String>();
  798           for (ErrorPageType errorPageType : errorPageArray) {
  799               if (errorPageType.isSetErrorCode()) {
  800                   errorPageMap.put(errorPageType.getErrorCode().getStringValue().trim(), errorPageType.getLocation().getStringValue().trim());
  801               } else {
  802                   errorPageMap.put(errorPageType.getExceptionType().getStringValue().trim(), errorPageType.getLocation().getStringValue().trim());
  803               }
  804           }
  805           webModuleData.setAttribute("errorPages", errorPageMap);
  806       }
  807   
  808       private void configureLocaleEncodingMappingLists(WebAppType webApp, GBeanData webModuleData) {
  809           LocaleEncodingMappingListType[] localeEncodingMappingListArray = webApp.getLocaleEncodingMappingListArray();
  810           Map<String, String> localeEncodingMappingMap = new HashMap<String, String>(defaultLocaleEncodingMappings);
  811           for (LocaleEncodingMappingListType aLocaleEncodingMappingListArray : localeEncodingMappingListArray) {
  812               LocaleEncodingMappingType[] localeEncodingMappingArray = aLocaleEncodingMappingListArray.getLocaleEncodingMappingArray();
  813               for (LocaleEncodingMappingType localeEncodingMapping : localeEncodingMappingArray) {
  814                   localeEncodingMappingMap.put(localeEncodingMapping.getLocale().trim(), localeEncodingMapping.getEncoding().trim());
  815               }
  816           }
  817           webModuleData.setAttribute("localeEncodingMapping", localeEncodingMappingMap);
  818       }
  819   
  820       private void configureWelcomeFileLists(WebAppType webApp, GBeanData webModuleData) {
  821           WelcomeFileListType[] welcomeFileArray = webApp.getWelcomeFileListArray();
  822           List<String> welcomeFiles;
  823           if (welcomeFileArray.length > 0) {
  824               welcomeFiles = new ArrayList<String>();
  825               for (WelcomeFileListType aWelcomeFileArray : welcomeFileArray) {
  826                   String[] welcomeFileListType = aWelcomeFileArray.getWelcomeFileArray();
  827                   for (String welcomeFile : welcomeFileListType) {
  828                       welcomeFiles.add(welcomeFile.trim());
  829                   }
  830               }
  831           } else {
  832               welcomeFiles = new ArrayList<String>(defaultWelcomeFiles);
  833           }
  834           webModuleData.setAttribute("welcomeFiles", welcomeFiles.toArray(new String[welcomeFiles.size()]));
  835       }
  836   
  837       private void configureMimeMappings(WebAppType webApp, GBeanData webModuleData) {
  838           MimeMappingType[] mimeMappingArray = webApp.getMimeMappingArray();
  839           Map<String, String> mimeMappingMap = new HashMap<String, String>(defaultMimeTypeMappings);
  840           for (MimeMappingType mimeMappingType : mimeMappingArray) {
  841               mimeMappingMap.put(mimeMappingType.getExtension().getStringValue().trim(), mimeMappingType.getMimeType().getStringValue().trim());
  842           }
  843           webModuleData.setAttribute("mimeMap", mimeMappingMap);
  844       }
  845   
  846       private void configureListeners(WebAppType webApp, GBeanData webModuleData) {
  847           ListenerType[] listenerArray = webApp.getListenerArray();
  848           Collection<String> listeners = new ArrayList<String>();
  849           for (ListenerType listenerType : listenerArray) {
  850               listeners.add(listenerType.getListenerClass().getStringValue().trim());
  851           }
  852           webModuleData.setAttribute("listenerClassNames", listeners);
  853       }
  854   
  855       private void configureContextParams(WebAppType webApp, GBeanData webModuleData) {
  856           ParamValueType[] contextParamArray = webApp.getContextParamArray();
  857           Map<String, String> contextParams = new HashMap<String, String>();
  858           for (ParamValueType contextParam : contextParamArray) {
  859               contextParams.put(contextParam.getParamName().getStringValue().trim(), contextParam.getParamValue().getStringValue().trim());
  860           }
  861           webModuleData.setAttribute("contextParamMap", contextParams);
  862       }
  863   
  864       private void configureHosts(EARContext earContext, JettyWebAppType jettyWebApp, GBeanData webModuleData) throws GBeanAlreadyExistsException {
  865           String[] hosts = jettyWebApp.getHostArray();
  866           for (int i = 0; i < hosts.length; i++) {
  867               hosts[i] = hosts[i].trim();
  868           }
  869           String[] virtualHosts = jettyWebApp.getVirtualHostArray();
  870           for (int i = 0; i < virtualHosts.length; i++) {
  871               virtualHosts[i] = virtualHosts[i].trim();
  872           }
  873           if (hosts.length > 0 || virtualHosts.length > 0) {
  874               //use name same as module
  875               AbstractName hostName = earContext.getNaming().createChildName(webModuleData.getAbstractName(), "Host", "Host");
  876               GBeanData hostData = new GBeanData(hostName, Host.GBEAN_INFO);
  877               hostData.setAttribute("hosts", hosts);
  878               hostData.setAttribute("virtualHosts", virtualHosts);
  879               earContext.addGBean(hostData);
  880               webModuleData.setReferencePattern("Host", hostName);
  881           }
  882       }
  883   
  884       public String getSchemaNamespace() {
  885           return JETTY_NAMESPACE;
  886       }
  887   
  888       /**
  889        * Adds the provided servlets, taking into account the load-on-startup ordering.
  890        *
  891        * @param webModuleName   an <code>ObjectName</code> value
  892        * @param module          a <code>Module</code> value
  893        * @param servletTypes    a <code>ServletType[]</code> value, contains the <code>servlet</code> entries from <code>web.xml</code>.
  894        * @param servletMappings a <code>Map</code> value
  895        * @param moduleContext   an <code>EARContext</code> value
  896        * @throws DeploymentException if an error occurs
  897        */
  898       private void addServlets(AbstractName webModuleName,
  899                                Module module,
  900                                ServletType[] servletTypes,
  901                                Map<String, Set<String>> servletMappings,
  902                                EARContext moduleContext) throws DeploymentException {
  903   
  904           // this TreeSet will order the ServletTypes based on whether
  905           // they have a load-on-startup element and what its value is
  906           TreeSet<ServletType> loadOrder = new TreeSet<ServletType>(new StartupOrderComparator());
  907   
  908           // add all of the servlets to the sorted set
  909           loadOrder.addAll(Arrays.asList(servletTypes));
  910   
  911           // now that they're sorted, read them in order and add them to
  912           // the context.  we'll use a GBean reference to enforce the
  913           // load order.  Each servlet GBean (except the first) has a
  914           // reference to the previous GBean.  The kernel will ensure
  915           // that each "previous" GBean is running before it starts any
  916           // other GBeans that reference it.  See also
  917           // o.a.g.jetty6.JettyFilterMapping which provided the example
  918           // of how to do this.
  919           // http://issues.apache.org/jira/browse/GERONIMO-645
  920           AbstractName previousServlet = null;
  921           for (Object aLoadOrder : loadOrder) {
  922               ServletType servletType = (ServletType) aLoadOrder;
  923               previousServlet = addServlet(webModuleName, module, previousServlet, servletType, servletMappings, moduleContext);
  924           }
  925       }
  926   
  927       /**
  928        * @param webModuleName AbstractName of the web module
  929        * @param module the web module being added
  930        * @param previousServlet the servlet to start before this one in init order
  931        * @param servletType XMLObject specifying the servlet configuration
  932        * @param servletMappings Map of servlet name to set of ServletMapping strings for this web app
  933        * @param moduleContext deployment context for this module
  934        * @return AbstractName of servlet gbean added
  935        * @throws DeploymentException if something goes wrong
  936        */
  937       private AbstractName addServlet(AbstractName webModuleName,
  938                                       Module module,
  939                                       AbstractName previousServlet,
  940                                       ServletType servletType,
  941                                       Map<String, Set<String>> servletMappings,
  942                                       EARContext moduleContext) throws DeploymentException {
  943           String servletName = servletType.getServletName().getStringValue().trim();
  944           AbstractName servletAbstractName = moduleContext.getNaming().createChildName(webModuleName, servletName, NameFactory.SERVLET);
  945           GBeanData servletData;
  946           Map<String, String> initParams = new HashMap<String, String>();
  947           if (servletType.isSetServletClass()) {
  948               ClassLoader webClassLoader = moduleContext.getClassLoader();
  949               String servletClassName = servletType.getServletClass().getStringValue().trim();
  950               Class servletClass;
  951               try {
  952                   servletClass = webClassLoader.loadClass(servletClassName);
  953               } catch (ClassNotFoundException e) {
  954                   throw new DeploymentException("Could not load servlet class " + servletClassName, e); // TODO identify web app in message
  955               }
  956               Class baseServletClass;
  957               try {
  958                   baseServletClass = webClassLoader.loadClass(Servlet.class.getName());
  959               } catch (ClassNotFoundException e) {
  960                   throw new DeploymentException("Could not load javax.servlet.Servlet in web classloader", e); // TODO identify web app in message
  961               }
  962               if (baseServletClass.isAssignableFrom(servletClass)) {
  963                   servletData = new GBeanData(servletAbstractName, JettyServletHolder.GBEAN_INFO);
  964                   servletData.setAttribute("servletClass", servletClassName);
  965               } else {
  966                   servletData = new GBeanData(pojoWebServiceTemplate);
  967                   servletData.setAbstractName(servletAbstractName);
  968                   //let the web service builder deal with configuring the gbean with the web service stack
  969   //                Object portInfo = portMap.get(servletName);
  970   //                if (portInfo == null) {
  971   //                    throw new DeploymentException("No web service deployment info for servlet name " + servletName); // TODO identify web app in message
  972   //                }
  973                   boolean configured = false;
  974                   for (Object aWebServiceBuilder : webServiceBuilder) {
  975                       WebServiceBuilder serviceBuilder = (WebServiceBuilder) aWebServiceBuilder;
  976                       if (serviceBuilder.configurePOJO(servletData, servletName, module, servletClassName, moduleContext)) {
  977                           configured = true;
  978                           break;
  979                       }
  980                   }
  981                   if (!configured) {
  982                       throw new DeploymentException("POJO web service: " + servletName + " not configured by any web service builder");
  983                   }
  984               }
  985           } else if (servletType.isSetJspFile()) {
  986               servletData = new GBeanData(servletAbstractName, JettyServletHolder.GBEAN_INFO);
  987               servletData.setAttribute("jspFile", servletType.getJspFile().getStringValue().trim());
  988               servletData.setAttribute("servletClass", jspServlet.getServletClassName());
  989               initParams.put("development", "false");
  990           } else {
  991               throw new DeploymentException("Neither servlet class nor jsp file is set for " + servletName); // TODO identify web app in message
  992           }
  993   
  994           // link to previous servlet, if there is one, so that we
  995           // preserve the <load-on-startup> ordering.
  996           // http://issues.apache.org/jira/browse/GERONIMO-645
  997           if (null != previousServlet) {
  998               servletData.addDependency(previousServlet);
  999           }
 1000   
 1001           //TODO in init param setter, add classpath if jspFile is not null.
 1002           servletData.setReferencePattern("JettyServletRegistration", webModuleName);
 1003           servletData.setAttribute("servletName", servletName);
 1004           ParamValueType[] initParamArray = servletType.getInitParamArray();
 1005           for (ParamValueType paramValueType : initParamArray) {
 1006               initParams.put(paramValueType.getParamName().getStringValue().trim(), paramValueType.getParamValue().getStringValue().trim());
 1007           }
 1008           servletData.setAttribute("initParams", initParams);
 1009           if (servletType.isSetLoadOnStartup()) {
 1010               Integer loadOnStartup = new Integer(servletType.xgetLoadOnStartup().getStringValue());
 1011               servletData.setAttribute("loadOnStartup", loadOnStartup);
 1012           }
 1013   
 1014           Set mappings = servletMappings.get(servletName);
 1015           servletData.setAttribute("servletMappings", mappings == null ? Collections.EMPTY_SET : mappings);
 1016   
 1017           //run-as
 1018           if (servletType.isSetRunAs()) {
 1019               String runAsRole = servletType.getRunAs().getRoleName().getStringValue().trim();
 1020               servletData.setAttribute("runAsRole", runAsRole);
 1021           }
 1022   
 1023           try {
 1024               moduleContext.addGBean(servletData);
 1025           } catch (GBeanAlreadyExistsException e) {
 1026               throw new DeploymentException("Could not add servlet gbean to context", e); // TODO identify web app in message
 1027           }
 1028           return servletAbstractName;
 1029       }
 1030   
 1031       public static final GBeanInfo GBEAN_INFO;
 1032   
 1033       static {
 1034           GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(JettyModuleBuilder.class, NameFactory.MODULE_BUILDER);
 1035           infoBuilder.addAttribute("defaultEnvironment", Environment.class, true, true);
 1036           infoBuilder.addAttribute("defaultSessionTimeoutSeconds", Integer.class, true, true);
 1037           infoBuilder.addAttribute("defaultWelcomeFiles", List.class, true, true);
 1038           infoBuilder.addAttribute("defaultLocaleEncodingMappings", Map.class, true, true);
 1039           infoBuilder.addAttribute("defaultMimeTypeMappings", Map.class, true, true);
 1040           infoBuilder.addAttribute("jettyContainerObjectName", AbstractNameQuery.class, true, true);
 1041           infoBuilder.addReference("JspServlet", JettyJspServletHolder.class, NameFactory.SERVLET_TEMPLATE);
 1042           infoBuilder.addReference("DefaultServlets", JettyDefaultServletHolder.class, NameFactory.SERVLET_TEMPLATE);
 1043           infoBuilder.addReference("DefaultFilters", Object.class);
 1044           infoBuilder.addReference("DefaultFilterMappings", Object.class);
 1045           infoBuilder.addReference("PojoWebServiceTemplate", Object.class, NameFactory.SERVLET_WEB_SERVICE_TEMPLATE);
 1046           infoBuilder.addReference("WebServiceBuilder", WebServiceBuilder.class, NameFactory.MODULE_BUILDER);
 1047           infoBuilder.addReference("ClusteringBuilders", NamespaceDrivenBuilder.class, NameFactory.MODULE_BUILDER);
 1048           infoBuilder.addReference("ServiceBuilders", NamespaceDrivenBuilder.class, NameFactory.MODULE_BUILDER);
 1049           infoBuilder.addReference("NamingBuilders", NamingBuilder.class, NameFactory.MODULE_BUILDER);
 1050           infoBuilder.addReference("ModuleBuilderExtensions", ModuleBuilderExtension.class, NameFactory.MODULE_BUILDER);
 1051           infoBuilder.addReference("ResourceEnvironmentSetter", ResourceEnvironmentSetter.class, NameFactory.MODULE_BUILDER);
 1052           infoBuilder.addAttribute("kernel", Kernel.class, false);
 1053           infoBuilder.addInterface(ModuleBuilder.class);
 1054   
 1055           infoBuilder.setConstructor(new String[]{
 1056                   "defaultEnvironment",
 1057                   "defaultSessionTimeoutSeconds",
 1058                   "defaultWelcomeFiles",
 1059                   "jettyContainerObjectName",
 1060                   "JspServlet",
 1061                   "DefaultServlets",
 1062                   "DefaultFilters",
 1063                   "DefaultFilterMappings",
 1064                   "defaultLocaleEncodingMappings",
 1065                   "defaultMimeTypeMappings",
 1066                   "PojoWebServiceTemplate",
 1067                   "WebServiceBuilder",
 1068                   "ClusteringBuilders",
 1069                   "ServiceBuilders",
 1070                   "NamingBuilders",
 1071                   "ModuleBuilderExtensions",
 1072                   "ResourceEnvironmentSetter",
 1073                   "kernel"});
 1074           GBEAN_INFO = infoBuilder.getBeanInfo();
 1075       }
 1076   
 1077       public static GBeanInfo getGBeanInfo() {
 1078           return GBEAN_INFO;
 1079       }
 1080   
 1081       static class StartupOrderComparator implements Comparator<ServletType> {
 1082           /**
 1083            * comparator that compares first on the basis of startup order, and then on the lexicographical
 1084            * ordering of servlet name.  Since the servlet names have a uniqueness constraint, this should
 1085            * provide a total ordering consistent with equals.  All servlets with no startup order are after
 1086            * all servlets with a startup order.
 1087            *
 1088            * @param s1 first ServletType object
 1089            * @param s2 second ServletType object
 1090            * @return an int < 0 if o1 precedes o2, 0 if they are equal, and > 0 if o2 preceeds o1.
 1091            */
 1092           public int compare(ServletType s1, ServletType s2) {
 1093   
 1094               // load-on-startup is set for neither.  the
 1095               // ordering at this point doesn't matter, but we
 1096               // should return "0" only if the two objects say
 1097               // they are equal
 1098               if (!s1.isSetLoadOnStartup() && !s2.isSetLoadOnStartup()) {
 1099                   return s1.equals(s2) ? 0 : s1.getServletName().getStringValue().trim().compareTo(s2.getServletName().getStringValue().trim());
 1100               }
 1101   
 1102               // load-on-startup is set for one but not the
 1103               // other.  whichever one is set will be "less
 1104               // than", i.e. it will be loaded first
 1105               if (s1.isSetLoadOnStartup() && !s2.isSetLoadOnStartup()) {
 1106                   return -1;
 1107               }
 1108               if (!s1.isSetLoadOnStartup() && s2.isSetLoadOnStartup()) {
 1109                   return 1;
 1110               }
 1111   
 1112               // load-on-startup is set for both.  whichever one
 1113               // has a smaller value is "less than"
 1114               int comp = new Integer(s1.xgetLoadOnStartup().getStringValue()).compareTo(new Integer(s2.xgetLoadOnStartup().getStringValue()));
 1115               if (comp == 0) {
 1116                   return s1.getServletName().getStringValue().trim().compareTo(s2.getServletName().getStringValue().trim());
 1117               }
 1118               return comp;
 1119           }
 1120       }
 1121   }

Home » geronimo-2.2-source-release » org.apache.geronimo.jetty6.deployment » [javadoc | source]