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
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
191 return trimPath(new File(moduleFile.getName()).getName());
192 }
193
194
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
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
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
260
261 libs.add(entry);
262 } else {
263 moduleContext.addFile(targetPath, warFile, entry);
264 }
265 }
266
267
268
269
270 moduleContext.getConfiguration().addToClassPath("WEB-INF/classes/");
271
272
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
280
281
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();
313 Map allMap = new HashMap();
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
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
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
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
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
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
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
591
592
593
594
595
596
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
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 }