001 /** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package org.apache.geronimo.jetty.deployment; 020 021 import java.io.File; 022 import java.io.FileNotFoundException; 023 import java.io.IOException; 024 import java.net.URL; 025 import java.security.Permission; 026 import java.security.PermissionCollection; 027 import java.security.Permissions; 028 import java.util.ArrayList; 029 import java.util.Collection; 030 import java.util.Collections; 031 import java.util.Comparator; 032 import java.util.Enumeration; 033 import java.util.HashMap; 034 import java.util.HashSet; 035 import java.util.Iterator; 036 import java.util.List; 037 import java.util.Map; 038 import java.util.Set; 039 import java.util.TreeSet; 040 import java.util.jar.JarFile; 041 042 import javax.management.ObjectName; 043 import javax.servlet.Servlet; 044 045 import org.apache.commons.logging.Log; 046 import org.apache.commons.logging.LogFactory; 047 import org.apache.geronimo.common.DeploymentException; 048 import org.apache.geronimo.deployment.ModuleIDBuilder; 049 import org.apache.geronimo.deployment.NamespaceDrivenBuilder; 050 import org.apache.geronimo.deployment.NamespaceDrivenBuilderCollection; 051 import org.apache.geronimo.deployment.service.EnvironmentBuilder; 052 import org.apache.geronimo.deployment.util.DeploymentUtil; 053 import org.apache.geronimo.deployment.xbeans.EnvironmentType; 054 import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil; 055 import org.apache.geronimo.gbean.AbstractName; 056 import org.apache.geronimo.gbean.AbstractNameQuery; 057 import org.apache.geronimo.gbean.GBeanData; 058 import org.apache.geronimo.gbean.GBeanInfo; 059 import org.apache.geronimo.gbean.GBeanInfoBuilder; 060 import org.apache.geronimo.gbean.SingleElementCollection; 061 import org.apache.geronimo.j2ee.deployment.EARContext; 062 import org.apache.geronimo.j2ee.deployment.Module; 063 import org.apache.geronimo.j2ee.deployment.ModuleBuilder; 064 import org.apache.geronimo.j2ee.deployment.NamingBuilder; 065 import org.apache.geronimo.j2ee.deployment.WebModule; 066 import org.apache.geronimo.j2ee.deployment.WebServiceBuilder; 067 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 068 import org.apache.geronimo.jetty.DefaultWebApplicationHandlerFactory; 069 import org.apache.geronimo.jetty.Host; 070 import org.apache.geronimo.jetty.JettyDefaultServletHolder; 071 import org.apache.geronimo.jetty.JettyFilterHolder; 072 import org.apache.geronimo.jetty.JettyFilterMapping; 073 import org.apache.geronimo.jetty.JettyServletHolder; 074 import org.apache.geronimo.jetty.JettyWebAppContext; 075 import org.apache.geronimo.jetty.NonAuthenticator; 076 import org.apache.geronimo.kernel.GBeanAlreadyExistsException; 077 import org.apache.geronimo.kernel.GBeanNotFoundException; 078 import org.apache.geronimo.kernel.Kernel; 079 import org.apache.geronimo.kernel.Naming; 080 import org.apache.geronimo.kernel.config.Configuration; 081 import org.apache.geronimo.kernel.config.ConfigurationData; 082 import org.apache.geronimo.kernel.repository.Environment; 083 import org.apache.geronimo.naming.deployment.ENCConfigBuilder; 084 import org.apache.geronimo.naming.deployment.GBeanResourceEnvironmentBuilder; 085 import org.apache.geronimo.naming.deployment.ResourceEnvironmentSetter; 086 import org.apache.geronimo.security.deploy.DefaultPrincipal; 087 import org.apache.geronimo.security.deployment.SecurityConfiguration; 088 import org.apache.geronimo.security.jacc.ComponentPermissions; 089 import org.apache.geronimo.web.deployment.AbstractWebModuleBuilder; 090 import org.apache.geronimo.web.deployment.GenericToSpecificPlanConverter; 091 import org.apache.geronimo.xbeans.geronimo.web.jetty.JettyWebAppDocument; 092 import org.apache.geronimo.xbeans.geronimo.web.jetty.JettyWebAppType; 093 import org.apache.geronimo.xbeans.geronimo.web.jetty.config.GerJettyDocument; 094 import org.apache.geronimo.xbeans.j2ee.DispatcherType; 095 import org.apache.geronimo.xbeans.j2ee.ErrorPageType; 096 import org.apache.geronimo.xbeans.j2ee.FilterMappingType; 097 import org.apache.geronimo.xbeans.j2ee.FilterType; 098 import org.apache.geronimo.xbeans.j2ee.FormLoginConfigType; 099 import org.apache.geronimo.xbeans.j2ee.JspConfigType; 100 import org.apache.geronimo.xbeans.j2ee.ListenerType; 101 import org.apache.geronimo.xbeans.j2ee.LocaleEncodingMappingListType; 102 import org.apache.geronimo.xbeans.j2ee.LocaleEncodingMappingType; 103 import org.apache.geronimo.xbeans.j2ee.LoginConfigType; 104 import org.apache.geronimo.xbeans.j2ee.MimeMappingType; 105 import org.apache.geronimo.xbeans.j2ee.ParamValueType; 106 import org.apache.geronimo.xbeans.j2ee.ServletMappingType; 107 import org.apache.geronimo.xbeans.j2ee.ServletType; 108 import org.apache.geronimo.xbeans.j2ee.TaglibType; 109 import org.apache.geronimo.xbeans.j2ee.WebAppDocument; 110 import org.apache.geronimo.xbeans.j2ee.WebAppType; 111 import org.apache.geronimo.xbeans.j2ee.WelcomeFileListType; 112 import org.apache.xmlbeans.XmlException; 113 import org.apache.xmlbeans.XmlObject; 114 import org.mortbay.http.BasicAuthenticator; 115 import org.mortbay.http.ClientCertAuthenticator; 116 import org.mortbay.http.DigestAuthenticator; 117 import org.mortbay.jetty.servlet.FormAuthenticator; 118 119 120 /** 121 * @version $Rev:385659 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $ 122 */ 123 public class JettyModuleBuilder extends AbstractWebModuleBuilder { 124 private final static Log log = LogFactory.getLog(JettyModuleBuilder.class); 125 private final Environment defaultEnvironment; 126 private final AbstractNameQuery jettyContainerObjectName; 127 private final Collection defaultServlets; 128 private final Collection defaultFilters; 129 private final Collection defaultFilterMappings; 130 private final GBeanData pojoWebServiceTemplate; 131 132 private final SingleElementCollection webServiceBuilder; 133 protected final NamespaceDrivenBuilderCollection clusteringBuilders; 134 135 private final List defaultWelcomeFiles; 136 private final Integer defaultSessionTimeoutSeconds; 137 138 private static final String JETTY_NAMESPACE = JettyWebAppDocument.type.getDocumentElementName().getNamespaceURI(); 139 140 public JettyModuleBuilder(Environment defaultEnvironment, 141 Integer defaultSessionTimeoutSeconds, 142 List defaultWelcomeFiles, 143 AbstractNameQuery jettyContainerName, 144 Collection defaultServlets, 145 Collection defaultFilters, 146 Collection defaultFilterMappings, 147 Object pojoWebServiceTemplate, 148 Collection webServiceBuilder, 149 Collection clusteringBuilders, 150 Collection securityBuilders, 151 Collection serviceBuilders, 152 NamingBuilder namingBuilders, 153 ResourceEnvironmentSetter resourceEnvironmentSetter, 154 Kernel kernel) throws GBeanNotFoundException { 155 super(kernel, securityBuilders, serviceBuilders, namingBuilders, resourceEnvironmentSetter); 156 this.defaultEnvironment = defaultEnvironment; 157 this.defaultSessionTimeoutSeconds = (defaultSessionTimeoutSeconds == null) ? new Integer(30 * 60) : defaultSessionTimeoutSeconds; 158 this.jettyContainerObjectName = jettyContainerName; 159 this.defaultServlets = defaultServlets; 160 this.defaultFilters = defaultFilters; 161 this.defaultFilterMappings = defaultFilterMappings; 162 this.pojoWebServiceTemplate = getGBeanData(kernel, pojoWebServiceTemplate); 163 this.webServiceBuilder = new SingleElementCollection(webServiceBuilder); 164 this.clusteringBuilders = new NamespaceDrivenBuilderCollection(clusteringBuilders); 165 166 //todo locale mappings 167 168 this.defaultWelcomeFiles = defaultWelcomeFiles; 169 } 170 171 private WebServiceBuilder getWebServiceBuilder() { 172 return (WebServiceBuilder) webServiceBuilder.getElement(); 173 } 174 175 private static GBeanData getGBeanData(Kernel kernel, Object template) throws GBeanNotFoundException { 176 if (template == null) { 177 return null; 178 } 179 AbstractName templateName = kernel.getAbstractNameFor(template); 180 return kernel.getGBeanData(templateName); 181 } 182 183 protected Module createModule(Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, boolean standAlone, String contextRoot, AbstractName earName, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException { 184 assert moduleFile != null: "moduleFile is null"; 185 assert targetPath != null: "targetPath is null"; 186 assert !targetPath.endsWith("/"): "targetPath must not end with a '/'"; 187 188 // parse the spec dd 189 String specDD; 190 WebAppType webApp; 191 try { 192 if (specDDUrl == null) { 193 specDDUrl = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/web.xml"); 194 } 195 196 // read in the entire specDD as a string, we need this for getDeploymentDescriptor 197 // on the J2ee management object 198 specDD = DeploymentUtil.readAll(specDDUrl); 199 } catch (Exception e) { 200 //no web.xml, not for us 201 return null; 202 } 203 //we found web.xml, if it won't parse that's an error. 204 try { 205 // parse it 206 XmlObject parsed = XmlBeansUtil.parse(specDD); 207 WebAppDocument webAppDoc = convertToServletSchema(parsed); 208 webApp = webAppDoc.getWebApp(); 209 } catch (XmlException xmle) { 210 // Output the target path in the error to make it clearer to the user which webapp 211 // has the problem. The targetPath is used, as moduleFile may have an unhelpful 212 // value such as C:\geronimo-1.1\var\temp\geronimo-deploymentUtil22826.tmpdir 213 throw new DeploymentException("Error parsing web.xml for " + targetPath, xmle); 214 } 215 check(webApp); 216 217 // parse vendor dd 218 JettyWebAppType jettyWebApp = getJettyWebApp(plan, moduleFile, standAlone, targetPath, webApp); 219 if (contextRoot == null || contextRoot.trim().equals("")) { 220 if (jettyWebApp.isSetContextRoot()) { 221 contextRoot = jettyWebApp.getContextRoot(); 222 } else { 223 contextRoot = determineDefaultContextRoot(webApp, standAlone, moduleFile, targetPath); 224 } 225 } 226 227 contextRoot = contextRoot.trim(); 228 229 EnvironmentType environmentType = jettyWebApp.getEnvironment(); 230 Environment environment = EnvironmentBuilder.buildEnvironment(environmentType, defaultEnvironment); 231 232 Boolean distributable = webApp.getDistributableArray().length == 1 ? Boolean.TRUE : Boolean.FALSE; 233 if (Boolean.TRUE == distributable) { 234 clusteringBuilders.buildEnvironment(jettyWebApp, environment); 235 } 236 237 getNamingBuilders().buildEnvironment(webApp, jettyWebApp, environment); 238 239 // Note: logic elsewhere depends on the default artifact ID being the file name less extension (ConfigIDExtractor) 240 String warName = new File(moduleFile.getName()).getName(); 241 if (warName.lastIndexOf('.') > -1) { 242 warName = warName.substring(0, warName.lastIndexOf('.')); 243 } 244 idBuilder.resolve(environment, warName, "war"); 245 246 Map servletNameToPathMap = buildServletNameToPathMap(webApp, contextRoot); 247 248 Map portMap = getWebServiceBuilder().findWebServices(moduleFile, false, servletNameToPathMap, environment); 249 AbstractName moduleName; 250 if (earName == null) { 251 earName = naming.createRootName(environment.getConfigId(), NameFactory.NULL, NameFactory.J2EE_APPLICATION); 252 moduleName = naming.createChildName(earName, environment.getConfigId().toString(), NameFactory.WEB_MODULE); 253 } else { 254 moduleName = naming.createChildName(earName, targetPath, NameFactory.WEB_MODULE); 255 } 256 257 return new WebModule(standAlone, moduleName, environment, moduleFile, targetPath, webApp, jettyWebApp, specDD, contextRoot, portMap, JETTY_NAMESPACE); 258 } 259 260 JettyWebAppType getJettyWebApp(Object plan, JarFile moduleFile, boolean standAlone, String targetPath, WebAppType webApp) throws DeploymentException { 261 XmlObject rawPlan = null; 262 try { 263 // load the geronimo-web.xml from either the supplied plan or from the earFile 264 try { 265 if (plan instanceof XmlObject) { 266 rawPlan = (XmlObject) plan; 267 } else { 268 if (plan != null) { 269 rawPlan = XmlBeansUtil.parse(((File) plan).toURL(), getClass().getClassLoader()); 270 } else { 271 URL path = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/geronimo-web.xml"); 272 try { 273 rawPlan = XmlBeansUtil.parse(path, getClass().getClassLoader()); 274 } catch (FileNotFoundException e) { 275 path = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/geronimo-jetty.xml"); 276 try { 277 rawPlan = XmlBeansUtil.parse(path, getClass().getClassLoader()); 278 } catch (FileNotFoundException e1) { 279 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."); 280 } 281 } 282 } 283 } 284 } catch (IOException e) { 285 log.warn(e); 286 } 287 288 JettyWebAppType jettyWebApp; 289 if (rawPlan != null) { 290 XmlObject webPlan = new GenericToSpecificPlanConverter(GerJettyDocument.type.getDocumentElementName().getNamespaceURI(), 291 JettyWebAppDocument.type.getDocumentElementName().getNamespaceURI(), "jetty").convertToSpecificPlan(rawPlan); 292 jettyWebApp = (JettyWebAppType) webPlan.changeType(JettyWebAppType.type); 293 XmlBeansUtil.validateDD(jettyWebApp); 294 } else { 295 String defaultContextRoot = determineDefaultContextRoot(webApp, standAlone, moduleFile, targetPath); 296 jettyWebApp = createDefaultPlan(defaultContextRoot); 297 } 298 return jettyWebApp; 299 } catch (XmlException e) { 300 throw new DeploymentException("xml problem for web app " + targetPath, e); 301 } 302 } 303 304 private JettyWebAppType createDefaultPlan(String contextRoot) { 305 JettyWebAppType jettyWebApp = JettyWebAppType.Factory.newInstance(); 306 jettyWebApp.setContextRoot(contextRoot); 307 return jettyWebApp; 308 } 309 310 public void initContext(EARContext earContext, Module module, ClassLoader cl) throws DeploymentException { 311 WebAppType webApp = (WebAppType) module.getSpecDD(); 312 // MessageDestinationType[] messageDestinations = webApp.getMessageDestinationArray(); 313 JettyWebAppType gerWebApp = (JettyWebAppType) module.getVendorDD(); 314 // GerMessageDestinationType[] gerMessageDestinations = gerWebApp.getMessageDestinationArray(); 315 316 // ENCConfigBuilder.registerMessageDestinations(earContext, module.getName(), messageDestinations, gerMessageDestinations); 317 getNamingBuilders().initContext(webApp, gerWebApp, module.getEarContext().getConfiguration(), earContext.getConfiguration(), module); 318 if ((webApp.getSecurityConstraintArray().length > 0 || webApp.getSecurityRoleArray().length > 0) && 319 !gerWebApp.isSetSecurityRealmName()) { 320 throw new DeploymentException("web.xml for web app " + module.getName() + " includes security elements but Geronimo deployment plan is not provided or does not contain <security-realm-name> element necessary to configure security accordingly."); 321 } 322 boolean hasSecurityRealmName = gerWebApp.isSetSecurityRealmName(); 323 buildSubstitutionGroups(gerWebApp, hasSecurityRealmName, module, earContext); 324 } 325 326 public void addGBeans(EARContext earContext, Module module, ClassLoader cl, Collection repository) throws DeploymentException { 327 EARContext moduleContext = module.getEarContext(); 328 AbstractName moduleName = moduleContext.getModuleName(); 329 WebModule webModule = (WebModule) module; 330 331 WebAppType webApp = (WebAppType) webModule.getSpecDD(); 332 JettyWebAppType jettyWebApp = (JettyWebAppType) webModule.getVendorDD(); 333 334 335 GBeanData webModuleData = new GBeanData(moduleName, JettyWebAppContext.GBEAN_INFO); 336 try { 337 moduleContext.addGBean(webModuleData); 338 if (moduleContext.getServerName() != null) { 339 webModuleData.setReferencePattern("J2EEServer", moduleContext.getServerName()); 340 } 341 if (!module.isStandAlone()) { 342 webModuleData.setReferencePattern("J2EEApplication", earContext.getModuleName()); 343 } 344 345 webModuleData.setAttribute("deploymentDescriptor", module.getOriginalSpecDD()); 346 Set securityRoles = collectRoleNames(webApp); 347 Map rolePermissions = new HashMap(); 348 349 // configure hosts and virtual-hosts 350 configureHosts(earContext, jettyWebApp, webModuleData); 351 352 //Add dependencies on managed connection factories and ejbs in this app 353 //This is overkill, but allows for people not using java:comp context (even though we don't support it) 354 //and sidesteps the problem of circular references between ejbs. 355 Set dependencies = findGBeanDependencies(earContext); 356 webModuleData.addDependencies(dependencies); 357 358 //N.B. we use the ear context which has all the gbeans we could possibly be looking up from this ear. 359 Map buildingContext = new HashMap(); 360 buildingContext.put(NamingBuilder.JNDI_KEY, new HashMap()); 361 buildingContext.put(NamingBuilder.GBEAN_NAME_KEY, moduleName); 362 Configuration earConfiguration = earContext.getConfiguration(); 363 getNamingBuilders().buildNaming(webApp, jettyWebApp, earConfiguration, earConfiguration, (Module)webModule, buildingContext); 364 Map compContext = (Map) buildingContext.get(NamingBuilder.JNDI_KEY); 365 366 webModuleData.setAttribute("componentContext", compContext); 367 //classpath may have been augmented with enhanced classes 368 // webModuleData.setAttribute("webClassPath", webModule.getWebClasspath()); 369 // unsharableResources, applicationManagedSecurityResources 370 GBeanResourceEnvironmentBuilder rebuilder = new GBeanResourceEnvironmentBuilder(webModuleData); 371 //N.B. use earContext not moduleContext 372 resourceEnvironmentSetter.setResourceEnvironment(rebuilder, webApp.getResourceRefArray(), jettyWebApp.getResourceRefArray()); 373 374 webModuleData.setAttribute("contextPath", webModule.getContextRoot()); 375 376 webModuleData.setReferencePattern("TransactionManager", moduleContext.getTransactionManagerName()); 377 webModuleData.setReferencePattern("TrackedConnectionAssociator", moduleContext.getConnectionTrackerName()); 378 if (jettyWebApp.isSetWebContainer()) { 379 AbstractNameQuery webContainerName = ENCConfigBuilder.getGBeanQuery(NameFactory.GERONIMO_SERVICE, jettyWebApp.getWebContainer()); 380 webModuleData.setReferencePattern("JettyContainer", webContainerName); 381 } else { 382 webModuleData.setReferencePattern("JettyContainer", jettyContainerObjectName); 383 } 384 //stuff that jetty used to do 385 if (webApp.getDisplayNameArray().length > 0) { 386 webModuleData.setAttribute("displayName", webApp.getDisplayNameArray()[0].getStringValue()); 387 } 388 389 // configure context parameters. 390 configureContextParams(webApp, webModuleData); 391 392 // configure listeners. 393 configureListeners(webApp, webModuleData); 394 395 webModuleData.setAttribute(JettyWebAppContext.GBEAN_ATTR_SESSION_TIMEOUT, 396 (webApp.getSessionConfigArray().length == 1 && webApp.getSessionConfigArray(0).getSessionTimeout() != null) ? 397 new Integer(webApp.getSessionConfigArray(0).getSessionTimeout().getBigIntegerValue().intValue() * 60) : 398 defaultSessionTimeoutSeconds); 399 400 Boolean distributable = webApp.getDistributableArray().length == 1 ? Boolean.TRUE : Boolean.FALSE; 401 webModuleData.setAttribute("distributable", distributable); 402 if (Boolean.TRUE == distributable) { 403 clusteringBuilders.build(jettyWebApp, earContext, moduleContext); 404 if (webModuleData.getReferencePatterns(JettyWebAppContext.GBEAN_REF_WEB_APPLICATION_HANDLER_FACTORY) == null) { 405 log.warn("No clustering builders configured: app will not be clustered"); 406 configureNoClustering(moduleContext, webModuleData); 407 } 408 } else { 409 configureNoClustering(moduleContext, webModuleData); 410 } 411 412 413 // configure mime mappings. 414 configureMimeMappings(webApp, webModuleData); 415 416 // configure welcome file lists. 417 configureWelcomeFileLists(webApp, webModuleData); 418 419 // configure local encoding mapping lists. 420 configureLocalEncodingMappingLists(webApp, webModuleData); 421 422 // configure error pages. 423 configureErrorPages(webApp, webModuleData); 424 425 // configure tag libs. 426 configureTagLibs(module, webApp, webModuleData); 427 428 // configure login configs. 429 configureLoginConfigs(module, webApp, jettyWebApp, webModuleData); 430 431 // Make sure that servlet mappings point to available servlets and never add a duplicate pattern. 432 Set knownServletMappings = new HashSet(); 433 Map servletMappings = new HashMap(); 434 435 buildServletMappings(module, webApp, servletMappings, knownServletMappings); 436 437 //"previous" filter mapping for linked list to keep dd's ordering. 438 AbstractName previous = null; 439 440 //add default filters 441 if (defaultFilters != null) { 442 previous = addDefaultFiltersGBeans(earContext, moduleContext, moduleName, previous); 443 } 444 445 //add default filtermappings 446 // if (defaultFilterMappings != null) { 447 // for (Iterator iterator = defaultFilterMappings.iterator(); iterator.hasNext();) { 448 // Object defaultFilterMapping = iterator.next(); 449 // GBeanData filterMappingGBeanData = getGBeanData(kernel, defaultFilterMapping); 450 // String filterName = (String) filterMappingGBeanData.getAttribute("filterName"); 451 // ObjectName defaultFilterMappingObjectName; 452 // if (filterMappingGBeanData.getAttribute("urlPattern") != null) { 453 // String urlPattern = (String) filterMappingGBeanData.getAttribute("urlPattern"); 454 // defaultFilterMappingObjectName = NameFactory.getWebFilterMappingName(null, null, null, null, filterName, null, urlPattern, moduleName); 455 // } else { 456 // Set servletNames = filterMappingGBeanData.getReferencePatterns("Servlet"); 457 // if (servletNames == null || servletNames.size() != 1) { 458 // throw new DeploymentException("Exactly one servlet name must be supplied"); 459 // } 460 // ObjectName servletObjectName = (ObjectName) servletNames.iterator().next(); 461 // String servletName = servletObjectName.getKeyProperty("name"); 462 // defaultFilterMappingObjectName = NameFactory.getWebFilterMappingName(null, null, null, null, filterName, servletName, null, moduleName); 463 // } 464 // filterMappingGBeanData.setName(defaultFilterMappingObjectName); 465 // filterMappingGBeanData.setReferencePattern("JettyFilterMappingRegistration", webModuleName); 466 // moduleContext.addGBean(filterMappingGBeanData); 467 // } 468 // } 469 470 // add filter mapping GBeans. 471 addFilterMappingsGBeans(earContext, moduleContext, moduleName, webApp, previous); 472 473 // add filter GBeans. 474 addFiltersGBeans(earContext, moduleContext, moduleName, webApp); 475 476 //add default servlets 477 if (defaultServlets != null) { 478 addDefaultServletsGBeans(earContext, moduleContext, moduleName, knownServletMappings); 479 } 480 481 //set up servlet gbeans. 482 Map portMap = webModule.getPortMap(); 483 484 ServletType[] servletTypes = webApp.getServletArray(); 485 addServlets(moduleName, webModule, servletTypes, servletMappings, securityRoles, rolePermissions, portMap, moduleContext); 486 487 if (jettyWebApp.isSetSecurityRealmName()) { 488 configureSecurityRealm(earContext, webApp, jettyWebApp, webModuleData, securityRoles, rolePermissions); 489 } 490 if (!module.isStandAlone()) { 491 ConfigurationData moduleConfigurationData = moduleContext.getConfigurationData(); 492 earContext.addChildConfiguration(module.getTargetPath(), moduleConfigurationData); 493 } 494 } catch (DeploymentException de) { 495 throw de; 496 } catch (Exception e) { 497 throw new DeploymentException("Unable to initialize webapp GBean for " + module.getName(), e); 498 } 499 } 500 501 private void configureNoClustering(EARContext moduleContext, GBeanData webModuleData) throws GBeanAlreadyExistsException { 502 AbstractName name = moduleContext.getNaming().createChildName(moduleContext.getModuleName(), 503 "DefaultWebApplicationHandlerFactory", 504 NameFactory.GERONIMO_SERVICE); 505 GBeanData beanData = new GBeanData(name, DefaultWebApplicationHandlerFactory.GBEAN_INFO); 506 webModuleData.setReferencePattern(JettyWebAppContext.GBEAN_REF_WEB_APPLICATION_HANDLER_FACTORY, name); 507 moduleContext.addGBean(beanData); 508 } 509 510 private void configureSecurityRealm(EARContext earContext, WebAppType webApp, JettyWebAppType jettyWebApp, GBeanData webModuleData, Set securityRoles, Map rolePermissions) throws DeploymentException { 511 AbstractName moduleName = webModuleData.getAbstractName(); 512 if (earContext.getSecurityConfiguration() == null) { 513 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)"); 514 } 515 String securityRealmName = jettyWebApp.getSecurityRealmName().trim(); 516 webModuleData.setAttribute("securityRealmName", securityRealmName); 517 518 /** 519 * TODO - go back to commented version when possible. 520 */ 521 String policyContextID = moduleName.toString().replaceAll("[, :]", "_"); 522 //String policyContextID = webModuleName.getCanonicalName(); 523 webModuleData.setAttribute("policyContextID", policyContextID); 524 525 ComponentPermissions componentPermissions = buildSpecSecurityConfig(webApp, securityRoles, rolePermissions); 526 webModuleData.setAttribute("excludedPermissions", componentPermissions.getExcludedPermissions()); 527 PermissionCollection checkedPermissions = new Permissions(); 528 for (Iterator iterator = rolePermissions.values().iterator(); iterator.hasNext();) { 529 PermissionCollection permissionsForRole = (PermissionCollection) iterator.next(); 530 for (Enumeration iterator2 = permissionsForRole.elements(); iterator2.hasMoreElements();) { 531 Permission permission = (Permission) iterator2.nextElement(); 532 checkedPermissions.add(permission); 533 } 534 } 535 webModuleData.setAttribute("checkedPermissions", checkedPermissions); 536 537 earContext.addSecurityContext(policyContextID, componentPermissions); 538 DefaultPrincipal defaultPrincipal = ((SecurityConfiguration) earContext.getSecurityConfiguration()).getDefaultPrincipal(); 539 webModuleData.setAttribute("defaultPrincipal", defaultPrincipal); 540 } 541 542 private void addDefaultServletsGBeans(EARContext earContext, EARContext moduleContext, AbstractName moduleName, Set knownServletMappings) throws GBeanNotFoundException, GBeanAlreadyExistsException { 543 for (Iterator iterator = defaultServlets.iterator(); iterator.hasNext();) { 544 Object defaultServlet = iterator.next(); 545 GBeanData servletGBeanData = getGBeanData(kernel, defaultServlet); 546 AbstractName defaultServletObjectName = earContext.getNaming().createChildName(moduleName, (String) servletGBeanData.getAttribute("servletName"), NameFactory.SERVLET); 547 servletGBeanData.setAbstractName(defaultServletObjectName); 548 servletGBeanData.setReferencePattern("JettyServletRegistration", moduleName); 549 Set defaultServletMappings = new HashSet((Collection) servletGBeanData.getAttribute("servletMappings")); 550 defaultServletMappings.removeAll(knownServletMappings); 551 servletGBeanData.setAttribute("servletMappings", defaultServletMappings); 552 moduleContext.addGBean(servletGBeanData); 553 } 554 } 555 556 private void addFiltersGBeans(EARContext earContext, EARContext moduleContext, AbstractName moduleName, WebAppType webApp) throws GBeanAlreadyExistsException { 557 FilterType[] filterArray = webApp.getFilterArray(); 558 for (int i = 0; i < filterArray.length; i++) { 559 FilterType filterType = filterArray[i]; 560 String filterName = filterType.getFilterName().getStringValue().trim(); 561 AbstractName filterAbstractName = earContext.getNaming().createChildName(moduleName, filterName, NameFactory.WEB_FILTER); 562 GBeanData filterData = new GBeanData(filterAbstractName, JettyFilterHolder.GBEAN_INFO); 563 filterData.setAttribute("filterName", filterName); 564 filterData.setAttribute("filterClass", filterType.getFilterClass().getStringValue().trim()); 565 Map initParams = new HashMap(); 566 ParamValueType[] initParamArray = filterType.getInitParamArray(); 567 for (int j = 0; j < initParamArray.length; j++) { 568 ParamValueType paramValueType = initParamArray[j]; 569 initParams.put(paramValueType.getParamName().getStringValue().trim(), paramValueType.getParamValue().getStringValue().trim()); 570 } 571 filterData.setAttribute("initParams", initParams); 572 filterData.setReferencePattern("JettyServletRegistration", moduleName); 573 moduleContext.addGBean(filterData); 574 } 575 } 576 577 private void addFilterMappingsGBeans(EARContext earContext, EARContext moduleContext, AbstractName moduleName, WebAppType webApp, AbstractName previous) throws GBeanAlreadyExistsException { 578 FilterMappingType[] filterMappingArray = webApp.getFilterMappingArray(); 579 for (int i = 0; i < filterMappingArray.length; i++) { 580 FilterMappingType filterMappingType = filterMappingArray[i]; 581 String filterName = filterMappingType.getFilterName().getStringValue().trim(); 582 GBeanData filterMappingData = new GBeanData(JettyFilterMapping.GBEAN_INFO); 583 if (previous != null) { 584 filterMappingData.setReferencePattern("Previous", previous); 585 } 586 filterMappingData.setReferencePattern("JettyServletRegistration", moduleName); 587 AbstractName filterAbstractName = earContext.getNaming().createChildName(moduleName, filterName, NameFactory.WEB_FILTER); 588 589 AbstractName filterMappingName = null; 590 if (filterMappingType.isSetUrlPattern()) { 591 String urlPattern = filterMappingType.getUrlPattern().getStringValue().trim(); 592 filterMappingData.setAttribute("urlPattern", urlPattern); 593 filterMappingName = earContext.getNaming().createChildName(filterAbstractName, ObjectName.quote(urlPattern), NameFactory.URL_WEB_FILTER_MAPPING); 594 } 595 if (filterMappingType.isSetServletName()) { 596 String servletName = filterMappingType.getServletName().getStringValue().trim(); 597 AbstractName servletAbstractName = earContext.getNaming().createChildName(moduleName, servletName, NameFactory.SERVLET); 598 filterMappingData.setReferencePattern("Servlet", servletAbstractName); 599 filterMappingName = earContext.getNaming().createChildName(filterAbstractName, servletName, NameFactory.SERVLET_WEB_FILTER_MAPPING); 600 } 601 filterMappingData.setAbstractName(filterMappingName); 602 previous = filterMappingName; 603 604 boolean request = filterMappingType.getDispatcherArray().length == 0; 605 boolean forward = false; 606 boolean include = false; 607 boolean error = false; 608 for (int j = 0; j < filterMappingType.getDispatcherArray().length; j++) { 609 DispatcherType dispatcherType = filterMappingType.getDispatcherArray()[j]; 610 if (dispatcherType.getStringValue().equals("REQUEST")) { 611 request = true; 612 } else if (dispatcherType.getStringValue().equals("FORWARD")) { 613 forward = true; 614 } else if (dispatcherType.getStringValue().equals("INCLUDE")) { 615 include = true; 616 } else if (dispatcherType.getStringValue().equals("ERROR")) { 617 error = true; 618 } 619 } 620 filterMappingData.setAttribute("requestDispatch", Boolean.valueOf(request)); 621 filterMappingData.setAttribute("forwardDispatch", Boolean.valueOf(forward)); 622 filterMappingData.setAttribute("includeDispatch", Boolean.valueOf(include)); 623 filterMappingData.setAttribute("errorDispatch", Boolean.valueOf(error)); 624 filterMappingData.setReferencePattern("Filter", filterAbstractName); 625 moduleContext.addGBean(filterMappingData); 626 } 627 } 628 629 private AbstractName addDefaultFiltersGBeans(EARContext earContext, EARContext moduleContext, AbstractName moduleName, AbstractName previous) throws GBeanNotFoundException, GBeanAlreadyExistsException { 630 for (Iterator iterator = defaultFilters.iterator(); iterator.hasNext();) { 631 Object defaultFilter = iterator.next(); 632 GBeanData filterGBeanData = getGBeanData(kernel, defaultFilter); 633 String filterName = (String) filterGBeanData.getAttribute("filterName"); 634 AbstractName defaultFilterAbstractName = earContext.getNaming().createChildName(moduleName, filterName, NameFactory.WEB_FILTER); 635 filterGBeanData.setAbstractName(defaultFilterAbstractName); 636 filterGBeanData.setReferencePattern("JettyServletRegistration", moduleName); 637 moduleContext.addGBean(filterGBeanData); 638 //add a mapping to /* 639 640 GBeanData filterMappingGBeanData = new GBeanData(JettyFilterMapping.GBEAN_INFO); 641 if (previous != null) { 642 filterMappingGBeanData.setReferencePattern("Previous", previous); 643 } 644 filterMappingGBeanData.setReferencePattern("JettyServletRegistration", moduleName); 645 String urlPattern = "/*"; 646 filterMappingGBeanData.setAttribute("urlPattern", urlPattern); 647 AbstractName filterMappingName = earContext.getNaming().createChildName(defaultFilterAbstractName, urlPattern, NameFactory.URL_WEB_FILTER_MAPPING); 648 filterMappingGBeanData.setAbstractName(filterMappingName); 649 previous = filterMappingName; 650 651 652 filterMappingGBeanData.setAttribute("requestDispatch", Boolean.TRUE); 653 filterMappingGBeanData.setAttribute("forwardDispatch", Boolean.TRUE); 654 filterMappingGBeanData.setAttribute("includeDispatch", Boolean.TRUE); 655 filterMappingGBeanData.setAttribute("errorDispatch", Boolean.FALSE); 656 filterMappingGBeanData.setReferencePattern("Filter", defaultFilterAbstractName); 657 moduleContext.addGBean(filterMappingGBeanData); 658 } 659 return previous; 660 } 661 662 private Map buildServletMappings(Module module, WebAppType webApp, Map servletMappings, Set knownServletMappings) throws DeploymentException { 663 ServletType[] servletTypes = webApp.getServletArray(); 664 Set knownServlets = new HashSet(); 665 for (int i = 0; i < servletTypes.length; i++) { 666 ServletType type = servletTypes[i]; 667 knownServlets.add(type.getServletName().getStringValue().trim()); 668 } 669 670 ServletMappingType[] servletMappingArray = webApp.getServletMappingArray(); 671 for (int i = 0; i < servletMappingArray.length; i++) { 672 ServletMappingType servletMappingType = servletMappingArray[i]; 673 String servletName = servletMappingType.getServletName().getStringValue().trim(); 674 if (!knownServlets.contains(servletName)) { 675 throw new DeploymentException("Web app " + module.getName() + 676 " contains a servlet mapping that refers to servlet '" + servletName + 677 "' but no such servlet was found!"); 678 } 679 String urlPattern = servletMappingType.getUrlPattern().getStringValue().trim(); 680 if (!knownServletMappings.contains(urlPattern)) { 681 knownServletMappings.add(urlPattern); 682 checkString(urlPattern); 683 Set urlsForServlet = (Set) servletMappings.get(servletName); 684 if (urlsForServlet == null) { 685 urlsForServlet = new HashSet(); 686 servletMappings.put(servletName, urlsForServlet); 687 } 688 urlsForServlet.add(urlPattern); 689 } 690 } 691 692 return servletMappings; 693 } 694 695 private void configureLoginConfigs(Module module, WebAppType webApp, JettyWebAppType jettyWebApp, GBeanData webModuleData) throws DeploymentException { 696 LoginConfigType[] loginConfigArray = webApp.getLoginConfigArray(); 697 if (loginConfigArray.length > 1) { 698 throw new DeploymentException("Web app " + module.getName() + " cannot have more than one login-config element. Currently has " + loginConfigArray.length + " login-config elements."); 699 } 700 if (loginConfigArray.length == 1) { 701 LoginConfigType loginConfig = loginConfigArray[0]; 702 if (loginConfig.isSetAuthMethod()) { 703 String authMethod = loginConfig.getAuthMethod().getStringValue(); 704 if ("BASIC".equals(authMethod)) { 705 webModuleData.setAttribute("authenticator", new BasicAuthenticator()); 706 } else if ("DIGEST".equals(authMethod)) { 707 webModuleData.setAttribute("authenticator", new DigestAuthenticator()); 708 } else if ("FORM".equals(authMethod)) { 709 710 FormAuthenticator formAuthenticator = new FormAuthenticator(); 711 webModuleData.setAttribute("authenticator", formAuthenticator); 712 if (loginConfig.isSetFormLoginConfig()) { 713 FormLoginConfigType formLoginConfig = loginConfig.getFormLoginConfig(); 714 formAuthenticator.setLoginPage(formLoginConfig.getFormLoginPage().getStringValue()); 715 formAuthenticator.setErrorPage(formLoginConfig.getFormErrorPage().getStringValue()); 716 } 717 } else if ("CLIENT-CERT".equals(authMethod)) { 718 webModuleData.setAttribute("authenticator", new ClientCertAuthenticator()); 719 } 720 } 721 if (loginConfig.isSetRealmName()) { 722 webModuleData.setAttribute("realmName", loginConfig.getRealmName().getStringValue()); 723 } 724 725 } else if (jettyWebApp.isSetSecurityRealmName()) { 726 webModuleData.setAttribute("authenticator", new NonAuthenticator()); 727 } 728 } 729 730 private void configureTagLibs(Module module, WebAppType webApp, GBeanData webModuleData) throws DeploymentException { 731 JspConfigType[] jspConfigArray = webApp.getJspConfigArray(); 732 if (jspConfigArray.length > 1) { 733 throw new DeploymentException("Web app "+ module.getName() +" cannot have more than one jsp-config element. Currently has " + jspConfigArray.length +" jsp-config elements."); 734 } 735 Map tagLibMap = new HashMap(); 736 for (int i = 0; i < jspConfigArray.length; i++) { 737 TaglibType[] tagLibArray = jspConfigArray[i].getTaglibArray(); 738 for (int j = 0; j < tagLibArray.length; j++) { 739 TaglibType taglib = tagLibArray[j]; 740 tagLibMap.put(taglib.getTaglibUri().getStringValue().trim(), taglib.getTaglibLocation().getStringValue().trim()); 741 } 742 } 743 webModuleData.setAttribute("tagLibMap", tagLibMap); 744 } 745 746 private void configureErrorPages(WebAppType webApp, GBeanData webModuleData) { 747 ErrorPageType[] errorPageArray = webApp.getErrorPageArray(); 748 Map errorPageMap = new HashMap(); 749 for (int i = 0; i < errorPageArray.length; i++) { 750 ErrorPageType errorPageType = errorPageArray[i]; 751 if (errorPageType.isSetErrorCode()) { 752 errorPageMap.put(errorPageType.getErrorCode().getStringValue(), errorPageType.getLocation().getStringValue()); 753 } else { 754 errorPageMap.put(errorPageType.getExceptionType().getStringValue(), errorPageType.getLocation().getStringValue()); 755 } 756 } 757 webModuleData.setAttribute("errorPages", errorPageMap); 758 } 759 760 private void configureLocalEncodingMappingLists(WebAppType webApp, GBeanData webModuleData) { 761 LocaleEncodingMappingListType[] localeEncodingMappingListArray = webApp.getLocaleEncodingMappingListArray(); 762 Map localeEncodingMappingMap = new HashMap(); 763 for (int i = 0; i < localeEncodingMappingListArray.length; i++) { 764 LocaleEncodingMappingType[] localeEncodingMappingArray = localeEncodingMappingListArray[i].getLocaleEncodingMappingArray(); 765 for (int j = 0; j < localeEncodingMappingArray.length; j++) { 766 LocaleEncodingMappingType localeEncodingMapping = localeEncodingMappingArray[j]; 767 localeEncodingMappingMap.put(localeEncodingMapping.getLocale(), localeEncodingMapping.getEncoding()); 768 } 769 } 770 webModuleData.setAttribute("localeEncodingMapping", localeEncodingMappingMap); 771 } 772 773 private void configureWelcomeFileLists(WebAppType webApp, GBeanData webModuleData) { 774 WelcomeFileListType[] welcomeFileArray = webApp.getWelcomeFileListArray(); 775 List welcomeFiles; 776 if (welcomeFileArray.length > 0) { 777 welcomeFiles = new ArrayList(); 778 for (int i = 0; i < welcomeFileArray.length; i++) { 779 String[] welcomeFileListType = welcomeFileArray[i].getWelcomeFileArray(); 780 for (int j = 0; j < welcomeFileListType.length; j++) { 781 String welcomeFile = welcomeFileListType[j].trim(); 782 welcomeFiles.add(welcomeFile); 783 } 784 } 785 } else { 786 welcomeFiles = new ArrayList(defaultWelcomeFiles); 787 } 788 webModuleData.setAttribute("welcomeFiles", welcomeFiles.toArray(new String[welcomeFiles.size()])); 789 } 790 791 private void configureMimeMappings(WebAppType webApp, GBeanData webModuleData) { 792 MimeMappingType[] mimeMappingArray = webApp.getMimeMappingArray(); 793 Map mimeMappingMap = new HashMap(); 794 for (int i = 0; i < mimeMappingArray.length; i++) { 795 MimeMappingType mimeMappingType = mimeMappingArray[i]; 796 mimeMappingMap.put(mimeMappingType.getExtension().getStringValue(), mimeMappingType.getMimeType().getStringValue()); 797 } 798 webModuleData.setAttribute("mimeMap", mimeMappingMap); 799 } 800 801 private void configureListeners(WebAppType webApp, GBeanData webModuleData) { 802 ListenerType[] listenerArray = webApp.getListenerArray(); 803 Collection listeners = new ArrayList(); 804 for (int i = 0; i < listenerArray.length; i++) { 805 ListenerType listenerType = listenerArray[i]; 806 listeners.add(listenerType.getListenerClass().getStringValue()); 807 } 808 webModuleData.setAttribute("listenerClassNames", listeners); 809 } 810 811 private void configureContextParams(WebAppType webApp, GBeanData webModuleData) { 812 ParamValueType[] contextParamArray = webApp.getContextParamArray(); 813 Map contextParams = new HashMap(); 814 for (int i = 0; i < contextParamArray.length; i++) { 815 ParamValueType contextParam = contextParamArray[i]; 816 contextParams.put(contextParam.getParamName().getStringValue().trim(), contextParam.getParamValue().getStringValue().trim()); 817 } 818 webModuleData.setAttribute("contextParamMap", contextParams); 819 } 820 821 private void configureHosts(EARContext earContext, JettyWebAppType jettyWebApp, GBeanData webModuleData) throws GBeanAlreadyExistsException { 822 String[] hosts = jettyWebApp.getHostArray(); 823 for (int i = 0; i < hosts.length; i++) { 824 hosts[i] = hosts[i].trim(); 825 } 826 String[] virtualHosts = jettyWebApp.getVirtualHostArray(); 827 for (int i = 0; i < virtualHosts.length; i++) { 828 virtualHosts[i] = virtualHosts[i].trim(); 829 } 830 if (hosts.length > 0 || virtualHosts.length > 0) { 831 //use name same as module 832 AbstractName hostName = earContext.getNaming().createChildName(webModuleData.getAbstractName(), "Host", "Host"); 833 GBeanData hostData = new GBeanData(hostName, Host.GBEAN_INFO); 834 hostData.setAttribute("hosts", hosts); 835 hostData.setAttribute("virtualHosts", virtualHosts); 836 earContext.addGBean(hostData); 837 webModuleData.setReferencePattern("Host", hostName); 838 } 839 } 840 841 public String getSchemaNamespace() { 842 return JETTY_NAMESPACE; 843 } 844 845 /** 846 * Adds the provided servlets, taking into account the load-on-startup ordering. 847 * 848 * @param webModuleName an <code>ObjectName</code> value 849 * @param module a <code>WebModule</code> value 850 * @param servletTypes a <code>ServletType[]</code> value, contains the <code>servlet</code> entries from <code>web.xml</code>. 851 * @param servletMappings a <code>Map</code> value 852 * @param securityRoles a <code>Set</code> value 853 * @param rolePermissions a <code>Map</code> value 854 * @param portMap a <code>Map</code> value 855 * @param moduleContext 856 * @throws DeploymentException if an error occurs 857 */ 858 private void addServlets(AbstractName webModuleName, 859 WebModule module, 860 ServletType[] servletTypes, 861 Map servletMappings, 862 Set securityRoles, 863 Map rolePermissions, 864 Map portMap, 865 EARContext moduleContext) throws DeploymentException { 866 867 // this TreeSet will order the ServletTypes based on whether 868 // they have a load-on-startup element and what its value is 869 TreeSet loadOrder = new TreeSet(new StartupOrderComparator()); 870 871 // add all of the servlets to the sorted set 872 for (int i = 0; i < servletTypes.length; i++) { 873 loadOrder.add(servletTypes[i]); 874 } 875 876 // now that they're sorted, read them in order and add them to 877 // the context. we'll use a GBean reference to enforce the 878 // load order. Each servlet GBean (except the first) has a 879 // reference to the previous GBean. The kernel will ensure 880 // that each "previous" GBean is running before it starts any 881 // other GBeans that reference it. See also 882 // o.a.g.jetty.JettyFilterMapping which provided the example 883 // of how to do this. 884 // http://issues.apache.org/jira/browse/GERONIMO-645 885 AbstractName previousServlet = null; 886 for (Iterator servlets = loadOrder.iterator(); servlets.hasNext();) { 887 ServletType servletType = (ServletType) servlets.next(); 888 previousServlet = addServlet(webModuleName, module, previousServlet, servletType, servletMappings, securityRoles, rolePermissions, portMap, moduleContext); 889 } 890 891 // JACC v1.0 secion B.19 892 addUnmappedJSPPermissions(securityRoles, rolePermissions); 893 } 894 895 /** 896 * @param webModuleName 897 * @param module 898 * @param previousServlet 899 * @param servletType 900 * @param servletMappings 901 * @param securityRoles 902 * @param rolePermissions 903 * @param portMap 904 * @param moduleContext 905 * @return AbstractName of servlet gbean added 906 * @throws DeploymentException 907 */ 908 private AbstractName addServlet(AbstractName webModuleName, 909 WebModule module, 910 AbstractName previousServlet, 911 ServletType servletType, 912 Map servletMappings, 913 Set securityRoles, 914 Map rolePermissions, 915 Map portMap, 916 EARContext moduleContext) throws DeploymentException { 917 ClassLoader webClassLoader = moduleContext.getClassLoader(); 918 String servletName = servletType.getServletName().getStringValue().trim(); 919 AbstractName servletAbstractName = moduleContext.getNaming().createChildName(webModuleName, servletName, NameFactory.SERVLET); 920 GBeanData servletData; 921 Map initParams = new HashMap(); 922 Class baseServletClass; 923 try { 924 baseServletClass = webClassLoader.loadClass(Servlet.class.getName()); 925 } catch (ClassNotFoundException e) { 926 throw new DeploymentException("Could not load javax.servlet.Servlet in web classloader", e); // TODO identify web app in message 927 } 928 if (servletType.isSetServletClass()) { 929 String servletClassName = servletType.getServletClass().getStringValue().trim(); 930 Class servletClass; 931 try { 932 servletClass = webClassLoader.loadClass(servletClassName); 933 } catch (ClassNotFoundException e) { 934 throw new DeploymentException("Could not load servlet class " + servletClassName, e); // TODO identify web app in message 935 } 936 if (baseServletClass.isAssignableFrom(servletClass)) { 937 servletData = new GBeanData(servletAbstractName, JettyServletHolder.GBEAN_INFO); 938 servletData.setAttribute("servletClass", servletClassName); 939 } else { 940 servletData = new GBeanData(pojoWebServiceTemplate); 941 servletData.setAbstractName(servletAbstractName); 942 //let the web service builder deal with configuring the gbean with the web service stack 943 Object portInfo = portMap.get(servletName); 944 // if (portInfo == null) { 945 // throw new DeploymentException("No web service deployment info for servlet name " + servletName); // TODO identify web app in message 946 // } 947 getWebServiceBuilder().configurePOJO(servletData, module, portInfo, servletClassName, moduleContext); 948 } 949 } else if (servletType.isSetJspFile()) { 950 servletData = new GBeanData(servletAbstractName, JettyServletHolder.GBEAN_INFO); 951 servletData.setAttribute("jspFile", servletType.getJspFile().getStringValue().trim()); 952 //TODO MAKE THIS CONFIGURABLE!!! Jetty uses the servlet mapping set up from the default-web.xml 953 servletData.setAttribute("servletClass", "org.apache.jasper.servlet.JspServlet"); 954 initParams.put("development", "false"); 955 } else { 956 throw new DeploymentException("Neither servlet class nor jsp file is set for " + servletName); // TODO identify web app in message 957 } 958 959 // link to previous servlet, if there is one, so that we 960 // preserve the <load-on-startup> ordering. 961 // http://issues.apache.org/jira/browse/GERONIMO-645 962 if (null != previousServlet) { 963 servletData.setReferencePattern("Previous", previousServlet); 964 } 965 966 //TODO in init param setter, add classpath if jspFile is not null. 967 servletData.setReferencePattern("JettyServletRegistration", webModuleName); 968 servletData.setAttribute("servletName", servletName); 969 ParamValueType[] initParamArray = servletType.getInitParamArray(); 970 for (int j = 0; j < initParamArray.length; j++) { 971 ParamValueType paramValueType = initParamArray[j]; 972 initParams.put(paramValueType.getParamName().getStringValue().trim(), paramValueType.getParamValue().getStringValue().trim()); 973 } 974 servletData.setAttribute("initParams", initParams); 975 if (servletType.isSetLoadOnStartup()) { 976 Integer loadOnStartup = new Integer(servletType.getLoadOnStartup().getBigIntegerValue().intValue()); 977 servletData.setAttribute("loadOnStartup", loadOnStartup); 978 } 979 980 Set mappings = (Set) servletMappings.get(servletName); 981 servletData.setAttribute("servletMappings", mappings == null ? Collections.EMPTY_SET : mappings); 982 983 //run-as 984 if (servletType.isSetRunAs()) { 985 servletData.setAttribute("runAsRole", servletType.getRunAs().getRoleName().getStringValue().trim()); 986 } 987 988 processRoleRefPermissions(servletType, securityRoles, rolePermissions); 989 990 try { 991 moduleContext.addGBean(servletData); 992 } catch (GBeanAlreadyExistsException e) { 993 throw new DeploymentException("Could not add servlet gbean to context", e); // TODO identify web app in message 994 } 995 return servletAbstractName; 996 } 997 998 public static final GBeanInfo GBEAN_INFO; 999 1000 static { 1001 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(JettyModuleBuilder.class, NameFactory.MODULE_BUILDER); 1002 infoBuilder.addAttribute("defaultEnvironment", Environment.class, true, true); 1003 infoBuilder.addAttribute("defaultSessionTimeoutSeconds", Integer.class, true, true); 1004 infoBuilder.addAttribute("defaultWelcomeFiles", List.class, true, true); 1005 infoBuilder.addAttribute("jettyContainerObjectName", AbstractNameQuery.class, true, true); 1006 infoBuilder.addReference("DefaultServlets", JettyDefaultServletHolder.class, NameFactory.SERVLET_TEMPLATE); 1007 infoBuilder.addReference("DefaultFilters", Object.class); 1008 infoBuilder.addReference("DefaultFilterMappings", Object.class); 1009 infoBuilder.addReference("PojoWebServiceTemplate", Object.class, NameFactory.SERVLET_WEB_SERVICE_TEMPLATE); 1010 infoBuilder.addReference("WebServiceBuilder", WebServiceBuilder.class, NameFactory.MODULE_BUILDER); 1011 infoBuilder.addReference("ClusteringBuilders", NamespaceDrivenBuilder.class, NameFactory.MODULE_BUILDER); 1012 infoBuilder.addReference("SecurityBuilders", NamespaceDrivenBuilder.class, NameFactory.MODULE_BUILDER); 1013 infoBuilder.addReference("ServiceBuilders", NamespaceDrivenBuilder.class, NameFactory.MODULE_BUILDER); 1014 infoBuilder.addReference("NamingBuilders", NamingBuilder.class, NameFactory.MODULE_BUILDER); 1015 infoBuilder.addReference("ResourceEnvironmentSetter", ResourceEnvironmentSetter.class, NameFactory.MODULE_BUILDER); 1016 infoBuilder.addAttribute("kernel", Kernel.class, false); 1017 infoBuilder.addInterface(ModuleBuilder.class); 1018 1019 infoBuilder.setConstructor(new String[]{ 1020 "defaultEnvironment", 1021 "defaultSessionTimeoutSeconds", 1022 "defaultWelcomeFiles", 1023 "jettyContainerObjectName", 1024 "DefaultServlets", 1025 "DefaultFilters", 1026 "DefaultFilterMappings", 1027 "PojoWebServiceTemplate", 1028 "WebServiceBuilder", 1029 "ClusteringBuilders", 1030 "SecurityBuilders", 1031 "ServiceBuilders", 1032 "NamingBuilders", 1033 "ResourceEnvironmentSetter", 1034 "kernel"}); 1035 GBEAN_INFO = infoBuilder.getBeanInfo(); 1036 } 1037 1038 public static GBeanInfo getGBeanInfo() { 1039 return GBEAN_INFO; 1040 } 1041 1042 static class StartupOrderComparator implements Comparator { 1043 /** 1044 * comparator that compares first on the basis of startup order, and then on the lexicographical 1045 * ordering of servlet name. Since the servlet names have a uniqueness constraint, this should 1046 * provide a total ordering consistent with equals. All servlets with no startup order are after 1047 * all servlets with a startup order. 1048 * 1049 * @param o1 first ServletType object 1050 * @param o2 second ServletType object 1051 * @return an int < 0 if o1 precedes o2, 0 if they are equal, and > 0 if o2 preceeds o1. 1052 */ 1053 public int compare(Object o1, Object o2) { 1054 ServletType s1 = (ServletType) o1; 1055 ServletType s2 = (ServletType) o2; 1056 1057 // load-on-startup is set for neither. the 1058 // ordering at this point doesn't matter, but we 1059 // should return "0" only if the two objects say 1060 // they are equal 1061 if (!s1.isSetLoadOnStartup() && !s2.isSetLoadOnStartup()) { 1062 return s1.equals(s2) ? 0 : s1.getServletName().getStringValue().trim().compareTo(s2.getServletName().getStringValue().trim()); 1063 } 1064 1065 // load-on-startup is set for one but not the 1066 // other. whichever one is set will be "less 1067 // than", i.e. it will be loaded first 1068 if (s1.isSetLoadOnStartup() && !s2.isSetLoadOnStartup()) { 1069 return -1; 1070 } 1071 if (!s1.isSetLoadOnStartup() && s2.isSetLoadOnStartup()) { 1072 return 1; 1073 } 1074 1075 // load-on-startup is set for both. whichever one 1076 // has a smaller value is "less than" 1077 int comp = s1.getLoadOnStartup().getBigIntegerValue().compareTo(s2.getLoadOnStartup().getBigIntegerValue()); 1078 if (comp == 0) { 1079 return s1.getServletName().getStringValue().trim().compareTo(s2.getServletName().getStringValue().trim()); 1080 } 1081 return comp; 1082 } 1083 } 1084 }