001: /**
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */package org.apache.openejb.tomcat.catalina;
018:
019: import static org.apache.openejb.tomcat.catalina.BackportUtil.getServlet;
020: import static org.apache.openejb.tomcat.catalina.BackportUtil.*;
021: import org.apache.openejb.tomcat.common.LegacyAnnotationProcessor;
022: import org.apache.openejb.tomcat.common.TomcatVersion;
023: import org.apache.catalina.Container;
024: import org.apache.catalina.Engine;
025: import org.apache.catalina.LifecycleListener;
026: import org.apache.catalina.ServerFactory;
027: import org.apache.catalina.Service;
028: import org.apache.catalina.Wrapper;
029: import org.apache.catalina.core.StandardContext;
030: import org.apache.catalina.core.StandardHost;
031: import org.apache.catalina.core.StandardServer;
032: import org.apache.catalina.core.ContainerBase;
033: import org.apache.catalina.deploy.ContextEnvironment;
034: import org.apache.catalina.deploy.ContextResource;
035: import org.apache.catalina.deploy.ContextResourceLink;
036: import org.apache.catalina.deploy.NamingResources;
037: import org.apache.catalina.startup.ContextConfig;
038: import org.apache.catalina.startup.HostConfig;
039: import org.apache.naming.ContextAccessController;
040: import org.apache.naming.ContextBindings;
041: import org.apache.openejb.OpenEJBException;
042: import org.apache.openejb.Injection;
043: import org.apache.openejb.ClassLoaderUtil;
044: import org.apache.openejb.spi.ContainerSystem;
045: import org.apache.openejb.server.webservices.WsServlet;
046: import org.apache.openejb.server.webservices.WsService;
047: import org.apache.openejb.assembler.classic.AppInfo;
048: import org.apache.openejb.assembler.classic.Assembler;
049: import org.apache.openejb.util.LinkResolver;
050: import org.apache.openejb.assembler.classic.WebAppBuilder;
051: import org.apache.openejb.assembler.classic.WebAppInfo;
052: import org.apache.openejb.assembler.classic.EjbJarInfo;
053: import org.apache.openejb.assembler.classic.ConnectorInfo;
054: import org.apache.openejb.assembler.classic.InjectionBuilder;
055: import org.apache.openejb.config.AnnotationDeployer;
056: import org.apache.openejb.config.AppModule;
057: import org.apache.openejb.config.ConfigurationFactory;
058: import org.apache.openejb.config.DeploymentLoader;
059: import org.apache.openejb.config.EjbModule;
060: import org.apache.openejb.config.ReadDescriptors;
061: import org.apache.openejb.config.UnknownModuleTypeException;
062: import org.apache.openejb.config.WebModule;
063: import org.apache.openejb.core.ivm.naming.SystemComponentReference;
064: import org.apache.openejb.core.webservices.JaxWsUtils;
065: import org.apache.openejb.core.CoreWebDeploymentInfo;
066: import org.apache.openejb.core.CoreContainerSystem;
067: import org.apache.openejb.jee.EnvEntry;
068: import org.apache.openejb.jee.WebApp;
069: import org.apache.openejb.loader.SystemInstance;
070: import org.apache.openejb.util.LogCategory;
071: import org.apache.openejb.util.Logger;
072: import org.apache.openejb.util.URLs;
073: import org.apache.xbean.finder.ResourceFinder;
074: import org.apache.xbean.finder.UrlSet;
075: import org.omg.CORBA.ORB;
076:
077: import javax.ejb.spi.HandleDelegate;
078: import javax.naming.Context;
079: import javax.naming.NamingException;
080: import javax.persistence.EntityManagerFactory;
081: import javax.servlet.ServletContext;
082: import javax.transaction.TransactionManager;
083: import javax.transaction.TransactionSynchronizationRegistry;
084: import java.io.File;
085: import java.io.IOException;
086: import java.net.URL;
087: import java.util.List;
088: import java.util.Map;
089: import java.util.TreeMap;
090: import java.util.HashMap;
091: import java.util.Iterator;
092:
093: public class TomcatWebAppBuilder implements WebAppBuilder,
094: ContextListener {
095: public static final String IGNORE_CONTEXT = TomcatWebAppBuilder.class
096: .getName()
097: + ".IGNORE";
098: private static final Logger logger = Logger.getInstance(
099: LogCategory.OPENEJB.createChild("tomcat"),
100: "org.apache.openejb.util.resources");
101:
102: private final TreeMap<String, ContextInfo> infos = new TreeMap<String, ContextInfo>();
103: private final GlobalListenerSupport globalListenerSupport;
104: private final ConfigurationFactory configurationFactory;
105: private final Map<String, HostConfig> deployers = new TreeMap<String, HostConfig>();
106: // todo merge this map witth the infos map above
107: private final Map<String, DeployedApplication> deployedApps = new TreeMap<String, DeployedApplication>();
108: private final DeploymentLoader deploymentLoader;
109: private Assembler assembler;
110: private CoreContainerSystem containerSystem;
111:
112: public TomcatWebAppBuilder() {
113: StandardServer standardServer = (StandardServer) ServerFactory
114: .getServer();
115: globalListenerSupport = new GlobalListenerSupport(
116: standardServer, this );
117:
118: for (Service service : standardServer.findServices()) {
119: if (service.getContainer() instanceof Engine) {
120: Engine engine = (Engine) service.getContainer();
121: for (Container engineChild : engine.findChildren()) {
122: if (engineChild instanceof StandardHost) {
123: StandardHost host = (StandardHost) engineChild;
124: for (LifecycleListener listener : host
125: .findLifecycleListeners()) {
126: if (listener instanceof HostConfig) {
127: HostConfig hostConfig = (HostConfig) listener;
128: deployers.put(host.getName(),
129: hostConfig);
130: }
131: }
132: }
133: }
134: }
135: }
136:
137: // MBeanServer mbeanServer;
138: // List mbeanServers = MBeanServerFactory.findMBeanServer(null);
139: // if (mbeanServers.size() > 0) {
140: // mbeanServer = (MBeanServer) mbeanServers.get(0);
141: // } else {
142: // mbeanServer = MBeanServerFactory.createMBeanServer();
143: // }
144:
145: configurationFactory = new ConfigurationFactory();
146: deploymentLoader = new DeploymentLoader();
147: assembler = (Assembler) SystemInstance.get().getComponent(
148: org.apache.openejb.spi.Assembler.class);
149: containerSystem = (CoreContainerSystem) SystemInstance.get()
150: .getComponent(ContainerSystem.class);
151: }
152:
153: public void start() {
154: globalListenerSupport.start();
155:
156: }
157:
158: public void stop() {
159: globalListenerSupport.stop();
160: }
161:
162: //
163: // OpenEJB WebAppBuilder
164: //
165:
166: public void deployWebApps(AppInfo appInfo, ClassLoader classLoader)
167: throws Exception {
168: for (WebAppInfo webApp : appInfo.webApps) {
169: if (getContextInfo(webApp) == null) {
170: StandardContext standardContext = new StandardContext();
171: standardContext
172: .addLifecycleListener(new ContextConfig());
173: standardContext.setPath("/" + webApp.contextRoot);
174: standardContext.setDocBase(webApp.codebase);
175: standardContext.setParentClassLoader(classLoader);
176: standardContext.setDelegate(true);
177:
178: String host = webApp.host;
179: if (host == null)
180: host = "localhost";
181: HostConfig deployer = deployers.get(host);
182: if (deployer != null) {
183: // host isn't set until we call deployer.manageApp, so pass it
184: ContextInfo contextInfo = addContextInfo(host,
185: standardContext);
186: contextInfo.appInfo = appInfo;
187: contextInfo.deployer = deployer;
188: contextInfo.standardContext = standardContext;
189: deployer.manageApp(standardContext);
190: }
191: }
192: }
193: }
194:
195: public void undeployWebApps(AppInfo appInfo) throws Exception {
196: for (WebAppInfo webApp : appInfo.webApps) {
197: ContextInfo contextInfo = getContextInfo(webApp);
198: if (contextInfo != null && contextInfo.deployer != null) {
199: StandardContext standardContext = contextInfo.standardContext;
200: HostConfig deployer = contextInfo.deployer;
201: deployer.unmanageApp(standardContext.getPath());
202: deleteDir(new File(standardContext.getServletContext()
203: .getRealPath("")));
204: removeContextInfo(standardContext);
205: }
206: }
207: }
208:
209: private void deleteDir(File dir) {
210: if (dir == null)
211: return;
212: if (dir.isFile())
213: return;
214: for (File file : dir.listFiles()) {
215: if (file.isDirectory()) {
216: deleteDir(file);
217: } else {
218: file.delete();
219: }
220: }
221: dir.delete();
222: }
223:
224: //
225: // Tomcat Listener
226: //
227:
228: public void init(StandardContext standardContext) {
229: }
230:
231: public void beforeStart(StandardContext standardContext) {
232: }
233:
234: // context class loader is now defined, but no classes should have been loaded
235: public void start(StandardContext standardContext) {
236: if (standardContext.getServletContext().getAttribute(
237: IGNORE_CONTEXT) != null)
238: return;
239:
240: Assembler assembler = getAssembler();
241: if (assembler == null) {
242: logger
243: .warning("OpenEJB has not been initialized so war will not be scanned for nested modules "
244: + standardContext.getPath());
245: return;
246: }
247:
248: ContextInfo contextInfo = getContextInfo(standardContext);
249: if (contextInfo == null) {
250: AppModule appModule = loadApplication(standardContext);
251: if (appModule != null) {
252: try {
253: contextInfo = addContextInfo(standardContext
254: .getHostname(), standardContext);
255: AppInfo appInfo = configurationFactory
256: .configureApplication(appModule);
257: contextInfo.appInfo = appInfo;
258:
259: assembler.createApplication(contextInfo.appInfo,
260: standardContext.getLoader()
261: .getClassLoader());
262: // todo add watched resources to context
263: } catch (Exception e) {
264: logger.error(
265: "Unable to deploy collapsed ear in war "
266: + standardContext.getPath()
267: + ": Exception: " + e.getMessage(),
268: e);
269: }
270: }
271: }
272:
273: contextInfo.standardContext = standardContext;
274:
275: WebAppInfo webAppInfo = null;
276: // appInfo is null when deployment fails
277: if (contextInfo.appInfo != null) {
278: for (WebAppInfo w : contextInfo.appInfo.webApps) {
279: if (("/" + w.contextRoot).equals(standardContext
280: .getPath())) {
281: webAppInfo = w;
282: break;
283: }
284: }
285: }
286:
287: if (webAppInfo != null) {
288: try {
289: // determind the injections
290: InjectionBuilder injectionBuilder = new InjectionBuilder(
291: standardContext.getLoader().getClassLoader());
292: List<Injection> injections = injectionBuilder
293: .buildInjections(webAppInfo.jndiEnc);
294:
295: // merge OpenEJB jndi into Tomcat jndi
296: TomcatJndiBuilder jndiBuilder = new TomcatJndiBuilder(
297: standardContext, webAppInfo, injections);
298: jndiBuilder.mergeJndi();
299:
300: // add WebDeploymentInfo to ContainerSystem
301: CoreWebDeploymentInfo webDeploymentInfo = new CoreWebDeploymentInfo();
302: webDeploymentInfo.setId(webAppInfo.moduleId);
303: webDeploymentInfo.setClassLoader(standardContext
304: .getLoader().getClassLoader());
305: webDeploymentInfo.getInjections().addAll(injections);
306: getContainerSystem()
307: .addWebDeployment(webDeploymentInfo);
308: } catch (Exception e) {
309: logger.error(
310: "Error merging OpenEJB JNDI entries in to war "
311: + standardContext.getPath()
312: + ": Exception: " + e.getMessage(), e);
313: }
314: }
315: }
316:
317: public void afterStart(StandardContext standardContext) {
318: if (standardContext.getServletContext().getAttribute(
319: IGNORE_CONTEXT) != null)
320: return;
321:
322: // if appInfo is null this is a failed deployment... just ignore
323: ContextInfo contextInfo = getContextInfo(standardContext);
324: if (contextInfo.appInfo == null)
325: return;
326:
327: WsService wsService = SystemInstance.get().getComponent(
328: WsService.class);
329: if (wsService != null) {
330: List<WebAppInfo> webApps = contextInfo.appInfo.webApps;
331: for (WebAppInfo webApp : webApps) {
332: wsService.afterApplicationCreated(webApp);
333: }
334: }
335:
336: // replace any webservices with the webservice servlet
337: // HACK: use a temp class loader because the class may have been loaded before
338: // the openejb classes were added to the system class path so the WebService anntation
339: // will not be present on the class
340: ClassLoader tempClassLoader = ClassLoaderUtil
341: .createTempClassLoader(standardContext.getLoader()
342: .getClassLoader());
343: for (Container container : standardContext.findChildren()) {
344: if (container instanceof Wrapper) {
345: Wrapper wrapper = (Wrapper) container;
346: String servletClass = wrapper.getServletClass();
347: try {
348: Class<?> clazz = tempClassLoader
349: .loadClass(servletClass);
350: if (JaxWsUtils.isWebService(clazz)) {
351: wrapper.setServletClass(WsServlet.class
352: .getName());
353: if (getServlet(wrapper) != null) {
354: wrapper.load();
355: wrapper.unload();
356: }
357: }
358: } catch (Exception e) {
359: // will be reported by the tomcat
360: }
361: }
362: }
363:
364: // bind extra stuff at the java:comp level which can only be
365: // bound after the context is created
366: String listenerName = getNamingContextListener(standardContext)
367: .getName();
368: ContextAccessController.setWritable(listenerName,
369: standardContext);
370: try {
371:
372: Context openejbContext = SystemInstance.get().getComponent(
373: ContainerSystem.class).getJNDIContext();
374: openejbContext = (Context) openejbContext.lookup("openejb");
375:
376: Context root = (Context) ContextBindings.getClassLoader()
377: .lookup("");
378: safeBind(root, "openejb", openejbContext);
379:
380: Context comp = (Context) ContextBindings.getClassLoader()
381: .lookup("comp");
382:
383: // add context to WebDeploymentInfo
384: for (WebAppInfo webAppInfo : contextInfo.appInfo.webApps) {
385: if (("/" + webAppInfo.contextRoot)
386: .equals(standardContext.getPath())) {
387: CoreWebDeploymentInfo webDeploymentInfo = (CoreWebDeploymentInfo) getContainerSystem()
388: .getWebDeploymentInfo(webAppInfo.moduleId);
389: if (webDeploymentInfo != null) {
390: webDeploymentInfo.setJndiEnc(comp);
391: }
392: break;
393: }
394: }
395:
396: // bind TransactionManager
397: TransactionManager transactionManager = SystemInstance
398: .get().getComponent(TransactionManager.class);
399: safeBind(comp, "TransactionManager", transactionManager);
400:
401: // bind TransactionSynchronizationRegistry
402: TransactionSynchronizationRegistry synchronizationRegistry = SystemInstance
403: .get().getComponent(
404: TransactionSynchronizationRegistry.class);
405: safeBind(comp, "TransactionSynchronizationRegistry",
406: synchronizationRegistry);
407:
408: safeBind(comp, "ORB", new SystemComponentReference(
409: ORB.class));
410: safeBind(comp, "HandleDelegate",
411: new SystemComponentReference(HandleDelegate.class));
412: } catch (NamingException e) {
413: }
414: ContextAccessController.setReadOnly(listenerName);
415:
416: if (!TomcatVersion.hasAnnotationProcessingSupport()) {
417: try {
418: Context compEnv = (Context) ContextBindings
419: .getClassLoader().lookup("comp/env");
420:
421: LegacyAnnotationProcessor annotationProcessor = new LegacyAnnotationProcessor(
422: compEnv);
423:
424: standardContext
425: .addContainerListener(new ProcessAnnotatedListenersListener(
426: annotationProcessor));
427:
428: for (Container container : standardContext
429: .findChildren()) {
430: if (container instanceof Wrapper) {
431: Wrapper wrapper = (Wrapper) container;
432: wrapper
433: .addInstanceListener(new ProcessAnnotatedServletsListener(
434: annotationProcessor));
435: }
436: }
437: } catch (NamingException e) {
438: }
439: }
440:
441: OpenEJBValve openejbValve = new OpenEJBValve();
442: standardContext.getPipeline().addValve(openejbValve);
443: }
444:
445: public void beforeStop(StandardContext standardContext) {
446: }
447:
448: public void stop(StandardContext standardContext) {
449: }
450:
451: public void afterStop(StandardContext standardContext) {
452: if (standardContext.getServletContext().getAttribute(
453: IGNORE_CONTEXT) != null)
454: return;
455:
456: ContextInfo contextInfo = getContextInfo(standardContext);
457: if (contextInfo != null && contextInfo.appInfo != null
458: && contextInfo.deployer == null) {
459: try {
460: assembler
461: .destroyApplication(contextInfo.appInfo.jarPath);
462: } catch (Exception e) {
463: logger.error("Unable to stop web application "
464: + standardContext.getPath() + ": Exception: "
465: + e.getMessage(), e);
466: }
467: }
468: removeContextInfo(standardContext);
469: }
470:
471: public void destroy(StandardContext standardContext) {
472: }
473:
474: public void afterStop(StandardServer standardServer) {
475: // clean ear based webapps after shutdown
476: for (ContextInfo contextInfo : infos.values()) {
477: if (contextInfo != null && contextInfo.deployer != null) {
478: StandardContext standardContext = contextInfo.standardContext;
479: HostConfig deployer = contextInfo.deployer;
480: deployer.unmanageApp(standardContext.getPath());
481: String realPath = standardContext.getServletContext()
482: .getRealPath("");
483: if (realPath != null) {
484: deleteDir(new File(realPath));
485: }
486: }
487: }
488: }
489:
490: public void checkHost(StandardHost standardHost) {
491: if (standardHost.getAutoDeploy()) {
492: // Undeploy any modified application
493: for (Iterator<Map.Entry<String, DeployedApplication>> iterator = deployedApps
494: .entrySet().iterator(); iterator.hasNext();) {
495: Map.Entry<String, DeployedApplication> entry = iterator
496: .next();
497: DeployedApplication deployedApplication = entry
498: .getValue();
499: if (deployedApplication.isModified()) {
500: try {
501: assembler
502: .destroyApplication(deployedApplication.appInfo.jarPath);
503: } catch (Exception e) {
504: logger.error("Unable to application "
505: + deployedApplication.appInfo.jarPath
506: + ": Exception: " + e.getMessage(), e);
507: }
508: iterator.remove();
509: }
510: }
511:
512: // Deploy new applications
513: File appBase = appBase(standardHost);
514: File[] files = appBase.listFiles();
515: for (File file : files) {
516: String name = file.getName();
517: // ignore war files
518: if (name.toLowerCase().endsWith(".war")
519: || name.equals("ROOT")
520: || name.equalsIgnoreCase("META-INF")
521: || name.equalsIgnoreCase("WEB-INF"))
522: continue;
523: // ignore unpacked web apps
524: if (file.isDirectory()
525: && new File(file, "WEB-INF").exists())
526: continue;
527: // ignore unpacked apps where packed version is present (packed version is owner)
528: if (file.isDirectory()
529: && (new File(file.getParent(), file.getName()
530: + ".ear").exists()
531: || new File(file.getParent(), file
532: .getName()
533: + ".war").exists() || new File(
534: file.getParent(), file.getName()
535: + ".rar").exists())) {
536: continue;
537: }
538: // ignore already deployed apps
539: if (isDeployed(file, standardHost))
540: continue;
541:
542: AppInfo appInfo = null;
543: try {
544: file = file.getCanonicalFile().getAbsoluteFile();
545:
546: AppModule appModule = deploymentLoader.load(file);
547:
548: // Ignore any standalone web modules - this happens when the app is unpaked and doesn't have a WEB-INF dir
549: if (appModule.getDeploymentModule().size() == 1
550: && appModule.getWebModules().size() == 1) {
551: WebModule webModule = appModule.getWebModules()
552: .iterator().next();
553: if (file.getAbsolutePath().equals(
554: webModule.getJarLocation())) {
555: continue;
556: }
557: }
558:
559: // if this is an unpacked dir, tomcat will pick it up as a webapp so undeploy it first
560: if (file.isDirectory()) {
561: ContainerBase context = (ContainerBase) standardHost
562: .findChild("/" + name);
563: if (context != null) {
564: try {
565: standardHost.removeChild(context);
566: } catch (Throwable t) {
567: logger.warning(
568: "Error undeploying wep application from Tomcat "
569: + name, t);
570: }
571: try {
572: context.destroy();
573: } catch (Throwable t) {
574: logger.warning(
575: "Error destroying Tomcat web context "
576: + name, t);
577: }
578: }
579: }
580:
581: // tell web modules to deploy using this host
582: for (WebModule webModule : appModule
583: .getWebModules()) {
584: webModule.setHost(standardHost.getName());
585: }
586:
587: appInfo = configurationFactory
588: .configureApplication(appModule);
589: assembler.createApplication(appInfo);
590: } catch (Throwable e) {
591: logger.warning("Error deploying application "
592: + file.getAbsolutePath(), e);
593: }
594: deployedApps.put(file.getAbsolutePath(),
595: new DeployedApplication(file, appInfo));
596: }
597: }
598: }
599:
600: private boolean isDeployed(File file, StandardHost standardHost) {
601: if (deployedApps.containsKey(file.getAbsolutePath())) {
602: return true;
603: }
604:
605: // check if this is a deployed web application
606: String name = "/" + file.getName();
607:
608: // ROOT context is a special case
609: if (name.equals("/ROOT"))
610: name = "";
611:
612: return file.isFile() && standardHost.findChild(name) != null;
613: }
614:
615: protected File appBase(StandardHost standardHost) {
616: File file = new File(standardHost.getAppBase());
617: if (!file.isAbsolute()) {
618: file = new File(System.getProperty("catalina.base"),
619: standardHost.getAppBase());
620: }
621: try {
622: file = file.getCanonicalFile();
623: } catch (IOException e) {
624: }
625: return file;
626: }
627:
628: private AppModule loadApplication(StandardContext standardContext) {
629: // create the web module
630: WebModule webModule = createWebModule(standardContext);
631:
632: // create the app module
633: AppModule appModule = new AppModule(webModule.getClassLoader(),
634: webModule.getJarLocation());
635:
636: // add the web module itself
637: appModule.getWebModules().add(webModule);
638:
639: // check each url to determine if it is an ejb jar
640: for (URL url : getUrls(standardContext)) {
641: try {
642: Class moduleType = DeploymentLoader.discoverModuleType(
643: url, standardContext.getLoader()
644: .getClassLoader(), true);
645: if (EjbModule.class.isAssignableFrom(moduleType)) {
646: File file;
647: if (url.getProtocol().equals("jar")) {
648: url = new URL(url.getFile().replaceFirst(
649: "!.*$", ""));
650: file = URLs.toFile(url);
651: } else if (url.getProtocol().equals("file")) {
652: file = URLs.toFile(url);
653: } else {
654: logger.warning("Not loading "
655: + moduleType.getSimpleName()
656: + ". Unknown protocol "
657: + url.getProtocol());
658: continue;
659: }
660:
661: logger.info("Found ejb module "
662: + moduleType.getSimpleName() + " in war "
663: + standardContext.getPath());
664:
665: // creat the module
666: EjbModule ejbModule = new EjbModule(webModule
667: .getClassLoader(), file.getAbsolutePath(),
668: null, null);
669:
670: // EJB deployment descriptors
671: try {
672: ResourceFinder ejbResourceFinder = new ResourceFinder(
673: "", standardContext.getLoader()
674: .getClassLoader(), file.toURL());
675: Map<String, URL> descriptors = ejbResourceFinder
676: .getResourcesMap("META-INF/");
677: ejbModule.getAltDDs().putAll(descriptors);
678: } catch (IOException e) {
679: logger
680: .error(
681: "Unable to determine descriptors in jar.",
682: e);
683: }
684:
685: // add module to app
686: appModule.getEjbModules().add(ejbModule);
687: }
688: } catch (IOException e) {
689: logger.warning(
690: "Unable to determine the module type of "
691: + url.toExternalForm()
692: + ": Exception: " + e.getMessage(), e);
693: } catch (UnknownModuleTypeException ignore) {
694: }
695:
696: }
697:
698: // Persistence Units via META-INF/persistence.xml
699: try {
700: ResourceFinder finder = new ResourceFinder("",
701: standardContext.getLoader().getClassLoader());
702: List<URL> persistenceUrls = finder
703: .findAll("META-INF/persistence.xml");
704: appModule.getAltDDs().put("persistence.xml",
705: persistenceUrls);
706: } catch (IOException e) {
707: logger.warning(
708: "Cannot load persistence-units from 'META-INF/persistence.xml' : "
709: + e.getMessage(), e);
710: }
711:
712: return appModule;
713: }
714:
715: private WebModule createWebModule(StandardContext standardContext) {
716: // todo replace this code with DeploymentLoader
717: ServletContext servletContext = standardContext
718: .getServletContext();
719:
720: // read the web.xml
721: WebApp webApp = new WebApp();
722: try {
723: URL webXmlUrl = servletContext
724: .getResource("/WEB-INF/web.xml");
725: if (webXmlUrl != null) {
726: webApp = ReadDescriptors.readWebApp(webXmlUrl);
727: }
728: } catch (Exception e) {
729: logger.error("Unable to load web.xml in war "
730: + standardContext.getPath() + ": Exception: "
731: + e.getMessage(), e);
732: }
733:
734: // create the web module
735: String basePath = new File(servletContext.getRealPath("."))
736: .getParentFile().getAbsolutePath();
737: ClassLoader classLoader = ClassLoaderUtil
738: .createTempClassLoader(standardContext.getLoader()
739: .getClassLoader());
740: String path = standardContext.getPath();
741: System.out.println("context path = " + path);
742: WebModule webModule = new WebModule(webApp, path, classLoader,
743: basePath, getId(standardContext));
744: webModule.setHost(standardContext.getHostname());
745:
746: // Add all Tomcat env entries to context so they can be overriden by the env.properties file
747: NamingResources naming = standardContext.getNamingResources();
748: for (ContextEnvironment environment : naming.findEnvironments()) {
749: EnvEntry envEntry = webApp.getEnvEntryMap().get(
750: environment.getName());
751: if (envEntry == null) {
752: envEntry = new EnvEntry();
753: envEntry.setName(environment.getName());
754: webApp.getEnvEntry().add(envEntry);
755: }
756:
757: envEntry.setEnvEntryValue(environment.getValue());
758: envEntry.setEnvEntryType(environment.getType());
759: }
760:
761: // process the annotations
762: try {
763: AnnotationDeployer annotationDeployer = new AnnotationDeployer();
764: annotationDeployer.deploy(webModule);
765: } catch (OpenEJBException e) {
766: logger.error("Unable to process annotation in "
767: + standardContext.getPath() + ": Exception: "
768: + e.getMessage(), e);
769: }
770:
771: // remove all jndi entries where there is a configured Tomcat resource or resource-link
772: webApp = webModule.getWebApp();
773: for (ContextResource resource : naming.findResources()) {
774: String name = resource.getName();
775: removeRef(webApp, name);
776: }
777: for (ContextResourceLink resourceLink : naming
778: .findResourceLinks()) {
779: String name = resourceLink.getName();
780: removeRef(webApp, name);
781: }
782:
783: // remove all env entries from the web xml that are not overridable
784: for (ContextEnvironment environment : naming.findEnvironments()) {
785: if (!environment.getOverride()) {
786: // overrides are not allowed
787: webApp.getEnvEntryMap().remove(environment.getName());
788: }
789: }
790:
791: return webModule;
792: }
793:
794: private void removeRef(WebApp webApp, String name) {
795: webApp.getEnvEntryMap().remove(name);
796: webApp.getEjbRefMap().remove(name);
797: webApp.getEjbLocalRefMap().remove(name);
798: webApp.getMessageDestinationRefMap().remove(name);
799: webApp.getPersistenceContextRefMap().remove(name);
800: webApp.getPersistenceUnitRefMap().remove(name);
801: webApp.getResourceRefMap().remove(name);
802: webApp.getResourceEnvRefMap().remove(name);
803: }
804:
805: private List<URL> getUrls(StandardContext standardContext) {
806: List<URL> urls = null;
807: try {
808: ClassLoader classLoader = standardContext.getLoader()
809: .getClassLoader();
810: UrlSet urlSet = new UrlSet(classLoader);
811: urlSet = urlSet.exclude(classLoader.getParent());
812: urls = urlSet.getUrls();
813: } catch (IOException e) {
814: logger.warning(
815: "Unable to determine URLs in web application "
816: + standardContext.getPath(), e);
817: }
818: return urls;
819: }
820:
821: //
822: // helper methods
823: //
824:
825: private void safeBind(Context comp, String name, Object value) {
826: try {
827: comp.bind(name, value);
828: } catch (NamingException e) {
829: }
830: }
831:
832: private Assembler getAssembler() {
833: if (assembler == null) {
834: assembler = (Assembler) SystemInstance.get().getComponent(
835: org.apache.openejb.spi.Assembler.class);
836: }
837: return assembler;
838: }
839:
840: private CoreContainerSystem getContainerSystem() {
841: if (containerSystem == null) {
842: containerSystem = (CoreContainerSystem) SystemInstance
843: .get().getComponent(ContainerSystem.class);
844: }
845: return containerSystem;
846: }
847:
848: private String getId(StandardContext standardContext) {
849: String contextRoot = standardContext.getName();
850: if (!contextRoot.startsWith("/"))
851: contextRoot = "/" + contextRoot;
852: return standardContext.getHostname() + contextRoot;
853: }
854:
855: private ContextInfo getContextInfo(StandardContext standardContext) {
856: String id = getId(standardContext);
857: ContextInfo contextInfo = infos.get(id);
858: return contextInfo;
859: }
860:
861: private ContextInfo getContextInfo(WebAppInfo webAppInfo) {
862: String host = webAppInfo.host;
863: if (host == null)
864: host = "localhost";
865: String contextRoot = webAppInfo.contextRoot;
866: String id = host + "/" + contextRoot;
867: ContextInfo contextInfo = infos.get(id);
868: return contextInfo;
869: }
870:
871: private ContextInfo addContextInfo(String host,
872: StandardContext standardContext) {
873: String contextRoot = standardContext.getName();
874: if (!contextRoot.startsWith("/"))
875: contextRoot = "/" + contextRoot;
876: String id = host + contextRoot;
877: ContextInfo contextInfo = infos.get(id);
878: if (contextInfo == null) {
879: contextInfo = new ContextInfo();
880: infos.put(id, contextInfo);
881: }
882: return contextInfo;
883: }
884:
885: private void removeContextInfo(StandardContext standardContext) {
886: String id = getId(standardContext);
887: infos.remove(id);
888: }
889:
890: private static class ContextInfo {
891: public AppInfo appInfo;
892: public StandardContext standardContext;
893: public HostConfig deployer;
894: public LinkResolver<EntityManagerFactory> emfLinkResolver;
895: }
896:
897: private static class DeployedApplication {
898: private AppInfo appInfo;
899: private final Map<File, Long> watchedResource = new HashMap<File, Long>();
900:
901: public DeployedApplication(File base, AppInfo appInfo) {
902: this .appInfo = appInfo;
903: watchedResource.put(base, base.lastModified());
904: if (appInfo != null) {
905: for (String resource : appInfo.watchedResources) {
906: File file = new File(resource);
907: watchedResource.put(file, file.lastModified());
908: }
909: for (EjbJarInfo info : appInfo.ejbJars) {
910: for (String resource : info.watchedResources) {
911: File file = new File(resource);
912: watchedResource.put(file, file.lastModified());
913: }
914: }
915: for (WebAppInfo info : appInfo.webApps) {
916: for (String resource : info.watchedResources) {
917: File file = new File(resource);
918: watchedResource.put(file, file.lastModified());
919: }
920: }
921: for (ConnectorInfo info : appInfo.connectors) {
922: for (String resource : info.watchedResources) {
923: File file = new File(resource);
924: watchedResource.put(file, file.lastModified());
925: }
926: }
927: }
928: }
929:
930: public boolean isModified() {
931: for (Map.Entry<File, Long> entry : watchedResource
932: .entrySet()) {
933: File file = entry.getKey();
934: long lastModified = entry.getValue();
935: if ((!file.exists() && lastModified != 0L)
936: || (file.lastModified() != lastModified)) {
937: return true;
938: }
939: }
940: return false;
941: }
942: }
943: }
|