1 17 18 package org.apache.geronimo.tomcat.deployment; 19 20 import java.io.File ; 21 import java.io.FileNotFoundException ; 22 import java.io.IOException ; 23 import java.net.URL ; 24 import java.security.Permission ; 25 import java.security.PermissionCollection ; 26 import java.security.Permissions ; 27 import java.util.Collection ; 28 import java.util.Enumeration ; 29 import java.util.HashMap ; 30 import java.util.Iterator ; 31 import java.util.Map ; 32 import java.util.Set ; 33 import java.util.jar.JarFile ; 34 35 import javax.servlet.Servlet ; 36 37 import org.apache.commons.logging.Log; 38 import org.apache.commons.logging.LogFactory; 39 import org.apache.geronimo.common.DeploymentException; 40 import org.apache.geronimo.deployment.ModuleIDBuilder; 41 import org.apache.geronimo.deployment.NamespaceDrivenBuilder; 42 import org.apache.geronimo.deployment.service.EnvironmentBuilder; 43 import org.apache.geronimo.deployment.util.DeploymentUtil; 44 import org.apache.geronimo.deployment.xbeans.EnvironmentType; 45 import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil; 46 import org.apache.geronimo.gbean.AbstractName; 47 import org.apache.geronimo.gbean.AbstractNameQuery; 48 import org.apache.geronimo.gbean.GBeanData; 49 import org.apache.geronimo.gbean.GBeanInfo; 50 import org.apache.geronimo.gbean.GBeanInfoBuilder; 51 import org.apache.geronimo.gbean.ReferencePatterns; 52 import org.apache.geronimo.j2ee.deployment.EARContext; 53 import org.apache.geronimo.j2ee.deployment.Module; 54 import org.apache.geronimo.j2ee.deployment.ModuleBuilder; 55 import org.apache.geronimo.j2ee.deployment.NamingBuilder; 56 import org.apache.geronimo.j2ee.deployment.WebModule; 57 import org.apache.geronimo.j2ee.deployment.WebServiceBuilder; 58 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 59 import org.apache.geronimo.kernel.Kernel; 60 import org.apache.geronimo.kernel.Naming; 61 import org.apache.geronimo.kernel.config.Configuration; 62 import org.apache.geronimo.kernel.config.ConfigurationData; 63 import org.apache.geronimo.kernel.repository.Environment; 64 import org.apache.geronimo.naming.deployment.ENCConfigBuilder; 65 import org.apache.geronimo.naming.deployment.GBeanResourceEnvironmentBuilder; 66 import org.apache.geronimo.naming.deployment.ResourceEnvironmentSetter; 67 import org.apache.geronimo.security.deploy.DefaultPrincipal; 68 import org.apache.geronimo.security.deployment.SecurityConfiguration; 69 import org.apache.geronimo.security.jacc.ComponentPermissions; 70 import org.apache.geronimo.tomcat.ManagerGBean; 71 import org.apache.geronimo.tomcat.RealmGBean; 72 import org.apache.geronimo.tomcat.TomcatWebAppContext; 73 import org.apache.geronimo.tomcat.ValveGBean; 74 import org.apache.geronimo.tomcat.util.SecurityHolder; 75 import org.apache.geronimo.web25.deployment.AbstractWebModuleBuilder; 76 import org.apache.geronimo.web.deployment.GenericToSpecificPlanConverter; 77 import org.apache.geronimo.xbeans.geronimo.web.tomcat.TomcatWebAppDocument; 78 import org.apache.geronimo.xbeans.geronimo.web.tomcat.TomcatWebAppType; 79 import org.apache.geronimo.xbeans.geronimo.web.tomcat.config.GerTomcatDocument; 80 import org.apache.geronimo.xbeans.javaee.ServletType; 81 import org.apache.geronimo.xbeans.javaee.WebAppDocument; 82 import org.apache.geronimo.xbeans.javaee.WebAppType; 83 import org.apache.xmlbeans.XmlException; 84 import org.apache.xmlbeans.XmlObject; 85 86 87 90 public class TomcatModuleBuilder extends AbstractWebModuleBuilder { 91 92 private static final Log log = LogFactory.getLog(TomcatModuleBuilder.class); 93 94 private final Environment defaultEnvironment; 95 private final AbstractNameQuery tomcatContainerName; 96 97 private final Collection webServiceBuilder; 98 99 private static final String TOMCAT_NAMESPACE = TomcatWebAppDocument.type.getDocumentElementName().getNamespaceURI(); 100 101 public TomcatModuleBuilder(Environment defaultEnvironment, 102 AbstractNameQuery tomcatContainerName, 103 Collection webServiceBuilder, 104 Collection securityBuilders, 105 Collection serviceBuilders, 106 NamingBuilder namingBuilders, 107 ResourceEnvironmentSetter resourceEnvironmentSetter, 108 Kernel kernel) { 109 super(kernel, securityBuilders, serviceBuilders, namingBuilders, resourceEnvironmentSetter); 110 this.defaultEnvironment = defaultEnvironment; 111 112 this.tomcatContainerName = tomcatContainerName; 113 this.webServiceBuilder = webServiceBuilder; 114 } 115 116 protected Module createModule(Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, boolean standAlone, String contextRoot, AbstractName earName, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException { 117 assert moduleFile != null: "moduleFile is null"; 118 assert targetPath != null: "targetPath is null"; 119 assert !targetPath.endsWith("/"): "targetPath must not end with a '/'"; 120 121 String specDD; 123 WebAppType webApp; 124 try { 125 if (specDDUrl == null) { 126 specDDUrl = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/web.xml"); 127 } 128 129 specDD = DeploymentUtil.readAll(specDDUrl); 132 } catch (Exception e) { 133 return null; 135 } 136 try { 138 XmlObject parsed = XmlBeansUtil.parse(specDD); 140 WebAppDocument webAppDoc = convertToServletSchema(parsed); 141 webApp = webAppDoc.getWebApp(); 142 } catch (XmlException xmle) { 143 throw new DeploymentException("Error parsing web.xml for " + targetPath, xmle); 147 } 148 check(webApp); 149 150 TomcatWebAppType tomcatWebApp = getTomcatWebApp(plan, moduleFile, standAlone, targetPath, webApp); 152 153 if (contextRoot == null || contextRoot.trim().equals("")) { 154 if (tomcatWebApp.isSetContextRoot()) { 155 contextRoot = tomcatWebApp.getContextRoot(); 156 } else { 157 contextRoot = determineDefaultContextRoot(webApp, standAlone, moduleFile, targetPath); 158 } 159 } 160 161 contextRoot = contextRoot.trim(); 162 163 EnvironmentType environmentType = tomcatWebApp.getEnvironment(); 164 Environment environment = EnvironmentBuilder.buildEnvironment(environmentType, defaultEnvironment); 165 166 getNamingBuilders().buildEnvironment(webApp, tomcatWebApp, environment); 167 168 String warName = ""; 170 File temp = new File (moduleFile.getName()); 171 if(temp.isFile()) { 172 warName = temp.getName(); 173 if(warName.lastIndexOf('.') > -1) { 174 warName = warName.substring(0, warName.lastIndexOf('.')); 175 } 176 } else { 177 try { 178 warName = temp.getCanonicalFile().getName(); 179 if(warName.equals("")) { 180 warName = "$root-dir$"; 182 } 183 } catch (IOException e) { 184 } 185 } 186 idBuilder.resolve(environment, warName, "war"); 187 188 Map servletNameToPathMap = buildServletNameToPathMap(webApp, contextRoot); 189 190 Map sharedContext = new HashMap (); 191 for (Iterator iterator = webServiceBuilder.iterator(); iterator.hasNext();) { 192 WebServiceBuilder serviceBuilder = (WebServiceBuilder) iterator.next(); 193 serviceBuilder.findWebServices(moduleFile, false, servletNameToPathMap, environment, sharedContext); 194 } 195 AbstractName moduleName; 196 if (earName == null) { 197 earName = naming.createRootName(environment.getConfigId(), NameFactory.NULL, NameFactory.J2EE_APPLICATION); 198 moduleName = naming.createChildName(earName, environment.getConfigId().toString(), NameFactory.WEB_MODULE); 199 } else { 200 moduleName = naming.createChildName(earName, targetPath, NameFactory.WEB_MODULE); 201 } 202 203 return new WebModule(standAlone, moduleName, environment, moduleFile, targetPath, webApp, tomcatWebApp, specDD, contextRoot, sharedContext, TOMCAT_NAMESPACE); 204 } 205 206 207 TomcatWebAppType getTomcatWebApp(Object plan, JarFile moduleFile, boolean standAlone, String targetPath, WebAppType webApp) throws DeploymentException { 208 XmlObject rawPlan = null; 209 try { 210 try { 212 if (plan instanceof XmlObject) { 213 rawPlan = (XmlObject) plan; 214 } else { 215 if (plan != null) { 216 rawPlan = XmlBeansUtil.parse(((File ) plan).toURL(), getClass().getClassLoader()); 217 } else { 218 URL path = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/geronimo-web.xml"); 219 try { 220 rawPlan = XmlBeansUtil.parse(path, getClass().getClassLoader()); 221 } catch (FileNotFoundException e) { 222 path = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/geronimo-tomcat.xml"); 223 try { 224 rawPlan = XmlBeansUtil.parse(path, getClass().getClassLoader()); 225 } catch (FileNotFoundException e1) { 226 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."); 227 } 228 } 229 } 230 } 231 } catch (IOException e) { 232 log.warn(e); 233 } 234 235 TomcatWebAppType tomcatWebApp; 236 if (rawPlan != null) { 237 XmlObject webPlan = new GenericToSpecificPlanConverter(GerTomcatDocument.type.getDocumentElementName().getNamespaceURI(), 238 TomcatWebAppDocument.type.getDocumentElementName().getNamespaceURI(), "tomcat").convertToSpecificPlan(rawPlan); 239 tomcatWebApp = (TomcatWebAppType) webPlan.changeType(TomcatWebAppType.type); 240 XmlBeansUtil.validateDD(tomcatWebApp); 241 } else { 242 String defaultContextRoot = determineDefaultContextRoot(webApp, standAlone, moduleFile, targetPath); 243 tomcatWebApp = createDefaultPlan(defaultContextRoot); 244 } 245 return tomcatWebApp; 246 } catch (XmlException e) { 247 throw new DeploymentException("xml problem for web app " + targetPath, e); 248 } 249 } 250 251 private TomcatWebAppType createDefaultPlan(String path) { 252 TomcatWebAppType tomcatWebApp = TomcatWebAppType.Factory.newInstance(); 253 if (path!=null && !path.startsWith("/")) { 254 tomcatWebApp.setContextRoot("/" + path); 255 } else { 256 tomcatWebApp.setContextRoot(path); 257 } 258 return tomcatWebApp; 259 } 260 261 262 public void initContext(EARContext earContext, Module module, ClassLoader cl) throws DeploymentException { 263 WebAppType webApp = (WebAppType) module.getSpecDD(); 264 TomcatWebAppType gerWebApp = (TomcatWebAppType) module.getVendorDD(); 266 268 getNamingBuilders().initContext(webApp, gerWebApp, module.getEarContext().getConfiguration(), earContext.getConfiguration(), module); 270 if ((webApp.getSecurityConstraintArray().length > 0 || webApp.getSecurityRoleArray().length > 0) && 271 !gerWebApp.isSetSecurityRealmName()) { 272 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."); 273 } 274 boolean hasSecurityRealmName = gerWebApp.isSetSecurityRealmName(); 275 buildSubstitutionGroups(gerWebApp, hasSecurityRealmName, module, earContext); 276 } 277 278 public void addGBeans(EARContext earContext, Module module, ClassLoader cl, Collection repository) throws DeploymentException { 279 EARContext moduleContext = module.getEarContext(); 280 ClassLoader webClassLoader = moduleContext.getClassLoader(); 281 AbstractName moduleName = moduleContext.getModuleName(); 282 WebModule webModule = (WebModule) module; 283 284 WebAppType webApp = (WebAppType) webModule.getSpecDD(); 285 TomcatWebAppType tomcatWebApp = (TomcatWebAppType) webModule.getVendorDD(); 286 287 GBeanData webModuleData = new GBeanData(moduleName, TomcatWebAppContext.GBEAN_INFO); 288 try { 289 webModuleData.setReferencePattern("J2EEServer", moduleContext.getServerName()); 290 if (!module.isStandAlone()) { 291 webModuleData.setReferencePattern("J2EEApplication", earContext.getModuleName()); 292 } 293 294 webModuleData.setAttribute("deploymentDescriptor", module.getOriginalSpecDD()); 295 Set securityRoles = collectRoleNames(webApp); 296 Map rolePermissions = new HashMap (); 297 298 webModuleData.setAttribute("contextPath", webModule.getContextRoot()); 299 300 Set dependencies = findGBeanDependencies(earContext); 304 webModuleData.addDependencies(dependencies); 305 306 Map buildingContext = new HashMap (); 308 buildingContext.put(NamingBuilder.JNDI_KEY, new HashMap ()); 309 buildingContext.put(NamingBuilder.GBEAN_NAME_KEY, moduleName); 310 Configuration earConfiguration = earContext.getConfiguration(); 311 getNamingBuilders().buildNaming(webApp, tomcatWebApp, earConfiguration, earConfiguration, webModule, buildingContext); 312 Map compContext = (Map ) buildingContext.get(NamingBuilder.JNDI_KEY); 313 314 webModuleData.setAttribute("componentContext", compContext); 315 GBeanResourceEnvironmentBuilder rebuilder = new GBeanResourceEnvironmentBuilder(webModuleData); 317 resourceEnvironmentSetter.setResourceEnvironment(rebuilder, webApp.getResourceRefArray(), tomcatWebApp.getResourceRefArray()); 319 320 webModuleData.setReferencePattern("TransactionManager", earContext.getTransactionManagerName()); 321 webModuleData.setReferencePattern("TrackedConnectionAssociator", earContext.getConnectionTrackerName()); 322 323 if (tomcatWebApp.isSetWebContainer()) { 324 AbstractNameQuery webContainerName = ENCConfigBuilder.getGBeanQuery(NameFactory.GERONIMO_SERVICE, tomcatWebApp.getWebContainer()); 325 webModuleData.setReferencePattern("Container", webContainerName); 326 } else { 327 webModuleData.setReferencePattern("Container", tomcatContainerName); 328 } 329 if (tomcatWebApp.isSetHost()) { 331 String virtualServer = tomcatWebApp.getHost().trim(); 332 webModuleData.setAttribute("virtualServer", virtualServer); 333 } 334 if (tomcatWebApp.isSetCrossContext()) { 335 webModuleData.setAttribute("crossContext", Boolean.TRUE); 336 } 337 if (tomcatWebApp.isSetDisableCookies()) { 338 webModuleData.setAttribute("disableCookies", Boolean.TRUE); 339 } 340 if (tomcatWebApp.isSetTomcatRealm()) { 341 String tomcatRealm = tomcatWebApp.getTomcatRealm().trim(); 342 AbstractName realmName = earContext.getNaming().createChildName(moduleName, tomcatRealm, RealmGBean.GBEAN_INFO.getJ2eeType()); 343 webModuleData.setReferencePattern("TomcatRealm", realmName); 344 } 345 if (tomcatWebApp.isSetValveChain()) { 346 String valveChain = tomcatWebApp.getValveChain().trim(); 347 AbstractName valveName = earContext.getNaming().createChildName(moduleName, valveChain, ValveGBean.J2EE_TYPE); 348 webModuleData.setReferencePattern("TomcatValveChain", valveName); 349 } 350 351 357 if (tomcatWebApp.isSetManager()) { 358 String manager = tomcatWebApp.getManager().trim(); 359 AbstractName managerName = earContext.getNaming().createChildName(moduleName, manager, ManagerGBean.J2EE_TYPE); 360 webModuleData.setReferencePattern("Manager", managerName); 361 } 362 Map portMap = webModule.getSharedContext(); 363 364 ServletType[] servletTypes = webApp.getServletArray(); 366 Map webServices = new HashMap (); 367 Class baseServletClass; 368 try { 369 baseServletClass = webClassLoader.loadClass(Servlet .class.getName()); 370 } catch (ClassNotFoundException e) { 371 throw new DeploymentException("Could not load javax.servlet.Servlet in web classloader", e); } 373 for (int i = 0; i < servletTypes.length; i++) { 374 ServletType servletType = servletTypes[i]; 375 376 processRoleRefPermissions(servletType, securityRoles, rolePermissions); 378 379 if (servletType.isSetServletClass()) { 380 String servletName = servletType.getServletName().getStringValue().trim(); 381 String servletClassName = servletType.getServletClass().getStringValue().trim(); 382 Class servletClass; 383 try { 384 servletClass = webClassLoader.loadClass(servletClassName); 385 } catch (ClassNotFoundException e) { 386 throw new DeploymentException("Could not load servlet class " + servletClassName, e); } 388 if (!baseServletClass.isAssignableFrom(servletClass)) { 389 AbstractName servletAbstractName = moduleContext.getNaming().createChildName(moduleName, servletName, NameFactory.SERVLET); 391 GBeanData servletData = new GBeanData(); 392 servletData.setAbstractName(servletAbstractName); 393 boolean configured = false; 396 for (Iterator iterator = webServiceBuilder.iterator(); iterator.hasNext();) { 397 WebServiceBuilder serviceBuilder = (WebServiceBuilder) iterator.next(); 398 if (serviceBuilder.configurePOJO(servletData, servletName, module, servletClassName, moduleContext)) { 399 configured = true; 400 break; 401 } 402 } 403 if (!configured) { 404 throw new DeploymentException("POJO web service: " + servletName + " not configured by any web service builder"); 405 } 406 ReferencePatterns patterns = servletData.getReferencePatterns("WebServiceContainerFactory"); 407 AbstractName wsContainerFactoryName = patterns.getAbstractName(); 408 webServices.put(servletName, wsContainerFactoryName); 409 webModuleData.addDependency(wsContainerFactoryName); 411 } 412 } 413 } 414 415 addUnmappedJSPPermissions(securityRoles, rolePermissions); 417 418 webModuleData.setAttribute("webServices", webServices); 419 420 if (tomcatWebApp.isSetSecurityRealmName()) { 421 if (earContext.getSecurityConfiguration() == null) { 422 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)"); 423 } 424 425 SecurityHolder securityHolder = new SecurityHolder(); 426 securityHolder.setSecurityRealm(tomcatWebApp.getSecurityRealmName().trim()); 427 428 431 String policyContextID = moduleName.toString().replaceAll("[, :]", "_"); 432 securityHolder.setPolicyContextID(policyContextID); 433 434 ComponentPermissions componentPermissions = buildSpecSecurityConfig(webApp, securityRoles, rolePermissions); 435 securityHolder.setExcluded(componentPermissions.getExcludedPermissions()); 436 PermissionCollection checkedPermissions = new Permissions (); 437 for (Iterator iterator = rolePermissions.values().iterator(); iterator.hasNext();) { 438 PermissionCollection permissionsForRole = (PermissionCollection ) iterator.next(); 439 for (Enumeration iterator2 = permissionsForRole.elements(); iterator2.hasMoreElements();) { 440 Permission permission = (Permission ) iterator2.nextElement(); 441 checkedPermissions.add(permission); 442 } 443 } 444 securityHolder.setChecked(checkedPermissions); 445 earContext.addSecurityContext(policyContextID, componentPermissions); 446 DefaultPrincipal defaultPrincipal = ((SecurityConfiguration) earContext.getSecurityConfiguration()).getDefaultPrincipal(); 447 securityHolder.setDefaultPrincipal(defaultPrincipal); 448 if (defaultPrincipal != null) { 449 securityHolder.setSecurity(true); 450 } 451 452 webModuleData.setAttribute("securityHolder", securityHolder); 453 } 454 455 moduleContext.addGBean(webModuleData); 456 457 if (!module.isStandAlone()) { 458 ConfigurationData moduleConfigurationData = moduleContext.getConfigurationData(); 459 earContext.addChildConfiguration(module.getTargetPath(), moduleConfigurationData); 460 } 461 } catch (DeploymentException de) { 462 throw de; 463 } catch (Exception e) { 464 throw new DeploymentException("Unable to initialize GBean for web app " + module.getName(), e); 465 } 466 } 467 468 public String getSchemaNamespace() { 469 return TOMCAT_NAMESPACE; 470 } 471 472 473 public static final GBeanInfo GBEAN_INFO; 474 475 static { 476 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(TomcatModuleBuilder.class, NameFactory.MODULE_BUILDER); 477 infoBuilder.addAttribute("defaultEnvironment", Environment.class, true, true); 478 infoBuilder.addAttribute("tomcatContainerName", AbstractNameQuery.class, true, true); 479 infoBuilder.addReference("WebServiceBuilder", WebServiceBuilder.class, NameFactory.MODULE_BUILDER); 480 infoBuilder.addReference("SecurityBuilders", NamespaceDrivenBuilder.class, NameFactory.MODULE_BUILDER); 481 infoBuilder.addReference("ServiceBuilders", NamespaceDrivenBuilder.class, NameFactory.MODULE_BUILDER); 482 infoBuilder.addReference("NamingBuilders", NamingBuilder.class, NameFactory.MODULE_BUILDER); 483 infoBuilder.addReference("ResourceEnvironmentSetter", ResourceEnvironmentSetter.class, NameFactory.MODULE_BUILDER); 484 infoBuilder.addAttribute("kernel", Kernel.class, false); 485 infoBuilder.addInterface(ModuleBuilder.class); 486 487 infoBuilder.setConstructor(new String []{ 488 "defaultEnvironment", 489 "tomcatContainerName", 490 "WebServiceBuilder", 491 "SecurityBuilders", 492 "ServiceBuilders", 493 "NamingBuilders", 494 "ResourceEnvironmentSetter", 495 "kernel"}); 496 GBEAN_INFO = infoBuilder.getBeanInfo(); 497 } 498 499 public static GBeanInfo getGBeanInfo() { 500 return GBEAN_INFO; 501 } 502 503 } 504 | Popular Tags |