0001: /**
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */package org.apache.geronimo.jetty6.deployment;
0017:
0018: import java.io.File;
0019: import java.io.FileNotFoundException;
0020: import java.io.IOException;
0021: import static java.lang.Boolean.FALSE;
0022: import static java.lang.Boolean.TRUE;
0023: import java.net.URL;
0024: import java.security.PermissionCollection;
0025: import java.util.ArrayList;
0026: import java.util.Arrays;
0027: import java.util.Collection;
0028: import java.util.Collections;
0029: import java.util.Comparator;
0030: import java.util.HashMap;
0031: import java.util.HashSet;
0032: import java.util.List;
0033: import java.util.Map;
0034: import java.util.Set;
0035: import java.util.TreeSet;
0036: import java.util.jar.JarFile;
0037:
0038: import javax.management.ObjectName;
0039: import javax.servlet.Servlet;
0040:
0041: import org.apache.commons.logging.Log;
0042: import org.apache.commons.logging.LogFactory;
0043: import org.apache.geronimo.common.DeploymentException;
0044: import org.apache.geronimo.deployment.ModuleIDBuilder;
0045: import org.apache.geronimo.deployment.NamespaceDrivenBuilder;
0046: import org.apache.geronimo.deployment.NamespaceDrivenBuilderCollection;
0047: import org.apache.geronimo.deployment.service.EnvironmentBuilder;
0048: import org.apache.geronimo.deployment.util.DeploymentUtil;
0049: import org.apache.geronimo.deployment.xbeans.EnvironmentType;
0050: import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
0051: import org.apache.geronimo.gbean.AbstractName;
0052: import org.apache.geronimo.gbean.AbstractNameQuery;
0053: import org.apache.geronimo.gbean.GBeanData;
0054: import org.apache.geronimo.gbean.GBeanInfo;
0055: import org.apache.geronimo.gbean.GBeanInfoBuilder;
0056: import org.apache.geronimo.gbean.GBeanLifecycle;
0057: import org.apache.geronimo.j2ee.deployment.EARContext;
0058: import org.apache.geronimo.j2ee.deployment.Module;
0059: import org.apache.geronimo.j2ee.deployment.ModuleBuilder;
0060: import org.apache.geronimo.j2ee.deployment.ModuleBuilderExtension;
0061: import org.apache.geronimo.j2ee.deployment.NamingBuilder;
0062: import org.apache.geronimo.j2ee.deployment.WebModule;
0063: import org.apache.geronimo.j2ee.deployment.WebServiceBuilder;
0064: import org.apache.geronimo.j2ee.deployment.annotation.AnnotatedWebApp;
0065: import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
0066: import org.apache.geronimo.jetty6.Host;
0067: import org.apache.geronimo.jetty6.JettyDefaultServletHolder;
0068: import org.apache.geronimo.jetty6.JettyFilterHolder;
0069: import org.apache.geronimo.jetty6.JettyFilterMapping;
0070: import org.apache.geronimo.jetty6.JettyServletHolder;
0071: import org.apache.geronimo.jetty6.JettyWebAppContext;
0072: import org.apache.geronimo.jetty6.NonAuthenticator;
0073: import org.apache.geronimo.jetty6.JettyJspServletHolder;
0074: import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
0075: import org.apache.geronimo.kernel.GBeanNotFoundException;
0076: import org.apache.geronimo.kernel.Kernel;
0077: import org.apache.geronimo.kernel.Naming;
0078: import org.apache.geronimo.kernel.config.ConfigurationData;
0079: import org.apache.geronimo.kernel.repository.Environment;
0080: import org.apache.geronimo.naming.deployment.ENCConfigBuilder;
0081: import org.apache.geronimo.naming.deployment.GBeanResourceEnvironmentBuilder;
0082: import org.apache.geronimo.naming.deployment.ResourceEnvironmentSetter;
0083: import org.apache.geronimo.security.jacc.ComponentPermissions;
0084: import org.apache.geronimo.web.deployment.GenericToSpecificPlanConverter;
0085: import org.apache.geronimo.web25.deployment.AbstractWebModuleBuilder;
0086: import org.apache.geronimo.xbeans.geronimo.j2ee.GerClusteringDocument;
0087: import org.apache.geronimo.xbeans.geronimo.web.jetty.JettyWebAppDocument;
0088: import org.apache.geronimo.xbeans.geronimo.web.jetty.JettyWebAppType;
0089: import org.apache.geronimo.xbeans.geronimo.web.jetty.config.GerJettyDocument;
0090: import org.apache.geronimo.xbeans.javaee.DispatcherType;
0091: import org.apache.geronimo.xbeans.javaee.ErrorPageType;
0092: import org.apache.geronimo.xbeans.javaee.FilterMappingType;
0093: import org.apache.geronimo.xbeans.javaee.FilterType;
0094: import org.apache.geronimo.xbeans.javaee.FormLoginConfigType;
0095: import org.apache.geronimo.xbeans.javaee.JspConfigType;
0096: import org.apache.geronimo.xbeans.javaee.ListenerType;
0097: import org.apache.geronimo.xbeans.javaee.LocaleEncodingMappingListType;
0098: import org.apache.geronimo.xbeans.javaee.LocaleEncodingMappingType;
0099: import org.apache.geronimo.xbeans.javaee.LoginConfigType;
0100: import org.apache.geronimo.xbeans.javaee.MimeMappingType;
0101: import org.apache.geronimo.xbeans.javaee.ParamValueType;
0102: import org.apache.geronimo.xbeans.javaee.ServletMappingType;
0103: import org.apache.geronimo.xbeans.javaee.ServletType;
0104: import org.apache.geronimo.xbeans.javaee.TaglibType;
0105: import org.apache.geronimo.xbeans.javaee.UrlPatternType;
0106: import org.apache.geronimo.xbeans.javaee.WebAppDocument;
0107: import org.apache.geronimo.xbeans.javaee.WebAppType;
0108: import org.apache.geronimo.xbeans.javaee.WelcomeFileListType;
0109: import org.apache.geronimo.xbeans.javaee.JspPropertyGroupType;
0110: import org.apache.xmlbeans.XmlException;
0111: import org.apache.xmlbeans.XmlObject;
0112: import org.mortbay.jetty.security.BasicAuthenticator;
0113: import org.mortbay.jetty.security.ClientCertAuthenticator;
0114: import org.mortbay.jetty.security.DigestAuthenticator;
0115: import org.mortbay.jetty.security.FormAuthenticator;
0116:
0117: /**
0118: * @version $Rev:385659 $ $Date: 2008-01-10 17:27:36 -0800 (Thu, 10 Jan 2008) $
0119: */
0120: public class JettyModuleBuilder extends AbstractWebModuleBuilder
0121: implements GBeanLifecycle {
0122: private final static Log log = LogFactory
0123: .getLog(JettyModuleBuilder.class);
0124: private static final Map<String, String> NAMESPACE_UPDATES = new HashMap<String, String>();
0125: static {
0126: NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web",
0127: "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
0128: NAMESPACE_UPDATES.put(
0129: "http://geronimo.apache.org/xml/ns/j2ee/web-1.1",
0130: "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
0131: NAMESPACE_UPDATES.put(
0132: "http://geronimo.apache.org/xml/ns/j2ee/web-1.2",
0133: "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
0134: NAMESPACE_UPDATES.put(
0135: "http://geronimo.apache.org/xml/ns/j2ee/web-2.0",
0136: "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
0137: NAMESPACE_UPDATES
0138: .put("http://geronimo.apache.org/xml/ns/web/jetty",
0139: "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.1");
0140: NAMESPACE_UPDATES
0141: .put(
0142: "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-1.1",
0143: "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.2");
0144: NAMESPACE_UPDATES
0145: .put(
0146: "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-1.2",
0147: "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.2");
0148: NAMESPACE_UPDATES
0149: .put(
0150: "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0",
0151: "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.2");
0152: NAMESPACE_UPDATES
0153: .put(
0154: "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.1",
0155: "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.2");
0156: NAMESPACE_UPDATES
0157: .put(
0158: "http://geronimo.apache.org/xml/ns/web/jetty/config",
0159: "http://geronimo.apache.org/xml/ns/web/jetty/config-1.0.1");
0160: NAMESPACE_UPDATES
0161: .put(
0162: "http://geronimo.apache.org/xml/ns/web/jetty/config-1.0",
0163: "http://geronimo.apache.org/xml/ns/web/jetty/config-1.0.1");
0164: }
0165:
0166: private final Environment defaultEnvironment;
0167: private final AbstractNameQuery jettyContainerObjectName;
0168: private final JettyJspServletHolder jspServlet;
0169: private final Collection defaultServlets;
0170: private final Collection defaultFilters;
0171: private final Collection defaultFilterMappings;
0172: private final GBeanData pojoWebServiceTemplate;
0173:
0174: protected final NamespaceDrivenBuilderCollection clusteringBuilders;
0175:
0176: private final List<String> defaultWelcomeFiles;
0177: private final Integer defaultSessionTimeoutSeconds;
0178: private final Map<String, String> defaultLocaleEncodingMappings;
0179: private final Map<String, String> defaultMimeTypeMappings;
0180:
0181: private static final String JETTY_NAMESPACE = JettyWebAppDocument.type
0182: .getDocumentElementName().getNamespaceURI();
0183:
0184: public JettyModuleBuilder(Environment defaultEnvironment,
0185: Integer defaultSessionTimeoutSeconds,
0186: List<String> defaultWelcomeFiles,
0187: AbstractNameQuery jettyContainerName,
0188: JettyJspServletHolder jspServlet,
0189: Collection defaultServlets, Collection defaultFilters,
0190: Collection defaultFilterMappings,
0191: Map<String, String> defaultLocaleEncodingMappings,
0192: Map<String, String> defaultMimeTypeMappings,
0193: Object pojoWebServiceTemplate,
0194: Collection<WebServiceBuilder> webServiceBuilder,
0195: Collection clusteringBuilders, Collection securityBuilders,
0196: Collection serviceBuilders, NamingBuilder namingBuilders,
0197: Collection<ModuleBuilderExtension> moduleBuilderExtensions,
0198: ResourceEnvironmentSetter resourceEnvironmentSetter,
0199: Kernel kernel) throws GBeanNotFoundException {
0200: super (kernel, securityBuilders, serviceBuilders,
0201: namingBuilders, resourceEnvironmentSetter,
0202: webServiceBuilder, moduleBuilderExtensions);
0203: this .defaultEnvironment = defaultEnvironment;
0204: this .defaultSessionTimeoutSeconds = (defaultSessionTimeoutSeconds == null) ? 30 * 60
0205: : defaultSessionTimeoutSeconds;
0206: this .jettyContainerObjectName = jettyContainerName;
0207: this .jspServlet = jspServlet;
0208: this .defaultServlets = defaultServlets;
0209: this .defaultFilters = defaultFilters;
0210: this .defaultFilterMappings = defaultFilterMappings;
0211: this .pojoWebServiceTemplate = getGBeanData(kernel,
0212: pojoWebServiceTemplate);
0213: this .clusteringBuilders = new NamespaceDrivenBuilderCollection(
0214: clusteringBuilders, GerClusteringDocument.type
0215: .getDocumentElementName());
0216:
0217: this .defaultWelcomeFiles = defaultWelcomeFiles == null ? new ArrayList<String>()
0218: : defaultWelcomeFiles;
0219: this .defaultLocaleEncodingMappings = defaultLocaleEncodingMappings == null ? new HashMap<String, String>()
0220: : defaultLocaleEncodingMappings;
0221: this .defaultMimeTypeMappings = defaultMimeTypeMappings == null ? new HashMap<String, String>()
0222: : defaultMimeTypeMappings;
0223: }
0224:
0225: public void doStart() throws Exception {
0226: XmlBeansUtil.registerNamespaceUpdates(NAMESPACE_UPDATES);
0227: }
0228:
0229: public void doStop() {
0230: XmlBeansUtil.unregisterNamespaceUpdates(NAMESPACE_UPDATES);
0231: }
0232:
0233: public void doFail() {
0234: doStop();
0235: }
0236:
0237: private static GBeanData getGBeanData(Kernel kernel, Object template)
0238: throws GBeanNotFoundException {
0239: if (template == null) {
0240: return null;
0241: }
0242: AbstractName templateName = kernel.getAbstractNameFor(template);
0243: return kernel.getGBeanData(templateName);
0244: }
0245:
0246: protected Module createModule(Object plan, JarFile moduleFile,
0247: String targetPath, URL specDDUrl, boolean standAlone,
0248: String contextRoot, AbstractName earName, Naming naming,
0249: ModuleIDBuilder idBuilder) throws DeploymentException {
0250: assert moduleFile != null : "moduleFile is null";
0251: assert targetPath != null : "targetPath is null";
0252: assert !targetPath.endsWith("/") : "targetPath must not end with a '/'";
0253:
0254: // parse the spec dd
0255: String specDD = null;
0256: WebAppType webApp = null;
0257: try {
0258: if (specDDUrl == null) {
0259: specDDUrl = DeploymentUtil.createJarURL(moduleFile,
0260: "WEB-INF/web.xml");
0261: }
0262:
0263: // read in the entire specDD as a string, we need this for getDeploymentDescriptor
0264: // on the J2ee management object
0265: specDD = DeploymentUtil.readAll(specDDUrl);
0266:
0267: // we found web.xml, if it won't parse that's an error.
0268: XmlObject parsed = XmlBeansUtil.parse(specDD);
0269: WebAppDocument webAppDoc = convertToServletSchema(parsed);
0270: webApp = webAppDoc.getWebApp();
0271: check(webApp);
0272: } catch (XmlException e) {
0273: // Output the target path in the error to make it clearer to the user which webapp
0274: // has the problem. The targetPath is used, as moduleFile may have an unhelpful
0275: // value such as C:\geronimo-1.1\var\temp\geronimo-deploymentUtil22826.tmpdir
0276: throw new DeploymentException("Error parsing web.xml for "
0277: + targetPath, e);
0278: } catch (Exception e) {
0279: if (!moduleFile.getName().endsWith(".war")) {
0280: //not for us
0281: return null;
0282: }
0283: //else ignore as jee5 allows optional spec dd for .war's
0284: }
0285:
0286: if (webApp == null) {
0287: webApp = WebAppType.Factory.newInstance();
0288: }
0289:
0290: // parse vendor dd
0291: JettyWebAppType jettyWebApp = getJettyWebApp(plan, moduleFile,
0292: standAlone, targetPath, webApp);
0293: contextRoot = getContextRoot(jettyWebApp, contextRoot, webApp,
0294: standAlone, moduleFile, targetPath);
0295:
0296: EnvironmentType environmentType = jettyWebApp.getEnvironment();
0297: Environment environment = EnvironmentBuilder.buildEnvironment(
0298: environmentType, defaultEnvironment);
0299:
0300: Boolean distributable = webApp.getDistributableArray().length == 1 ? TRUE
0301: : FALSE;
0302: if (TRUE == distributable) {
0303: clusteringBuilders.buildEnvironment(jettyWebApp,
0304: environment);
0305: }
0306:
0307: // Note: logic elsewhere depends on the default artifact ID being the file name less extension (ConfigIDExtractor)
0308: String warName = new File(moduleFile.getName()).getName();
0309: if (warName.lastIndexOf('.') > -1) {
0310: warName = warName.substring(0, warName.lastIndexOf('.'));
0311: }
0312: idBuilder.resolve(environment, warName, "war");
0313:
0314: AbstractName moduleName;
0315: if (earName == null) {
0316: earName = naming.createRootName(environment.getConfigId(),
0317: NameFactory.NULL, NameFactory.J2EE_APPLICATION);
0318: moduleName = naming.createChildName(earName, environment
0319: .getConfigId().toString(), NameFactory.WEB_MODULE);
0320: } else {
0321: moduleName = naming.createChildName(earName, targetPath,
0322: NameFactory.WEB_MODULE);
0323: }
0324:
0325: // Create the AnnotatedApp interface for the WebModule
0326: AnnotatedWebApp annotatedWebApp = new AnnotatedWebApp(webApp);
0327:
0328: WebModule module = new WebModule(standAlone, moduleName,
0329: environment, moduleFile, targetPath, webApp,
0330: jettyWebApp, specDD, contextRoot, JETTY_NAMESPACE,
0331: annotatedWebApp);
0332:
0333: for (ModuleBuilderExtension mbe : moduleBuilderExtensions) {
0334: mbe.createModule(module, plan, moduleFile, targetPath,
0335: specDDUrl, environment, contextRoot, earName,
0336: naming, idBuilder);
0337: }
0338: return module;
0339: }
0340:
0341: String getContextRoot(JettyWebAppType jettyWebApp,
0342: String contextRoot, WebAppType webApp, boolean standAlone,
0343: JarFile moduleFile, String targetPath) {
0344: if (jettyWebApp.isSetContextRoot()) {
0345: contextRoot = jettyWebApp.getContextRoot();
0346: } else if (contextRoot == null || contextRoot.trim().equals("")) {
0347: contextRoot = determineDefaultContextRoot(webApp,
0348: standAlone, moduleFile, targetPath);
0349: }
0350:
0351: contextRoot = contextRoot.trim();
0352: return contextRoot;
0353: }
0354:
0355: JettyWebAppType getJettyWebApp(Object plan, JarFile moduleFile,
0356: boolean standAlone, String targetPath, WebAppType webApp)
0357: throws DeploymentException {
0358: XmlObject rawPlan = null;
0359: try {
0360: // load the geronimo-web.xml from either the supplied plan or from the earFile
0361: try {
0362: if (plan instanceof XmlObject) {
0363: rawPlan = (XmlObject) plan;
0364: } else {
0365: if (plan != null) {
0366: rawPlan = XmlBeansUtil.parse(((File) plan)
0367: .toURL(), getClass().getClassLoader());
0368: } else {
0369: URL path = DeploymentUtil.createJarURL(
0370: moduleFile, "WEB-INF/geronimo-web.xml");
0371: try {
0372: rawPlan = XmlBeansUtil.parse(path,
0373: getClass().getClassLoader());
0374: } catch (FileNotFoundException e) {
0375: path = DeploymentUtil.createJarURL(
0376: moduleFile,
0377: "WEB-INF/geronimo-jetty.xml");
0378: try {
0379: rawPlan = XmlBeansUtil.parse(path,
0380: getClass().getClassLoader());
0381: } catch (FileNotFoundException e1) {
0382: log
0383: .warn("Web application "
0384: + targetPath
0385: + " 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.");
0386: }
0387: }
0388: }
0389: }
0390: } catch (IOException e) {
0391: log.warn(e);
0392: }
0393:
0394: JettyWebAppType jettyWebApp;
0395: if (rawPlan != null) {
0396: XmlObject webPlan = new GenericToSpecificPlanConverter(
0397: GerJettyDocument.type.getDocumentElementName()
0398: .getNamespaceURI(),
0399: JettyWebAppDocument.type
0400: .getDocumentElementName()
0401: .getNamespaceURI(), "jetty")
0402: .convertToSpecificPlan(rawPlan);
0403: jettyWebApp = (JettyWebAppType) webPlan
0404: .changeType(JettyWebAppType.type);
0405: XmlBeansUtil.validateDD(jettyWebApp);
0406: } else {
0407: jettyWebApp = createDefaultPlan();
0408: }
0409: return jettyWebApp;
0410: } catch (XmlException e) {
0411: throw new DeploymentException("xml problem for web app "
0412: + targetPath, e);
0413: }
0414: }
0415:
0416: private JettyWebAppType createDefaultPlan() {
0417: return JettyWebAppType.Factory.newInstance();
0418: }
0419:
0420: public void initContext(EARContext earContext, Module module,
0421: ClassLoader cl) throws DeploymentException {
0422: JettyWebAppType gerWebApp = (JettyWebAppType) module
0423: .getVendorDD();
0424: boolean hasSecurityRealmName = gerWebApp
0425: .isSetSecurityRealmName();
0426: basicInitContext(earContext, module, gerWebApp,
0427: hasSecurityRealmName);
0428: for (ModuleBuilderExtension mbe : moduleBuilderExtensions) {
0429: mbe.initContext(earContext, module, cl);
0430: }
0431: }
0432:
0433: public void addGBeans(EARContext earContext, Module module,
0434: ClassLoader cl, Collection repository)
0435: throws DeploymentException {
0436: EARContext moduleContext = module.getEarContext();
0437: AbstractName moduleName = moduleContext.getModuleName();
0438: WebModule webModule = (WebModule) module;
0439:
0440: WebAppType webApp = (WebAppType) webModule.getSpecDD();
0441: JettyWebAppType jettyWebApp = (JettyWebAppType) webModule
0442: .getVendorDD();
0443: GBeanData webModuleData = new GBeanData(moduleName,
0444: JettyWebAppContext.GBEAN_INFO);
0445:
0446: configureBasicWebModuleAttributes(webApp, jettyWebApp,
0447: moduleContext, earContext, webModule, webModuleData);
0448:
0449: // unsharableResources, applicationManagedSecurityResources
0450: GBeanResourceEnvironmentBuilder rebuilder = new GBeanResourceEnvironmentBuilder(
0451: webModuleData);
0452: //N.B. use earContext not moduleContext
0453: //TODO fix this for javaee 5 !!!
0454: resourceEnvironmentSetter.setResourceEnvironment(rebuilder,
0455: webApp.getResourceRefArray(), jettyWebApp
0456: .getResourceRefArray());
0457: try {
0458: moduleContext.addGBean(webModuleData);
0459: Set<String> securityRoles = collectRoleNames(webApp);
0460: Map<String, PermissionCollection> rolePermissions = new HashMap<String, PermissionCollection>();
0461:
0462: // configure hosts and virtual-hosts
0463: configureHosts(earContext, jettyWebApp, webModuleData);
0464:
0465: String contextPath = webModule.getContextRoot();
0466: if (contextPath == null) {
0467: throw new DeploymentException("null contextPath");
0468: }
0469: if (!contextPath.startsWith("/")) {
0470: contextPath = "/" + contextPath;
0471: }
0472: webModuleData.setAttribute("contextPath", contextPath);
0473:
0474: if (jettyWebApp.isSetWorkDir()) {
0475: String workDir = jettyWebApp.getWorkDir();
0476: webModuleData.setAttribute("workDir", workDir);
0477: }
0478:
0479: if (jettyWebApp.isSetWebContainer()) {
0480: AbstractNameQuery webContainerName = ENCConfigBuilder
0481: .getGBeanQuery(NameFactory.GERONIMO_SERVICE,
0482: jettyWebApp.getWebContainer());
0483: webModuleData.setReferencePattern("JettyContainer",
0484: webContainerName);
0485: } else {
0486: webModuleData.setReferencePattern("JettyContainer",
0487: jettyContainerObjectName);
0488: }
0489: //stuff that jetty used to do
0490: if (webApp.getDisplayNameArray().length > 0) {
0491: webModuleData.setAttribute("displayName", webApp
0492: .getDisplayNameArray()[0].getStringValue());
0493: }
0494:
0495: // configure context parameters.
0496: configureContextParams(webApp, webModuleData);
0497:
0498: // configure listeners.
0499: configureListeners(webApp, webModuleData);
0500:
0501: webModuleData
0502: .setAttribute(
0503: JettyWebAppContext.GBEAN_ATTR_SESSION_TIMEOUT,
0504: (webApp.getSessionConfigArray().length == 1 && webApp
0505: .getSessionConfigArray(0)
0506: .getSessionTimeout() != null) ? webApp
0507: .getSessionConfigArray(0)
0508: .getSessionTimeout()
0509: .getBigIntegerValue().intValue() * 60
0510: : defaultSessionTimeoutSeconds);
0511:
0512: Boolean distributable = webApp.getDistributableArray().length == 1 ? TRUE
0513: : FALSE;
0514: webModuleData.setAttribute("distributable", distributable);
0515: if (TRUE == distributable) {
0516: clusteringBuilders.build(jettyWebApp, earContext,
0517: moduleContext);
0518: if (webModuleData
0519: .getReferencePatterns(JettyWebAppContext.GBEAN_REF_SESSION_HANDLER_FACTORY) == null) {
0520: log
0521: .warn("No clustering builders configured: app will not be clustered");
0522: configureNoClustering(moduleContext, webModuleData);
0523: }
0524: } else {
0525: configureNoClustering(moduleContext, webModuleData);
0526: }
0527:
0528: // configure mime mappings.
0529: configureMimeMappings(webApp, webModuleData);
0530:
0531: // configure welcome file lists.
0532: configureWelcomeFileLists(webApp, webModuleData);
0533:
0534: // configure local encoding mapping lists.
0535: configureLocaleEncodingMappingLists(webApp, webModuleData);
0536:
0537: // configure error pages.
0538: configureErrorPages(webApp, webModuleData);
0539:
0540: // configure tag libs.
0541: Set<String> knownServletMappings = new HashSet<String>();
0542: Map<String, Set<String>> servletMappings = new HashMap<String, Set<String>>();
0543: if (jspServlet != null) {
0544: configureTagLibs(module, webApp, webModuleData,
0545: servletMappings, knownServletMappings,
0546: jspServlet.getServletName());
0547: GBeanData jspServletData = configureDefaultServlet(
0548: jspServlet, earContext, moduleName,
0549: knownServletMappings, moduleContext);
0550: Set<String> jspMappings = (Set<String>) jspServletData
0551: .getAttribute("servletMappings");
0552: jspMappings.addAll(knownServletMappings);
0553: jspServletData.setAttribute("servletMappings",
0554: jspMappings);
0555: }
0556:
0557: // configure login configs.
0558: configureLoginConfigs(module, webApp, jettyWebApp,
0559: webModuleData);
0560:
0561: // Make sure that servlet mappings point to available servlets and never add a duplicate pattern.
0562:
0563: buildServletMappings(module, webApp, servletMappings,
0564: knownServletMappings);
0565:
0566: //"previous" filter mapping for linked list to keep dd's ordering.
0567: AbstractName previous = null;
0568:
0569: //add default filters
0570: if (defaultFilters != null) {
0571: previous = addDefaultFiltersGBeans(earContext,
0572: moduleContext, moduleName, previous);
0573: }
0574:
0575: //add default filtermappings
0576: // if (defaultFilterMappings != null) {
0577: // for (Iterator iterator = defaultFilterMappings.iterator(); iterator.hasNext();) {
0578: // Object defaultFilterMapping = iterator.next();
0579: // GBeanData filterMappingGBeanData = getGBeanData(kernel, defaultFilterMapping);
0580: // String filterName = (String) filterMappingGBeanData.getAttribute("filterName");
0581: // ObjectName defaultFilterMappingObjectName;
0582: // if (filterMappingGBeanData.getAttribute("urlPattern") != null) {
0583: // String urlPattern = (String) filterMappingGBeanData.getAttribute("urlPattern");
0584: // defaultFilterMappingObjectName = NameFactory.getWebFilterMappingName(null, null, null, null, filterName, null, urlPattern, moduleName);
0585: // } else {
0586: // Set servletNames = filterMappingGBeanData.getReferencePatterns("Servlet");
0587: // if (servletNames == null || servletNames.size() != 1) {
0588: // throw new DeploymentException("Exactly one servlet name must be supplied");
0589: // }
0590: // ObjectName servletObjectName = (ObjectName) servletNames.iterator().next();
0591: // String servletName = servletObjectName.getKeyProperty("name");
0592: // defaultFilterMappingObjectName = NameFactory.getWebFilterMappingName(null, null, null, null, filterName, servletName, null, moduleName);
0593: // }
0594: // filterMappingGBeanData.setName(defaultFilterMappingObjectName);
0595: // filterMappingGBeanData.setReferencePattern("JettyFilterMappingRegistration", webModuleName);
0596: // moduleContext.addGBean(filterMappingGBeanData);
0597: // }
0598: // }
0599:
0600: // add filter mapping GBeans.
0601: addFilterMappingsGBeans(earContext, moduleContext,
0602: moduleName, webApp, previous);
0603:
0604: // add filter GBeans.
0605: addFiltersGBeans(earContext, moduleContext, moduleName,
0606: webApp);
0607:
0608: //add default servlets
0609: if (defaultServlets != null) {
0610: addDefaultServletsGBeans(earContext, moduleContext,
0611: moduleName, knownServletMappings);
0612: }
0613:
0614: //set up servlet gbeans.
0615: ServletType[] servletTypes = webApp.getServletArray();
0616: addServlets(moduleName, webModule, servletTypes,
0617: servletMappings, securityRoles, rolePermissions,
0618: moduleContext);
0619:
0620: if (jettyWebApp.isSetSecurityRealmName()) {
0621: configureSecurityRealm(earContext, webApp, jettyWebApp,
0622: webModuleData, securityRoles, rolePermissions);
0623: }
0624:
0625: //See Jetty-386, GERONIMO-3738
0626: if (jettyWebApp.getCompactPath()) {
0627: webModuleData.setAttribute("compactPath", Boolean.TRUE);
0628: }
0629:
0630: //TODO this may definitely not be the best place for this!
0631: for (ModuleBuilderExtension mbe : moduleBuilderExtensions) {
0632: mbe.addGBeans(earContext, module, cl, repository);
0633: }
0634:
0635: //not truly metadata complete until MBEs have run
0636: if (!webApp.getMetadataComplete()) {
0637: webApp.setMetadataComplete(true);
0638: module.setOriginalSpecDD(module.getSpecDD().toString());
0639: webModuleData.setAttribute("deploymentDescriptor",
0640: module.getOriginalSpecDD());
0641: }
0642:
0643: if (!module.isStandAlone()) {
0644: ConfigurationData moduleConfigurationData = moduleContext
0645: .getConfigurationData();
0646: earContext
0647: .addChildConfiguration(module.getTargetPath(),
0648: moduleConfigurationData);
0649: }
0650: } catch (DeploymentException de) {
0651: throw de;
0652: } catch (Exception e) {
0653: throw new DeploymentException(
0654: "Unable to initialize webapp GBean for "
0655: + module.getName(), e);
0656: }
0657:
0658: }
0659:
0660: private void configureNoClustering(EARContext moduleContext,
0661: GBeanData webModuleData) throws GBeanAlreadyExistsException {
0662: // AbstractName name = moduleContext.getNaming().createChildName(moduleContext.getModuleName(),
0663: // "DefaultWebApplicationHandlerFactory",
0664: // NameFactory.GERONIMO_SERVICE);
0665: // GBeanData beanData = new GBeanData(name, DefaultWebApplicationHandlerFactory.GBEAN_INFO);
0666: // webModuleData.setReferencePattern(JettyWebAppContext.GBEAN_REF_WEB_APPLICATION_HANDLER_FACTORY, name);
0667: // moduleContext.addGBean(beanData);
0668: }
0669:
0670: private void configureSecurityRealm(EARContext earContext,
0671: WebAppType webApp, JettyWebAppType jettyWebApp,
0672: GBeanData webModuleData, Set<String> securityRoles,
0673: Map<String, PermissionCollection> rolePermissions)
0674: throws DeploymentException {
0675: AbstractName moduleName = webModuleData.getAbstractName();
0676: if (earContext.getSecurityConfiguration() == null) {
0677: throw new DeploymentException(
0678: "You have specified a <security-realm-name> for the webapp "
0679: + moduleName
0680: + " 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)");
0681: }
0682: String securityRealmName = jettyWebApp.getSecurityRealmName()
0683: .trim();
0684: webModuleData.setAttribute("securityRealmName",
0685: securityRealmName);
0686: webModuleData.setReferencePattern("RunAsSource", earContext
0687: .getJaccManagerName());
0688:
0689: /**
0690: * TODO - go back to commented version when possible.
0691: */
0692: String policyContextID = moduleName.toString().replaceAll(
0693: "[, :]", "_");
0694: //String policyContextID = webModuleName.getCanonicalName();
0695: webModuleData.setAttribute("policyContextID", policyContextID);
0696:
0697: ComponentPermissions componentPermissions = buildSpecSecurityConfig(
0698: webApp, securityRoles, rolePermissions);
0699:
0700: earContext.addSecurityContext(policyContextID,
0701: componentPermissions);
0702: }
0703:
0704: private void addDefaultServletsGBeans(EARContext earContext,
0705: EARContext moduleContext, AbstractName moduleName,
0706: Set knownServletMappings) throws GBeanNotFoundException,
0707: GBeanAlreadyExistsException {
0708: for (Object defaultServlet : defaultServlets) {
0709: configureDefaultServlet(defaultServlet, earContext,
0710: moduleName, knownServletMappings, moduleContext);
0711: }
0712: }
0713:
0714: private GBeanData configureDefaultServlet(Object defaultServlet,
0715: EARContext earContext, AbstractName moduleName,
0716: Set knownServletMappings, EARContext moduleContext)
0717: throws GBeanNotFoundException, GBeanAlreadyExistsException {
0718: GBeanData servletGBeanData = getGBeanData(kernel,
0719: defaultServlet);
0720: AbstractName defaultServletObjectName = earContext.getNaming()
0721: .createChildName(
0722: moduleName,
0723: (String) servletGBeanData
0724: .getAttribute("servletName"),
0725: NameFactory.SERVLET);
0726: servletGBeanData.setAbstractName(defaultServletObjectName);
0727: servletGBeanData.setReferencePattern(
0728: "JettyServletRegistration", moduleName);
0729: Set<String> defaultServletMappings = new HashSet<String>(
0730: (Collection<String>) servletGBeanData
0731: .getAttribute("servletMappings"));
0732: defaultServletMappings.removeAll(knownServletMappings);
0733: servletGBeanData.setAttribute("servletMappings",
0734: defaultServletMappings);
0735: moduleContext.addGBean(servletGBeanData);
0736: return servletGBeanData;
0737: }
0738:
0739: private void addFiltersGBeans(EARContext earContext,
0740: EARContext moduleContext, AbstractName moduleName,
0741: WebAppType webApp) throws GBeanAlreadyExistsException {
0742: FilterType[] filterArray = webApp.getFilterArray();
0743: for (FilterType filterType : filterArray) {
0744: String filterName = filterType.getFilterName()
0745: .getStringValue().trim();
0746: AbstractName filterAbstractName = earContext.getNaming()
0747: .createChildName(moduleName, filterName,
0748: NameFactory.WEB_FILTER);
0749: GBeanData filterData = new GBeanData(filterAbstractName,
0750: JettyFilterHolder.GBEAN_INFO);
0751: filterData.setAttribute("filterName", filterName);
0752: filterData.setAttribute("filterClass", filterType
0753: .getFilterClass().getStringValue().trim());
0754: Map<String, String> initParams = new HashMap<String, String>();
0755: ParamValueType[] initParamArray = filterType
0756: .getInitParamArray();
0757: for (ParamValueType paramValueType : initParamArray) {
0758: initParams.put(paramValueType.getParamName()
0759: .getStringValue().trim(), paramValueType
0760: .getParamValue().getStringValue().trim());
0761: }
0762: filterData.setAttribute("initParams", initParams);
0763: filterData.setReferencePattern("JettyServletRegistration",
0764: moduleName);
0765: moduleContext.addGBean(filterData);
0766: }
0767: }
0768:
0769: private void addFilterMappingsGBeans(EARContext earContext,
0770: EARContext moduleContext, AbstractName moduleName,
0771: WebAppType webApp, AbstractName previous)
0772: throws GBeanAlreadyExistsException {
0773: FilterMappingType[] filterMappingArray = webApp
0774: .getFilterMappingArray();
0775: for (FilterMappingType filterMappingType : filterMappingArray) {
0776: String filterName = filterMappingType.getFilterName()
0777: .getStringValue().trim();
0778: GBeanData filterMappingData = new GBeanData(
0779: JettyFilterMapping.GBEAN_INFO);
0780: if (previous != null) {
0781: filterMappingData.addDependency(previous);
0782: }
0783: filterMappingData.setReferencePattern(
0784: "JettyServletRegistration", moduleName);
0785: AbstractName filterAbstractName = earContext.getNaming()
0786: .createChildName(moduleName, filterName,
0787: NameFactory.WEB_FILTER);
0788:
0789: AbstractName filterMappingName = null;
0790: if (filterMappingType.sizeOfUrlPatternArray() > 0) {
0791: String[] urlPatterns = new String[filterMappingType
0792: .sizeOfUrlPatternArray()];
0793: for (int j = 0; j < urlPatterns.length; j++) {
0794: urlPatterns[j] = filterMappingType
0795: .getUrlPatternArray(j).getStringValue()
0796: .trim();
0797: }
0798:
0799: filterMappingData.setAttribute("urlPatterns",
0800: urlPatterns);
0801: filterMappingName = earContext.getNaming()
0802: .createChildName(
0803: filterAbstractName,
0804: ObjectName.quote(Arrays
0805: .deepToString(urlPatterns)),
0806: NameFactory.URL_WEB_FILTER_MAPPING);
0807: }
0808: if (filterMappingType.sizeOfServletNameArray() > 0) {
0809: Set<AbstractName> servletNameSet = new HashSet<AbstractName>();
0810: for (int j = 0; j < filterMappingType
0811: .sizeOfServletNameArray(); j++) {
0812: String servletName = filterMappingType
0813: .getServletNameArray(j).getStringValue()
0814: .trim();
0815: AbstractName abstractServletName = earContext
0816: .getNaming().createChildName(moduleName,
0817: servletName, NameFactory.SERVLET);
0818: servletNameSet.add(abstractServletName);
0819: filterMappingData
0820: .addDependency(abstractServletName);
0821: }
0822:
0823: filterMappingData.setReferencePatterns("Servlets",
0824: servletNameSet);
0825: filterMappingName = earContext.getNaming()
0826: .createChildName(
0827: filterAbstractName,
0828: ObjectName.quote(Arrays
0829: .deepToString(servletNameSet
0830: .toArray())),
0831: NameFactory.SERVLET_WEB_FILTER_MAPPING);
0832:
0833: }
0834: filterMappingData.setAbstractName(filterMappingName);
0835: previous = filterMappingName;
0836:
0837: boolean request = filterMappingType.getDispatcherArray().length == 0;
0838: boolean forward = false;
0839: boolean include = false;
0840: boolean error = false;
0841: for (int j = 0; j < filterMappingType.getDispatcherArray().length; j++) {
0842: DispatcherType dispatcherType = filterMappingType
0843: .getDispatcherArray()[j];
0844: if (dispatcherType.getStringValue().equals("REQUEST")) {
0845: request = true;
0846: } else if (dispatcherType.getStringValue().equals(
0847: "FORWARD")) {
0848: forward = true;
0849: } else if (dispatcherType.getStringValue().equals(
0850: "INCLUDE")) {
0851: include = true;
0852: } else if (dispatcherType.getStringValue().equals(
0853: "ERROR")) {
0854: error = true;
0855: }
0856: }
0857: filterMappingData.setAttribute("requestDispatch", request);
0858: filterMappingData.setAttribute("forwardDispatch", forward);
0859: filterMappingData.setAttribute("includeDispatch", include);
0860: filterMappingData.setAttribute("errorDispatch", error);
0861: filterMappingData.setReferencePattern("Filter",
0862: filterAbstractName);
0863: moduleContext.addGBean(filterMappingData);
0864: }
0865: }
0866:
0867: private AbstractName addDefaultFiltersGBeans(EARContext earContext,
0868: EARContext moduleContext, AbstractName moduleName,
0869: AbstractName previous) throws GBeanNotFoundException,
0870: GBeanAlreadyExistsException {
0871: for (Object defaultFilter : defaultFilters) {
0872: GBeanData filterGBeanData = getGBeanData(kernel,
0873: defaultFilter);
0874: String filterName = (String) filterGBeanData
0875: .getAttribute("filterName");
0876: AbstractName defaultFilterAbstractName = earContext
0877: .getNaming().createChildName(moduleName,
0878: filterName, NameFactory.WEB_FILTER);
0879: filterGBeanData.setAbstractName(defaultFilterAbstractName);
0880: filterGBeanData.setReferencePattern(
0881: "JettyServletRegistration", moduleName);
0882: moduleContext.addGBean(filterGBeanData);
0883: //add a mapping to /*
0884:
0885: GBeanData filterMappingGBeanData = new GBeanData(
0886: JettyFilterMapping.GBEAN_INFO);
0887: if (previous != null) {
0888: filterMappingGBeanData.addDependency(previous);
0889: }
0890: filterMappingGBeanData.setReferencePattern(
0891: "JettyServletRegistration", moduleName);
0892: String urlPattern = "/*";
0893: filterMappingGBeanData.setAttribute("urlPattern",
0894: urlPattern);
0895: AbstractName filterMappingName = earContext.getNaming()
0896: .createChildName(defaultFilterAbstractName,
0897: urlPattern,
0898: NameFactory.URL_WEB_FILTER_MAPPING);
0899: filterMappingGBeanData.setAbstractName(filterMappingName);
0900: previous = filterMappingName;
0901:
0902: filterMappingGBeanData
0903: .setAttribute("requestDispatch", TRUE);
0904: filterMappingGBeanData
0905: .setAttribute("forwardDispatch", TRUE);
0906: filterMappingGBeanData
0907: .setAttribute("includeDispatch", TRUE);
0908: filterMappingGBeanData.setAttribute("errorDispatch", FALSE);
0909: filterMappingGBeanData.setReferencePattern("Filter",
0910: defaultFilterAbstractName);
0911: moduleContext.addGBean(filterMappingGBeanData);
0912: }
0913: return previous;
0914: }
0915:
0916: private Map buildServletMappings(Module module, WebAppType webApp,
0917: Map<String, Set<String>> servletMappings,
0918: Set<String> knownServletMappings)
0919: throws DeploymentException {
0920: ServletType[] servletTypes = webApp.getServletArray();
0921: Set<String> knownServlets = new HashSet<String>();
0922: for (ServletType type : servletTypes) {
0923: knownServlets.add(type.getServletName().getStringValue()
0924: .trim());
0925: }
0926:
0927: ServletMappingType[] servletMappingArray = webApp
0928: .getServletMappingArray();
0929: for (ServletMappingType servletMappingType : servletMappingArray) {
0930: String servletName = servletMappingType.getServletName()
0931: .getStringValue().trim();
0932: if (!knownServlets.contains(servletName)) {
0933: throw new DeploymentException(
0934: "Web app "
0935: + module.getName()
0936: + " contains a servlet mapping that refers to servlet '"
0937: + servletName
0938: + "' but no such servlet was found!");
0939: }
0940: UrlPatternType[] urlPatterns = servletMappingType
0941: .getUrlPatternArray();
0942: addMappingsForServlet(servletName, urlPatterns,
0943: knownServletMappings, servletMappings);
0944: }
0945:
0946: return servletMappings;
0947: }
0948:
0949: private void addMappingsForServlet(String servletName,
0950: UrlPatternType[] urlPatterns,
0951: Set<String> knownServletMappings,
0952: Map<String, Set<String>> servletMappings)
0953: throws DeploymentException {
0954: for (UrlPatternType patternType : urlPatterns) {
0955: String urlPattern = patternType.getStringValue().trim();
0956: if (!urlPattern.startsWith("*")
0957: && !urlPattern.startsWith("/")) {
0958: urlPattern = "/" + urlPattern;
0959: }
0960: if (!knownServletMappings.contains(urlPattern)) {
0961: knownServletMappings.add(urlPattern);
0962: checkString(urlPattern);
0963: Set<String> urlsForServlet = servletMappings
0964: .get(servletName);
0965: if (urlsForServlet == null) {
0966: urlsForServlet = new HashSet<String>();
0967: servletMappings.put(servletName, urlsForServlet);
0968: }
0969: urlsForServlet.add(urlPattern);
0970: }
0971: }
0972: }
0973:
0974: private void configureLoginConfigs(Module module,
0975: WebAppType webApp, JettyWebAppType jettyWebApp,
0976: GBeanData webModuleData) throws DeploymentException {
0977: LoginConfigType[] loginConfigArray = webApp
0978: .getLoginConfigArray();
0979: if (loginConfigArray.length > 1) {
0980: throw new DeploymentException(
0981: "Web app "
0982: + module.getName()
0983: + " cannot have more than one login-config element. Currently has "
0984: + loginConfigArray.length
0985: + " login-config elements.");
0986: }
0987: if (loginConfigArray.length == 1) {
0988: LoginConfigType loginConfig = loginConfigArray[0];
0989: if (loginConfig.isSetAuthMethod()) {
0990: String authMethod = loginConfig.getAuthMethod()
0991: .getStringValue();
0992: if ("BASIC".equals(authMethod)) {
0993: webModuleData.setAttribute("authenticator",
0994: new BasicAuthenticator());
0995: } else if ("DIGEST".equals(authMethod)) {
0996: webModuleData.setAttribute("authenticator",
0997: new DigestAuthenticator());
0998: } else if ("FORM".equals(authMethod)) {
0999:
1000: FormAuthenticator formAuthenticator = new FormAuthenticator();
1001: webModuleData.setAttribute("authenticator",
1002: formAuthenticator);
1003: if (loginConfig.isSetFormLoginConfig()) {
1004: FormLoginConfigType formLoginConfig = loginConfig
1005: .getFormLoginConfig();
1006: formAuthenticator.setLoginPage(formLoginConfig
1007: .getFormLoginPage().getStringValue());
1008: formAuthenticator.setErrorPage(formLoginConfig
1009: .getFormErrorPage().getStringValue());
1010: }
1011: } else if ("CLIENT-CERT".equals(authMethod)) {
1012: webModuleData.setAttribute("authenticator",
1013: new ClientCertAuthenticator());
1014: }
1015: }
1016: if (loginConfig.isSetRealmName()) {
1017: webModuleData.setAttribute("realmName", loginConfig
1018: .getRealmName().getStringValue());
1019: }
1020:
1021: } else if (jettyWebApp.isSetSecurityRealmName()) {
1022: webModuleData.setAttribute("authenticator",
1023: new NonAuthenticator());
1024: }
1025: }
1026:
1027: private void configureTagLibs(Module module, WebAppType webApp,
1028: GBeanData webModuleData,
1029: Map<String, Set<String>> servletMappings,
1030: Set<String> knownServletMappings, String jspServletName)
1031: throws DeploymentException {
1032: JspConfigType[] jspConfigArray = webApp.getJspConfigArray();
1033: if (jspConfigArray.length > 1) {
1034: throw new DeploymentException(
1035: "Web app "
1036: + module.getName()
1037: + " cannot have more than one jsp-config element. Currently has "
1038: + jspConfigArray.length
1039: + " jsp-config elements.");
1040: }
1041: Map<String, String> tagLibMap = new HashMap<String, String>();
1042: for (JspConfigType aJspConfigArray : jspConfigArray) {
1043: TaglibType[] tagLibArray = aJspConfigArray.getTaglibArray();
1044: for (TaglibType taglib : tagLibArray) {
1045: tagLibMap.put(taglib.getTaglibUri().getStringValue()
1046: .trim(), taglib.getTaglibLocation()
1047: .getStringValue().trim());
1048: }
1049: for (JspPropertyGroupType propertyGroup : aJspConfigArray
1050: .getJspPropertyGroupArray()) {
1051: UrlPatternType[] urlPatterns = propertyGroup
1052: .getUrlPatternArray();
1053: addMappingsForServlet(jspServletName, urlPatterns,
1054: knownServletMappings, servletMappings);
1055: }
1056: }
1057: webModuleData.setAttribute("tagLibMap", tagLibMap);
1058: }
1059:
1060: private void configureErrorPages(WebAppType webApp,
1061: GBeanData webModuleData) {
1062: ErrorPageType[] errorPageArray = webApp.getErrorPageArray();
1063: Map<String, String> errorPageMap = new HashMap<String, String>();
1064: for (ErrorPageType errorPageType : errorPageArray) {
1065: if (errorPageType.isSetErrorCode()) {
1066: errorPageMap.put(errorPageType.getErrorCode()
1067: .getStringValue().trim(), errorPageType
1068: .getLocation().getStringValue().trim());
1069: } else {
1070: errorPageMap.put(errorPageType.getExceptionType()
1071: .getStringValue().trim(), errorPageType
1072: .getLocation().getStringValue().trim());
1073: }
1074: }
1075: webModuleData.setAttribute("errorPages", errorPageMap);
1076: }
1077:
1078: private void configureLocaleEncodingMappingLists(WebAppType webApp,
1079: GBeanData webModuleData) {
1080: LocaleEncodingMappingListType[] localeEncodingMappingListArray = webApp
1081: .getLocaleEncodingMappingListArray();
1082: Map<String, String> localeEncodingMappingMap = new HashMap<String, String>(
1083: defaultLocaleEncodingMappings);
1084: for (LocaleEncodingMappingListType aLocaleEncodingMappingListArray : localeEncodingMappingListArray) {
1085: LocaleEncodingMappingType[] localeEncodingMappingArray = aLocaleEncodingMappingListArray
1086: .getLocaleEncodingMappingArray();
1087: for (LocaleEncodingMappingType localeEncodingMapping : localeEncodingMappingArray) {
1088: localeEncodingMappingMap.put(localeEncodingMapping
1089: .getLocale().trim(), localeEncodingMapping
1090: .getEncoding().trim());
1091: }
1092: }
1093: webModuleData.setAttribute("localeEncodingMapping",
1094: localeEncodingMappingMap);
1095: }
1096:
1097: private void configureWelcomeFileLists(WebAppType webApp,
1098: GBeanData webModuleData) {
1099: WelcomeFileListType[] welcomeFileArray = webApp
1100: .getWelcomeFileListArray();
1101: List<String> welcomeFiles;
1102: if (welcomeFileArray.length > 0) {
1103: welcomeFiles = new ArrayList<String>();
1104: for (WelcomeFileListType aWelcomeFileArray : welcomeFileArray) {
1105: String[] welcomeFileListType = aWelcomeFileArray
1106: .getWelcomeFileArray();
1107: for (String welcomeFile : welcomeFileListType) {
1108: welcomeFiles.add(welcomeFile.trim());
1109: }
1110: }
1111: } else {
1112: welcomeFiles = new ArrayList<String>(defaultWelcomeFiles);
1113: }
1114: webModuleData.setAttribute("welcomeFiles", welcomeFiles
1115: .toArray(new String[welcomeFiles.size()]));
1116: }
1117:
1118: private void configureMimeMappings(WebAppType webApp,
1119: GBeanData webModuleData) {
1120: MimeMappingType[] mimeMappingArray = webApp
1121: .getMimeMappingArray();
1122: Map<String, String> mimeMappingMap = new HashMap<String, String>(
1123: defaultMimeTypeMappings);
1124: for (MimeMappingType mimeMappingType : mimeMappingArray) {
1125: mimeMappingMap.put(mimeMappingType.getExtension()
1126: .getStringValue().trim(), mimeMappingType
1127: .getMimeType().getStringValue().trim());
1128: }
1129: webModuleData.setAttribute("mimeMap", mimeMappingMap);
1130: }
1131:
1132: private void configureListeners(WebAppType webApp,
1133: GBeanData webModuleData) {
1134: ListenerType[] listenerArray = webApp.getListenerArray();
1135: Collection<String> listeners = new ArrayList<String>();
1136: for (ListenerType listenerType : listenerArray) {
1137: listeners.add(listenerType.getListenerClass()
1138: .getStringValue().trim());
1139: }
1140: webModuleData.setAttribute("listenerClassNames", listeners);
1141: }
1142:
1143: private void configureContextParams(WebAppType webApp,
1144: GBeanData webModuleData) {
1145: ParamValueType[] contextParamArray = webApp
1146: .getContextParamArray();
1147: Map<String, String> contextParams = new HashMap<String, String>();
1148: for (ParamValueType contextParam : contextParamArray) {
1149: contextParams.put(contextParam.getParamName()
1150: .getStringValue().trim(), contextParam
1151: .getParamValue().getStringValue().trim());
1152: }
1153: webModuleData.setAttribute("contextParamMap", contextParams);
1154: }
1155:
1156: private void configureHosts(EARContext earContext,
1157: JettyWebAppType jettyWebApp, GBeanData webModuleData)
1158: throws GBeanAlreadyExistsException {
1159: String[] hosts = jettyWebApp.getHostArray();
1160: for (int i = 0; i < hosts.length; i++) {
1161: hosts[i] = hosts[i].trim();
1162: }
1163: String[] virtualHosts = jettyWebApp.getVirtualHostArray();
1164: for (int i = 0; i < virtualHosts.length; i++) {
1165: virtualHosts[i] = virtualHosts[i].trim();
1166: }
1167: if (hosts.length > 0 || virtualHosts.length > 0) {
1168: //use name same as module
1169: AbstractName hostName = earContext.getNaming()
1170: .createChildName(webModuleData.getAbstractName(),
1171: "Host", "Host");
1172: GBeanData hostData = new GBeanData(hostName,
1173: Host.GBEAN_INFO);
1174: hostData.setAttribute("hosts", hosts);
1175: hostData.setAttribute("virtualHosts", virtualHosts);
1176: earContext.addGBean(hostData);
1177: webModuleData.setReferencePattern("Host", hostName);
1178: }
1179: }
1180:
1181: public String getSchemaNamespace() {
1182: return JETTY_NAMESPACE;
1183: }
1184:
1185: /**
1186: * Adds the provided servlets, taking into account the load-on-startup ordering.
1187: *
1188: * @param webModuleName an <code>ObjectName</code> value
1189: * @param module a <code>Module</code> value
1190: * @param servletTypes a <code>ServletType[]</code> value, contains the <code>servlet</code> entries from <code>web.xml</code>.
1191: * @param servletMappings a <code>Map</code> value
1192: * @param securityRoles a <code>Set</code> value
1193: * @param rolePermissions a <code>Map</code> value
1194: * @param moduleContext an <code>EARContext</code> value
1195: * @throws DeploymentException if an error occurs
1196: */
1197: private void addServlets(AbstractName webModuleName, Module module,
1198: ServletType[] servletTypes,
1199: Map<String, Set<String>> servletMappings,
1200: Set<String> securityRoles,
1201: Map<String, PermissionCollection> rolePermissions,
1202: EARContext moduleContext) throws DeploymentException {
1203:
1204: // this TreeSet will order the ServletTypes based on whether
1205: // they have a load-on-startup element and what its value is
1206: TreeSet<ServletType> loadOrder = new TreeSet<ServletType>(
1207: new StartupOrderComparator());
1208:
1209: // add all of the servlets to the sorted set
1210: for (ServletType servletType1 : servletTypes) {
1211: loadOrder.add(servletType1);
1212: }
1213:
1214: // now that they're sorted, read them in order and add them to
1215: // the context. we'll use a GBean reference to enforce the
1216: // load order. Each servlet GBean (except the first) has a
1217: // reference to the previous GBean. The kernel will ensure
1218: // that each "previous" GBean is running before it starts any
1219: // other GBeans that reference it. See also
1220: // o.a.g.jetty6.JettyFilterMapping which provided the example
1221: // of how to do this.
1222: // http://issues.apache.org/jira/browse/GERONIMO-645
1223: AbstractName previousServlet = null;
1224: for (Object aLoadOrder : loadOrder) {
1225: ServletType servletType = (ServletType) aLoadOrder;
1226: previousServlet = addServlet(webModuleName, module,
1227: previousServlet, servletType, servletMappings,
1228: securityRoles, rolePermissions, moduleContext);
1229: }
1230:
1231: // JACC v1.0 secion B.19
1232: addUnmappedJSPPermissions(securityRoles, rolePermissions);
1233: }
1234:
1235: /**
1236: * @param webModuleName AbstractName of the web module
1237: * @param module the web module being added
1238: * @param previousServlet the servlet to start before this one in init order
1239: * @param servletType XMLObject specifying the servlet configuration
1240: * @param servletMappings Map of servlet name to set of ServletMapping strings for this web app
1241: * @param securityRoles security roles in the web app
1242: * @param rolePermissions RolePermissions for the roles this servlet needs to access
1243: * @param moduleContext deployment context for this module
1244: * @return AbstractName of servlet gbean added
1245: * @throws DeploymentException if something goes wrong
1246: */
1247: private AbstractName addServlet(AbstractName webModuleName,
1248: Module module, AbstractName previousServlet,
1249: ServletType servletType,
1250: Map<String, Set<String>> servletMappings,
1251: Set<String> securityRoles,
1252: Map<String, PermissionCollection> rolePermissions,
1253: EARContext moduleContext) throws DeploymentException {
1254: String servletName = servletType.getServletName()
1255: .getStringValue().trim();
1256: AbstractName servletAbstractName = moduleContext.getNaming()
1257: .createChildName(webModuleName, servletName,
1258: NameFactory.SERVLET);
1259: GBeanData servletData;
1260: Map<String, String> initParams = new HashMap<String, String>();
1261: if (servletType.isSetServletClass()) {
1262: ClassLoader webClassLoader = moduleContext.getClassLoader();
1263: String servletClassName = servletType.getServletClass()
1264: .getStringValue().trim();
1265: Class servletClass;
1266: try {
1267: servletClass = webClassLoader
1268: .loadClass(servletClassName);
1269: } catch (ClassNotFoundException e) {
1270: throw new DeploymentException(
1271: "Could not load servlet class "
1272: + servletClassName, e); // TODO identify web app in message
1273: }
1274: Class baseServletClass;
1275: try {
1276: baseServletClass = webClassLoader
1277: .loadClass(Servlet.class.getName());
1278: } catch (ClassNotFoundException e) {
1279: throw new DeploymentException(
1280: "Could not load javax.servlet.Servlet in web classloader",
1281: e); // TODO identify web app in message
1282: }
1283: if (baseServletClass.isAssignableFrom(servletClass)) {
1284: servletData = new GBeanData(servletAbstractName,
1285: JettyServletHolder.GBEAN_INFO);
1286: servletData.setAttribute("servletClass",
1287: servletClassName);
1288: } else {
1289: servletData = new GBeanData(pojoWebServiceTemplate);
1290: servletData.setAbstractName(servletAbstractName);
1291: //let the web service builder deal with configuring the gbean with the web service stack
1292: // Object portInfo = portMap.get(servletName);
1293: // if (portInfo == null) {
1294: // throw new DeploymentException("No web service deployment info for servlet name " + servletName); // TODO identify web app in message
1295: // }
1296: boolean configured = false;
1297: for (Object aWebServiceBuilder : webServiceBuilder) {
1298: WebServiceBuilder serviceBuilder = (WebServiceBuilder) aWebServiceBuilder;
1299: if (serviceBuilder.configurePOJO(servletData,
1300: servletName, module, servletClassName,
1301: moduleContext)) {
1302: configured = true;
1303: break;
1304: }
1305: }
1306: if (!configured) {
1307: throw new DeploymentException(
1308: "POJO web service: "
1309: + servletName
1310: + " not configured by any web service builder");
1311: }
1312: }
1313: } else if (servletType.isSetJspFile()) {
1314: servletData = new GBeanData(servletAbstractName,
1315: JettyServletHolder.GBEAN_INFO);
1316: servletData.setAttribute("jspFile", servletType
1317: .getJspFile().getStringValue().trim());
1318: servletData.setAttribute("servletClass", jspServlet
1319: .getServletClassName());
1320: initParams.put("development", "false");
1321: } else {
1322: throw new DeploymentException(
1323: "Neither servlet class nor jsp file is set for "
1324: + servletName); // TODO identify web app in message
1325: }
1326:
1327: // link to previous servlet, if there is one, so that we
1328: // preserve the <load-on-startup> ordering.
1329: // http://issues.apache.org/jira/browse/GERONIMO-645
1330: if (null != previousServlet) {
1331: servletData.addDependency(previousServlet);
1332: }
1333:
1334: //TODO in init param setter, add classpath if jspFile is not null.
1335: servletData.setReferencePattern("JettyServletRegistration",
1336: webModuleName);
1337: servletData.setAttribute("servletName", servletName);
1338: ParamValueType[] initParamArray = servletType
1339: .getInitParamArray();
1340: for (ParamValueType paramValueType : initParamArray) {
1341: initParams.put(paramValueType.getParamName()
1342: .getStringValue().trim(), paramValueType
1343: .getParamValue().getStringValue().trim());
1344: }
1345: servletData.setAttribute("initParams", initParams);
1346: if (servletType.isSetLoadOnStartup()) {
1347: Integer loadOnStartup = new Integer(servletType
1348: .xgetLoadOnStartup().getStringValue());
1349: servletData.setAttribute("loadOnStartup", loadOnStartup);
1350: }
1351:
1352: Set mappings = servletMappings.get(servletName);
1353: servletData.setAttribute("servletMappings",
1354: mappings == null ? Collections.EMPTY_SET : mappings);
1355:
1356: //run-as
1357: if (servletType.isSetRunAs()) {
1358: String runAsRole = servletType.getRunAs().getRoleName()
1359: .getStringValue().trim();
1360: servletData.setAttribute("runAsRole", runAsRole);
1361: }
1362:
1363: processRoleRefPermissions(servletType, securityRoles,
1364: rolePermissions);
1365:
1366: try {
1367: moduleContext.addGBean(servletData);
1368: } catch (GBeanAlreadyExistsException e) {
1369: throw new DeploymentException(
1370: "Could not add servlet gbean to context", e); // TODO identify web app in message
1371: }
1372: return servletAbstractName;
1373: }
1374:
1375: public static final GBeanInfo GBEAN_INFO;
1376:
1377: static {
1378: GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(
1379: JettyModuleBuilder.class, NameFactory.MODULE_BUILDER);
1380: infoBuilder.addAttribute("defaultEnvironment",
1381: Environment.class, true, true);
1382: infoBuilder.addAttribute("defaultSessionTimeoutSeconds",
1383: Integer.class, true, true);
1384: infoBuilder.addAttribute("defaultWelcomeFiles", List.class,
1385: true, true);
1386: infoBuilder.addAttribute("defaultLocaleEncodingMappings",
1387: Map.class, true, true);
1388: infoBuilder.addAttribute("defaultMimeTypeMappings", Map.class,
1389: true, true);
1390: infoBuilder.addAttribute("jettyContainerObjectName",
1391: AbstractNameQuery.class, true, true);
1392: infoBuilder.addReference("JspServlet",
1393: JettyJspServletHolder.class,
1394: NameFactory.SERVLET_TEMPLATE);
1395: infoBuilder.addReference("DefaultServlets",
1396: JettyDefaultServletHolder.class,
1397: NameFactory.SERVLET_TEMPLATE);
1398: infoBuilder.addReference("DefaultFilters", Object.class);
1399: infoBuilder.addReference("DefaultFilterMappings", Object.class);
1400: infoBuilder.addReference("PojoWebServiceTemplate",
1401: Object.class, NameFactory.SERVLET_WEB_SERVICE_TEMPLATE);
1402: infoBuilder.addReference("WebServiceBuilder",
1403: WebServiceBuilder.class, NameFactory.MODULE_BUILDER);
1404: infoBuilder.addReference("ClusteringBuilders",
1405: NamespaceDrivenBuilder.class,
1406: NameFactory.MODULE_BUILDER);
1407: infoBuilder.addReference("SecurityBuilders",
1408: NamespaceDrivenBuilder.class,
1409: NameFactory.MODULE_BUILDER);
1410: infoBuilder.addReference("ServiceBuilders",
1411: NamespaceDrivenBuilder.class,
1412: NameFactory.MODULE_BUILDER);
1413: infoBuilder.addReference("NamingBuilders", NamingBuilder.class,
1414: NameFactory.MODULE_BUILDER);
1415: infoBuilder.addReference("ModuleBuilderExtensions",
1416: ModuleBuilderExtension.class,
1417: NameFactory.MODULE_BUILDER);
1418: infoBuilder.addReference("ResourceEnvironmentSetter",
1419: ResourceEnvironmentSetter.class,
1420: NameFactory.MODULE_BUILDER);
1421: infoBuilder.addAttribute("kernel", Kernel.class, false);
1422: infoBuilder.addInterface(ModuleBuilder.class);
1423:
1424: infoBuilder.setConstructor(new String[] { "defaultEnvironment",
1425: "defaultSessionTimeoutSeconds", "defaultWelcomeFiles",
1426: "jettyContainerObjectName", "JspServlet",
1427: "DefaultServlets", "DefaultFilters",
1428: "DefaultFilterMappings",
1429: "defaultLocaleEncodingMappings",
1430: "defaultMimeTypeMappings", "PojoWebServiceTemplate",
1431: "WebServiceBuilder", "ClusteringBuilders",
1432: "SecurityBuilders", "ServiceBuilders",
1433: "NamingBuilders", "ModuleBuilderExtensions",
1434: "ResourceEnvironmentSetter", "kernel" });
1435: GBEAN_INFO = infoBuilder.getBeanInfo();
1436: }
1437:
1438: public static GBeanInfo getGBeanInfo() {
1439: return GBEAN_INFO;
1440: }
1441:
1442: static class StartupOrderComparator implements
1443: Comparator<ServletType> {
1444: /**
1445: * comparator that compares first on the basis of startup order, and then on the lexicographical
1446: * ordering of servlet name. Since the servlet names have a uniqueness constraint, this should
1447: * provide a total ordering consistent with equals. All servlets with no startup order are after
1448: * all servlets with a startup order.
1449: *
1450: * @param s1 first ServletType object
1451: * @param s2 second ServletType object
1452: * @return an int < 0 if o1 precedes o2, 0 if they are equal, and > 0 if o2 preceeds o1.
1453: */
1454: public int compare(ServletType s1, ServletType s2) {
1455:
1456: // load-on-startup is set for neither. the
1457: // ordering at this point doesn't matter, but we
1458: // should return "0" only if the two objects say
1459: // they are equal
1460: if (!s1.isSetLoadOnStartup() && !s2.isSetLoadOnStartup()) {
1461: return s1.equals(s2) ? 0 : s1.getServletName()
1462: .getStringValue().trim().compareTo(
1463: s2.getServletName().getStringValue()
1464: .trim());
1465: }
1466:
1467: // load-on-startup is set for one but not the
1468: // other. whichever one is set will be "less
1469: // than", i.e. it will be loaded first
1470: if (s1.isSetLoadOnStartup() && !s2.isSetLoadOnStartup()) {
1471: return -1;
1472: }
1473: if (!s1.isSetLoadOnStartup() && s2.isSetLoadOnStartup()) {
1474: return 1;
1475: }
1476:
1477: // load-on-startup is set for both. whichever one
1478: // has a smaller value is "less than"
1479: int comp = new Integer(s1.xgetLoadOnStartup()
1480: .getStringValue()).compareTo(new Integer(s2
1481: .xgetLoadOnStartup().getStringValue()));
1482: if (comp == 0) {
1483: return s1.getServletName().getStringValue().trim()
1484: .compareTo(
1485: s2.getServletName().getStringValue()
1486: .trim());
1487: }
1488: return comp;
1489: }
1490: }
1491: }
|