001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.geronimo.tomcat.deployment; 019 020 import static java.lang.Boolean.FALSE; 021 import static java.lang.Boolean.TRUE; 022 023 import java.io.File; 024 import java.io.FileNotFoundException; 025 import java.io.FileWriter; 026 import java.io.IOException; 027 import java.net.URL; 028 import java.security.PermissionCollection; 029 import java.util.Collection; 030 import java.util.HashMap; 031 import java.util.Map; 032 import java.util.Set; 033 import java.util.jar.JarFile; 034 035 import javax.servlet.Servlet; 036 037 import org.apache.commons.logging.Log; 038 import org.apache.commons.logging.LogFactory; 039 import org.apache.geronimo.common.DeploymentException; 040 import org.apache.geronimo.deployment.ModuleIDBuilder; 041 import org.apache.geronimo.deployment.NamespaceDrivenBuilder; 042 import org.apache.geronimo.deployment.NamespaceDrivenBuilderCollection; 043 import org.apache.geronimo.deployment.service.EnvironmentBuilder; 044 import org.apache.geronimo.deployment.util.DeploymentUtil; 045 import org.apache.geronimo.deployment.xbeans.EnvironmentType; 046 import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil; 047 import org.apache.geronimo.gbean.AbstractName; 048 import org.apache.geronimo.gbean.AbstractNameQuery; 049 import org.apache.geronimo.gbean.GBeanData; 050 import org.apache.geronimo.gbean.GBeanInfo; 051 import org.apache.geronimo.gbean.GBeanInfoBuilder; 052 import org.apache.geronimo.gbean.ReferencePatterns; 053 import org.apache.geronimo.gbean.GBeanLifecycle; 054 import org.apache.geronimo.j2ee.deployment.EARContext; 055 import org.apache.geronimo.j2ee.deployment.Module; 056 import org.apache.geronimo.j2ee.deployment.ModuleBuilder; 057 import org.apache.geronimo.j2ee.deployment.ModuleBuilderExtension; 058 import org.apache.geronimo.j2ee.deployment.NamingBuilder; 059 import org.apache.geronimo.j2ee.deployment.WebModule; 060 import org.apache.geronimo.j2ee.deployment.WebServiceBuilder; 061 import org.apache.geronimo.j2ee.deployment.annotation.AnnotatedWebApp; 062 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 063 import org.apache.geronimo.kernel.Kernel; 064 import org.apache.geronimo.kernel.Naming; 065 import org.apache.geronimo.kernel.config.ConfigurationData; 066 import org.apache.geronimo.kernel.repository.Environment; 067 import org.apache.geronimo.naming.deployment.ENCConfigBuilder; 068 import org.apache.geronimo.naming.deployment.GBeanResourceEnvironmentBuilder; 069 import org.apache.geronimo.naming.deployment.ResourceEnvironmentSetter; 070 import org.apache.geronimo.security.jacc.ComponentPermissions; 071 import org.apache.geronimo.tomcat.LifecycleListenerGBean; 072 import org.apache.geronimo.tomcat.ManagerGBean; 073 import org.apache.geronimo.tomcat.RealmGBean; 074 import org.apache.geronimo.tomcat.TomcatWebAppContext; 075 import org.apache.geronimo.tomcat.ValveGBean; 076 import org.apache.geronimo.tomcat.cluster.CatalinaClusterGBean; 077 import org.apache.geronimo.tomcat.util.SecurityHolder; 078 import org.apache.geronimo.web.deployment.GenericToSpecificPlanConverter; 079 import org.apache.geronimo.web25.deployment.AbstractWebModuleBuilder; 080 import org.apache.geronimo.xbeans.geronimo.j2ee.GerClusteringDocument; 081 import org.apache.geronimo.xbeans.geronimo.web.tomcat.TomcatWebAppDocument; 082 import org.apache.geronimo.xbeans.geronimo.web.tomcat.TomcatWebAppType; 083 import org.apache.geronimo.xbeans.geronimo.web.tomcat.config.GerTomcatDocument; 084 import org.apache.geronimo.xbeans.javaee.EjbLocalRefType; 085 import org.apache.geronimo.xbeans.javaee.EjbRefType; 086 import org.apache.geronimo.xbeans.javaee.EnvEntryType; 087 import org.apache.geronimo.xbeans.javaee.LifecycleCallbackType; 088 import org.apache.geronimo.xbeans.javaee.MessageDestinationRefType; 089 import org.apache.geronimo.xbeans.javaee.MessageDestinationType; 090 import org.apache.geronimo.xbeans.javaee.PersistenceContextRefType; 091 import org.apache.geronimo.xbeans.javaee.PersistenceUnitRefType; 092 import org.apache.geronimo.xbeans.javaee.ResourceEnvRefType; 093 import org.apache.geronimo.xbeans.javaee.ResourceRefType; 094 import org.apache.geronimo.xbeans.javaee.ServiceRefType; 095 import org.apache.geronimo.xbeans.javaee.ServletType; 096 import org.apache.geronimo.xbeans.javaee.WebAppDocument; 097 import org.apache.geronimo.xbeans.javaee.WebAppType; 098 import org.apache.xmlbeans.XmlCursor; 099 import org.apache.xmlbeans.XmlException; 100 import org.apache.xmlbeans.XmlObject; 101 import org.apache.xmlbeans.XmlOptions; 102 103 /** 104 * @version $Rev:385659 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 105 */ 106 public class TomcatModuleBuilder extends AbstractWebModuleBuilder implements GBeanLifecycle { 107 108 private static final Log log = LogFactory.getLog(TomcatModuleBuilder.class); 109 110 private static final String TOMCAT_NAMESPACE = TomcatWebAppDocument.type.getDocumentElementName().getNamespaceURI(); 111 private static final String IS_JAVAEE = "IS_JAVAEE"; 112 private static final Map<String, String> NAMESPACE_UPDATES = new HashMap<String, String>(); 113 static { 114 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web", "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1"); 115 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web-1.1", "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1"); 116 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web-1.2", "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1"); 117 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web-2.0", "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1"); 118 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/tomcat", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1"); 119 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.1", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1"); 120 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.2", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1"); 121 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1"); 122 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/tomcat/config", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat/config-1.0"); 123 } 124 125 private final Environment defaultEnvironment; 126 private final AbstractNameQuery tomcatContainerName; 127 protected final NamespaceDrivenBuilderCollection clusteringBuilders; 128 129 public TomcatModuleBuilder(Environment defaultEnvironment, 130 AbstractNameQuery tomcatContainerName, 131 Collection<WebServiceBuilder> webServiceBuilder, 132 Collection securityBuilders, 133 Collection serviceBuilders, 134 NamingBuilder namingBuilders, 135 Collection<NamespaceDrivenBuilder> clusteringBuilders, 136 Collection<ModuleBuilderExtension> moduleBuilderExtensions, 137 ResourceEnvironmentSetter resourceEnvironmentSetter, 138 Kernel kernel) { 139 super(kernel, securityBuilders, serviceBuilders, namingBuilders, resourceEnvironmentSetter, webServiceBuilder, moduleBuilderExtensions); 140 this.defaultEnvironment = defaultEnvironment; 141 this.clusteringBuilders = new NamespaceDrivenBuilderCollection(clusteringBuilders, GerClusteringDocument.type.getDocumentElementName()); 142 this.tomcatContainerName = tomcatContainerName; 143 } 144 145 public void doStart() throws Exception { 146 XmlBeansUtil.registerNamespaceUpdates(NAMESPACE_UPDATES); 147 } 148 149 public void doStop() { 150 XmlBeansUtil.unregisterNamespaceUpdates(NAMESPACE_UPDATES); 151 } 152 153 public void doFail() { 154 doStop(); 155 } 156 157 protected Module createModule(Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, boolean standAlone, String contextRoot, AbstractName earName, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException { 158 assert moduleFile != null : "moduleFile is null"; 159 assert targetPath != null : "targetPath is null"; 160 assert !targetPath.endsWith("/") : "targetPath must not end with a '/'"; 161 162 // parse the spec dd 163 String specDD = null; 164 WebAppType webApp = null; 165 Boolean isJavaee; 166 try { 167 if (specDDUrl == null) { 168 specDDUrl = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/web.xml"); 169 } 170 171 // read in the entire specDD as a string, we need this for getDeploymentDescriptor 172 // on the J2ee management object 173 specDD = DeploymentUtil.readAll(specDDUrl); 174 175 // we found web.xml, if it won't parse that's an error. 176 XmlObject parsed = XmlBeansUtil.parse(specDD); 177 //Dont save updated xml if it isn't javaee 178 XmlCursor cursor = parsed.newCursor(); 179 try { 180 cursor.toStartDoc(); 181 cursor.toFirstChild(); 182 isJavaee = "http://java.sun.com/xml/ns/javaee".equals(cursor.getName().getNamespaceURI()); 183 } finally { 184 cursor.dispose(); 185 } 186 WebAppDocument webAppDoc = convertToServletSchema(parsed); 187 webApp = webAppDoc.getWebApp(); 188 check(webApp); 189 } catch (XmlException e) { 190 // Output the target path in the error to make it clearer to the user which webapp 191 // has the problem. The targetPath is used, as moduleFile may have an unhelpful 192 // value such as C:\geronimo-1.1\var\temp\geronimo-deploymentUtil22826.tmpdir 193 throw new DeploymentException("Error parsing web.xml for " + targetPath, e); 194 } catch (Exception e) { 195 if (!moduleFile.getName().endsWith(".war")) { 196 //not for us 197 return null; 198 } 199 isJavaee = true; 200 //else ignore as jee5 allows optional spec dd for .war's 201 } 202 203 if (webApp == null) 204 webApp = WebAppType.Factory.newInstance(); 205 206 // parse vendor dd 207 TomcatWebAppType tomcatWebApp = getTomcatWebApp(plan, moduleFile, standAlone, targetPath, webApp); 208 contextRoot = getContextRoot(tomcatWebApp, contextRoot, webApp, standAlone, moduleFile, targetPath); 209 210 EnvironmentType environmentType = tomcatWebApp.getEnvironment(); 211 Environment environment = EnvironmentBuilder.buildEnvironment(environmentType, defaultEnvironment); 212 213 Boolean distributable = webApp.getDistributableArray().length == 1 ? TRUE : FALSE; 214 if (TRUE == distributable) { 215 clusteringBuilders.buildEnvironment(tomcatWebApp, environment); 216 } 217 218 // Note: logic elsewhere depends on the default artifact ID being the file name less extension (ConfigIDExtractor) 219 String warName = ""; 220 File temp = new File(moduleFile.getName()); 221 if (temp.isFile()) { 222 warName = temp.getName(); 223 if (warName.lastIndexOf('.') > -1) { 224 warName = warName.substring(0, warName.lastIndexOf('.')); 225 } 226 } else { 227 try { 228 warName = temp.getCanonicalFile().getName(); 229 if (warName.equals("")) { 230 // Root directory 231 warName = "$root-dir$"; 232 } 233 } catch (IOException e) { 234 //really? 235 } 236 } 237 idBuilder.resolve(environment, warName, "war"); 238 239 AbstractName moduleName; 240 if (earName == null) { 241 earName = naming.createRootName(environment.getConfigId(), NameFactory.NULL, NameFactory.J2EE_APPLICATION); 242 moduleName = naming.createChildName(earName, environment.getConfigId().toString(), NameFactory.WEB_MODULE); 243 } else { 244 moduleName = naming.createChildName(earName, targetPath, NameFactory.WEB_MODULE); 245 } 246 247 // Create the AnnotatedApp interface for the WebModule 248 AnnotatedWebApp annotatedWebApp = new AnnotatedWebApp(webApp); 249 250 WebModule module = new WebModule(standAlone, moduleName, environment, moduleFile, targetPath, webApp, tomcatWebApp, specDD, contextRoot, TOMCAT_NAMESPACE, annotatedWebApp); 251 for (ModuleBuilderExtension mbe : moduleBuilderExtensions) { 252 mbe.createModule(module, plan, moduleFile, targetPath, specDDUrl, environment, contextRoot, earName, naming, idBuilder); 253 } 254 module.getSharedContext().put(IS_JAVAEE, isJavaee); 255 return module; 256 } 257 258 private String getContextRoot(TomcatWebAppType tomcatWebApp, String contextRoot, WebAppType webApp, boolean standAlone, JarFile moduleFile, String targetPath) { 259 //If we have a context root, override everything 260 if (tomcatWebApp.isSetContextRoot()) { 261 contextRoot = tomcatWebApp.getContextRoot(); 262 } else if (contextRoot == null || contextRoot.trim().equals("")) { 263 //Otherwise if no contextRoot was passed in from the ear, then make up a default 264 contextRoot = determineDefaultContextRoot(webApp, standAlone, moduleFile, targetPath); 265 } 266 contextRoot = contextRoot.trim(); 267 if (contextRoot.length() > 0) { 268 // only force the context root to start with a forward slash 269 // if it is not null 270 if (!contextRoot.startsWith("/")) { 271 //I'm not sure if we should always fix up peculiar context roots. 272 contextRoot = "/" + contextRoot; 273 } 274 } 275 return contextRoot; 276 } 277 278 279 TomcatWebAppType getTomcatWebApp(Object plan, JarFile moduleFile, boolean standAlone, String targetPath, WebAppType webApp) throws DeploymentException { 280 XmlObject rawPlan = null; 281 try { 282 // load the geronimo-web.xml from either the supplied plan or from the earFile 283 try { 284 if (plan instanceof XmlObject) { 285 rawPlan = (XmlObject) plan; 286 } else { 287 if (plan != null) { 288 rawPlan = XmlBeansUtil.parse(((File) plan).toURL(), getClass().getClassLoader()); 289 } else { 290 URL path = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/geronimo-web.xml"); 291 try { 292 rawPlan = XmlBeansUtil.parse(path, getClass().getClassLoader()); 293 } catch (FileNotFoundException e) { 294 path = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/geronimo-tomcat.xml"); 295 try { 296 rawPlan = XmlBeansUtil.parse(path, getClass().getClassLoader()); 297 } catch (FileNotFoundException e1) { 298 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."); 299 } 300 } 301 } 302 } 303 } catch (IOException e) { 304 log.warn(e); 305 } 306 307 TomcatWebAppType tomcatWebApp; 308 if (rawPlan != null) { 309 XmlObject webPlan = new GenericToSpecificPlanConverter(GerTomcatDocument.type.getDocumentElementName().getNamespaceURI(), 310 TomcatWebAppDocument.type.getDocumentElementName().getNamespaceURI(), "tomcat").convertToSpecificPlan(rawPlan); 311 tomcatWebApp = (TomcatWebAppType) webPlan.changeType(TomcatWebAppType.type); 312 XmlBeansUtil.validateDD(tomcatWebApp); 313 } else { 314 tomcatWebApp = createDefaultPlan(); 315 } 316 return tomcatWebApp; 317 } catch (XmlException e) { 318 throw new DeploymentException("xml problem for web app " + targetPath, e); 319 } 320 } 321 322 private TomcatWebAppType createDefaultPlan() { 323 return TomcatWebAppType.Factory.newInstance(); 324 } 325 326 327 public void initContext(EARContext earContext, Module module, ClassLoader cl) throws DeploymentException { 328 TomcatWebAppType gerWebApp = (TomcatWebAppType) module.getVendorDD(); 329 boolean hasSecurityRealmName = gerWebApp.isSetSecurityRealmName(); 330 basicInitContext(earContext, module, gerWebApp, hasSecurityRealmName); 331 for (ModuleBuilderExtension mbe : moduleBuilderExtensions) { 332 mbe.initContext(earContext, module, cl); 333 } 334 } 335 336 public void addGBeans(EARContext earContext, Module module, ClassLoader cl, Collection repository) throws DeploymentException { 337 EARContext moduleContext = module.getEarContext(); 338 ClassLoader webClassLoader = moduleContext.getClassLoader(); 339 AbstractName moduleName = moduleContext.getModuleName(); 340 WebModule webModule = (WebModule) module; 341 342 WebAppType webApp = (WebAppType) webModule.getSpecDD(); 343 344 TomcatWebAppType tomcatWebApp = (TomcatWebAppType) webModule.getVendorDD(); 345 346 GBeanData webModuleData = new GBeanData(moduleName, TomcatWebAppContext.GBEAN_INFO); 347 configureBasicWebModuleAttributes(webApp, tomcatWebApp, moduleContext, earContext, webModule, webModuleData); 348 try { 349 moduleContext.addGBean(webModuleData); 350 Set<String> securityRoles = collectRoleNames(webApp); 351 Map<String, PermissionCollection> rolePermissions = new HashMap<String, PermissionCollection>(); 352 webModuleData.setAttribute("contextPath", webModule.getContextRoot()); 353 // unsharableResources, applicationManagedSecurityResources 354 GBeanResourceEnvironmentBuilder rebuilder = new GBeanResourceEnvironmentBuilder(webModuleData); 355 //N.B. use earContext not moduleContext 356 resourceEnvironmentSetter.setResourceEnvironment(rebuilder, webApp.getResourceRefArray(), tomcatWebApp.getResourceRefArray()); 357 358 if (tomcatWebApp.isSetWebContainer()) { 359 AbstractNameQuery webContainerName = ENCConfigBuilder.getGBeanQuery(NameFactory.GERONIMO_SERVICE, tomcatWebApp.getWebContainer()); 360 webModuleData.setReferencePattern("Container", webContainerName); 361 } else { 362 webModuleData.setReferencePattern("Container", tomcatContainerName); 363 } 364 // Process the Tomcat container-config elements 365 if (tomcatWebApp.isSetHost()) { 366 String virtualServer = tomcatWebApp.getHost().trim(); 367 webModuleData.setAttribute("virtualServer", virtualServer); 368 } 369 if (tomcatWebApp.isSetCrossContext()) { 370 webModuleData.setAttribute("crossContext", Boolean.TRUE); 371 } 372 if (tomcatWebApp.isSetWorkDir()) { 373 String workDir = tomcatWebApp.getWorkDir(); 374 webModuleData.setAttribute("workDir", workDir); 375 } 376 if (tomcatWebApp.isSetDisableCookies()) { 377 webModuleData.setAttribute("disableCookies", Boolean.TRUE); 378 } 379 if (tomcatWebApp.isSetTomcatRealm()) { 380 String tomcatRealm = tomcatWebApp.getTomcatRealm().trim(); 381 AbstractName realmName = earContext.getNaming().createChildName(moduleName, tomcatRealm, RealmGBean.GBEAN_INFO.getJ2eeType()); 382 webModuleData.setReferencePattern("TomcatRealm", realmName); 383 } 384 if (tomcatWebApp.isSetValveChain()) { 385 String valveChain = tomcatWebApp.getValveChain().trim(); 386 AbstractName valveName = earContext.getNaming().createChildName(moduleName, valveChain, ValveGBean.J2EE_TYPE); 387 webModuleData.setReferencePattern("TomcatValveChain", valveName); 388 } 389 390 if (tomcatWebApp.isSetListenerChain()) { 391 String listenerChain = tomcatWebApp.getListenerChain().trim(); 392 AbstractName listenerName = earContext.getNaming().createChildName(moduleName, listenerChain, LifecycleListenerGBean.J2EE_TYPE); 393 webModuleData.setReferencePattern("LifecycleListenerChain", listenerName); 394 } 395 396 if (tomcatWebApp.isSetCluster()) { 397 String cluster = tomcatWebApp.getCluster().trim(); 398 AbstractName clusterName = earContext.getNaming().createChildName(moduleName, cluster, CatalinaClusterGBean.J2EE_TYPE); 399 webModuleData.setReferencePattern("Cluster", clusterName); 400 } 401 402 if (tomcatWebApp.isSetManager()) { 403 String manager = tomcatWebApp.getManager().trim(); 404 AbstractName managerName = earContext.getNaming().createChildName(moduleName, manager, ManagerGBean.J2EE_TYPE); 405 webModuleData.setReferencePattern("Manager", managerName); 406 } 407 408 Boolean distributable = webApp.getDistributableArray().length == 1 ? TRUE : FALSE; 409 if (TRUE == distributable) { 410 clusteringBuilders.build(tomcatWebApp, earContext, moduleContext); 411 if (null == webModuleData.getReferencePatterns(TomcatWebAppContext.GBEAN_REF_CLUSTERED_VALVE_RETRIEVER)) { 412 log.warn("No clustering builders configured: app will not be clustered"); 413 } 414 } 415 416 //Handle the role permissions and webservices on the servlets. 417 ServletType[] servletTypes = webApp.getServletArray(); 418 Map<String, AbstractName> webServices = new HashMap<String, AbstractName>(); 419 Class baseServletClass; 420 try { 421 baseServletClass = webClassLoader.loadClass(Servlet.class.getName()); 422 } catch (ClassNotFoundException e) { 423 throw new DeploymentException("Could not load javax.servlet.Servlet in web classloader", e); // TODO identify web app in message 424 } 425 for (ServletType servletType : servletTypes) { 426 //Handle the Role Ref Permissions 427 processRoleRefPermissions(servletType, securityRoles, rolePermissions); 428 429 if (servletType.isSetServletClass()) { 430 String servletName = servletType.getServletName().getStringValue().trim(); 431 String servletClassName = servletType.getServletClass().getStringValue().trim(); 432 Class servletClass; 433 try { 434 servletClass = webClassLoader.loadClass(servletClassName); 435 } catch (ClassNotFoundException e) { 436 throw new DeploymentException("Could not load servlet class " + servletClassName, e); // TODO identify web app in message 437 } 438 if (!baseServletClass.isAssignableFrom(servletClass)) { 439 //fake servletData 440 AbstractName servletAbstractName = moduleContext.getNaming().createChildName(moduleName, servletName, NameFactory.SERVLET); 441 GBeanData servletData = new GBeanData(); 442 servletData.setAbstractName(servletAbstractName); 443 //let the web service builder deal with configuring the gbean with the web service stack 444 //Here we just extract the factory reference 445 boolean configured = false; 446 for (WebServiceBuilder serviceBuilder : webServiceBuilder) { 447 if (serviceBuilder.configurePOJO(servletData, servletName, module, servletClassName, moduleContext)) { 448 configured = true; 449 break; 450 } 451 } 452 if (!configured) { 453 throw new DeploymentException("POJO web service: " + servletName + " not configured by any web service builder"); 454 } 455 ReferencePatterns patterns = servletData.getReferencePatterns("WebServiceContainerFactory"); 456 AbstractName wsContainerFactoryName = patterns.getAbstractName(); 457 webServices.put(servletName, wsContainerFactoryName); 458 //force all the factories to start before the web app that needs them. 459 webModuleData.addDependency(wsContainerFactoryName); 460 } 461 462 } 463 } 464 465 // JACC v1.0 secion B.19 466 addUnmappedJSPPermissions(securityRoles, rolePermissions); 467 468 webModuleData.setAttribute("webServices", webServices); 469 470 if (tomcatWebApp.isSetSecurityRealmName()) { 471 if (earContext.getSecurityConfiguration() == null) { 472 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)"); 473 } 474 475 SecurityHolder securityHolder = new SecurityHolder(); 476 securityHolder.setSecurityRealm(tomcatWebApp.getSecurityRealmName().trim()); 477 478 webModuleData.setReferencePattern("RunAsSource", earContext.getJaccManagerName()); 479 480 /** 481 * TODO - go back to commented version when possible. 482 */ 483 String policyContextID = moduleName.toString().replaceAll("[, :]", "_"); 484 securityHolder.setPolicyContextID(policyContextID); 485 486 ComponentPermissions componentPermissions = buildSpecSecurityConfig(webApp, securityRoles, rolePermissions); 487 earContext.addSecurityContext(policyContextID, componentPermissions); 488 //TODO WTF is this for? 489 securityHolder.setSecurity(true); 490 491 webModuleData.setAttribute("securityHolder", securityHolder); 492 } 493 494 //listeners added directly to the StandardContext will get loaded by the tomcat classloader, not the app classloader! 495 //TODO this may definitely not be the best place for this! 496 for (ModuleBuilderExtension mbe : moduleBuilderExtensions) { 497 mbe.addGBeans(earContext, module, cl, repository); 498 } 499 //not truly metadata complete until MBEs have run 500 if (!webApp.getMetadataComplete()) { 501 webApp.setMetadataComplete(true); 502 module.setOriginalSpecDD(module.getSpecDD().toString()); 503 } 504 webModuleData.setAttribute("deploymentDescriptor", module.getOriginalSpecDD()); 505 /** 506 * This next bit of code is kind of a kludge to get Tomcat to get a default 507 * web.xml if one does not exist. This is primarily for jaxws. This code is 508 * necessary because Tomcat either has a bug or there is a problem dynamically 509 * adding a wrapper to an already running context. Although the wrapper 510 * can be added, the url mappings do not get picked up at the proper level 511 * and therefore Tomcat cannot dispatch the request. Hence, creating and 512 * writing out a web.xml to the deployed location is the only way around this 513 * until Tomcat fixes that bug. 514 * 515 * For myfaces/jsf, the spec dd may have been updated with a listener. So, we need to write it out again whether or not 516 * there originally was one. This might not work on windows due to file locking problems. 517 */ 518 519 if ((Boolean)module.getSharedContext().get(IS_JAVAEE)) { 520 WebAppType shortWebApp = (WebAppType) webApp.copy(); 521 shortWebApp.setEjbLocalRefArray(new EjbLocalRefType[0]); 522 shortWebApp.setEjbRefArray(new EjbRefType[0]); 523 shortWebApp.setEnvEntryArray(new EnvEntryType[0]); 524 shortWebApp.setMessageDestinationArray(new MessageDestinationType[0]); 525 shortWebApp.setMessageDestinationRefArray(new MessageDestinationRefType[0]); 526 shortWebApp.setPersistenceContextRefArray(new PersistenceContextRefType[0]); 527 shortWebApp.setPersistenceUnitRefArray(new PersistenceUnitRefType[0]); 528 shortWebApp.setPostConstructArray(new LifecycleCallbackType[0]); 529 shortWebApp.setPreDestroyArray(new LifecycleCallbackType[0]); 530 shortWebApp.setResourceEnvRefArray(new ResourceEnvRefType[0]); 531 shortWebApp.setResourceRefArray(new ResourceRefType[0]); 532 shortWebApp.setServiceRefArray(new ServiceRefType[0]); 533 // TODO Tomcat will fail web services tck tests if the following security settings are set in shortWebApp 534 // need to figure out why... 535 //One clue is that without this stuff tomcat does not install an authenticator.... so there's no security 536 // shortWebApp.setSecurityConstraintArray(new SecurityConstraintType[0]); 537 // shortWebApp.setSecurityRoleArray(new SecurityRoleType[0]); 538 File webXml = new File(moduleContext.getBaseDir(), "/WEB-INF/web.xml"); 539 File inPlaceDir = moduleContext.getInPlaceConfigurationDir(); 540 if (inPlaceDir != null) { 541 webXml = new File(inPlaceDir, "/WEB-INF/web.xml"); 542 } 543 // boolean webXmlExists = (inPlaceDir != null && new File(inPlaceDir,"/WEB-INF/web.xml").exists()) || webXml.exists(); 544 // if (!webXmlExists) { 545 webXml.getParentFile().mkdirs(); 546 try { 547 FileWriter outFile = new FileWriter(webXml); 548 549 XmlOptions opts = new XmlOptions(); 550 opts.setSaveAggressiveNamespaces(); 551 opts.setSaveSyntheticDocumentElement(WebAppDocument.type.getDocumentElementName()); 552 opts.setUseDefaultNamespace(); 553 opts.setSavePrettyPrint(); 554 555 // WebAppDocument doc = WebAppDocument.Factory.newInstance(); 556 // doc.setWebApp(webApp); 557 558 outFile.write(shortWebApp.xmlText(opts)); 559 outFile.flush(); 560 outFile.close(); 561 } catch (Exception e) { 562 throw new DeploymentException(e); 563 } 564 // } 565 } 566 567 if (!module.isStandAlone()) { 568 ConfigurationData moduleConfigurationData = moduleContext.getConfigurationData(); 569 earContext.addChildConfiguration(module.getTargetPath(), moduleConfigurationData); 570 } 571 } catch (DeploymentException de) { 572 throw de; 573 } catch (Exception e) { 574 throw new DeploymentException("Unable to initialize GBean for web app " + module.getName(), e); 575 } 576 } 577 578 public String getSchemaNamespace() { 579 return TOMCAT_NAMESPACE; 580 } 581 582 583 public static final GBeanInfo GBEAN_INFO; 584 public static final String GBEAN_REF_CLUSTERING_BUILDERS = "ClusteringBuilders"; 585 586 static { 587 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(TomcatModuleBuilder.class, NameFactory.MODULE_BUILDER); 588 infoBuilder.addAttribute("defaultEnvironment", Environment.class, true, true); 589 infoBuilder.addAttribute("tomcatContainerName", AbstractNameQuery.class, true, true); 590 infoBuilder.addReference("WebServiceBuilder", WebServiceBuilder.class, NameFactory.MODULE_BUILDER); 591 infoBuilder.addReference("SecurityBuilders", NamespaceDrivenBuilder.class, NameFactory.MODULE_BUILDER); 592 infoBuilder.addReference("ServiceBuilders", NamespaceDrivenBuilder.class, NameFactory.MODULE_BUILDER); 593 infoBuilder.addReference("NamingBuilders", NamingBuilder.class, NameFactory.MODULE_BUILDER); 594 infoBuilder.addReference(GBEAN_REF_CLUSTERING_BUILDERS, NamespaceDrivenBuilder.class, NameFactory.MODULE_BUILDER); 595 infoBuilder.addReference("ModuleBuilderExtensions", ModuleBuilderExtension.class, NameFactory.MODULE_BUILDER); 596 infoBuilder.addReference("ResourceEnvironmentSetter", ResourceEnvironmentSetter.class, NameFactory.MODULE_BUILDER); 597 infoBuilder.addAttribute("kernel", Kernel.class, false); 598 infoBuilder.addInterface(ModuleBuilder.class); 599 600 infoBuilder.setConstructor(new String[]{ 601 "defaultEnvironment", 602 "tomcatContainerName", 603 "WebServiceBuilder", 604 "SecurityBuilders", 605 "ServiceBuilders", 606 "NamingBuilders", 607 GBEAN_REF_CLUSTERING_BUILDERS, 608 "ModuleBuilderExtensions", 609 "ResourceEnvironmentSetter", 610 "kernel"}); 611 GBEAN_INFO = infoBuilder.getBeanInfo(); 612 } 613 614 public static GBeanInfo getGBeanInfo() { 615 return GBEAN_INFO; 616 } 617 618 }