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.openejb.config;
017:
018: import static org.apache.openejb.util.URLs.toFile;
019: import org.apache.openejb.assembler.classic.AppInfo;
020: import org.apache.openejb.assembler.classic.EjbJarInfo;
021: import org.apache.openejb.assembler.classic.EnterpriseBeanInfo;
022: import org.apache.openejb.assembler.classic.PersistenceUnitInfo;
023: import org.apache.openejb.assembler.classic.JndiEncInfo;
024: import org.apache.openejb.assembler.classic.ClientInfo;
025: import org.apache.openejb.assembler.classic.ConnectorInfo;
026: import org.apache.openejb.assembler.classic.ResourceInfo;
027: import org.apache.openejb.assembler.classic.MdbContainerInfo;
028: import org.apache.openejb.assembler.classic.WebAppInfo;
029: import org.apache.openejb.assembler.classic.ServletInfo;
030: import org.apache.openejb.assembler.classic.PortInfo;
031: import org.apache.openejb.assembler.classic.HandlerChainInfo;
032: import org.apache.openejb.assembler.classic.MessageDrivenBeanInfo;
033: import org.apache.openejb.OpenEJBException;
034: import org.apache.openejb.util.Logger;
035: import org.apache.openejb.util.LogCategory;
036: import org.apache.openejb.util.Messages;
037: import org.apache.openejb.jee.oejb3.EjbDeployment;
038: import org.apache.openejb.jee.jpa.unit.Persistence;
039: import org.apache.openejb.jee.jpa.unit.PersistenceUnit;
040: import org.apache.openejb.jee.jpa.unit.Property;
041: import org.apache.openejb.jee.jpa.JpaJaxbUtil;
042: import org.apache.openejb.jee.jpa.EntityMappings;
043: import org.apache.openejb.jee.EnterpriseBean;
044: import org.apache.openejb.jee.ApplicationClient;
045: import org.apache.openejb.jee.Connector;
046: import org.apache.openejb.jee.ResourceAdapter;
047: import org.apache.openejb.jee.ConfigProperty;
048: import org.apache.openejb.jee.OutboundResourceAdapter;
049: import org.apache.openejb.jee.ConnectionDefinition;
050: import org.apache.openejb.jee.InboundResource;
051: import org.apache.openejb.jee.MessageListener;
052: import org.apache.openejb.jee.AdminObject;
053: import org.apache.openejb.jee.WebApp;
054: import org.apache.openejb.jee.Servlet;
055: import org.apache.openejb.jee.Webservices;
056: import org.apache.openejb.jee.WebserviceDescription;
057: import org.apache.openejb.jee.PortComponent;
058: import org.apache.openejb.jee.ServiceImplBean;
059:
060: import javax.xml.bind.JAXBException;
061: import java.util.Map;
062: import java.util.TreeMap;
063: import java.util.List;
064: import java.util.Properties;
065: import java.util.Arrays;
066: import java.util.ArrayList;
067: import java.net.URL;
068: import java.io.File;
069: import java.io.IOException;
070:
071: /**
072: * @version $Rev: 634140 $ $Date: 2008-03-05 19:20:40 -0800 $
073: */
074: class AppInfoBuilder {
075:
076: private static final Logger logger = Logger.getInstance(
077: LogCategory.OPENEJB_STARTUP_CONFIG,
078: "org.apache.openejb.util.resources");
079: private static final Messages messages = new Messages(
080: "org.apache.openejb.util.resources");
081:
082: private final ConfigurationFactory configFactory;
083:
084: private EjbJarInfoBuilder ejbJarInfoBuilder = new EjbJarInfoBuilder();
085:
086: public AppInfoBuilder(ConfigurationFactory configFactory) {
087: this .configFactory = configFactory;
088: }
089:
090: public AppInfo build(AppModule appModule) throws OpenEJBException {
091: AppInfo appInfo = new AppInfo();
092:
093: //
094: // Persistence Units
095: //
096:
097: buildPersistenceModules(appModule, appInfo);
098:
099: //
100: // EJB Jars
101: //
102:
103: Map<String, EjbJarInfo> ejbJarInfos = new TreeMap<String, EjbJarInfo>();
104: for (EjbModule ejbModule : appModule.getEjbModules()) {
105: try {
106: EjbJarInfo ejbJarInfo = ejbJarInfoBuilder
107: .buildInfo(ejbModule);
108:
109: Map<String, EjbDeployment> deploymentsByEjbName = ejbModule
110: .getOpenejbJar().getDeploymentsByEjbName();
111:
112: for (EnterpriseBeanInfo bean : ejbJarInfo.enterpriseBeans) {
113: EjbDeployment d = deploymentsByEjbName
114: .get(bean.ejbName);
115:
116: if (!configFactory.getContainerIds().contains(
117: d.getContainerId())
118: && !skipMdb(bean)) {
119: String msg = messages.format(
120: "config.noContainerFound", d
121: .getContainerId(), d
122: .getEjbName());
123: logger.fatal(msg);
124: throw new OpenEJBException(msg);
125: }
126:
127: bean.containerId = d.getContainerId();
128: }
129:
130: ejbJarInfo.portInfos
131: .addAll(configureWebservices(ejbModule
132: .getWebservices()));
133:
134: ejbJarInfos.put(ejbJarInfo.moduleId, ejbJarInfo);
135:
136: appInfo.ejbJars.add(ejbJarInfo);
137:
138: } catch (OpenEJBException e) {
139: ConfigUtils.logger.warning("conf.0004", ejbModule
140: .getJarLocation(), e.getMessage());
141: throw e;
142: }
143: }
144:
145: // Create the JNDI info builder
146: JndiEncInfoBuilder jndiEncInfoBuilder = new JndiEncInfoBuilder(
147: appInfo);
148:
149: // Build the JNDI tree for each ejb
150: for (EjbModule ejbModule : appModule.getEjbModules()) {
151:
152: EjbJarInfo ejbJar = ejbJarInfos
153: .get(ejbModule.getModuleId());
154:
155: Map<String, EnterpriseBean> beanData = ejbModule
156: .getEjbJar().getEnterpriseBeansByEjbName();
157:
158: for (EnterpriseBeanInfo beanInfo : ejbJar.enterpriseBeans) {
159:
160: // Get the ejb-jar.xml object
161: EnterpriseBean enterpriseBean = beanData
162: .get(beanInfo.ejbName);
163:
164: // Build the JNDI info tree for the EJB
165: JndiEncInfo jndi = jndiEncInfoBuilder.build(
166: enterpriseBean, beanInfo.ejbName,
167: ejbJar.moduleId);
168:
169: beanInfo.jndiEnc = jndi;
170: }
171: }
172:
173: //
174: // Application Clients
175: //
176:
177: buildClientModules(appModule, appInfo, jndiEncInfoBuilder);
178:
179: //
180: // J2EE Connectors
181: //
182:
183: buildConnectorModules(appModule, appInfo);
184:
185: //
186: // Webapps
187: //
188:
189: buildWebModules(appModule, jndiEncInfoBuilder, appInfo);
190:
191: //
192: // Final AppInfo creation
193: //
194:
195: appInfo.jarPath = appModule.getJarLocation();
196: appInfo.watchedResources
197: .addAll(appModule.getWatchedResources());
198: List<URL> additionalLibraries = appModule
199: .getAdditionalLibraries();
200: for (URL url : additionalLibraries) {
201: File file = toFile(url);
202: try {
203: appInfo.libs.add(file.getCanonicalPath());
204: } catch (IOException e) {
205: throw new OpenEJBException(
206: "Invalid application lib path "
207: + file.getAbsolutePath());
208: }
209: }
210:
211: if (appModule.getCmpMappings() != null) {
212: try {
213: String cmpMappingsXml = JpaJaxbUtil.marshal(
214: EntityMappings.class, appModule
215: .getCmpMappings());
216: appInfo.cmpMappingsXml = cmpMappingsXml;
217: } catch (JAXBException e) {
218: throw new OpenEJBException(
219: "Unable to marshal cmp entity mappings", e);
220: }
221: }
222:
223: ReportValidationResults reportValidationResults = new ReportValidationResults();
224: reportValidationResults.deploy(appModule);
225:
226: logger.info("Loaded Module: " + appInfo.jarPath);
227: return appInfo;
228:
229: }
230:
231: private void buildClientModules(AppModule appModule,
232: AppInfo appInfo, JndiEncInfoBuilder jndiEncInfoBuilder)
233: throws OpenEJBException {
234: for (ClientModule clientModule : appModule.getClientModules()) {
235: ApplicationClient applicationClient = clientModule
236: .getApplicationClient();
237: ClientInfo clientInfo = new ClientInfo();
238: clientInfo.description = applicationClient.getDescription();
239: clientInfo.displayName = applicationClient.getDisplayName();
240: clientInfo.codebase = clientModule.getJarLocation();
241: clientInfo.mainClass = clientModule.getMainClass();
242: clientInfo.callbackHandler = applicationClient
243: .getCallbackHandler();
244: clientInfo.moduleId = getClientModuleId(clientModule);
245: clientInfo.watchedResources.addAll(clientModule
246: .getWatchedResources());
247:
248: clientInfo.jndiEnc = jndiEncInfoBuilder.build(
249: applicationClient, clientModule.getJarLocation(),
250: clientInfo.moduleId);
251: appInfo.clients.add(clientInfo);
252: }
253: }
254:
255: private void buildWebModules(AppModule appModule,
256: JndiEncInfoBuilder jndiEncInfoBuilder, AppInfo appInfo)
257: throws OpenEJBException {
258: for (WebModule webModule : appModule.getWebModules()) {
259: WebApp webApp = webModule.getWebApp();
260: WebAppInfo webAppInfo = new WebAppInfo();
261: webAppInfo.description = webApp.getDescription();
262: webAppInfo.displayName = webApp.getDisplayName();
263: webAppInfo.codebase = webModule.getJarLocation();
264: webAppInfo.moduleId = webModule.getModuleId();
265: webAppInfo.watchedResources.addAll(webModule
266: .getWatchedResources());
267:
268: webAppInfo.host = webModule.getHost();
269: webAppInfo.contextRoot = webModule.getContextRoot();
270:
271: webAppInfo.jndiEnc = jndiEncInfoBuilder.build(webApp,
272: webModule.getJarLocation(), webAppInfo.moduleId);
273:
274: webAppInfo.portInfos.addAll(configureWebservices(webModule
275: .getWebservices()));
276:
277: for (Servlet servlet : webModule.getWebApp().getServlet()) {
278: ServletInfo servletInfo = new ServletInfo();
279: servletInfo.servletName = servlet.getServletName();
280: servletInfo.servletClass = servlet.getServletClass();
281: webAppInfo.servlets.add(servletInfo);
282: }
283:
284: appInfo.webApps.add(webAppInfo);
285: }
286: }
287:
288: private void buildConnectorModules(AppModule appModule,
289: AppInfo appInfo) {
290: for (ConnectorModule connectorModule : appModule
291: .getResourceModules()) {
292: //
293: // DEVELOPERS NOTE: if you change the id generation code here, you must change
294: // the id generation code in AutoConfig$AppResources
295: //
296:
297: Connector connector = connectorModule.getConnector();
298:
299: ConnectorInfo connectorInfo = new ConnectorInfo();
300: connectorInfo.description = connector.getDescription();
301: connectorInfo.displayName = connector.getDisplayName();
302: connectorInfo.codebase = connectorModule.getJarLocation();
303: connectorInfo.moduleId = connectorModule.getModuleId();
304: connectorInfo.watchedResources.addAll(connectorModule
305: .getWatchedResources());
306:
307: List<URL> libraries = connectorModule.getLibraries();
308: for (URL url : libraries) {
309: File file = toFile(url);
310: try {
311: connectorInfo.libs.add(file.getCanonicalPath());
312: } catch (IOException e) {
313: throw new IllegalArgumentException(
314: "Invalid application lib path "
315: + file.getAbsolutePath());
316: }
317: }
318:
319: ResourceAdapter resourceAdapter = connector
320: .getResourceAdapter();
321: if (resourceAdapter.getResourceAdapterClass() != null) {
322: ResourceInfo resourceInfo = new ResourceInfo();
323: resourceInfo.service = "Resource";
324: if (resourceAdapter.getId() != null) {
325: resourceInfo.id = resourceAdapter.getId();
326: } else {
327: resourceInfo.id = connectorModule.getModuleId()
328: + "RA";
329: }
330: resourceInfo.className = resourceAdapter
331: .getResourceAdapterClass();
332: resourceInfo.properties = new Properties();
333: for (ConfigProperty property : resourceAdapter
334: .getConfigProperty()) {
335: String name = property.getConfigPropertyName();
336: String value = property.getConfigPropertyValue();
337: if (value != null) {
338: resourceInfo.properties
339: .setProperty(name, value);
340: }
341: }
342: resourceInfo.properties.putAll(ConfigurationFactory
343: .getSystemProperties(resourceInfo.id,
344: "RESOURCE"));
345: connectorInfo.resourceAdapter = resourceInfo;
346: }
347:
348: OutboundResourceAdapter outbound = resourceAdapter
349: .getOutboundResourceAdapter();
350: if (outbound != null) {
351: String transactionSupport = "none";
352: switch (outbound.getTransactionSupport()) {
353: case LOCAL_TRANSACTION:
354: transactionSupport = "local";
355: break;
356: case NO_TRANSACTION:
357: transactionSupport = "none";
358: break;
359: case XA_TRANSACTION:
360: transactionSupport = "xa";
361: break;
362: }
363: for (ConnectionDefinition connection : outbound
364: .getConnectionDefinition()) {
365: ResourceInfo resourceInfo = new ResourceInfo();
366: resourceInfo.service = "Resource";
367: if (connection.getId() != null) {
368: resourceInfo.id = connection.getId();
369: } else if (outbound.getConnectionDefinition()
370: .size() == 1) {
371: resourceInfo.id = connectorModule.getModuleId();
372: } else {
373: resourceInfo.id = connectorModule.getModuleId()
374: + "-"
375: + connection
376: .getConnectionFactoryInterface();
377: }
378: resourceInfo.className = connection
379: .getManagedConnectionFactoryClass();
380: resourceInfo.types.add(connection
381: .getConnectionFactoryInterface());
382: resourceInfo.properties = new Properties();
383: for (ConfigProperty property : connection
384: .getConfigProperty()) {
385: String name = property.getConfigPropertyName();
386: String value = property
387: .getConfigPropertyValue();
388: if (value != null) {
389: resourceInfo.properties.setProperty(name,
390: value);
391: }
392: }
393: resourceInfo.properties.setProperty(
394: "TransactionSupport", transactionSupport);
395: resourceInfo.properties.setProperty(
396: "ResourceAdapter",
397: connectorInfo.resourceAdapter.id);
398: resourceInfo.properties.putAll(ConfigurationFactory
399: .getSystemProperties(resourceInfo.id,
400: "RESOURCE"));
401: connectorInfo.outbound.add(resourceInfo);
402: }
403: }
404:
405: InboundResource inbound = resourceAdapter
406: .getInboundResourceAdapter();
407: if (inbound != null) {
408: for (MessageListener messageListener : inbound
409: .getMessageAdapter().getMessageListener()) {
410: MdbContainerInfo mdbContainerInfo = new MdbContainerInfo();
411: mdbContainerInfo.service = "Container";
412: if (messageListener.getId() != null) {
413: mdbContainerInfo.id = messageListener.getId();
414: } else if (inbound.getMessageAdapter()
415: .getMessageListener().size() == 1) {
416: mdbContainerInfo.id = connectorModule
417: .getModuleId();
418: } else {
419: mdbContainerInfo.id = connectorModule
420: .getModuleId()
421: + "-"
422: + messageListener
423: .getMessageListenerType();
424: }
425:
426: mdbContainerInfo.properties = new Properties();
427: mdbContainerInfo.properties.setProperty(
428: "ResourceAdapter",
429: connectorInfo.resourceAdapter.id);
430: mdbContainerInfo.properties.setProperty(
431: "MessageListenerInterface", messageListener
432: .getMessageListenerType());
433: mdbContainerInfo.properties.setProperty(
434: "ActivationSpecClass", messageListener
435: .getActivationSpec()
436: .getActivationSpecClass());
437:
438: // todo provider system should fill in this information
439: mdbContainerInfo.types.add("MESSAGE");
440: mdbContainerInfo.className = "org.apache.openejb.core.mdb.MdbContainer";
441: mdbContainerInfo.constructorArgs.addAll(Arrays
442: .asList("id", "transactionManager",
443: "securityService",
444: "ResourceAdapter",
445: "MessageListenerInterface",
446: "ActivationSpecClass",
447: "InstanceLimit"));
448: mdbContainerInfo.properties.setProperty(
449: "InstanceLimit", "10");
450:
451: mdbContainerInfo.properties
452: .putAll(ConfigurationFactory
453: .getSystemProperties(
454: mdbContainerInfo.id,
455: "CONTAINER"));
456: connectorInfo.inbound.add(mdbContainerInfo);
457: }
458: }
459:
460: for (AdminObject adminObject : resourceAdapter
461: .getAdminObject()) {
462: ResourceInfo resourceInfo = new ResourceInfo();
463: resourceInfo.service = "Resource";
464: if (adminObject.getId() != null) {
465: resourceInfo.id = adminObject.getId();
466: } else if (resourceAdapter.getAdminObject().size() == 1) {
467: resourceInfo.id = connectorModule.getModuleId();
468: } else {
469: resourceInfo.id = connectorModule.getModuleId()
470: + "-"
471: + adminObject.getAdminObjectInterface();
472: }
473: resourceInfo.className = adminObject
474: .getAdminObjectClass();
475: resourceInfo.types.add(adminObject
476: .getAdminObjectInterface());
477: resourceInfo.properties = new Properties();
478: for (ConfigProperty property : adminObject
479: .getConfigProperty()) {
480: String name = property.getConfigPropertyName();
481: String value = property.getConfigPropertyValue();
482: if (value != null) {
483: resourceInfo.properties
484: .setProperty(name, value);
485: }
486: }
487: resourceInfo.properties.putAll(ConfigurationFactory
488: .getSystemProperties(resourceInfo.id,
489: "RESOURCE"));
490: connectorInfo.adminObject.add(resourceInfo);
491: }
492:
493: appInfo.connectors.add(connectorInfo);
494: }
495: }
496:
497: private void buildPersistenceModules(AppModule appModule,
498: AppInfo appInfo) {
499: for (PersistenceModule persistenceModule : appModule
500: .getPersistenceModules()) {
501: String rootUrl = persistenceModule.getRootUrl();
502: Persistence persistence = persistenceModule
503: .getPersistence();
504: for (PersistenceUnit persistenceUnit : persistence
505: .getPersistenceUnit()) {
506: PersistenceUnitInfo info = new PersistenceUnitInfo();
507: info.id = persistenceUnit.getName() + " "
508: + rootUrl.hashCode();
509: info.name = persistenceUnit.getName();
510: info.watchedResources.addAll(persistenceModule
511: .getWatchedResources());
512: info.persistenceUnitRootUrl = rootUrl;
513: info.provider = persistenceUnit.getProvider();
514: info.transactionType = persistenceUnit
515: .getTransactionType().toString();
516:
517: Boolean excludeUnlistedClasses = persistenceUnit
518: .isExcludeUnlistedClasses();
519: info.excludeUnlistedClasses = excludeUnlistedClasses != null
520: && excludeUnlistedClasses;
521:
522: info.jtaDataSource = persistenceUnit.getJtaDataSource();
523: info.nonJtaDataSource = persistenceUnit
524: .getNonJtaDataSource();
525:
526: info.jarFiles.addAll(persistenceUnit.getJarFile());
527: info.classes.addAll(persistenceUnit.getClazz());
528: info.mappingFiles.addAll(persistenceUnit
529: .getMappingFile());
530:
531: // Handle Properties
532: org.apache.openejb.jee.jpa.unit.Properties puiProperties = persistenceUnit
533: .getProperties();
534: if (puiProperties != null) {
535: for (Property property : puiProperties
536: .getProperty()) {
537: info.properties.put(property.getName(),
538: property.getValue());
539: }
540: }
541:
542: // Persistence Unit Root Url
543: appInfo.persistenceUnits.add(info);
544: }
545: }
546: }
547:
548: private static String getClientModuleId(ClientModule clientModule) {
549: String jarLocation = clientModule.getJarLocation();
550: File file = new File(jarLocation);
551: String name = file.getName();
552: if (name.endsWith(".jar") || name.endsWith(".zip")) {
553: name = name.replaceFirst("....$", "");
554: }
555: return name;
556: }
557:
558: private List<PortInfo> configureWebservices(Webservices webservices) {
559: List<PortInfo> portMap = new ArrayList<PortInfo>();
560: if (webservices == null) {
561: return portMap;
562: }
563:
564: for (WebserviceDescription desc : webservices
565: .getWebserviceDescription()) {
566: String wsdlFile = desc.getWsdlFile();
567: String serviceName = desc.getWebserviceDescriptionName();
568:
569: for (PortComponent port : desc.getPortComponent()) {
570: PortInfo portInfo = new PortInfo();
571:
572: ServiceImplBean serviceImplBean = port
573: .getServiceImplBean();
574: portInfo.serviceId = desc.getId();
575: portInfo.portId = port.getId();
576: portInfo.serviceLink = serviceImplBean.getEjbLink();
577: if (portInfo.serviceLink == null) {
578: portInfo.serviceLink = serviceImplBean
579: .getServletLink();
580: }
581:
582: portInfo.seiInterfaceName = port
583: .getServiceEndpointInterface();
584: portInfo.portName = port.getPortComponentName();
585: portInfo.binding = port.getProtocolBinding();
586: portInfo.serviceName = serviceName;
587: portInfo.wsdlFile = wsdlFile;
588: portInfo.mtomEnabled = port.isEnableMtom();
589: portInfo.wsdlPort = port.getWsdlPort();
590: portInfo.wsdlService = port.getWsdlService();
591: portInfo.location = port.getLocation();
592:
593: List<HandlerChainInfo> handlerChains = ConfigurationFactory
594: .toHandlerChainInfo(port.getHandlerChains());
595: portInfo.handlerChains.addAll(handlerChains);
596:
597: // todo configure jaxrpc mappings here
598:
599: portMap.add(portInfo);
600: }
601: }
602: return portMap;
603: }
604:
605: private static boolean skipMdb(EnterpriseBeanInfo bean) {
606: return bean instanceof MessageDrivenBeanInfo
607: && System.getProperty("duct tape") != null;
608: }
609:
610: }
|