001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.geronimo.tomcat.deployment;
017:
018: import static java.lang.Boolean.FALSE;
019: import static java.lang.Boolean.TRUE;
020:
021: import java.io.File;
022: import java.io.FileNotFoundException;
023: import java.io.FileWriter;
024: import java.io.IOException;
025: import java.net.URL;
026: import java.security.PermissionCollection;
027: import java.util.Collection;
028: import java.util.HashMap;
029: import java.util.Map;
030: import java.util.Set;
031: import java.util.jar.JarFile;
032:
033: import javax.servlet.Servlet;
034:
035: import org.apache.commons.logging.Log;
036: import org.apache.commons.logging.LogFactory;
037: import org.apache.geronimo.common.DeploymentException;
038: import org.apache.geronimo.deployment.ModuleIDBuilder;
039: import org.apache.geronimo.deployment.NamespaceDrivenBuilder;
040: import org.apache.geronimo.deployment.NamespaceDrivenBuilderCollection;
041: import org.apache.geronimo.deployment.service.EnvironmentBuilder;
042: import org.apache.geronimo.deployment.util.DeploymentUtil;
043: import org.apache.geronimo.deployment.xbeans.EnvironmentType;
044: import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
045: import org.apache.geronimo.gbean.AbstractName;
046: import org.apache.geronimo.gbean.AbstractNameQuery;
047: import org.apache.geronimo.gbean.GBeanData;
048: import org.apache.geronimo.gbean.GBeanInfo;
049: import org.apache.geronimo.gbean.GBeanInfoBuilder;
050: import org.apache.geronimo.gbean.ReferencePatterns;
051: import org.apache.geronimo.gbean.GBeanLifecycle;
052: import org.apache.geronimo.j2ee.deployment.EARContext;
053: import org.apache.geronimo.j2ee.deployment.Module;
054: import org.apache.geronimo.j2ee.deployment.ModuleBuilder;
055: import org.apache.geronimo.j2ee.deployment.ModuleBuilderExtension;
056: import org.apache.geronimo.j2ee.deployment.NamingBuilder;
057: import org.apache.geronimo.j2ee.deployment.WebModule;
058: import org.apache.geronimo.j2ee.deployment.WebServiceBuilder;
059: import org.apache.geronimo.j2ee.deployment.annotation.AnnotatedWebApp;
060: import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
061: import org.apache.geronimo.kernel.Kernel;
062: import org.apache.geronimo.kernel.Naming;
063: import org.apache.geronimo.kernel.config.ConfigurationData;
064: import org.apache.geronimo.kernel.repository.Environment;
065: import org.apache.geronimo.naming.deployment.ENCConfigBuilder;
066: import org.apache.geronimo.naming.deployment.GBeanResourceEnvironmentBuilder;
067: import org.apache.geronimo.naming.deployment.ResourceEnvironmentSetter;
068: import org.apache.geronimo.security.jacc.ComponentPermissions;
069: import org.apache.geronimo.tomcat.LifecycleListenerGBean;
070: import org.apache.geronimo.tomcat.ManagerGBean;
071: import org.apache.geronimo.tomcat.RealmGBean;
072: import org.apache.geronimo.tomcat.TomcatWebAppContext;
073: import org.apache.geronimo.tomcat.ValveGBean;
074: import org.apache.geronimo.tomcat.cluster.CatalinaClusterGBean;
075: import org.apache.geronimo.tomcat.util.SecurityHolder;
076: import org.apache.geronimo.web.deployment.GenericToSpecificPlanConverter;
077: import org.apache.geronimo.web25.deployment.AbstractWebModuleBuilder;
078: import org.apache.geronimo.xbeans.geronimo.j2ee.GerClusteringDocument;
079: import org.apache.geronimo.xbeans.geronimo.web.tomcat.TomcatWebAppDocument;
080: import org.apache.geronimo.xbeans.geronimo.web.tomcat.TomcatWebAppType;
081: import org.apache.geronimo.xbeans.geronimo.web.tomcat.config.GerTomcatDocument;
082: import org.apache.geronimo.xbeans.javaee.EjbLocalRefType;
083: import org.apache.geronimo.xbeans.javaee.EjbRefType;
084: import org.apache.geronimo.xbeans.javaee.EnvEntryType;
085: import org.apache.geronimo.xbeans.javaee.LifecycleCallbackType;
086: import org.apache.geronimo.xbeans.javaee.MessageDestinationRefType;
087: import org.apache.geronimo.xbeans.javaee.MessageDestinationType;
088: import org.apache.geronimo.xbeans.javaee.PersistenceContextRefType;
089: import org.apache.geronimo.xbeans.javaee.PersistenceUnitRefType;
090: import org.apache.geronimo.xbeans.javaee.ResourceEnvRefType;
091: import org.apache.geronimo.xbeans.javaee.ResourceRefType;
092: import org.apache.geronimo.xbeans.javaee.ServiceRefType;
093: import org.apache.geronimo.xbeans.javaee.ServletType;
094: import org.apache.geronimo.xbeans.javaee.WebAppDocument;
095: import org.apache.geronimo.xbeans.javaee.WebAppType;
096: import org.apache.xmlbeans.XmlCursor;
097: import org.apache.xmlbeans.XmlException;
098: import org.apache.xmlbeans.XmlObject;
099: import org.apache.xmlbeans.XmlOptions;
100:
101: /**
102: * @version $Rev:385659 $ $Date: 2008-01-10 03:07:04 -0800 (Thu, 10 Jan 2008) $
103: */
104: public class TomcatModuleBuilder extends AbstractWebModuleBuilder
105: implements GBeanLifecycle {
106:
107: private static final Log log = LogFactory
108: .getLog(TomcatModuleBuilder.class);
109:
110: private static final String TOMCAT_NAMESPACE = TomcatWebAppDocument.type
111: .getDocumentElementName().getNamespaceURI();
112: private static final String IS_JAVAEE = "IS_JAVAEE";
113: private static final Map<String, String> NAMESPACE_UPDATES = new HashMap<String, String>();
114: static {
115: NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web",
116: "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
117: NAMESPACE_UPDATES.put(
118: "http://geronimo.apache.org/xml/ns/j2ee/web-1.1",
119: "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
120: NAMESPACE_UPDATES.put(
121: "http://geronimo.apache.org/xml/ns/j2ee/web-1.2",
122: "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
123: NAMESPACE_UPDATES.put(
124: "http://geronimo.apache.org/xml/ns/j2ee/web-2.0",
125: "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
126: NAMESPACE_UPDATES
127: .put("http://geronimo.apache.org/xml/ns/web/tomcat",
128: "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1");
129: NAMESPACE_UPDATES
130: .put(
131: "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.1",
132: "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1");
133: NAMESPACE_UPDATES
134: .put(
135: "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.2",
136: "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1");
137: NAMESPACE_UPDATES
138: .put(
139: "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0",
140: "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1");
141: NAMESPACE_UPDATES
142: .put(
143: "http://geronimo.apache.org/xml/ns/web/tomcat/config",
144: "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat/config-1.0");
145: }
146:
147: private final Environment defaultEnvironment;
148: private final AbstractNameQuery tomcatContainerName;
149: protected final NamespaceDrivenBuilderCollection clusteringBuilders;
150:
151: public TomcatModuleBuilder(Environment defaultEnvironment,
152: AbstractNameQuery tomcatContainerName,
153: Collection<WebServiceBuilder> webServiceBuilder,
154: Collection securityBuilders, Collection serviceBuilders,
155: NamingBuilder namingBuilders,
156: Collection<NamespaceDrivenBuilder> clusteringBuilders,
157: Collection<ModuleBuilderExtension> moduleBuilderExtensions,
158: ResourceEnvironmentSetter resourceEnvironmentSetter,
159: Kernel kernel) {
160: super (kernel, securityBuilders, serviceBuilders,
161: namingBuilders, resourceEnvironmentSetter,
162: webServiceBuilder, moduleBuilderExtensions);
163: this .defaultEnvironment = defaultEnvironment;
164: this .clusteringBuilders = new NamespaceDrivenBuilderCollection(
165: clusteringBuilders, GerClusteringDocument.type
166: .getDocumentElementName());
167: this .tomcatContainerName = tomcatContainerName;
168: }
169:
170: public void doStart() throws Exception {
171: XmlBeansUtil.registerNamespaceUpdates(NAMESPACE_UPDATES);
172: }
173:
174: public void doStop() {
175: XmlBeansUtil.unregisterNamespaceUpdates(NAMESPACE_UPDATES);
176: }
177:
178: public void doFail() {
179: doStop();
180: }
181:
182: protected Module createModule(Object plan, JarFile moduleFile,
183: String targetPath, URL specDDUrl, boolean standAlone,
184: String contextRoot, AbstractName earName, Naming naming,
185: ModuleIDBuilder idBuilder) throws DeploymentException {
186: assert moduleFile != null : "moduleFile is null";
187: assert targetPath != null : "targetPath is null";
188: assert !targetPath.endsWith("/") : "targetPath must not end with a '/'";
189:
190: // parse the spec dd
191: String specDD = null;
192: WebAppType webApp = null;
193: Boolean isJavaee;
194: try {
195: if (specDDUrl == null) {
196: specDDUrl = DeploymentUtil.createJarURL(moduleFile,
197: "WEB-INF/web.xml");
198: }
199:
200: // read in the entire specDD as a string, we need this for getDeploymentDescriptor
201: // on the J2ee management object
202: specDD = DeploymentUtil.readAll(specDDUrl);
203:
204: // we found web.xml, if it won't parse that's an error.
205: XmlObject parsed = XmlBeansUtil.parse(specDD);
206: //Dont save updated xml if it isn't javaee
207: XmlCursor cursor = parsed.newCursor();
208: try {
209: cursor.toStartDoc();
210: cursor.toFirstChild();
211: isJavaee = "http://java.sun.com/xml/ns/javaee"
212: .equals(cursor.getName().getNamespaceURI());
213: } finally {
214: cursor.dispose();
215: }
216: WebAppDocument webAppDoc = convertToServletSchema(parsed);
217: webApp = webAppDoc.getWebApp();
218: check(webApp);
219: } catch (XmlException e) {
220: // Output the target path in the error to make it clearer to the user which webapp
221: // has the problem. The targetPath is used, as moduleFile may have an unhelpful
222: // value such as C:\geronimo-1.1\var\temp\geronimo-deploymentUtil22826.tmpdir
223: throw new DeploymentException("Error parsing web.xml for "
224: + targetPath, e);
225: } catch (Exception e) {
226: if (!moduleFile.getName().endsWith(".war")) {
227: //not for us
228: return null;
229: }
230: isJavaee = true;
231: //else ignore as jee5 allows optional spec dd for .war's
232: }
233:
234: if (webApp == null)
235: webApp = WebAppType.Factory.newInstance();
236:
237: // parse vendor dd
238: TomcatWebAppType tomcatWebApp = getTomcatWebApp(plan,
239: moduleFile, standAlone, targetPath, webApp);
240: contextRoot = getContextRoot(tomcatWebApp, contextRoot, webApp,
241: standAlone, moduleFile, targetPath);
242:
243: EnvironmentType environmentType = tomcatWebApp.getEnvironment();
244: Environment environment = EnvironmentBuilder.buildEnvironment(
245: environmentType, defaultEnvironment);
246:
247: Boolean distributable = webApp.getDistributableArray().length == 1 ? TRUE
248: : FALSE;
249: if (TRUE == distributable) {
250: clusteringBuilders.buildEnvironment(tomcatWebApp,
251: environment);
252: }
253:
254: // Note: logic elsewhere depends on the default artifact ID being the file name less extension (ConfigIDExtractor)
255: String warName = "";
256: File temp = new File(moduleFile.getName());
257: if (temp.isFile()) {
258: warName = temp.getName();
259: if (warName.lastIndexOf('.') > -1) {
260: warName = warName
261: .substring(0, warName.lastIndexOf('.'));
262: }
263: } else {
264: try {
265: warName = temp.getCanonicalFile().getName();
266: if (warName.equals("")) {
267: // Root directory
268: warName = "$root-dir$";
269: }
270: } catch (IOException e) {
271: //really?
272: }
273: }
274: idBuilder.resolve(environment, warName, "war");
275:
276: AbstractName moduleName;
277: if (earName == null) {
278: earName = naming.createRootName(environment.getConfigId(),
279: NameFactory.NULL, NameFactory.J2EE_APPLICATION);
280: moduleName = naming.createChildName(earName, environment
281: .getConfigId().toString(), NameFactory.WEB_MODULE);
282: } else {
283: moduleName = naming.createChildName(earName, targetPath,
284: NameFactory.WEB_MODULE);
285: }
286:
287: // Create the AnnotatedApp interface for the WebModule
288: AnnotatedWebApp annotatedWebApp = new AnnotatedWebApp(webApp);
289:
290: WebModule module = new WebModule(standAlone, moduleName,
291: environment, moduleFile, targetPath, webApp,
292: tomcatWebApp, specDD, contextRoot, TOMCAT_NAMESPACE,
293: annotatedWebApp);
294: for (ModuleBuilderExtension mbe : moduleBuilderExtensions) {
295: mbe.createModule(module, plan, moduleFile, targetPath,
296: specDDUrl, environment, contextRoot, earName,
297: naming, idBuilder);
298: }
299: module.getSharedContext().put(IS_JAVAEE, isJavaee);
300: return module;
301: }
302:
303: private String getContextRoot(TomcatWebAppType tomcatWebApp,
304: String contextRoot, WebAppType webApp, boolean standAlone,
305: JarFile moduleFile, String targetPath) {
306: //If we have a context root, override everything
307: if (tomcatWebApp.isSetContextRoot()) {
308: contextRoot = tomcatWebApp.getContextRoot();
309: } else if (contextRoot == null || contextRoot.trim().equals("")) {
310: //Otherwise if no contextRoot was passed in from the ear, then make up a default
311: contextRoot = determineDefaultContextRoot(webApp,
312: standAlone, moduleFile, targetPath);
313: }
314: contextRoot = contextRoot.trim();
315: if (!contextRoot.startsWith("/")) {
316: //I'm not sure if we should always fix up peculiar context roots.
317: contextRoot = "/" + contextRoot;
318: }
319: return contextRoot;
320: }
321:
322: TomcatWebAppType getTomcatWebApp(Object plan, JarFile moduleFile,
323: boolean standAlone, String targetPath, WebAppType webApp)
324: throws DeploymentException {
325: XmlObject rawPlan = null;
326: try {
327: // load the geronimo-web.xml from either the supplied plan or from the earFile
328: try {
329: if (plan instanceof XmlObject) {
330: rawPlan = (XmlObject) plan;
331: } else {
332: if (plan != null) {
333: rawPlan = XmlBeansUtil.parse(((File) plan)
334: .toURL(), getClass().getClassLoader());
335: } else {
336: URL path = DeploymentUtil.createJarURL(
337: moduleFile, "WEB-INF/geronimo-web.xml");
338: try {
339: rawPlan = XmlBeansUtil.parse(path,
340: getClass().getClassLoader());
341: } catch (FileNotFoundException e) {
342: path = DeploymentUtil.createJarURL(
343: moduleFile,
344: "WEB-INF/geronimo-tomcat.xml");
345: try {
346: rawPlan = XmlBeansUtil.parse(path,
347: getClass().getClassLoader());
348: } catch (FileNotFoundException e1) {
349: log
350: .warn("Web application "
351: + targetPath
352: + " 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.");
353: }
354: }
355: }
356: }
357: } catch (IOException e) {
358: log.warn(e);
359: }
360:
361: TomcatWebAppType tomcatWebApp;
362: if (rawPlan != null) {
363: XmlObject webPlan = new GenericToSpecificPlanConverter(
364: GerTomcatDocument.type.getDocumentElementName()
365: .getNamespaceURI(),
366: TomcatWebAppDocument.type
367: .getDocumentElementName()
368: .getNamespaceURI(), "tomcat")
369: .convertToSpecificPlan(rawPlan);
370: tomcatWebApp = (TomcatWebAppType) webPlan
371: .changeType(TomcatWebAppType.type);
372: XmlBeansUtil.validateDD(tomcatWebApp);
373: } else {
374: tomcatWebApp = createDefaultPlan();
375: }
376: return tomcatWebApp;
377: } catch (XmlException e) {
378: throw new DeploymentException("xml problem for web app "
379: + targetPath, e);
380: }
381: }
382:
383: private TomcatWebAppType createDefaultPlan() {
384: return TomcatWebAppType.Factory.newInstance();
385: }
386:
387: public void initContext(EARContext earContext, Module module,
388: ClassLoader cl) throws DeploymentException {
389: TomcatWebAppType gerWebApp = (TomcatWebAppType) module
390: .getVendorDD();
391: boolean hasSecurityRealmName = gerWebApp
392: .isSetSecurityRealmName();
393: basicInitContext(earContext, module, gerWebApp,
394: hasSecurityRealmName);
395: for (ModuleBuilderExtension mbe : moduleBuilderExtensions) {
396: mbe.initContext(earContext, module, cl);
397: }
398: }
399:
400: public void addGBeans(EARContext earContext, Module module,
401: ClassLoader cl, Collection repository)
402: throws DeploymentException {
403: EARContext moduleContext = module.getEarContext();
404: ClassLoader webClassLoader = moduleContext.getClassLoader();
405: AbstractName moduleName = moduleContext.getModuleName();
406: WebModule webModule = (WebModule) module;
407:
408: WebAppType webApp = (WebAppType) webModule.getSpecDD();
409:
410: TomcatWebAppType tomcatWebApp = (TomcatWebAppType) webModule
411: .getVendorDD();
412:
413: GBeanData webModuleData = new GBeanData(moduleName,
414: TomcatWebAppContext.GBEAN_INFO);
415: configureBasicWebModuleAttributes(webApp, tomcatWebApp,
416: moduleContext, earContext, webModule, webModuleData);
417: try {
418: moduleContext.addGBean(webModuleData);
419: Set<String> securityRoles = collectRoleNames(webApp);
420: Map<String, PermissionCollection> rolePermissions = new HashMap<String, PermissionCollection>();
421: webModuleData.setAttribute("contextPath", webModule
422: .getContextRoot());
423: // unsharableResources, applicationManagedSecurityResources
424: GBeanResourceEnvironmentBuilder rebuilder = new GBeanResourceEnvironmentBuilder(
425: webModuleData);
426: //N.B. use earContext not moduleContext
427: resourceEnvironmentSetter.setResourceEnvironment(rebuilder,
428: webApp.getResourceRefArray(), tomcatWebApp
429: .getResourceRefArray());
430:
431: if (tomcatWebApp.isSetWebContainer()) {
432: AbstractNameQuery webContainerName = ENCConfigBuilder
433: .getGBeanQuery(NameFactory.GERONIMO_SERVICE,
434: tomcatWebApp.getWebContainer());
435: webModuleData.setReferencePattern("Container",
436: webContainerName);
437: } else {
438: webModuleData.setReferencePattern("Container",
439: tomcatContainerName);
440: }
441: // Process the Tomcat container-config elements
442: if (tomcatWebApp.isSetHost()) {
443: String virtualServer = tomcatWebApp.getHost().trim();
444: webModuleData.setAttribute("virtualServer",
445: virtualServer);
446: }
447: if (tomcatWebApp.isSetCrossContext()) {
448: webModuleData
449: .setAttribute("crossContext", Boolean.TRUE);
450: }
451: if (tomcatWebApp.isSetWorkDir()) {
452: String workDir = tomcatWebApp.getWorkDir();
453: webModuleData.setAttribute("workDir", workDir);
454: }
455: if (tomcatWebApp.isSetDisableCookies()) {
456: webModuleData.setAttribute("disableCookies",
457: Boolean.TRUE);
458: }
459: if (tomcatWebApp.isSetTomcatRealm()) {
460: String tomcatRealm = tomcatWebApp.getTomcatRealm()
461: .trim();
462: AbstractName realmName = earContext.getNaming()
463: .createChildName(moduleName, tomcatRealm,
464: RealmGBean.GBEAN_INFO.getJ2eeType());
465: webModuleData.setReferencePattern("TomcatRealm",
466: realmName);
467: }
468: if (tomcatWebApp.isSetValveChain()) {
469: String valveChain = tomcatWebApp.getValveChain().trim();
470: AbstractName valveName = earContext.getNaming()
471: .createChildName(moduleName, valveChain,
472: ValveGBean.J2EE_TYPE);
473: webModuleData.setReferencePattern("TomcatValveChain",
474: valveName);
475: }
476:
477: if (tomcatWebApp.isSetListenerChain()) {
478: String listenerChain = tomcatWebApp.getListenerChain()
479: .trim();
480: AbstractName listenerName = earContext.getNaming()
481: .createChildName(moduleName, listenerChain,
482: LifecycleListenerGBean.J2EE_TYPE);
483: webModuleData.setReferencePattern(
484: "LifecycleListenerChain", listenerName);
485: }
486:
487: if (tomcatWebApp.isSetCluster()) {
488: String cluster = tomcatWebApp.getCluster().trim();
489: AbstractName clusterName = earContext.getNaming()
490: .createChildName(moduleName, cluster,
491: CatalinaClusterGBean.J2EE_TYPE);
492: webModuleData.setReferencePattern("Cluster",
493: clusterName);
494: }
495:
496: if (tomcatWebApp.isSetManager()) {
497: String manager = tomcatWebApp.getManager().trim();
498: AbstractName managerName = earContext.getNaming()
499: .createChildName(moduleName, manager,
500: ManagerGBean.J2EE_TYPE);
501: webModuleData.setReferencePattern("Manager",
502: managerName);
503: }
504:
505: Boolean distributable = webApp.getDistributableArray().length == 1 ? TRUE
506: : FALSE;
507: if (TRUE == distributable) {
508: clusteringBuilders.build(tomcatWebApp, earContext,
509: moduleContext);
510: if (null == webModuleData
511: .getReferencePatterns(TomcatWebAppContext.GBEAN_REF_CLUSTERED_VALVE_RETRIEVER)) {
512: log
513: .warn("No clustering builders configured: app will not be clustered");
514: }
515: }
516:
517: //Handle the role permissions and webservices on the servlets.
518: ServletType[] servletTypes = webApp.getServletArray();
519: Map<String, AbstractName> webServices = new HashMap<String, AbstractName>();
520: Class baseServletClass;
521: try {
522: baseServletClass = webClassLoader
523: .loadClass(Servlet.class.getName());
524: } catch (ClassNotFoundException e) {
525: throw new DeploymentException(
526: "Could not load javax.servlet.Servlet in web classloader",
527: e); // TODO identify web app in message
528: }
529: for (ServletType servletType : servletTypes) {
530: //Handle the Role Ref Permissions
531: processRoleRefPermissions(servletType, securityRoles,
532: rolePermissions);
533:
534: if (servletType.isSetServletClass()) {
535: String servletName = servletType.getServletName()
536: .getStringValue().trim();
537: String servletClassName = servletType
538: .getServletClass().getStringValue().trim();
539: Class servletClass;
540: try {
541: servletClass = webClassLoader
542: .loadClass(servletClassName);
543: } catch (ClassNotFoundException e) {
544: throw new DeploymentException(
545: "Could not load servlet class "
546: + servletClassName, e); // TODO identify web app in message
547: }
548: if (!baseServletClass
549: .isAssignableFrom(servletClass)) {
550: //fake servletData
551: AbstractName servletAbstractName = moduleContext
552: .getNaming().createChildName(
553: moduleName, servletName,
554: NameFactory.SERVLET);
555: GBeanData servletData = new GBeanData();
556: servletData
557: .setAbstractName(servletAbstractName);
558: //let the web service builder deal with configuring the gbean with the web service stack
559: //Here we just extract the factory reference
560: boolean configured = false;
561: for (WebServiceBuilder serviceBuilder : webServiceBuilder) {
562: if (serviceBuilder.configurePOJO(
563: servletData, servletName, module,
564: servletClassName, moduleContext)) {
565: configured = true;
566: break;
567: }
568: }
569: if (!configured) {
570: throw new DeploymentException(
571: "POJO web service: "
572: + servletName
573: + " not configured by any web service builder");
574: }
575: ReferencePatterns patterns = servletData
576: .getReferencePatterns("WebServiceContainerFactory");
577: AbstractName wsContainerFactoryName = patterns
578: .getAbstractName();
579: webServices.put(servletName,
580: wsContainerFactoryName);
581: //force all the factories to start before the web app that needs them.
582: webModuleData
583: .addDependency(wsContainerFactoryName);
584: }
585:
586: }
587: }
588:
589: // JACC v1.0 secion B.19
590: addUnmappedJSPPermissions(securityRoles, rolePermissions);
591:
592: webModuleData.setAttribute("webServices", webServices);
593:
594: if (tomcatWebApp.isSetSecurityRealmName()) {
595: if (earContext.getSecurityConfiguration() == null) {
596: throw new DeploymentException(
597: "You have specified a <security-realm-name> for the webapp "
598: + moduleName
599: + " 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)");
600: }
601:
602: SecurityHolder securityHolder = new SecurityHolder();
603: securityHolder.setSecurityRealm(tomcatWebApp
604: .getSecurityRealmName().trim());
605:
606: webModuleData.setReferencePattern("RunAsSource",
607: earContext.getJaccManagerName());
608:
609: /**
610: * TODO - go back to commented version when possible.
611: */
612: String policyContextID = moduleName.toString()
613: .replaceAll("[, :]", "_");
614: securityHolder.setPolicyContextID(policyContextID);
615:
616: ComponentPermissions componentPermissions = buildSpecSecurityConfig(
617: webApp, securityRoles, rolePermissions);
618: earContext.addSecurityContext(policyContextID,
619: componentPermissions);
620: //TODO WTF is this for?
621: securityHolder.setSecurity(true);
622:
623: webModuleData.setAttribute("securityHolder",
624: securityHolder);
625: }
626:
627: //listeners added directly to the StandardContext will get loaded by the tomcat classloader, not the app classloader!
628: //TODO this may definitely not be the best place for this!
629: for (ModuleBuilderExtension mbe : moduleBuilderExtensions) {
630: mbe.addGBeans(earContext, module, cl, repository);
631: }
632: //not truly metadata complete until MBEs have run
633: if (!webApp.getMetadataComplete()) {
634: webApp.setMetadataComplete(true);
635: module.setOriginalSpecDD(module.getSpecDD().toString());
636: webModuleData.setAttribute("deploymentDescriptor",
637: module.getOriginalSpecDD());
638: }
639: /**
640: * This next bit of code is kind of a kludge to get Tomcat to get a default
641: * web.xml if one does not exist. This is primarily for jaxws. This code is
642: * necessary because Tomcat either has a bug or there is a problem dynamically
643: * adding a wrapper to an already running context. Although the wrapper
644: * can be added, the url mappings do not get picked up at the proper level
645: * and therefore Tomcat cannot dispatch the request. Hence, creating and
646: * writing out a web.xml to the deployed location is the only way around this
647: * until Tomcat fixes that bug.
648: *
649: * For myfaces/jsf, the spec dd may have been updated with a listener. So, we need to write it out again whether or not
650: * there originally was one. This might not work on windows due to file locking problems.
651: */
652:
653: if ((Boolean) module.getSharedContext().get(IS_JAVAEE)) {
654: WebAppType shortWebApp = (WebAppType) webApp.copy();
655: shortWebApp.setEjbLocalRefArray(new EjbLocalRefType[0]);
656: shortWebApp.setEjbRefArray(new EjbRefType[0]);
657: shortWebApp.setEnvEntryArray(new EnvEntryType[0]);
658: shortWebApp
659: .setMessageDestinationArray(new MessageDestinationType[0]);
660: shortWebApp
661: .setMessageDestinationRefArray(new MessageDestinationRefType[0]);
662: shortWebApp
663: .setPersistenceContextRefArray(new PersistenceContextRefType[0]);
664: shortWebApp
665: .setPersistenceUnitRefArray(new PersistenceUnitRefType[0]);
666: shortWebApp
667: .setPostConstructArray(new LifecycleCallbackType[0]);
668: shortWebApp
669: .setPreDestroyArray(new LifecycleCallbackType[0]);
670: shortWebApp
671: .setResourceEnvRefArray(new ResourceEnvRefType[0]);
672: shortWebApp.setResourceRefArray(new ResourceRefType[0]);
673: shortWebApp.setServiceRefArray(new ServiceRefType[0]);
674: // TODO Tomcat will fail web services tck tests if the following security settings are set in shortWebApp
675: // need to figure out why...
676: //One clue is that without this stuff tomcat does not install an authenticator.... so there's no security
677: // shortWebApp.setSecurityConstraintArray(new SecurityConstraintType[0]);
678: // shortWebApp.setSecurityRoleArray(new SecurityRoleType[0]);
679: File webXml = new File(moduleContext.getBaseDir(),
680: "/WEB-INF/web.xml");
681: File inPlaceDir = moduleContext
682: .getInPlaceConfigurationDir();
683: if (inPlaceDir != null) {
684: webXml = new File(inPlaceDir, "/WEB-INF/web.xml");
685: }
686: // boolean webXmlExists = (inPlaceDir != null && new File(inPlaceDir,"/WEB-INF/web.xml").exists()) || webXml.exists();
687: // if (!webXmlExists) {
688: webXml.getParentFile().mkdirs();
689: try {
690: FileWriter outFile = new FileWriter(webXml);
691:
692: XmlOptions opts = new XmlOptions();
693: opts.setSaveAggressiveNamespaces();
694: opts
695: .setSaveSyntheticDocumentElement(WebAppDocument.type
696: .getDocumentElementName());
697: opts.setUseDefaultNamespace();
698: opts.setSavePrettyPrint();
699:
700: // WebAppDocument doc = WebAppDocument.Factory.newInstance();
701: // doc.setWebApp(webApp);
702:
703: outFile.write(shortWebApp.xmlText(opts));
704: outFile.flush();
705: outFile.close();
706: } catch (Exception e) {
707: throw new DeploymentException(e);
708: }
709: // }
710: }
711:
712: if (!module.isStandAlone()) {
713: ConfigurationData moduleConfigurationData = moduleContext
714: .getConfigurationData();
715: earContext
716: .addChildConfiguration(module.getTargetPath(),
717: moduleConfigurationData);
718: }
719: } catch (DeploymentException de) {
720: throw de;
721: } catch (Exception e) {
722: throw new DeploymentException(
723: "Unable to initialize GBean for web app "
724: + module.getName(), e);
725: }
726: }
727:
728: public String getSchemaNamespace() {
729: return TOMCAT_NAMESPACE;
730: }
731:
732: public static final GBeanInfo GBEAN_INFO;
733: public static final String GBEAN_REF_CLUSTERING_BUILDERS = "ClusteringBuilders";
734:
735: static {
736: GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(
737: TomcatModuleBuilder.class, NameFactory.MODULE_BUILDER);
738: infoBuilder.addAttribute("defaultEnvironment",
739: Environment.class, true, true);
740: infoBuilder.addAttribute("tomcatContainerName",
741: AbstractNameQuery.class, true, true);
742: infoBuilder.addReference("WebServiceBuilder",
743: WebServiceBuilder.class, NameFactory.MODULE_BUILDER);
744: infoBuilder.addReference("SecurityBuilders",
745: NamespaceDrivenBuilder.class,
746: NameFactory.MODULE_BUILDER);
747: infoBuilder.addReference("ServiceBuilders",
748: NamespaceDrivenBuilder.class,
749: NameFactory.MODULE_BUILDER);
750: infoBuilder.addReference("NamingBuilders", NamingBuilder.class,
751: NameFactory.MODULE_BUILDER);
752: infoBuilder.addReference(GBEAN_REF_CLUSTERING_BUILDERS,
753: NamespaceDrivenBuilder.class,
754: NameFactory.MODULE_BUILDER);
755: infoBuilder.addReference("ModuleBuilderExtensions",
756: ModuleBuilderExtension.class,
757: NameFactory.MODULE_BUILDER);
758: infoBuilder.addReference("ResourceEnvironmentSetter",
759: ResourceEnvironmentSetter.class,
760: NameFactory.MODULE_BUILDER);
761: infoBuilder.addAttribute("kernel", Kernel.class, false);
762: infoBuilder.addInterface(ModuleBuilder.class);
763:
764: infoBuilder.setConstructor(new String[] { "defaultEnvironment",
765: "tomcatContainerName", "WebServiceBuilder",
766: "SecurityBuilders", "ServiceBuilders",
767: "NamingBuilders", GBEAN_REF_CLUSTERING_BUILDERS,
768: "ModuleBuilderExtensions", "ResourceEnvironmentSetter",
769: "kernel" });
770: GBEAN_INFO = infoBuilder.getBeanInfo();
771: }
772:
773: public static GBeanInfo getGBeanInfo() {
774: return GBEAN_INFO;
775: }
776:
777: }
|