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
19 package org.apache.geronimo.jetty.deployment;
20
21 import java.io.File;
22 import java.io.FileNotFoundException;
23 import java.io.IOException;
24 import java.net.URL;
25 import java.security.Permission;
26 import java.security.PermissionCollection;
27 import java.security.Permissions;
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Comparator;
32 import java.util.Enumeration;
33 import java.util.HashMap;
34 import java.util.HashSet;
35 import java.util.Iterator;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Set;
39 import java.util.TreeSet;
40 import java.util.jar.JarFile;
41
42 import javax.management.ObjectName;
43 import javax.servlet.Servlet;
44
45 import org.apache.commons.logging.Log;
46 import org.apache.commons.logging.LogFactory;
47 import org.apache.geronimo.common.DeploymentException;
48 import org.apache.geronimo.deployment.ModuleIDBuilder;
49 import org.apache.geronimo.deployment.NamespaceDrivenBuilder;
50 import org.apache.geronimo.deployment.NamespaceDrivenBuilderCollection;
51 import org.apache.geronimo.deployment.service.EnvironmentBuilder;
52 import org.apache.geronimo.deployment.util.DeploymentUtil;
53 import org.apache.geronimo.deployment.xbeans.EnvironmentType;
54 import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
55 import org.apache.geronimo.gbean.AbstractName;
56 import org.apache.geronimo.gbean.AbstractNameQuery;
57 import org.apache.geronimo.gbean.GBeanData;
58 import org.apache.geronimo.gbean.GBeanInfo;
59 import org.apache.geronimo.gbean.GBeanInfoBuilder;
60 import org.apache.geronimo.gbean.SingleElementCollection;
61 import org.apache.geronimo.j2ee.deployment.EARContext;
62 import org.apache.geronimo.j2ee.deployment.Module;
63 import org.apache.geronimo.j2ee.deployment.ModuleBuilder;
64 import org.apache.geronimo.j2ee.deployment.NamingBuilder;
65 import org.apache.geronimo.j2ee.deployment.WebModule;
66 import org.apache.geronimo.j2ee.deployment.WebServiceBuilder;
67 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
68 import org.apache.geronimo.jetty.DefaultWebApplicationHandlerFactory;
69 import org.apache.geronimo.jetty.Host;
70 import org.apache.geronimo.jetty.JettyDefaultServletHolder;
71 import org.apache.geronimo.jetty.JettyFilterHolder;
72 import org.apache.geronimo.jetty.JettyFilterMapping;
73 import org.apache.geronimo.jetty.JettyServletHolder;
74 import org.apache.geronimo.jetty.JettyWebAppContext;
75 import org.apache.geronimo.jetty.NonAuthenticator;
76 import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
77 import org.apache.geronimo.kernel.GBeanNotFoundException;
78 import org.apache.geronimo.kernel.Kernel;
79 import org.apache.geronimo.kernel.Naming;
80 import org.apache.geronimo.kernel.config.Configuration;
81 import org.apache.geronimo.kernel.config.ConfigurationData;
82 import org.apache.geronimo.kernel.repository.Environment;
83 import org.apache.geronimo.naming.deployment.ENCConfigBuilder;
84 import org.apache.geronimo.naming.deployment.GBeanResourceEnvironmentBuilder;
85 import org.apache.geronimo.naming.deployment.ResourceEnvironmentSetter;
86 import org.apache.geronimo.security.deploy.DefaultPrincipal;
87 import org.apache.geronimo.security.deployment.SecurityConfiguration;
88 import org.apache.geronimo.security.jacc.ComponentPermissions;
89 import org.apache.geronimo.web.deployment.AbstractWebModuleBuilder;
90 import org.apache.geronimo.web.deployment.GenericToSpecificPlanConverter;
91 import org.apache.geronimo.xbeans.geronimo.web.jetty.JettyWebAppDocument;
92 import org.apache.geronimo.xbeans.geronimo.web.jetty.JettyWebAppType;
93 import org.apache.geronimo.xbeans.geronimo.web.jetty.config.GerJettyDocument;
94 import org.apache.geronimo.xbeans.j2ee.DispatcherType;
95 import org.apache.geronimo.xbeans.j2ee.ErrorPageType;
96 import org.apache.geronimo.xbeans.j2ee.FilterMappingType;
97 import org.apache.geronimo.xbeans.j2ee.FilterType;
98 import org.apache.geronimo.xbeans.j2ee.FormLoginConfigType;
99 import org.apache.geronimo.xbeans.j2ee.JspConfigType;
100 import org.apache.geronimo.xbeans.j2ee.ListenerType;
101 import org.apache.geronimo.xbeans.j2ee.LocaleEncodingMappingListType;
102 import org.apache.geronimo.xbeans.j2ee.LocaleEncodingMappingType;
103 import org.apache.geronimo.xbeans.j2ee.LoginConfigType;
104 import org.apache.geronimo.xbeans.j2ee.MimeMappingType;
105 import org.apache.geronimo.xbeans.j2ee.ParamValueType;
106 import org.apache.geronimo.xbeans.j2ee.ServletMappingType;
107 import org.apache.geronimo.xbeans.j2ee.ServletType;
108 import org.apache.geronimo.xbeans.j2ee.TaglibType;
109 import org.apache.geronimo.xbeans.j2ee.WebAppDocument;
110 import org.apache.geronimo.xbeans.j2ee.WebAppType;
111 import org.apache.geronimo.xbeans.j2ee.WelcomeFileListType;
112 import org.apache.xmlbeans.XmlException;
113 import org.apache.xmlbeans.XmlObject;
114 import org.mortbay.http.BasicAuthenticator;
115 import org.mortbay.http.ClientCertAuthenticator;
116 import org.mortbay.http.DigestAuthenticator;
117 import org.mortbay.jetty.servlet.FormAuthenticator;
118
119
120 /**
121 * @version $Rev:385659 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
122 */
123 public class JettyModuleBuilder extends AbstractWebModuleBuilder {
124 private final static Log log = LogFactory.getLog(JettyModuleBuilder.class);
125 private final Environment defaultEnvironment;
126 private final AbstractNameQuery jettyContainerObjectName;
127 private final Collection defaultServlets;
128 private final Collection defaultFilters;
129 private final Collection defaultFilterMappings;
130 private final GBeanData pojoWebServiceTemplate;
131
132 private final SingleElementCollection webServiceBuilder;
133 protected final NamespaceDrivenBuilderCollection clusteringBuilders;
134
135 private final List defaultWelcomeFiles;
136 private final Integer defaultSessionTimeoutSeconds;
137
138 private static final String JETTY_NAMESPACE = JettyWebAppDocument.type.getDocumentElementName().getNamespaceURI();
139
140 public JettyModuleBuilder(Environment defaultEnvironment,
141 Integer defaultSessionTimeoutSeconds,
142 List defaultWelcomeFiles,
143 AbstractNameQuery jettyContainerName,
144 Collection defaultServlets,
145 Collection defaultFilters,
146 Collection defaultFilterMappings,
147 Object pojoWebServiceTemplate,
148 Collection webServiceBuilder,
149 Collection clusteringBuilders,
150 Collection securityBuilders,
151 Collection serviceBuilders,
152 NamingBuilder namingBuilders,
153 ResourceEnvironmentSetter resourceEnvironmentSetter,
154 Kernel kernel) throws GBeanNotFoundException {
155 super(kernel, securityBuilders, serviceBuilders, namingBuilders, resourceEnvironmentSetter);
156 this.defaultEnvironment = defaultEnvironment;
157 this.defaultSessionTimeoutSeconds = (defaultSessionTimeoutSeconds == null) ? new Integer(30 * 60) : defaultSessionTimeoutSeconds;
158 this.jettyContainerObjectName = jettyContainerName;
159 this.defaultServlets = defaultServlets;
160 this.defaultFilters = defaultFilters;
161 this.defaultFilterMappings = defaultFilterMappings;
162 this.pojoWebServiceTemplate = getGBeanData(kernel, pojoWebServiceTemplate);
163 this.webServiceBuilder = new SingleElementCollection(webServiceBuilder);
164 this.clusteringBuilders = new NamespaceDrivenBuilderCollection(clusteringBuilders);
165
166
167
168 this.defaultWelcomeFiles = defaultWelcomeFiles;
169 }
170
171 private WebServiceBuilder getWebServiceBuilder() {
172 return (WebServiceBuilder) webServiceBuilder.getElement();
173 }
174
175 private static GBeanData getGBeanData(Kernel kernel, Object template) throws GBeanNotFoundException {
176 if (template == null) {
177 return null;
178 }
179 AbstractName templateName = kernel.getAbstractNameFor(template);
180 return kernel.getGBeanData(templateName);
181 }
182
183 protected Module createModule(Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, boolean standAlone, String contextRoot, AbstractName earName, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException {
184 assert moduleFile != null: "moduleFile is null";
185 assert targetPath != null: "targetPath is null";
186 assert !targetPath.endsWith("/"): "targetPath must not end with a '/'";
187
188
189 String specDD;
190 WebAppType webApp;
191 try {
192 if (specDDUrl == null) {
193 specDDUrl = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/web.xml");
194 }
195
196
197
198 specDD = DeploymentUtil.readAll(specDDUrl);
199 } catch (Exception e) {
200
201 return null;
202 }
203
204 try {
205
206 XmlObject parsed = XmlBeansUtil.parse(specDD);
207 WebAppDocument webAppDoc = convertToServletSchema(parsed);
208 webApp = webAppDoc.getWebApp();
209 } catch (XmlException xmle) {
210
211
212
213 throw new DeploymentException("Error parsing web.xml for " + targetPath, xmle);
214 }
215 check(webApp);
216
217
218 JettyWebAppType jettyWebApp = getJettyWebApp(plan, moduleFile, standAlone, targetPath, webApp);
219 if (contextRoot == null || contextRoot.trim().equals("")) {
220 if (jettyWebApp.isSetContextRoot()) {
221 contextRoot = jettyWebApp.getContextRoot();
222 } else {
223 contextRoot = determineDefaultContextRoot(webApp, standAlone, moduleFile, targetPath);
224 }
225 }
226
227 contextRoot = contextRoot.trim();
228
229 EnvironmentType environmentType = jettyWebApp.getEnvironment();
230 Environment environment = EnvironmentBuilder.buildEnvironment(environmentType, defaultEnvironment);
231
232 Boolean distributable = webApp.getDistributableArray().length == 1 ? Boolean.TRUE : Boolean.FALSE;
233 if (Boolean.TRUE == distributable) {
234 clusteringBuilders.buildEnvironment(jettyWebApp, environment);
235 }
236
237 getNamingBuilders().buildEnvironment(webApp, jettyWebApp, environment);
238
239
240 String warName = new File(moduleFile.getName()).getName();
241 if (warName.lastIndexOf('.') > -1) {
242 warName = warName.substring(0, warName.lastIndexOf('.'));
243 }
244 idBuilder.resolve(environment, warName, "war");
245
246 Map servletNameToPathMap = buildServletNameToPathMap(webApp, contextRoot);
247
248 Map portMap = getWebServiceBuilder().findWebServices(moduleFile, false, servletNameToPathMap, environment);
249 AbstractName moduleName;
250 if (earName == null) {
251 earName = naming.createRootName(environment.getConfigId(), NameFactory.NULL, NameFactory.J2EE_APPLICATION);
252 moduleName = naming.createChildName(earName, environment.getConfigId().toString(), NameFactory.WEB_MODULE);
253 } else {
254 moduleName = naming.createChildName(earName, targetPath, NameFactory.WEB_MODULE);
255 }
256
257 return new WebModule(standAlone, moduleName, environment, moduleFile, targetPath, webApp, jettyWebApp, specDD, contextRoot, portMap, JETTY_NAMESPACE);
258 }
259
260 JettyWebAppType getJettyWebApp(Object plan, JarFile moduleFile, boolean standAlone, String targetPath, WebAppType webApp) throws DeploymentException {
261 XmlObject rawPlan = null;
262 try {
263
264 try {
265 if (plan instanceof XmlObject) {
266 rawPlan = (XmlObject) plan;
267 } else {
268 if (plan != null) {
269 rawPlan = XmlBeansUtil.parse(((File) plan).toURL(), getClass().getClassLoader());
270 } else {
271 URL path = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/geronimo-web.xml");
272 try {
273 rawPlan = XmlBeansUtil.parse(path, getClass().getClassLoader());
274 } catch (FileNotFoundException e) {
275 path = DeploymentUtil.createJarURL(moduleFile, "WEB-INF/geronimo-jetty.xml");
276 try {
277 rawPlan = XmlBeansUtil.parse(path, getClass().getClassLoader());
278 } catch (FileNotFoundException e1) {
279 log.warn("Web application " + targetPath + " does not contain a WEB-INF/geronimo-web.xml deployment plan. This may or may not be a problem, depending on whether you have things like resource references that need to be resolved. You can also give the deployer a separate deployment plan file on the command line.");
280 }
281 }
282 }
283 }
284 } catch (IOException e) {
285 log.warn(e);
286 }
287
288 JettyWebAppType jettyWebApp;
289 if (rawPlan != null) {
290 XmlObject webPlan = new GenericToSpecificPlanConverter(GerJettyDocument.type.getDocumentElementName().getNamespaceURI(),
291 JettyWebAppDocument.type.getDocumentElementName().getNamespaceURI(), "jetty").convertToSpecificPlan(rawPlan);
292 jettyWebApp = (JettyWebAppType) webPlan.changeType(JettyWebAppType.type);
293 XmlBeansUtil.validateDD(jettyWebApp);
294 } else {
295 String defaultContextRoot = determineDefaultContextRoot(webApp, standAlone, moduleFile, targetPath);
296 jettyWebApp = createDefaultPlan(defaultContextRoot);
297 }
298 return jettyWebApp;
299 } catch (XmlException e) {
300 throw new DeploymentException("xml problem for web app " + targetPath, e);
301 }
302 }
303
304 private JettyWebAppType createDefaultPlan(String contextRoot) {
305 JettyWebAppType jettyWebApp = JettyWebAppType.Factory.newInstance();
306 jettyWebApp.setContextRoot(contextRoot);
307 return jettyWebApp;
308 }
309
310 public void initContext(EARContext earContext, Module module, ClassLoader cl) throws DeploymentException {
311 WebAppType webApp = (WebAppType) module.getSpecDD();
312
313 JettyWebAppType gerWebApp = (JettyWebAppType) module.getVendorDD();
314
315
316
317 getNamingBuilders().initContext(webApp, gerWebApp, module.getEarContext().getConfiguration(), earContext.getConfiguration(), module);
318 if ((webApp.getSecurityConstraintArray().length > 0 || webApp.getSecurityRoleArray().length > 0) &&
319 !gerWebApp.isSetSecurityRealmName()) {
320 throw new DeploymentException("web.xml for web app " + module.getName() + " includes security elements but Geronimo deployment plan is not provided or does not contain <security-realm-name> element necessary to configure security accordingly.");
321 }
322 boolean hasSecurityRealmName = gerWebApp.isSetSecurityRealmName();
323 buildSubstitutionGroups(gerWebApp, hasSecurityRealmName, module, earContext);
324 }
325
326 public void addGBeans(EARContext earContext, Module module, ClassLoader cl, Collection repository) throws DeploymentException {
327 EARContext moduleContext = module.getEarContext();
328 AbstractName moduleName = moduleContext.getModuleName();
329 WebModule webModule = (WebModule) module;
330
331 WebAppType webApp = (WebAppType) webModule.getSpecDD();
332 JettyWebAppType jettyWebApp = (JettyWebAppType) webModule.getVendorDD();
333
334
335 GBeanData webModuleData = new GBeanData(moduleName, JettyWebAppContext.GBEAN_INFO);
336 try {
337 moduleContext.addGBean(webModuleData);
338 if (moduleContext.getServerName() != null) {
339 webModuleData.setReferencePattern("J2EEServer", moduleContext.getServerName());
340 }
341 if (!module.isStandAlone()) {
342 webModuleData.setReferencePattern("J2EEApplication", earContext.getModuleName());
343 }
344
345 webModuleData.setAttribute("deploymentDescriptor", module.getOriginalSpecDD());
346 Set securityRoles = collectRoleNames(webApp);
347 Map rolePermissions = new HashMap();
348
349
350 configureHosts(earContext, jettyWebApp, webModuleData);
351
352
353
354
355 Set dependencies = findGBeanDependencies(earContext);
356 webModuleData.addDependencies(dependencies);
357
358
359 Map buildingContext = new HashMap();
360 buildingContext.put(NamingBuilder.JNDI_KEY, new HashMap());
361 buildingContext.put(NamingBuilder.GBEAN_NAME_KEY, moduleName);
362 Configuration earConfiguration = earContext.getConfiguration();
363 getNamingBuilders().buildNaming(webApp, jettyWebApp, earConfiguration, earConfiguration, (Module)webModule, buildingContext);
364 Map compContext = (Map) buildingContext.get(NamingBuilder.JNDI_KEY);
365
366 webModuleData.setAttribute("componentContext", compContext);
367
368
369
370 GBeanResourceEnvironmentBuilder rebuilder = new GBeanResourceEnvironmentBuilder(webModuleData);
371
372 resourceEnvironmentSetter.setResourceEnvironment(rebuilder, webApp.getResourceRefArray(), jettyWebApp.getResourceRefArray());
373
374 webModuleData.setAttribute("contextPath", webModule.getContextRoot());
375
376 webModuleData.setReferencePattern("TransactionManager", moduleContext.getTransactionManagerName());
377 webModuleData.setReferencePattern("TrackedConnectionAssociator", moduleContext.getConnectionTrackerName());
378 if (jettyWebApp.isSetWebContainer()) {
379 AbstractNameQuery webContainerName = ENCConfigBuilder.getGBeanQuery(NameFactory.GERONIMO_SERVICE, jettyWebApp.getWebContainer());
380 webModuleData.setReferencePattern("JettyContainer", webContainerName);
381 } else {
382 webModuleData.setReferencePattern("JettyContainer", jettyContainerObjectName);
383 }
384
385 if (webApp.getDisplayNameArray().length > 0) {
386 webModuleData.setAttribute("displayName", webApp.getDisplayNameArray()[0].getStringValue());
387 }
388
389
390 configureContextParams(webApp, webModuleData);
391
392
393 configureListeners(webApp, webModuleData);
394
395 webModuleData.setAttribute(JettyWebAppContext.GBEAN_ATTR_SESSION_TIMEOUT,
396 (webApp.getSessionConfigArray().length == 1 && webApp.getSessionConfigArray(0).getSessionTimeout() != null) ?
397 new Integer(webApp.getSessionConfigArray(0).getSessionTimeout().getBigIntegerValue().intValue() * 60) :
398 defaultSessionTimeoutSeconds);
399
400 Boolean distributable = webApp.getDistributableArray().length == 1 ? Boolean.TRUE : Boolean.FALSE;
401 webModuleData.setAttribute("distributable", distributable);
402 if (Boolean.TRUE == distributable) {
403 clusteringBuilders.build(jettyWebApp, earContext, moduleContext);
404 if (webModuleData.getReferencePatterns(JettyWebAppContext.GBEAN_REF_WEB_APPLICATION_HANDLER_FACTORY) == null) {
405 log.warn("No clustering builders configured: app will not be clustered");
406 configureNoClustering(moduleContext, webModuleData);
407 }
408 } else {
409 configureNoClustering(moduleContext, webModuleData);
410 }
411
412
413
414 configureMimeMappings(webApp, webModuleData);
415
416
417 configureWelcomeFileLists(webApp, webModuleData);
418
419
420 configureLocalEncodingMappingLists(webApp, webModuleData);
421
422
423 configureErrorPages(webApp, webModuleData);
424
425
426 configureTagLibs(module, webApp, webModuleData);
427
428
429 configureLoginConfigs(module, webApp, jettyWebApp, webModuleData);
430
431
432 Set knownServletMappings = new HashSet();
433 Map servletMappings = new HashMap();
434
435 buildServletMappings(module, webApp, servletMappings, knownServletMappings);
436
437
438 AbstractName previous = null;
439
440
441 if (defaultFilters != null) {
442 previous = addDefaultFiltersGBeans(earContext, moduleContext, moduleName, previous);
443 }
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471 addFilterMappingsGBeans(earContext, moduleContext, moduleName, webApp, previous);
472
473
474 addFiltersGBeans(earContext, moduleContext, moduleName, webApp);
475
476
477 if (defaultServlets != null) {
478 addDefaultServletsGBeans(earContext, moduleContext, moduleName, knownServletMappings);
479 }
480
481
482 Map portMap = webModule.getPortMap();
483
484 ServletType[] servletTypes = webApp.getServletArray();
485 addServlets(moduleName, webModule, servletTypes, servletMappings, securityRoles, rolePermissions, portMap, moduleContext);
486
487 if (jettyWebApp.isSetSecurityRealmName()) {
488 configureSecurityRealm(earContext, webApp, jettyWebApp, webModuleData, securityRoles, rolePermissions);
489 }
490 if (!module.isStandAlone()) {
491 ConfigurationData moduleConfigurationData = moduleContext.getConfigurationData();
492 earContext.addChildConfiguration(module.getTargetPath(), moduleConfigurationData);
493 }
494 } catch (DeploymentException de) {
495 throw de;
496 } catch (Exception e) {
497 throw new DeploymentException("Unable to initialize webapp GBean for " + module.getName(), e);
498 }
499 }
500
501 private void configureNoClustering(EARContext moduleContext, GBeanData webModuleData) throws GBeanAlreadyExistsException {
502 AbstractName name = moduleContext.getNaming().createChildName(moduleContext.getModuleName(),
503 "DefaultWebApplicationHandlerFactory",
504 NameFactory.GERONIMO_SERVICE);
505 GBeanData beanData = new GBeanData(name, DefaultWebApplicationHandlerFactory.GBEAN_INFO);
506 webModuleData.setReferencePattern(JettyWebAppContext.GBEAN_REF_WEB_APPLICATION_HANDLER_FACTORY, name);
507 moduleContext.addGBean(beanData);
508 }
509
510 private void configureSecurityRealm(EARContext earContext, WebAppType webApp, JettyWebAppType jettyWebApp, GBeanData webModuleData, Set securityRoles, Map rolePermissions) throws DeploymentException {
511 AbstractName moduleName = webModuleData.getAbstractName();
512 if (earContext.getSecurityConfiguration() == null) {
513 throw new DeploymentException("You have specified a <security-realm-name> for the webapp " + moduleName + " but no <security> configuration (role mapping) is supplied in the Geronimo plan for the web application (or the Geronimo plan for the EAR if the web app is in an EAR)");
514 }
515 String securityRealmName = jettyWebApp.getSecurityRealmName().trim();
516 webModuleData.setAttribute("securityRealmName", securityRealmName);
517
518 /**
519 * TODO - go back to commented version when possible.
520 */
521 String policyContextID = moduleName.toString().replaceAll("[, :]", "_");
522
523 webModuleData.setAttribute("policyContextID", policyContextID);
524
525 ComponentPermissions componentPermissions = buildSpecSecurityConfig(webApp, securityRoles, rolePermissions);
526 webModuleData.setAttribute("excludedPermissions", componentPermissions.getExcludedPermissions());
527 PermissionCollection checkedPermissions = new Permissions();
528 for (Iterator iterator = rolePermissions.values().iterator(); iterator.hasNext();) {
529 PermissionCollection permissionsForRole = (PermissionCollection) iterator.next();
530 for (Enumeration iterator2 = permissionsForRole.elements(); iterator2.hasMoreElements();) {
531 Permission permission = (Permission) iterator2.nextElement();
532 checkedPermissions.add(permission);
533 }
534 }
535 webModuleData.setAttribute("checkedPermissions", checkedPermissions);
536
537 earContext.addSecurityContext(policyContextID, componentPermissions);
538 DefaultPrincipal defaultPrincipal = ((SecurityConfiguration) earContext.getSecurityConfiguration()).getDefaultPrincipal();
539 webModuleData.setAttribute("defaultPrincipal", defaultPrincipal);
540 }
541
542 private void addDefaultServletsGBeans(EARContext earContext, EARContext moduleContext, AbstractName moduleName, Set knownServletMappings) throws GBeanNotFoundException, GBeanAlreadyExistsException {
543 for (Iterator iterator = defaultServlets.iterator(); iterator.hasNext();) {
544 Object defaultServlet = iterator.next();
545 GBeanData servletGBeanData = getGBeanData(kernel, defaultServlet);
546 AbstractName defaultServletObjectName = earContext.getNaming().createChildName(moduleName, (String) servletGBeanData.getAttribute("servletName"), NameFactory.SERVLET);
547 servletGBeanData.setAbstractName(defaultServletObjectName);
548 servletGBeanData.setReferencePattern("JettyServletRegistration", moduleName);
549 Set defaultServletMappings = new HashSet((Collection) servletGBeanData.getAttribute("servletMappings"));
550 defaultServletMappings.removeAll(knownServletMappings);
551 servletGBeanData.setAttribute("servletMappings", defaultServletMappings);
552 moduleContext.addGBean(servletGBeanData);
553 }
554 }
555
556 private void addFiltersGBeans(EARContext earContext, EARContext moduleContext, AbstractName moduleName, WebAppType webApp) throws GBeanAlreadyExistsException {
557 FilterType[] filterArray = webApp.getFilterArray();
558 for (int i = 0; i < filterArray.length; i++) {
559 FilterType filterType = filterArray[i];
560 String filterName = filterType.getFilterName().getStringValue().trim();
561 AbstractName filterAbstractName = earContext.getNaming().createChildName(moduleName, filterName, NameFactory.WEB_FILTER);
562 GBeanData filterData = new GBeanData(filterAbstractName, JettyFilterHolder.GBEAN_INFO);
563 filterData.setAttribute("filterName", filterName);
564 filterData.setAttribute("filterClass", filterType.getFilterClass().getStringValue().trim());
565 Map initParams = new HashMap();
566 ParamValueType[] initParamArray = filterType.getInitParamArray();
567 for (int j = 0; j < initParamArray.length; j++) {
568 ParamValueType paramValueType = initParamArray[j];
569 initParams.put(paramValueType.getParamName().getStringValue().trim(), paramValueType.getParamValue().getStringValue().trim());
570 }
571 filterData.setAttribute("initParams", initParams);
572 filterData.setReferencePattern("JettyServletRegistration", moduleName);
573 moduleContext.addGBean(filterData);
574 }
575 }
576
577 private void addFilterMappingsGBeans(EARContext earContext, EARContext moduleContext, AbstractName moduleName, WebAppType webApp, AbstractName previous) throws GBeanAlreadyExistsException {
578 FilterMappingType[] filterMappingArray = webApp.getFilterMappingArray();
579 for (int i = 0; i < filterMappingArray.length; i++) {
580 FilterMappingType filterMappingType = filterMappingArray[i];
581 String filterName = filterMappingType.getFilterName().getStringValue().trim();
582 GBeanData filterMappingData = new GBeanData(JettyFilterMapping.GBEAN_INFO);
583 if (previous != null) {
584 filterMappingData.setReferencePattern("Previous", previous);
585 }
586 filterMappingData.setReferencePattern("JettyServletRegistration", moduleName);
587 AbstractName filterAbstractName = earContext.getNaming().createChildName(moduleName, filterName, NameFactory.WEB_FILTER);
588
589 AbstractName filterMappingName = null;
590 if (filterMappingType.isSetUrlPattern()) {
591 String urlPattern = filterMappingType.getUrlPattern().getStringValue().trim();
592 filterMappingData.setAttribute("urlPattern", urlPattern);
593 filterMappingName = earContext.getNaming().createChildName(filterAbstractName, ObjectName.quote(urlPattern), NameFactory.URL_WEB_FILTER_MAPPING);
594 }
595 if (filterMappingType.isSetServletName()) {
596 String servletName = filterMappingType.getServletName().getStringValue().trim();
597 AbstractName servletAbstractName = earContext.getNaming().createChildName(moduleName, servletName, NameFactory.SERVLET);
598 filterMappingData.setReferencePattern("Servlet", servletAbstractName);
599 filterMappingName = earContext.getNaming().createChildName(filterAbstractName, servletName, NameFactory.SERVLET_WEB_FILTER_MAPPING);
600 }
601 filterMappingData.setAbstractName(filterMappingName);
602 previous = filterMappingName;
603
604 boolean request = filterMappingType.getDispatcherArray().length == 0;
605 boolean forward = false;
606 boolean include = false;
607 boolean error = false;
608 for (int j = 0; j < filterMappingType.getDispatcherArray().length; j++) {
609 DispatcherType dispatcherType = filterMappingType.getDispatcherArray()[j];
610 if (dispatcherType.getStringValue().equals("REQUEST")) {
611 request = true;
612 } else if (dispatcherType.getStringValue().equals("FORWARD")) {
613 forward = true;
614 } else if (dispatcherType.getStringValue().equals("INCLUDE")) {
615 include = true;
616 } else if (dispatcherType.getStringValue().equals("ERROR")) {
617 error = true;
618 }
619 }
620 filterMappingData.setAttribute("requestDispatch", Boolean.valueOf(request));
621 filterMappingData.setAttribute("forwardDispatch", Boolean.valueOf(forward));
622 filterMappingData.setAttribute("includeDispatch", Boolean.valueOf(include));
623 filterMappingData.setAttribute("errorDispatch", Boolean.valueOf(error));
624 filterMappingData.setReferencePattern("Filter", filterAbstractName);
625 moduleContext.addGBean(filterMappingData);
626 }
627 }
628
629 private AbstractName addDefaultFiltersGBeans(EARContext earContext, EARContext moduleContext, AbstractName moduleName, AbstractName previous) throws GBeanNotFoundException, GBeanAlreadyExistsException {
630 for (Iterator iterator = defaultFilters.iterator(); iterator.hasNext();) {
631 Object defaultFilter = iterator.next();
632 GBeanData filterGBeanData = getGBeanData(kernel, defaultFilter);
633 String filterName = (String) filterGBeanData.getAttribute("filterName");
634 AbstractName defaultFilterAbstractName = earContext.getNaming().createChildName(moduleName, filterName, NameFactory.WEB_FILTER);
635 filterGBeanData.setAbstractName(defaultFilterAbstractName);
636 filterGBeanData.setReferencePattern("JettyServletRegistration", moduleName);
637 moduleContext.addGBean(filterGBeanData);
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858 private void addServlets(AbstractName webModuleName,
859 WebModule module,
860 ServletType[] servletTypes,
861 Map servletMappings,
862 Set securityRoles,
863 Map rolePermissions,
864 Map portMap,
865 EARContext moduleContext) throws DeploymentException {
866
867
868
869 TreeSet loadOrder = new TreeSet(new StartupOrderComparator());
870
871
872 for (int i = 0; i < servletTypes.length; i++) {
873 loadOrder.add(servletTypes[i]);
874 }
875
876
877
878
879
880
881
882
883
884
885 AbstractName previousServlet = null;
886 for (Iterator servlets = loadOrder.iterator(); servlets.hasNext();) {
887 ServletType servletType = (ServletType) servlets.next();
888 previousServlet = addServlet(webModuleName, module, previousServlet, servletType, servletMappings, securityRoles, rolePermissions, portMap, moduleContext);
889 }
890
891
892 addUnmappedJSPPermissions(securityRoles, rolePermissions);
893 }
894
895 /**
896 * @param webModuleName
897 * @param module
898 * @param previousServlet
899 * @param servletType
900 * @param servletMappings
901 * @param securityRoles
902 * @param rolePermissions
903 * @param portMap
904 * @param moduleContext
905 * @return AbstractName of servlet gbean added
906 * @throws DeploymentException
907 */
908 private AbstractName addServlet(AbstractName webModuleName,
909 WebModule module,
910 AbstractName previousServlet,
911 ServletType servletType,
912 Map servletMappings,
913 Set securityRoles,
914 Map rolePermissions,
915 Map portMap,
916 EARContext moduleContext) throws DeploymentException {
917 ClassLoader webClassLoader = moduleContext.getClassLoader();
918 String servletName = servletType.getServletName().getStringValue().trim();
919 AbstractName servletAbstractName = moduleContext.getNaming().createChildName(webModuleName, servletName, NameFactory.SERVLET);
920 GBeanData servletData;
921 Map initParams = new HashMap();
922 Class baseServletClass;
923 try {
924 baseServletClass = webClassLoader.loadClass(Servlet.class.getName());
925 } catch (ClassNotFoundException e) {
926 throw new DeploymentException("Could not load javax.servlet.Servlet in web classloader", e);
927 }
928 if (servletType.isSetServletClass()) {
929 String servletClassName = servletType.getServletClass().getStringValue().trim();
930 Class servletClass;
931 try {
932 servletClass = webClassLoader.loadClass(servletClassName);
933 } catch (ClassNotFoundException e) {
934 throw new DeploymentException("Could not load servlet class " + servletClassName, e);
935 }
936 if (baseServletClass.isAssignableFrom(servletClass)) {
937 servletData = new GBeanData(servletAbstractName, JettyServletHolder.GBEAN_INFO);
938 servletData.setAttribute("servletClass", servletClassName);
939 } else {
940 servletData = new GBeanData(pojoWebServiceTemplate);
941 servletData.setAbstractName(servletAbstractName);
942
943 Object portInfo = portMap.get(servletName);
944
945
946
947 getWebServiceBuilder().configurePOJO(servletData, module, portInfo, servletClassName, moduleContext);
948 }
949 } else if (servletType.isSetJspFile()) {
950 servletData = new GBeanData(servletAbstractName, JettyServletHolder.GBEAN_INFO);
951 servletData.setAttribute("jspFile", servletType.getJspFile().getStringValue().trim());
952
953 servletData.setAttribute("servletClass", "org.apache.jasper.servlet.JspServlet");
954 initParams.put("development", "false");
955 } else {
956 throw new DeploymentException("Neither servlet class nor jsp file is set for " + servletName);
957 }
958
959
960
961
962 if (null != previousServlet) {
963 servletData.setReferencePattern("Previous", previousServlet);
964 }
965
966
967 servletData.setReferencePattern("JettyServletRegistration", webModuleName);
968 servletData.setAttribute("servletName", servletName);
969 ParamValueType[] initParamArray = servletType.getInitParamArray();
970 for (int j = 0; j < initParamArray.length; j++) {
971 ParamValueType paramValueType = initParamArray[j];
972 initParams.put(paramValueType.getParamName().getStringValue().trim(), paramValueType.getParamValue().getStringValue().trim());
973 }
974 servletData.setAttribute("initParams", initParams);
975 if (servletType.isSetLoadOnStartup()) {
976 Integer loadOnStartup = new Integer(servletType.getLoadOnStartup().getBigIntegerValue().intValue());
977 servletData.setAttribute("loadOnStartup", loadOnStartup);
978 }
979
980 Set mappings = (Set) servletMappings.get(servletName);
981 servletData.setAttribute("servletMappings", mappings == null ? Collections.EMPTY_SET : mappings);
982
983
984 if (servletType.isSetRunAs()) {
985 servletData.setAttribute("runAsRole", servletType.getRunAs().getRoleName().getStringValue().trim());
986 }
987
988 processRoleRefPermissions(servletType, securityRoles, rolePermissions);
989
990 try {
991 moduleContext.addGBean(servletData);
992 } catch (GBeanAlreadyExistsException e) {
993 throw new DeploymentException("Could not add servlet gbean to context", e);
994 }
995 return servletAbstractName;
996 }
997
998 public static final GBeanInfo GBEAN_INFO;
999
1000 static {
1001 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(JettyModuleBuilder.class, NameFactory.MODULE_BUILDER);
1002 infoBuilder.addAttribute("defaultEnvironment", Environment.class, true, true);
1003 infoBuilder.addAttribute("defaultSessionTimeoutSeconds", Integer.class, true, true);
1004 infoBuilder.addAttribute("defaultWelcomeFiles", List.class, true, true);
1005 infoBuilder.addAttribute("jettyContainerObjectName", AbstractNameQuery.class, true, true);
1006 infoBuilder.addReference("DefaultServlets", JettyDefaultServletHolder.class, NameFactory.SERVLET_TEMPLATE);
1007 infoBuilder.addReference("DefaultFilters", Object.class);
1008 infoBuilder.addReference("DefaultFilterMappings", Object.class);
1009 infoBuilder.addReference("PojoWebServiceTemplate", Object.class, NameFactory.SERVLET_WEB_SERVICE_TEMPLATE);
1010 infoBuilder.addReference("WebServiceBuilder", WebServiceBuilder.class, NameFactory.MODULE_BUILDER);
1011 infoBuilder.addReference("ClusteringBuilders", NamespaceDrivenBuilder.class, NameFactory.MODULE_BUILDER);
1012 infoBuilder.addReference("SecurityBuilders", NamespaceDrivenBuilder.class, NameFactory.MODULE_BUILDER);
1013 infoBuilder.addReference("ServiceBuilders", NamespaceDrivenBuilder.class, NameFactory.MODULE_BUILDER);
1014 infoBuilder.addReference("NamingBuilders", NamingBuilder.class, NameFactory.MODULE_BUILDER);
1015 infoBuilder.addReference("ResourceEnvironmentSetter", ResourceEnvironmentSetter.class, NameFactory.MODULE_BUILDER);
1016 infoBuilder.addAttribute("kernel", Kernel.class, false);
1017 infoBuilder.addInterface(ModuleBuilder.class);
1018
1019 infoBuilder.setConstructor(new String[]{
1020 "defaultEnvironment",
1021 "defaultSessionTimeoutSeconds",
1022 "defaultWelcomeFiles",
1023 "jettyContainerObjectName",
1024 "DefaultServlets",
1025 "DefaultFilters",
1026 "DefaultFilterMappings",
1027 "PojoWebServiceTemplate",
1028 "WebServiceBuilder",
1029 "ClusteringBuilders",
1030 "SecurityBuilders",
1031 "ServiceBuilders",
1032 "NamingBuilders",
1033 "ResourceEnvironmentSetter",
1034 "kernel"});
1035 GBEAN_INFO = infoBuilder.getBeanInfo();
1036 }
1037
1038 public static GBeanInfo getGBeanInfo() {
1039 return GBEAN_INFO;
1040 }
1041
1042 static class StartupOrderComparator implements Comparator {
1043 /**
1044 * comparator that compares first on the basis of startup order, and then on the lexicographical
1045 * ordering of servlet name. Since the servlet names have a uniqueness constraint, this should
1046 * provide a total ordering consistent with equals. All servlets with no startup order are after
1047 * all servlets with a startup order.
1048 *
1049 * @param o1 first ServletType object
1050 * @param o2 second ServletType object
1051 * @return an int < 0 if o1 precedes o2, 0 if they are equal, and > 0 if o2 preceeds o1.
1052 */
1053 public int compare(Object o1, Object o2) {
1054 ServletType s1 = (ServletType) o1;
1055 ServletType s2 = (ServletType) o2;
1056
1057
1058
1059
1060
1061 if (!s1.isSetLoadOnStartup() && !s2.isSetLoadOnStartup()) {
1062 return s1.equals(s2) ? 0 : s1.getServletName().getStringValue().trim().compareTo(s2.getServletName().getStringValue().trim());
1063 }
1064
1065
1066
1067
1068 if (s1.isSetLoadOnStartup() && !s2.isSetLoadOnStartup()) {
1069 return -1;
1070 }
1071 if (!s1.isSetLoadOnStartup() && s2.isSetLoadOnStartup()) {
1072 return 1;
1073 }
1074
1075
1076
1077 int comp = s1.getLoadOnStartup().getBigIntegerValue().compareTo(s2.getLoadOnStartup().getBigIntegerValue());
1078 if (comp == 0) {
1079 return s1.getServletName().getStringValue().trim().compareTo(s2.getServletName().getStringValue().trim());
1080 }
1081 return comp;
1082 }
1083 }
1084 }