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 package org.apache.geronimo.web.deployment; 019 020 import java.io.File; 021 import java.io.IOException; 022 import java.net.URI; 023 import java.net.URISyntaxException; 024 import java.net.URL; 025 import java.security.Permission; 026 import java.security.PermissionCollection; 027 import java.security.Permissions; 028 import java.util.Collection; 029 import java.util.Collections; 030 import java.util.Enumeration; 031 import java.util.HashMap; 032 import java.util.HashSet; 033 import java.util.Iterator; 034 import java.util.LinkedList; 035 import java.util.Map; 036 import java.util.Set; 037 import java.util.List; 038 import java.util.ArrayList; 039 import java.util.jar.JarFile; 040 import java.util.zip.ZipEntry; 041 042 import javax.security.jacc.WebResourcePermission; 043 import javax.security.jacc.WebRoleRefPermission; 044 import javax.security.jacc.WebUserDataPermission; 045 import javax.xml.namespace.QName; 046 047 import org.apache.commons.logging.Log; 048 import org.apache.commons.logging.LogFactory; 049 import org.apache.geronimo.common.DeploymentException; 050 import org.apache.geronimo.deployment.util.DeploymentUtil; 051 import org.apache.geronimo.deployment.ModuleIDBuilder; 052 import org.apache.geronimo.deployment.NamespaceDrivenBuilderCollection; 053 import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil; 054 import org.apache.geronimo.deployment.xbeans.ServiceDocument; 055 import org.apache.geronimo.gbean.AbstractName; 056 import org.apache.geronimo.gbean.AbstractNameQuery; 057 import org.apache.geronimo.j2ee.deployment.EARContext; 058 import org.apache.geronimo.j2ee.deployment.Module; 059 import org.apache.geronimo.j2ee.deployment.ModuleBuilder; 060 import org.apache.geronimo.j2ee.deployment.NamingBuilder; 061 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 062 import org.apache.geronimo.kernel.Kernel; 063 import org.apache.geronimo.kernel.Naming; 064 import org.apache.geronimo.kernel.config.ConfigurationModuleType; 065 import org.apache.geronimo.kernel.config.ConfigurationStore; 066 import org.apache.geronimo.kernel.repository.Artifact; 067 import org.apache.geronimo.kernel.repository.Environment; 068 import org.apache.geronimo.kernel.repository.ImportType; 069 import org.apache.geronimo.security.jacc.ComponentPermissions; 070 import org.apache.geronimo.security.util.URLPattern; 071 import org.apache.geronimo.xbeans.j2ee.FilterMappingType; 072 import org.apache.geronimo.xbeans.j2ee.HttpMethodType; 073 import org.apache.geronimo.xbeans.j2ee.RoleNameType; 074 import org.apache.geronimo.xbeans.j2ee.SecurityConstraintType; 075 import org.apache.geronimo.xbeans.j2ee.SecurityRoleRefType; 076 import org.apache.geronimo.xbeans.j2ee.SecurityRoleType; 077 import org.apache.geronimo.xbeans.j2ee.ServletMappingType; 078 import org.apache.geronimo.xbeans.j2ee.ServletType; 079 import org.apache.geronimo.xbeans.j2ee.UrlPatternType; 080 import org.apache.geronimo.xbeans.j2ee.WebAppType; 081 import org.apache.geronimo.xbeans.j2ee.WebResourceCollectionType; 082 import org.apache.geronimo.xbeans.j2ee.WebAppDocument; 083 import org.apache.geronimo.xbeans.geronimo.j2ee.GerSecurityDocument; 084 import org.apache.geronimo.naming.deployment.ResourceEnvironmentSetter; 085 import org.apache.geronimo.schema.SchemaConversionUtils; 086 import org.apache.xmlbeans.XmlObject; 087 import org.apache.xmlbeans.XmlException; 088 import org.apache.xmlbeans.XmlCursor; 089 import org.apache.xmlbeans.XmlDocumentProperties; 090 091 /** 092 * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $ 093 */ 094 public abstract class AbstractWebModuleBuilder implements ModuleBuilder { 095 private static final Log log = LogFactory.getLog(AbstractWebModuleBuilder.class); 096 private static final QName TAGLIB = new QName(SchemaConversionUtils.J2EE_NAMESPACE, "taglib"); 097 private static final String LINE_SEP = System.getProperty("line.separator"); 098 099 protected static final AbstractNameQuery MANAGED_CONNECTION_FACTORY_PATTERN; 100 private static final AbstractNameQuery ADMIN_OBJECT_PATTERN; 101 protected static final AbstractNameQuery STATELESS_SESSION_BEAN_PATTERN; 102 protected static final AbstractNameQuery STATEFUL_SESSION_BEAN_PATTERN; 103 protected static final AbstractNameQuery ENTITY_BEAN_PATTERN; 104 protected final Kernel kernel; 105 protected final NamespaceDrivenBuilderCollection securityBuilders; 106 protected final NamespaceDrivenBuilderCollection serviceBuilders; 107 protected final ResourceEnvironmentSetter resourceEnvironmentSetter; 108 109 protected final NamingBuilder namingBuilders; 110 111 private static final QName SECURITY_QNAME = GerSecurityDocument.type.getDocumentElementName(); 112 private static final QName SERVICE_QNAME = ServiceDocument.type.getDocumentElementName(); 113 114 /** 115 * Manifest classpath entries in a war configuration must be resolved relative to the war configuration, not the 116 * enclosing ear configuration. Resolving relative to he war configuration using this offset produces the same 117 * effect as URI.create(module.targetPath()).resolve(mcpEntry) executed in the ear configuration. 118 */ 119 private static final URI RELATIVE_MODULE_BASE_URI = URI.create("../"); 120 121 protected AbstractWebModuleBuilder(Kernel kernel, Collection securityBuilders, Collection serviceBuilders, NamingBuilder namingBuilders, ResourceEnvironmentSetter resourceEnvironmentSetter) { 122 this.kernel = kernel; 123 this.securityBuilders = new NamespaceDrivenBuilderCollection(securityBuilders); 124 this.serviceBuilders = new NamespaceDrivenBuilderCollection(serviceBuilders); 125 this.namingBuilders = namingBuilders; 126 this.resourceEnvironmentSetter = resourceEnvironmentSetter; 127 } 128 129 static { 130 MANAGED_CONNECTION_FACTORY_PATTERN = new AbstractNameQuery(null, Collections.singletonMap(NameFactory.J2EE_TYPE, NameFactory.JCA_MANAGED_CONNECTION_FACTORY)); 131 ADMIN_OBJECT_PATTERN = new AbstractNameQuery(null, Collections.singletonMap(NameFactory.J2EE_TYPE, NameFactory.JCA_ADMIN_OBJECT)); 132 STATELESS_SESSION_BEAN_PATTERN = new AbstractNameQuery(null, Collections.singletonMap(NameFactory.J2EE_TYPE, NameFactory.STATELESS_SESSION_BEAN)); 133 STATEFUL_SESSION_BEAN_PATTERN = new AbstractNameQuery(null, Collections.singletonMap(NameFactory.J2EE_TYPE, NameFactory.STATEFUL_SESSION_BEAN)); 134 ENTITY_BEAN_PATTERN = new AbstractNameQuery(null, Collections.singletonMap(NameFactory.J2EE_TYPE, NameFactory.ENTITY_BEAN)); 135 136 } 137 138 public NamingBuilder getNamingBuilders() { 139 return namingBuilders; 140 } 141 142 //TODO configid these need to be converted to ReferencePatterns 143 protected Set findGBeanDependencies(EARContext earContext) { 144 Set dependencies = new HashSet(); 145 dependencies.addAll(earContext.listGBeans(MANAGED_CONNECTION_FACTORY_PATTERN)); 146 dependencies.addAll(earContext.listGBeans(ADMIN_OBJECT_PATTERN)); 147 dependencies.addAll(earContext.listGBeans(STATELESS_SESSION_BEAN_PATTERN)); 148 dependencies.addAll(earContext.listGBeans(STATEFUL_SESSION_BEAN_PATTERN)); 149 dependencies.addAll(earContext.listGBeans(ENTITY_BEAN_PATTERN)); 150 return dependencies; 151 } 152 153 public Module createModule(File plan, JarFile moduleFile, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException { 154 return createModule(plan, moduleFile, ".", null, true, null, null, naming, idBuilder); 155 } 156 157 public Module createModule(Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, Environment environment, Object moduleContextInfo, AbstractName earName, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException { 158 return createModule(plan, moduleFile, targetPath, specDDUrl, false, (String) moduleContextInfo, earName, naming, idBuilder); 159 } 160 161 protected abstract Module createModule(Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, boolean standAlone, String contextRoot, AbstractName earName, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException; 162 163 /** 164 * Some servlets will have multiple url patterns. However, webservice servlets 165 * will only have one, which is what this method is intended for. 166 * 167 * @param webApp 168 * @param contextRoot 169 * @return map of servlet names to path mapped to them. Possibly inaccurate except for web services. 170 */ 171 protected Map buildServletNameToPathMap(WebAppType webApp, String contextRoot) { 172 contextRoot = "/" + contextRoot; 173 Map map = new HashMap(); 174 ServletMappingType[] servletMappings = webApp.getServletMappingArray(); 175 for (int j = 0; j < servletMappings.length; j++) { 176 ServletMappingType servletMapping = servletMappings[j]; 177 String servletName = servletMapping.getServletName().getStringValue().trim(); 178 map.put(servletName, contextRoot + servletMapping.getUrlPattern().getStringValue().trim()); 179 } 180 return map; 181 } 182 183 protected String determineDefaultContextRoot(WebAppType webApp, boolean isStandAlone, JarFile moduleFile, String targetPath) { 184 185 if (webApp != null && webApp.getId() != null) { 186 return webApp.getId(); 187 } 188 189 if (isStandAlone) { 190 // default configId is based on the moduleFile name 191 return trimPath(new File(moduleFile.getName()).getName()); 192 } 193 194 // default configId is based on the module uri from the application.xml 195 return trimPath(targetPath); 196 } 197 198 private String trimPath(String path) { 199 200 if (path == null) { 201 return null; 202 } 203 204 if (path.endsWith(".war")) { 205 path = path.substring(0, path.length() - 4); 206 } 207 if (path.endsWith("/")) { 208 path = path.substring(0, path.length() - 1); 209 } 210 211 return path; 212 } 213 214 public void installModule(JarFile earFile, EARContext earContext, Module module, Collection configurationStores, ConfigurationStore targetConfigurationStore, Collection repositories) throws DeploymentException { 215 EARContext moduleContext; 216 if (module.isStandAlone()) { 217 moduleContext = earContext; 218 } else { 219 Environment environment = module.getEnvironment(); 220 Artifact earConfigId = earContext.getConfigID(); 221 Artifact configId = new Artifact(earConfigId.getGroupId(), earConfigId.getArtifactId() + "_" + module.getTargetPath(), earConfigId.getVersion(), "car"); 222 environment.setConfigId(configId); 223 environment.addDependency(earConfigId, ImportType.ALL); 224 File configurationDir = new File(earContext.getBaseDir(), module.getTargetPath()); 225 configurationDir.mkdirs(); 226 227 // construct the web app deployment context... this is the same class used by the ear context 228 try { 229 File inPlaceConfigurationDir = null; 230 if (null != earContext.getInPlaceConfigurationDir()) { 231 inPlaceConfigurationDir = new File(earContext.getInPlaceConfigurationDir(), module.getTargetPath()); 232 } 233 moduleContext = new EARContext(configurationDir, 234 inPlaceConfigurationDir, 235 environment, 236 ConfigurationModuleType.WAR, 237 module.getModuleName(), 238 earContext); 239 } catch (DeploymentException e) { 240 cleanupConfigurationDir(configurationDir); 241 throw e; 242 } 243 } 244 module.setEarContext(moduleContext); 245 module.setRootEarContext(earContext); 246 247 try { 248 249 // add the warfile's content to the configuration 250 JarFile warFile = module.getModuleFile(); 251 Enumeration entries = warFile.entries(); 252 List libs = new ArrayList(); 253 while (entries.hasMoreElements()) { 254 ZipEntry entry = (ZipEntry) entries.nextElement(); 255 URI targetPath = new URI(null, entry.getName(), null); 256 if (entry.getName().equals("WEB-INF/web.xml")) { 257 moduleContext.addFile(targetPath, module.getOriginalSpecDD()); 258 } else if (entry.getName().startsWith("WEB-INF/lib") && entry.getName().endsWith(".jar")) { 259 // keep a collection of all libs in the war 260 // libs must be installed after WEB-INF/classes which must be installed after this copy phase 261 libs.add(entry); 262 } else { 263 moduleContext.addFile(targetPath, warFile, entry); 264 } 265 } 266 267 // always add WEB-INF/classes to the classpath regardless of whether 268 // any classes exist. This must be searched BEFORE the WEB-INF/lib jar files, 269 // per the servlet specifications. 270 moduleContext.getConfiguration().addToClassPath("WEB-INF/classes/"); 271 272 // install the libs 273 for (Iterator iterator = libs.iterator(); iterator.hasNext();) { 274 ZipEntry entry = (ZipEntry) iterator.next(); 275 URI targetPath = new URI(null, entry.getName(), null); 276 moduleContext.addInclude(targetPath, warFile, entry); 277 } 278 279 // add the manifest classpath entries declared in the war to the class loader 280 // we have to explicitly add these since we are unpacking the web module 281 // and the url class loader will not pick up a manifest from an unpacked dir 282 moduleContext.addManifestClassPath(warFile, RELATIVE_MODULE_BASE_URI); 283 284 } catch (IOException e) { 285 throw new DeploymentException("Problem deploying war", e); 286 } catch (URISyntaxException e) { 287 throw new DeploymentException("Could not construct URI for location of war entry", e); 288 } finally { 289 if (!module.isStandAlone()) { 290 try { 291 moduleContext.flush(); 292 } catch (IOException e) { 293 throw new DeploymentException("Problem closing war context", e); 294 } 295 } 296 } 297 } 298 299 protected void addUnmappedJSPPermissions(Set securityRoles, Map rolePermissions) { 300 for (Iterator iter = securityRoles.iterator(); iter.hasNext();) { 301 String roleName = (String) iter.next(); 302 addPermissionToRole(roleName, new WebRoleRefPermission("", roleName), rolePermissions); 303 } 304 } 305 306 protected ComponentPermissions buildSpecSecurityConfig(WebAppType webApp, Set securityRoles, Map rolePermissions) { 307 Map uncheckedPatterns = new HashMap(); 308 Map uncheckedResourcePatterns = new HashMap(); 309 Map uncheckedUserPatterns = new HashMap(); 310 Map excludedPatterns = new HashMap(); 311 Map rolesPatterns = new HashMap(); 312 Set allSet = new HashSet(); // == allMap.values() 313 Map allMap = new HashMap(); //uncheckedPatterns union excludedPatterns union rolesPatterns. 314 315 SecurityConstraintType[] securityConstraintArray = webApp.getSecurityConstraintArray(); 316 for (int i = 0; i < securityConstraintArray.length; i++) { 317 SecurityConstraintType securityConstraintType = securityConstraintArray[i]; 318 Map currentPatterns; 319 if (securityConstraintType.isSetAuthConstraint()) { 320 if (securityConstraintType.getAuthConstraint().getRoleNameArray().length == 0) { 321 currentPatterns = excludedPatterns; 322 } else { 323 currentPatterns = rolesPatterns; 324 } 325 } else { 326 currentPatterns = uncheckedPatterns; 327 } 328 329 String transport = ""; 330 if (securityConstraintType.isSetUserDataConstraint()) { 331 transport = securityConstraintType.getUserDataConstraint().getTransportGuarantee().getStringValue().trim().toUpperCase(); 332 } 333 334 WebResourceCollectionType[] webResourceCollectionTypeArray = securityConstraintType.getWebResourceCollectionArray(); 335 for (int j = 0; j < webResourceCollectionTypeArray.length; j++) { 336 WebResourceCollectionType webResourceCollectionType = webResourceCollectionTypeArray[j]; 337 UrlPatternType[] urlPatternTypeArray = webResourceCollectionType.getUrlPatternArray(); 338 for (int k = 0; k < urlPatternTypeArray.length; k++) { 339 UrlPatternType urlPatternType = urlPatternTypeArray[k]; 340 String url = urlPatternType.getStringValue().trim(); 341 URLPattern pattern = (URLPattern) currentPatterns.get(url); 342 if (pattern == null) { 343 pattern = new URLPattern(url); 344 currentPatterns.put(url, pattern); 345 } 346 347 URLPattern allPattern = (URLPattern) allMap.get(url); 348 if (allPattern == null) { 349 allPattern = new URLPattern(url); 350 allSet.add(allPattern); 351 allMap.put(url, allPattern); 352 } 353 354 HttpMethodType[] httpMethodTypeArray = webResourceCollectionType.getHttpMethodArray(); 355 if (httpMethodTypeArray.length == 0) { 356 pattern.addMethod(""); 357 allPattern.addMethod(""); 358 } else { 359 for (int l = 0; l < httpMethodTypeArray.length; l++) { 360 HttpMethodType httpMethodType = httpMethodTypeArray[l]; 361 //TODO is trim OK? 362 String method = httpMethodType.getStringValue().trim(); 363 pattern.addMethod(method); 364 allPattern.addMethod(method); 365 } 366 } 367 if (currentPatterns == rolesPatterns) { 368 RoleNameType[] roleNameTypeArray = securityConstraintType.getAuthConstraint().getRoleNameArray(); 369 for (int l = 0; l < roleNameTypeArray.length; l++) { 370 RoleNameType roleNameType = roleNameTypeArray[l]; 371 String role = roleNameType.getStringValue().trim(); 372 if (role.equals("*")) { 373 pattern.addAllRoles(securityRoles); 374 } else { 375 pattern.addRole(role); 376 } 377 } 378 } 379 380 pattern.setTransport(transport); 381 } 382 } 383 } 384 385 PermissionCollection excludedPermissions = new Permissions(); 386 PermissionCollection uncheckedPermissions = new Permissions(); 387 388 Iterator iter = excludedPatterns.keySet().iterator(); 389 while (iter.hasNext()) { 390 URLPattern pattern = (URLPattern) excludedPatterns.get(iter.next()); 391 String name = pattern.getQualifiedPattern(allSet); 392 String actions = pattern.getMethods(); 393 394 excludedPermissions.add(new WebResourcePermission(name, actions)); 395 excludedPermissions.add(new WebUserDataPermission(name, actions)); 396 } 397 398 iter = rolesPatterns.keySet().iterator(); 399 while (iter.hasNext()) { 400 URLPattern pattern = (URLPattern) rolesPatterns.get(iter.next()); 401 String name = pattern.getQualifiedPattern(allSet); 402 String actions = pattern.getMethods(); 403 WebResourcePermission permission = new WebResourcePermission(name, actions); 404 405 for (Iterator names = pattern.getRoles().iterator(); names.hasNext();) { 406 String roleName = (String) names.next(); 407 addPermissionToRole(roleName, permission, rolePermissions); 408 } 409 } 410 411 iter = uncheckedPatterns.keySet().iterator(); 412 while (iter.hasNext()) { 413 URLPattern pattern = (URLPattern) uncheckedPatterns.get(iter.next()); 414 String name = pattern.getQualifiedPattern(allSet); 415 String actions = pattern.getMethods(); 416 417 addOrUpdatePattern(uncheckedResourcePatterns, name, actions); 418 } 419 420 iter = rolesPatterns.keySet().iterator(); 421 while (iter.hasNext()) { 422 URLPattern pattern = (URLPattern) rolesPatterns.get(iter.next()); 423 String name = pattern.getQualifiedPattern(allSet); 424 String actions = pattern.getMethodsWithTransport(); 425 426 addOrUpdatePattern(uncheckedUserPatterns, name, actions); 427 } 428 429 iter = uncheckedPatterns.keySet().iterator(); 430 while (iter.hasNext()) { 431 URLPattern pattern = (URLPattern) uncheckedPatterns.get(iter.next()); 432 String name = pattern.getQualifiedPattern(allSet); 433 String actions = pattern.getMethodsWithTransport(); 434 435 addOrUpdatePattern(uncheckedUserPatterns, name, actions); 436 } 437 438 /** 439 * A <code>WebResourcePermission</code> and a <code>WebUserDataPermission</code> must be instantiated for 440 * each <tt>url-pattern</tt> in the deployment descriptor and the default pattern "/", that is not combined 441 * by the <tt>web-resource-collection</tt> elements of the deployment descriptor with ever HTTP method 442 * value. The permission objects must be contructed using the qualified pattern as their name and with 443 * actions defined by the subset of the HTTP methods that do not occur in combination with the pattern. 444 * The resulting permissions that must be added to the unchecked policy statements by calling the 445 * <code>addToUncheckedPolcy</code> method on the <code>PolicyConfiguration</code> object. 446 */ 447 iter = allSet.iterator(); 448 while (iter.hasNext()) { 449 URLPattern pattern = (URLPattern) iter.next(); 450 String name = pattern.getQualifiedPattern(allSet); 451 String actions = pattern.getComplementedMethods(); 452 453 if (actions.length() == 0) { 454 continue; 455 } 456 457 addOrUpdatePattern(uncheckedResourcePatterns, name, actions); 458 addOrUpdatePattern(uncheckedUserPatterns, name, actions); 459 } 460 461 URLPattern pattern = new URLPattern("/"); 462 if (!allSet.contains(pattern)) { 463 String name = pattern.getQualifiedPattern(allSet); 464 String actions = pattern.getComplementedMethods(); 465 466 addOrUpdatePattern(uncheckedResourcePatterns, name, actions); 467 addOrUpdatePattern(uncheckedUserPatterns, name, actions); 468 } 469 470 //Create the uncheckedPermissions for WebResourcePermissions 471 iter = uncheckedResourcePatterns.keySet().iterator(); 472 while (iter.hasNext()) { 473 UncheckedItem item = (UncheckedItem) iter.next(); 474 String actions = (String) uncheckedResourcePatterns.get(item); 475 476 uncheckedPermissions.add(new WebResourcePermission(item.getName(), actions)); 477 } 478 //Create the uncheckedPermissions for WebUserDataPermissions 479 iter = uncheckedUserPatterns.keySet().iterator(); 480 while (iter.hasNext()) { 481 UncheckedItem item = (UncheckedItem) iter.next(); 482 String actions = (String) uncheckedUserPatterns.get(item); 483 484 uncheckedPermissions.add(new WebUserDataPermission(item.getName(), actions)); 485 } 486 487 return new ComponentPermissions(excludedPermissions, uncheckedPermissions, rolePermissions); 488 489 } 490 491 protected void addPermissionToRole(String roleName, Permission permission, Map rolePermissions) { 492 PermissionCollection permissionsForRole = (PermissionCollection) rolePermissions.get(roleName); 493 if (permissionsForRole == null) { 494 permissionsForRole = new Permissions(); 495 rolePermissions.put(roleName, permissionsForRole); 496 } 497 permissionsForRole.add(permission); 498 } 499 500 private void addOrUpdatePattern(Map patternMap, String name, String actions) { 501 UncheckedItem item = new UncheckedItem(name, actions); 502 String existingActions = (String) patternMap.get(item); 503 if (existingActions != null) { 504 patternMap.put(item, actions + "," + existingActions); 505 return; 506 } 507 508 patternMap.put(item, actions); 509 } 510 511 protected static Set collectRoleNames(WebAppType webApp) { 512 Set roleNames = new HashSet(); 513 514 SecurityRoleType[] securityRoles = webApp.getSecurityRoleArray(); 515 for (int i = 0; i < securityRoles.length; i++) { 516 roleNames.add(securityRoles[i].getRoleName().getStringValue().trim()); 517 } 518 519 return roleNames; 520 } 521 522 protected static void check(WebAppType webApp) throws DeploymentException { 523 checkURLPattern(webApp); 524 checkMultiplicities(webApp); 525 } 526 527 private static void checkURLPattern(WebAppType webApp) throws DeploymentException { 528 529 FilterMappingType[] filterMappings = webApp.getFilterMappingArray(); 530 for (int i = 0; i < filterMappings.length; i++) { 531 if (filterMappings[i].isSetUrlPattern()) { 532 checkString(filterMappings[i].getUrlPattern().getStringValue().trim()); 533 } 534 } 535 536 ServletMappingType[] servletMappings = webApp.getServletMappingArray(); 537 for (int i = 0; i < servletMappings.length; i++) { 538 checkString(servletMappings[i].getUrlPattern().getStringValue().trim()); 539 } 540 541 SecurityConstraintType[] constraints = webApp.getSecurityConstraintArray(); 542 for (int i = 0; i < constraints.length; i++) { 543 WebResourceCollectionType[] collections = constraints[i].getWebResourceCollectionArray(); 544 for (int j = 0; j < collections.length; j++) { 545 UrlPatternType[] patterns = collections[j].getUrlPatternArray(); 546 for (int k = 0; k < patterns.length; k++) { 547 checkString(patterns[k].getStringValue().trim()); 548 } 549 } 550 } 551 } 552 553 protected static void checkString(String pattern) throws DeploymentException { 554 //j2ee_1_4.xsd explicitly requires preserving all whitespace. Do not trim. 555 if (pattern.indexOf(0x0D) >= 0) throw new DeploymentException("<url-pattern> must not contain CR(#xD)"); 556 if (pattern.indexOf(0x0A) >= 0) throw new DeploymentException("<url-pattern> must not contain LF(#xA)"); 557 } 558 559 private static void checkMultiplicities(WebAppType webApp) throws DeploymentException { 560 if (webApp.getSessionConfigArray().length > 1) throw new DeploymentException("Multiple <session-config> elements found"); 561 if (webApp.getJspConfigArray().length > 1) throw new DeploymentException("Multiple <jsp-config> elements found"); 562 if (webApp.getLoginConfigArray().length > 1) throw new DeploymentException("Multiple <login-config> elements found"); 563 } 564 565 private boolean cleanupConfigurationDir(File configurationDir) 566 { 567 LinkedList cannotBeDeletedList = new LinkedList(); 568 569 if (!DeploymentUtil.recursiveDelete(configurationDir,cannotBeDeletedList)) { 570 // Output a message to help user track down file problem 571 log.warn("Unable to delete " + cannotBeDeletedList.size() + 572 " files while recursively deleting directory " 573 + configurationDir + LINE_SEP + 574 "The first file that could not be deleted was:" + LINE_SEP + " "+ 575 ( !cannotBeDeletedList.isEmpty() ? cannotBeDeletedList.getFirst() : "") ); 576 return false; 577 } 578 return true; 579 } 580 581 protected void processRoleRefPermissions(ServletType servletType, Set securityRoles, Map rolePermissions) { 582 String servletName = servletType.getServletName().getStringValue().trim(); 583 //WebRoleRefPermissions 584 SecurityRoleRefType[] securityRoleRefTypeArray = servletType.getSecurityRoleRefArray(); 585 Set unmappedRoles = new HashSet(securityRoles); 586 for (int j = 0; j < securityRoleRefTypeArray.length; j++) { 587 SecurityRoleRefType securityRoleRefType = securityRoleRefTypeArray[j]; 588 String roleName = securityRoleRefType.getRoleName().getStringValue().trim(); 589 String roleLink = securityRoleRefType.getRoleLink().getStringValue().trim(); 590 //jacc 3.1.3.2 591 /* The name of the WebRoleRefPermission must be the servlet-name in whose 592 * context the security-role-ref is defined. The actions of the WebRoleRefPermission 593 * must be the value of the role-name (that is the reference), appearing in the security-role-ref. 594 * The deployment tools must call the addToRole method on the PolicyConfiguration object to add the 595 * WebRoleRefPermission object resulting from the translation to the role 596 * identified in the role-link appearing in the security-role-ref. 597 */ 598 addPermissionToRole(roleLink, new WebRoleRefPermission(servletName, roleName), rolePermissions); 599 unmappedRoles.remove(roleName); 600 } 601 for (Iterator iterator = unmappedRoles.iterator(); iterator.hasNext();) { 602 String roleName = (String) iterator.next(); 603 addPermissionToRole(roleName, new WebRoleRefPermission(servletName, roleName), rolePermissions); 604 } 605 // servletData.setAttribute("webRoleRefPermissions", webRoleRefPermissions); 606 } 607 608 protected void buildSubstitutionGroups(XmlObject gerWebApp, boolean hasSecurityRealmName, Module module, EARContext earContext) throws DeploymentException { 609 XmlObject[] securityElements = XmlBeansUtil.selectSubstitutionGroupElements(SECURITY_QNAME, gerWebApp); 610 if (securityElements.length > 0 && !hasSecurityRealmName) { 611 throw new DeploymentException("You have supplied a security configuration for web app " + module.getName() + " but no security-realm-name to allow login"); 612 } 613 securityBuilders.build(gerWebApp, earContext, module.getEarContext()); 614 serviceBuilders.build(gerWebApp, earContext, module.getEarContext()); 615 } 616 617 protected static WebAppDocument convertToServletSchema(XmlObject xmlObject) throws XmlException { 618 if (WebAppDocument.type.equals(xmlObject.schemaType())) { 619 XmlBeansUtil.validateDD(xmlObject); 620 return (WebAppDocument) xmlObject; 621 } 622 XmlCursor cursor = xmlObject.newCursor(); 623 try { 624 cursor.toStartDoc(); 625 cursor.toFirstChild(); 626 if (SchemaConversionUtils.J2EE_NAMESPACE.equals(cursor.getName().getNamespaceURI())) { 627 XmlObject result = xmlObject.changeType(WebAppDocument.type); 628 XmlBeansUtil.validateDD(result); 629 return (WebAppDocument) result; 630 } 631 632 XmlDocumentProperties xmlDocumentProperties = cursor.documentProperties(); 633 String publicId = xmlDocumentProperties.getDoctypePublicId(); 634 if ("-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN".equals(publicId) || 635 "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN".equals(publicId)) { 636 XmlCursor moveable = xmlObject.newCursor(); 637 try { 638 moveable.toStartDoc(); 639 moveable.toFirstChild(); 640 String schemaLocationURL = "http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"; 641 String version = "2.4"; 642 SchemaConversionUtils.convertToSchema(cursor, SchemaConversionUtils.J2EE_NAMESPACE, schemaLocationURL, version); 643 cursor.toStartDoc(); 644 cursor.toChild(SchemaConversionUtils.J2EE_NAMESPACE, "web-app"); 645 cursor.toFirstChild(); 646 SchemaConversionUtils.convertToDescriptionGroup(SchemaConversionUtils.J2EE_NAMESPACE, cursor, moveable); 647 SchemaConversionUtils.convertToJNDIEnvironmentRefsGroup(SchemaConversionUtils.J2EE_NAMESPACE, cursor, moveable); 648 cursor.push(); 649 if (cursor.toNextSibling(TAGLIB)) { 650 cursor.toPrevSibling(); 651 moveable.toCursor(cursor); 652 cursor.beginElement("jsp-config", SchemaConversionUtils.J2EE_NAMESPACE); 653 while (moveable.toNextSibling(TAGLIB)) { 654 moveable.moveXml(cursor); 655 } 656 } 657 cursor.pop(); 658 do { 659 String name = cursor.getName().getLocalPart(); 660 if ("filter".equals(name) || "servlet".equals(name) || "context-param".equals(name)) { 661 cursor.push(); 662 cursor.toFirstChild(); 663 SchemaConversionUtils.convertToDescriptionGroup(SchemaConversionUtils.J2EE_NAMESPACE, cursor, moveable); 664 while (cursor.toNextSibling(SchemaConversionUtils.J2EE_NAMESPACE, "init-param")) { 665 cursor.push(); 666 cursor.toFirstChild(); 667 SchemaConversionUtils.convertToDescriptionGroup(SchemaConversionUtils.J2EE_NAMESPACE, cursor, moveable); 668 cursor.pop(); 669 } 670 cursor.pop(); 671 } 672 } while (cursor.toNextSibling()); 673 } finally { 674 moveable.dispose(); 675 } 676 } 677 } finally { 678 cursor.dispose(); 679 } 680 XmlObject result = xmlObject.changeType(WebAppDocument.type); 681 if (result != null) { 682 XmlBeansUtil.validateDD(result); 683 return (WebAppDocument) result; 684 } 685 XmlBeansUtil.validateDD(xmlObject); 686 return (WebAppDocument) xmlObject; 687 } 688 689 class UncheckedItem { 690 final static int NA = 0x00; 691 final static int INTEGRAL = 0x01; 692 final static int CONFIDENTIAL = 0x02; 693 694 private int transportType = NA; 695 private String name; 696 697 public UncheckedItem(String name, String actions) { 698 setName(name); 699 setTransportType(actions); 700 } 701 702 public boolean equals(Object o) { 703 UncheckedItem item = (UncheckedItem) o; 704 return item.getKey().equals(this.getKey()); 705 } 706 707 public String getKey() { 708 return (name + transportType); 709 } 710 711 public int hashCode() { 712 return getKey().hashCode(); 713 } 714 715 public String getName() { 716 return name; 717 } 718 719 public void setName(String name) { 720 this.name = name; 721 } 722 723 public int getTransportType() { 724 return transportType; 725 } 726 727 public void setTransportType(String actions) { 728 String[] tokens = actions.split(":", 2); 729 if (tokens.length == 2) { 730 if (tokens[1].equals("INTEGRAL")) { 731 this.transportType = INTEGRAL; 732 } else if (tokens[1].equals("CONFIDENTIAL")) { 733 this.transportType = CONFIDENTIAL; 734 } 735 } 736 } 737 } 738 }