View Javadoc

1   /**
2    *
3    *  Licensed to the Apache Software Foundation (ASF) under one or more
4    *  contributor license agreements.  See the NOTICE file distributed with
5    *  this work for additional information regarding copyright ownership.
6    *  The ASF licenses this file to You under the Apache License, Version 2.0
7    *  (the "License"); you may not use this file except in compliance with
8    *  the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing, software
13   *  distributed under the License is distributed on an "AS IS" BASIS,
14   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *  See the License for the specific language governing permissions and
16   *  limitations under the License.
17   */
18  package org.apache.geronimo.web.deployment;
19  
20  import java.io.File;
21  import java.io.IOException;
22  import java.net.URI;
23  import java.net.URISyntaxException;
24  import java.net.URL;
25  import java.security.Permission;
26  import java.security.PermissionCollection;
27  import java.security.Permissions;
28  import java.util.Collection;
29  import java.util.Collections;
30  import java.util.Enumeration;
31  import java.util.HashMap;
32  import java.util.HashSet;
33  import java.util.Iterator;
34  import java.util.LinkedList;
35  import java.util.Map;
36  import java.util.Set;
37  import java.util.List;
38  import java.util.ArrayList;
39  import java.util.jar.JarFile;
40  import java.util.zip.ZipEntry;
41  
42  import javax.security.jacc.WebResourcePermission;
43  import javax.security.jacc.WebRoleRefPermission;
44  import javax.security.jacc.WebUserDataPermission;
45  import javax.xml.namespace.QName;
46  
47  import org.apache.commons.logging.Log;
48  import org.apache.commons.logging.LogFactory;
49  import org.apache.geronimo.common.DeploymentException;
50  import org.apache.geronimo.deployment.util.DeploymentUtil;
51  import org.apache.geronimo.deployment.ModuleIDBuilder;
52  import org.apache.geronimo.deployment.NamespaceDrivenBuilderCollection;
53  import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
54  import org.apache.geronimo.deployment.xbeans.ServiceDocument;
55  import org.apache.geronimo.gbean.AbstractName;
56  import org.apache.geronimo.gbean.AbstractNameQuery;
57  import org.apache.geronimo.j2ee.deployment.EARContext;
58  import org.apache.geronimo.j2ee.deployment.Module;
59  import org.apache.geronimo.j2ee.deployment.ModuleBuilder;
60  import org.apache.geronimo.j2ee.deployment.NamingBuilder;
61  import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
62  import org.apache.geronimo.kernel.Kernel;
63  import org.apache.geronimo.kernel.Naming;
64  import org.apache.geronimo.kernel.config.ConfigurationModuleType;
65  import org.apache.geronimo.kernel.config.ConfigurationStore;
66  import org.apache.geronimo.kernel.repository.Artifact;
67  import org.apache.geronimo.kernel.repository.Environment;
68  import org.apache.geronimo.kernel.repository.ImportType;
69  import org.apache.geronimo.security.jacc.ComponentPermissions;
70  import org.apache.geronimo.security.util.URLPattern;
71  import org.apache.geronimo.xbeans.j2ee.FilterMappingType;
72  import org.apache.geronimo.xbeans.j2ee.HttpMethodType;
73  import org.apache.geronimo.xbeans.j2ee.RoleNameType;
74  import org.apache.geronimo.xbeans.j2ee.SecurityConstraintType;
75  import org.apache.geronimo.xbeans.j2ee.SecurityRoleRefType;
76  import org.apache.geronimo.xbeans.j2ee.SecurityRoleType;
77  import org.apache.geronimo.xbeans.j2ee.ServletMappingType;
78  import org.apache.geronimo.xbeans.j2ee.ServletType;
79  import org.apache.geronimo.xbeans.j2ee.UrlPatternType;
80  import org.apache.geronimo.xbeans.j2ee.WebAppType;
81  import org.apache.geronimo.xbeans.j2ee.WebResourceCollectionType;
82  import org.apache.geronimo.xbeans.j2ee.WebAppDocument;
83  import org.apache.geronimo.xbeans.geronimo.j2ee.GerSecurityDocument;
84  import org.apache.geronimo.naming.deployment.ResourceEnvironmentSetter;
85  import org.apache.geronimo.schema.SchemaConversionUtils;
86  import org.apache.xmlbeans.XmlObject;
87  import org.apache.xmlbeans.XmlException;
88  import org.apache.xmlbeans.XmlCursor;
89  import org.apache.xmlbeans.XmlDocumentProperties;
90  
91  /**
92   * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
93   */
94  public abstract class AbstractWebModuleBuilder implements ModuleBuilder {
95      private static final Log log = LogFactory.getLog(AbstractWebModuleBuilder.class);
96      private static final QName TAGLIB = new QName(SchemaConversionUtils.J2EE_NAMESPACE, "taglib");
97      private static final String LINE_SEP = System.getProperty("line.separator");
98  
99      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 }