0001: /**
0002: *
0003: * Licensed to the Apache Software Foundation (ASF) under one or more
0004: * contributor license agreements. See the NOTICE file distributed with
0005: * this work for additional information regarding copyright ownership.
0006: * The ASF licenses this file to You under the Apache License, Version 2.0
0007: * (the "License"); you may not use this file except in compliance with
0008: * the License. You may obtain a copy of the License at
0009: *
0010: * http://www.apache.org/licenses/LICENSE-2.0
0011: *
0012: * Unless required by applicable law or agreed to in writing, software
0013: * distributed under the License is distributed on an "AS IS" BASIS,
0014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0015: * See the License for the specific language governing permissions and
0016: * limitations under the License.
0017: */package org.apache.openejb.config;
0018:
0019: import static org.apache.openejb.config.ServiceUtils.NONE;
0020: import static org.apache.openejb.config.ServiceUtils.ANY;
0021:
0022: import static java.util.Arrays.asList;
0023:
0024: import static org.apache.openejb.config.ServiceUtils.hasServiceProvider;
0025: import org.apache.openejb.OpenEJBException;
0026: import org.apache.openejb.config.sys.Resource;
0027: import org.apache.openejb.assembler.classic.ContainerInfo;
0028: import org.apache.openejb.assembler.classic.ResourceInfo;
0029: import org.apache.openejb.util.LinkResolver;
0030: import org.apache.openejb.util.UniqueDefaultLinkResolver;
0031: import org.apache.openejb.jee.MessageDrivenBean;
0032: import org.apache.openejb.jee.ActivationConfig;
0033: import org.apache.openejb.jee.EnterpriseBean;
0034: import org.apache.openejb.jee.MessageDestination;
0035: import org.apache.openejb.jee.AssemblyDescriptor;
0036: import org.apache.openejb.jee.PersistenceType;
0037: import org.apache.openejb.jee.SessionType;
0038: import org.apache.openejb.jee.MessageDestinationRef;
0039: import org.apache.openejb.jee.JndiReference;
0040: import org.apache.openejb.jee.ResourceRef;
0041: import org.apache.openejb.jee.JndiConsumer;
0042: import org.apache.openejb.jee.Connector;
0043: import org.apache.openejb.jee.ResourceAdapter;
0044: import org.apache.openejb.jee.OutboundResourceAdapter;
0045: import org.apache.openejb.jee.ConnectionDefinition;
0046: import org.apache.openejb.jee.InboundResource;
0047: import org.apache.openejb.jee.MessageListener;
0048: import org.apache.openejb.jee.AdminObject;
0049: import org.apache.openejb.jee.PersistenceContextRef;
0050: import org.apache.openejb.jee.PersistenceRef;
0051: import org.apache.openejb.jee.jpa.unit.Persistence;
0052: import org.apache.openejb.jee.jpa.unit.PersistenceUnit;
0053: import org.apache.openejb.jee.oejb3.EjbDeployment;
0054: import org.apache.openejb.jee.oejb3.OpenejbJar;
0055: import org.apache.openejb.jee.oejb3.ResourceLink;
0056: import org.apache.openejb.util.LogCategory;
0057: import org.apache.openejb.util.Logger;
0058: import org.apache.openejb.util.URISupport;
0059: import org.apache.openejb.util.SuperProperties;
0060: import static org.apache.openejb.util.Join.join;
0061:
0062: import javax.jms.Queue;
0063: import javax.jms.Topic;
0064: import java.util.List;
0065: import java.util.Map;
0066: import java.util.Properties;
0067: import java.util.Set;
0068: import java.util.TreeSet;
0069: import java.util.HashMap;
0070: import java.util.TreeMap;
0071: import java.util.ArrayList;
0072: import java.util.Collections;
0073: import java.util.Collection;
0074: import java.net.URI;
0075:
0076: public class AutoConfig implements DynamicDeployer {
0077:
0078: public static Logger logger = Logger.getInstance(
0079: LogCategory.OPENEJB_STARTUP_CONFIG, AutoConfig.class);
0080:
0081: private static Set<String> ignoredReferenceTypes = new TreeSet<String>();
0082: static {
0083: // Context objects are automatically handled
0084: ignoredReferenceTypes.add("javax.ejb.SessionContext");
0085: ignoredReferenceTypes.add("javax.ejb.EntityContext");
0086: ignoredReferenceTypes.add("javax.ejb.MessageDrivenContext");
0087: ignoredReferenceTypes.add("javax.xml.ws.WebServiceContext");
0088: // URLs are automatically handled
0089: ignoredReferenceTypes.add("java.net.URL");
0090: // User transaction is automatically handled
0091: ignoredReferenceTypes.add("javax.transaction.UserTransaction");
0092: ignoredReferenceTypes.add("javax.ejb.TimerService");
0093: }
0094:
0095: private final ConfigurationFactory configFactory;
0096: private boolean autoCreateContainers = true;
0097: private boolean autoCreateResources = true;
0098:
0099: public AutoConfig(ConfigurationFactory configFactory) {
0100: this .configFactory = configFactory;
0101: }
0102:
0103: public synchronized boolean autoCreateResources() {
0104: return autoCreateResources;
0105: }
0106:
0107: public synchronized void autoCreateResources(
0108: boolean autoCreateResources) {
0109: this .autoCreateResources = autoCreateResources;
0110: }
0111:
0112: public synchronized boolean autoCreateContainers() {
0113: return autoCreateContainers;
0114: }
0115:
0116: public synchronized void autoCreateContainers(
0117: boolean autoCreateContainers) {
0118: this .autoCreateContainers = autoCreateContainers;
0119: }
0120:
0121: public void init() throws OpenEJBException {
0122: }
0123:
0124: public synchronized AppModule deploy(AppModule appModule)
0125: throws OpenEJBException {
0126: AppResources appResources = new AppResources(appModule);
0127:
0128: for (EjbModule ejbModule : appModule.getEjbModules()) {
0129: processActivationConfig(ejbModule);
0130: }
0131: resolveDestinationLinks(appModule);
0132:
0133: resolvePersistenceRefs(appModule);
0134:
0135: for (EjbModule ejbModule : appModule.getEjbModules()) {
0136: deploy(ejbModule, appResources);
0137: }
0138: for (ClientModule clientModule : appModule.getClientModules()) {
0139: deploy(clientModule, appResources);
0140: }
0141: for (ConnectorModule connectorModule : appModule
0142: .getResourceModules()) {
0143: deploy(connectorModule);
0144: }
0145: for (WebModule webModule : appModule.getWebModules()) {
0146: deploy(webModule, appResources);
0147: }
0148: for (PersistenceModule persistenceModule : appModule
0149: .getPersistenceModules()) {
0150: deploy(persistenceModule);
0151: }
0152: return appModule;
0153: }
0154:
0155: private void resolvePersistenceRefs(AppModule appModule) {
0156: LinkResolver<PersistenceUnit> persistenceUnits = new UniqueDefaultLinkResolver<PersistenceUnit>();
0157:
0158: for (PersistenceModule module : appModule
0159: .getPersistenceModules()) {
0160: String rootUrl = module.getRootUrl();
0161: for (PersistenceUnit unit : module.getPersistence()
0162: .getPersistenceUnit()) {
0163: unit.setId(unit.getName() + " " + rootUrl.hashCode());
0164: persistenceUnits.add(rootUrl, unit.getName(), unit);
0165: }
0166: }
0167:
0168: for (EjbModule ejbModule : appModule.getEjbModules()) {
0169: URI moduleURI = URI.create(ejbModule.getModuleId());
0170:
0171: for (JndiConsumer component : ejbModule.getEjbJar()
0172: .getEnterpriseBeans()) {
0173: processPersistenceRefs(component, ejbModule,
0174: persistenceUnits, moduleURI);
0175: }
0176:
0177: }
0178:
0179: for (ClientModule clientModule : appModule.getClientModules()) {
0180: URI moduleURI = URI.create(clientModule.getModuleId());
0181: processPersistenceRefs(clientModule.getApplicationClient(),
0182: clientModule, persistenceUnits, moduleURI);
0183: }
0184:
0185: for (WebModule webModule : appModule.getWebModules()) {
0186: URI moduleURI = URI.create(webModule.getModuleId());
0187: processPersistenceRefs(webModule.getWebApp(), webModule,
0188: persistenceUnits, moduleURI);
0189: }
0190: }
0191:
0192: private void processPersistenceRefs(JndiConsumer component,
0193: DeploymentModule module,
0194: LinkResolver<PersistenceUnit> persistenceUnits,
0195: URI moduleURI) {
0196:
0197: String componentName = component.getJndiConsumerName();
0198:
0199: ValidationContext validation = module.getValidation();
0200:
0201: for (PersistenceRef ref : component.getPersistenceUnitRef()) {
0202:
0203: processPersistenceRef(persistenceUnits, ref, moduleURI,
0204: componentName, validation);
0205: }
0206:
0207: for (PersistenceRef ref : component.getPersistenceContextRef()) {
0208:
0209: processPersistenceRef(persistenceUnits, ref, moduleURI,
0210: componentName, validation);
0211: }
0212: }
0213:
0214: private PersistenceUnit processPersistenceRef(
0215: LinkResolver<PersistenceUnit> persistenceUnits,
0216: PersistenceRef ref, URI moduleURI, String componentName,
0217: ValidationContext validation) {
0218:
0219: if (ref.getMappedName() != null
0220: && ref.getMappedName().startsWith("jndi:")) {
0221: return null;
0222: }
0223:
0224: PersistenceUnit unit = persistenceUnits.resolveLink(ref
0225: .getPersistenceUnitName(), moduleURI);
0226:
0227: // Explicitly check if we messed up the "if there's only one,
0228: // that's what you get" rule by adding our "cmp" unit.
0229: Collection<PersistenceUnit> cmpUnits = persistenceUnits
0230: .values("cmp");
0231: if (unit == null
0232: && cmpUnits.size() > 0
0233: && persistenceUnits.values().size() - cmpUnits.size() == 1) {
0234: // We did, there is exactly one non-cmp unit. Let's find it.
0235: for (PersistenceUnit persistenceUnit : persistenceUnits
0236: .values()) {
0237: if (!persistenceUnit.getName().equals("cmp")) {
0238: // Found it
0239: unit = persistenceUnit;
0240: break;
0241: }
0242: }
0243: }
0244:
0245: // try again using the ref name
0246: if (unit == null) {
0247: unit = persistenceUnits.resolveLink(ref.getName(),
0248: moduleURI);
0249: }
0250:
0251: // try again using the ref name with any prefix removed
0252: if (unit == null) {
0253: String shortName = ref.getName().replaceFirst(".*/", "");
0254: unit = persistenceUnits.resolveLink(shortName, moduleURI);
0255: }
0256:
0257: if (unit != null) {
0258: ref.setMappedName(unit.getId());
0259: } else {
0260:
0261: // ----------------------------------------------
0262: // Nothing was found. Let's try and figure out
0263: // what went wrong and log a validation message
0264: // ----------------------------------------------
0265:
0266: String refType = "persistence";
0267: if (ref instanceof PersistenceContextRef) {
0268: refType += "ContextRef";
0269: } else
0270: refType += "UnitRef";
0271:
0272: String refShortName = ref.getName();
0273: if (refShortName.matches(".*\\..*/.*")) {
0274: refShortName = refShortName.replaceFirst(".*/", "");
0275: }
0276:
0277: List<String> availableUnits = new ArrayList<String>();
0278: for (PersistenceUnit persistenceUnit : persistenceUnits
0279: .values()) {
0280: availableUnits.add(persistenceUnit.getName());
0281: }
0282:
0283: Collections.sort(availableUnits);
0284:
0285: String unitName = ref.getPersistenceUnitName();
0286:
0287: if (availableUnits.size() == 0) {
0288: // Print a sample persistence.xml using their data
0289: if (unitName == null) {
0290: unitName = refShortName;
0291: }
0292: validation
0293: .fail(componentName, refType
0294: + ".noPersistenceUnits", refShortName,
0295: unitName);
0296: } else if (ref.getPersistenceUnitName() == null
0297: && availableUnits.size() > 1) {
0298: // Print a correct example of unitName in a ref
0299: // DMB: Idea, the ability to set a default unit-name in openejb-jar.xml via a property
0300: String sampleUnitName = availableUnits.get(0);
0301: validation.fail(componentName, refType + ".noUnitName",
0302: refShortName, join(", ", availableUnits),
0303: sampleUnitName);
0304: } else {
0305: Collection<PersistenceUnit> vagueMatches = persistenceUnits
0306: .values(ref.getPersistenceUnitName());
0307: if (vagueMatches.size() != 0) {
0308: // Print the full rootUrls
0309:
0310: List<String> possibleUnits = new ArrayList<String>();
0311: for (PersistenceUnit persistenceUnit : persistenceUnits
0312: .values()) {
0313: URI unitURI = URI.create(persistenceUnit
0314: .getId());
0315: unitURI = URISupport.relativize(moduleURI,
0316: unitURI);
0317: possibleUnits.add(unitURI.toString());
0318: }
0319:
0320: Collections.sort(possibleUnits);
0321:
0322: validation.fail(componentName, refType
0323: + ".vagueMatches", refShortName, unitName,
0324: possibleUnits.size(), join("\n",
0325: possibleUnits));
0326: } else {
0327: validation.fail(componentName, refType
0328: + ".noMatches", refShortName, unitName,
0329: join(", ", availableUnits));
0330: }
0331: }
0332: }
0333: return unit;
0334: }
0335:
0336: /**
0337: * Set destination, destinationType, clientId and subscriptionName in the MDB activation config.
0338: */
0339: private void processActivationConfig(EjbModule ejbModule)
0340: throws OpenEJBException {
0341: OpenejbJar openejbJar;
0342: if (ejbModule.getOpenejbJar() != null) {
0343: openejbJar = ejbModule.getOpenejbJar();
0344: } else {
0345: openejbJar = new OpenejbJar();
0346: ejbModule.setOpenejbJar(openejbJar);
0347: }
0348:
0349: Map<String, EjbDeployment> deployments = openejbJar
0350: .getDeploymentsByEjbName();
0351:
0352: for (EnterpriseBean bean : ejbModule.getEjbJar()
0353: .getEnterpriseBeans()) {
0354: if (bean instanceof MessageDrivenBean) {
0355: MessageDrivenBean mdb = (MessageDrivenBean) bean;
0356:
0357: EjbDeployment ejbDeployment = deployments.get(bean
0358: .getEjbName());
0359: if (ejbDeployment == null) {
0360: throw new OpenEJBException(
0361: "No ejb deployment found for ejb "
0362: + bean.getEjbName());
0363: }
0364:
0365: if (mdb.getActivationConfig() == null) {
0366: mdb.setActivationConfig(new ActivationConfig());
0367: }
0368:
0369: Properties properties = mdb.getActivationConfig()
0370: .toProperties();
0371:
0372: // destination
0373: String destination = properties.getProperty(
0374: "destination", properties
0375: .getProperty("destinationName"));
0376: if (destination == null) {
0377: destination = ejbDeployment.getDeploymentId();
0378: mdb.getActivationConfig().addProperty(
0379: "destination", destination);
0380: }
0381:
0382: // destination identifier
0383: ResourceLink link = ejbDeployment
0384: .getResourceLink("openejb/destination");
0385: if (link == null
0386: && mdb.getMessageDestinationLink() == null) {
0387: link = new ResourceLink();
0388: link.setResId(destination);
0389: link.setResRefName("openejb/destination");
0390: ejbDeployment.addResourceLink(link);
0391: }
0392:
0393: // destination type
0394: String destinationType = properties
0395: .getProperty("destinationType");
0396: if (destinationType == null
0397: && mdb.getMessageDestinationType() != null) {
0398: destinationType = mdb.getMessageDestinationType();
0399: mdb.getActivationConfig().addProperty(
0400: "destinationType", destinationType);
0401: }
0402: if (mdb.getMessageDestinationType() == null) {
0403: mdb.setMessageDestinationType(destinationType);
0404: }
0405:
0406: // topics need a clientId and subscriptionName
0407: if ("javax.jms.Topic".equals(destinationType)) {
0408: if (!properties.containsKey("clientId")) {
0409: mdb.getActivationConfig().addProperty(
0410: "clientId",
0411: ejbDeployment.getDeploymentId());
0412: }
0413: if (!properties.containsKey("subscriptionName")) {
0414: mdb.getActivationConfig().addProperty(
0415: "subscriptionName",
0416: ejbDeployment.getDeploymentId()
0417: + "_subscription");
0418: }
0419: }
0420: }
0421: }
0422: }
0423:
0424: /**
0425: * Set resource id in all message-destination-refs and MDBs that are using message destination links.
0426: */
0427: private void resolveDestinationLinks(AppModule appModule)
0428: throws OpenEJBException {
0429: // build up a link resolver
0430: LinkResolver<MessageDestination> destinationResolver = new LinkResolver<MessageDestination>();
0431: for (EjbModule ejbModule : appModule.getEjbModules()) {
0432: AssemblyDescriptor assembly = ejbModule.getEjbJar()
0433: .getAssemblyDescriptor();
0434: if (assembly != null) {
0435: String moduleId = ejbModule.getModuleId();
0436: for (MessageDestination destination : assembly
0437: .getMessageDestination()) {
0438: destinationResolver.add(moduleId, destination
0439: .getMessageDestinationName(), destination);
0440: }
0441: }
0442: }
0443: for (ClientModule clientModule : appModule.getClientModules()) {
0444: String moduleId = appModule.getModuleId();
0445: for (MessageDestination destination : clientModule
0446: .getApplicationClient().getMessageDestination()) {
0447: destinationResolver.add(moduleId, destination
0448: .getMessageDestinationName(), destination);
0449: }
0450: }
0451: for (WebModule webModule : appModule.getWebModules()) {
0452: String moduleId = appModule.getModuleId();
0453: for (MessageDestination destination : webModule.getWebApp()
0454: .getMessageDestination()) {
0455: destinationResolver.add(moduleId, destination
0456: .getMessageDestinationName(), destination);
0457: }
0458: }
0459:
0460: // remember the type of each destination so we can use it to fillin MDBs that don't declare destination type
0461: Map<MessageDestination, String> destinationTypes = new HashMap<MessageDestination, String>();
0462:
0463: // resolve all MDBs with destination links
0464: // if MessageDestination does not have a mapped name assigned, give it the destination from the MDB
0465: for (EjbModule ejbModule : appModule.getEjbModules()) {
0466: AssemblyDescriptor assembly = ejbModule.getEjbJar()
0467: .getAssemblyDescriptor();
0468: if (assembly == null) {
0469: continue;
0470: }
0471:
0472: URI moduleUri = URI.create(appModule.getModuleId());
0473: OpenejbJar openejbJar = ejbModule.getOpenejbJar();
0474:
0475: for (EnterpriseBean bean : ejbModule.getEjbJar()
0476: .getEnterpriseBeans()) {
0477: // MDB destination is deploymentId if none set
0478: if (bean instanceof MessageDrivenBean) {
0479: MessageDrivenBean mdb = (MessageDrivenBean) bean;
0480:
0481: EjbDeployment ejbDeployment = openejbJar
0482: .getDeploymentsByEjbName().get(
0483: bean.getEjbName());
0484: if (ejbDeployment == null) {
0485: throw new OpenEJBException(
0486: "No ejb deployment found for ejb "
0487: + bean.getEjbName());
0488: }
0489:
0490: // skip destination refs without a destination link
0491: String link = mdb.getMessageDestinationLink();
0492: if (link == null || link.length() == 0) {
0493: continue;
0494: }
0495:
0496: // resolve the destination... if we don't find one it is a configuration bug
0497: MessageDestination destination = destinationResolver
0498: .resolveLink(link, moduleUri);
0499: if (destination == null) {
0500: throw new OpenEJBException(
0501: "Message destination " + link
0502: + " for message driven bean "
0503: + mdb.getEjbName()
0504: + " not found");
0505: }
0506:
0507: // get the destinationId is the mapped name
0508: String destinationId = destination.getMappedName();
0509: if (destinationId == null) {
0510: // if we don't have a mapped name use the destination of the mdb
0511: Properties properties = mdb
0512: .getActivationConfig().toProperties();
0513: destinationId = properties
0514: .getProperty("destination");
0515: destination.setMappedName(destinationId);
0516: }
0517:
0518: if (mdb.getMessageDestinationType() != null
0519: && !destinationTypes
0520: .containsKey(destination)) {
0521: destinationTypes.put(destination, mdb
0522: .getMessageDestinationType());
0523: }
0524:
0525: // destination identifier
0526: ResourceLink resourceLink = ejbDeployment
0527: .getResourceLink("openejb/destination");
0528: if (resourceLink == null) {
0529: resourceLink = new ResourceLink();
0530: resourceLink
0531: .setResRefName("openejb/destination");
0532: ejbDeployment.addResourceLink(resourceLink);
0533: }
0534: resourceLink.setResId(destinationId);
0535: }
0536: }
0537: }
0538:
0539: // resolve all message destination refs with links and assign a ref id to the reference
0540: for (EjbModule ejbModule : appModule.getEjbModules()) {
0541: AssemblyDescriptor assembly = ejbModule.getEjbJar()
0542: .getAssemblyDescriptor();
0543: if (assembly == null) {
0544: continue;
0545: }
0546:
0547: URI moduleUri = URI.create(appModule.getModuleId());
0548: OpenejbJar openejbJar = ejbModule.getOpenejbJar();
0549:
0550: for (EnterpriseBean bean : ejbModule.getEjbJar()
0551: .getEnterpriseBeans()) {
0552: EjbDeployment ejbDeployment = openejbJar
0553: .getDeploymentsByEjbName().get(
0554: bean.getEjbName());
0555: if (ejbDeployment == null) {
0556: throw new OpenEJBException(
0557: "No ejb deployment found for ejb "
0558: + bean.getEjbName());
0559: }
0560:
0561: for (MessageDestinationRef ref : bean
0562: .getMessageDestinationRef()) {
0563: // skip destination refs with a resource link already assigned
0564: if (ref.getMappedName() == null
0565: && ejbDeployment.getResourceLink(ref
0566: .getName()) == null) {
0567: String destinationId = resolveDestinationId(
0568: ref, moduleUri, destinationResolver,
0569: destinationTypes);
0570: if (destinationId != null) {
0571: // build the link and add it
0572: ResourceLink resourceLink = new ResourceLink();
0573: resourceLink.setResId(destinationId);
0574: resourceLink.setResRefName(ref.getName());
0575: ejbDeployment.addResourceLink(resourceLink);
0576: }
0577:
0578: }
0579: }
0580: }
0581: }
0582:
0583: for (ClientModule clientModule : appModule.getClientModules()) {
0584: URI moduleUri = URI.create(appModule.getModuleId());
0585: for (MessageDestinationRef ref : clientModule
0586: .getApplicationClient().getMessageDestinationRef()) {
0587: String destinationId = resolveDestinationId(ref,
0588: moduleUri, destinationResolver,
0589: destinationTypes);
0590: if (destinationId != null) {
0591: // for client modules we put the destinationId in the mapped name
0592: ref.setMappedName(destinationId);
0593: }
0594: }
0595: }
0596:
0597: for (WebModule webModule : appModule.getWebModules()) {
0598: URI moduleUri = URI.create(appModule.getModuleId());
0599: for (MessageDestinationRef ref : webModule.getWebApp()
0600: .getMessageDestinationRef()) {
0601: String destinationId = resolveDestinationId(ref,
0602: moduleUri, destinationResolver,
0603: destinationTypes);
0604: if (destinationId != null) {
0605: // for web modules we put the destinationId in the mapped name
0606: ref.setMappedName(destinationId);
0607: }
0608: }
0609: }
0610:
0611: // Process MDBs one more time...
0612: // this time fill in the destination type (if not alreday specified) with
0613: // the info from the destination (which got filled in from the references)
0614: for (EjbModule ejbModule : appModule.getEjbModules()) {
0615: AssemblyDescriptor assembly = ejbModule.getEjbJar()
0616: .getAssemblyDescriptor();
0617: if (assembly == null) {
0618: continue;
0619: }
0620:
0621: URI moduleUri = URI.create(appModule.getModuleId());
0622: OpenejbJar openejbJar = ejbModule.getOpenejbJar();
0623:
0624: for (EnterpriseBean bean : ejbModule.getEjbJar()
0625: .getEnterpriseBeans()) {
0626: // MDB destination is deploymentId if none set
0627: if (bean instanceof MessageDrivenBean) {
0628: MessageDrivenBean mdb = (MessageDrivenBean) bean;
0629:
0630: EjbDeployment ejbDeployment = openejbJar
0631: .getDeploymentsByEjbName().get(
0632: bean.getEjbName());
0633: if (ejbDeployment == null) {
0634: throw new OpenEJBException(
0635: "No ejb deployment found for ejb "
0636: + bean.getEjbName());
0637: }
0638:
0639: // if destination type is already set in, continue
0640: String destinationType = mdb
0641: .getMessageDestinationType();
0642: if (destinationType != null) {
0643: continue;
0644: }
0645:
0646: String link = mdb.getMessageDestinationLink();
0647: if (link != null && link.length() != 0) {
0648: // resolve the destination... if we don't find one it is a configuration bug
0649: MessageDestination destination = destinationResolver
0650: .resolveLink(link, moduleUri);
0651: if (destination == null) {
0652: throw new OpenEJBException(
0653: "Message destination "
0654: + link
0655: + " for message driven bean "
0656: + mdb.getEjbName()
0657: + " not found");
0658: }
0659: destinationType = destinationTypes
0660: .get(destination);
0661: }
0662:
0663: if (destinationType == null) {
0664: // couldn't determine type... we'll have to guess
0665:
0666: // if destination name contains the string "queue" or "topic" we use that
0667: Properties properties = mdb
0668: .getActivationConfig().toProperties();
0669: String destination = properties.getProperty(
0670: "destination").toLowerCase();
0671: if (destination.indexOf("queue") >= 0) {
0672: destinationType = Queue.class.getName();
0673: } else if (destination.indexOf("topic") >= 0) {
0674: destinationType = Topic.class.getName();
0675: } else {
0676: // Queue is the default
0677: destinationType = Queue.class.getName();
0678: }
0679: logger
0680: .info("Auto-configuring a message driven bean "
0681: + ejbDeployment
0682: .getDeploymentId()
0683: + " destination "
0684: + properties
0685: .getProperty("destination")
0686: + " to be destinationType "
0687: + destinationType);
0688: }
0689:
0690: if (destinationType != null) {
0691: mdb.getActivationConfig().addProperty(
0692: "destinationType", destinationType);
0693: mdb.setMessageDestinationType(destinationType);
0694:
0695: // topics need a clientId and subscriptionName
0696: if ("javax.jms.Topic".equals(destinationType)) {
0697: Properties properties = mdb
0698: .getActivationConfig()
0699: .toProperties();
0700: if (!properties.containsKey("clientId")) {
0701: mdb
0702: .getActivationConfig()
0703: .addProperty(
0704: "clientId",
0705: ejbDeployment
0706: .getDeploymentId());
0707: }
0708: if (!properties
0709: .containsKey("subscriptionName")) {
0710: mdb.getActivationConfig().addProperty(
0711: "subscriptionName",
0712: ejbDeployment.getDeploymentId()
0713: + "_subscription");
0714: }
0715: }
0716: }
0717: }
0718: }
0719: }
0720:
0721: }
0722:
0723: private String resolveDestinationId(MessageDestinationRef ref,
0724: URI moduleUri,
0725: LinkResolver<MessageDestination> destinationResolver,
0726: Map<MessageDestination, String> destinationTypes)
0727: throws OpenEJBException {
0728: // skip destination refs without a destination link
0729: String link = ref.getMessageDestinationLink();
0730: if (link == null || link.length() == 0) {
0731: return null;
0732: }
0733:
0734: // resolve the destination... if we don't find one it is a configuration bug
0735: MessageDestination destination = destinationResolver
0736: .resolveLink(link, moduleUri);
0737: if (destination == null) {
0738: throw new OpenEJBException("Message destination " + link
0739: + " for message-destination-ref "
0740: + ref.getMessageDestinationRefName() + " not found");
0741: }
0742:
0743: // remember the type of each destination so we can use it to fillin MDBs that don't declare destination type
0744: if (ref.getMessageDestinationType() != null
0745: && !destinationTypes.containsKey(destination)) {
0746: destinationTypes.put(destination, ref
0747: .getMessageDestinationType());
0748: }
0749:
0750: // get the destinationId
0751: String destinationId = destination.getMappedName();
0752: if (destinationId == null)
0753: destination.getMessageDestinationName();
0754: return destinationId;
0755: }
0756:
0757: private void deploy(ClientModule clientModule,
0758: AppResources appResources) throws OpenEJBException {
0759: processJndiRefs(clientModule.getModuleId(), clientModule
0760: .getApplicationClient(), appResources);
0761: }
0762:
0763: @SuppressWarnings({"UnusedDeclaration"})
0764: private void deploy(ConnectorModule connectorModule)
0765: throws OpenEJBException {
0766: // Nothing to process for resource modules
0767: }
0768:
0769: private void deploy(WebModule webModule, AppResources appResources)
0770: throws OpenEJBException {
0771: processJndiRefs(webModule.getModuleId(), webModule.getWebApp(),
0772: appResources);
0773: }
0774:
0775: private void processJndiRefs(String moduleId,
0776: JndiConsumer jndiConsumer, AppResources appResources)
0777: throws OpenEJBException {
0778: // Resource reference
0779: for (ResourceRef ref : jndiConsumer.getResourceRef()) {
0780: // skip references such as URLs which are automatically handled by the server
0781: if (ignoredReferenceTypes.contains(ref.getType())) {
0782: continue;
0783: }
0784:
0785: // skip destinations with a global jndi name
0786: String mappedName = ref.getMappedName();
0787: if (mappedName == null)
0788: mappedName = "";
0789: if (mappedName.startsWith("jndi:")) {
0790: continue;
0791: }
0792:
0793: String destinationId = (mappedName.length() == 0) ? ref
0794: .getName() : mappedName;
0795: destinationId = getResourceId(moduleId, destinationId, ref
0796: .getType(), appResources);
0797: ref.setMappedName(destinationId);
0798: }
0799:
0800: // Resource env reference
0801: for (JndiReference ref : jndiConsumer.getResourceEnvRef()) {
0802: // skip references such as URLs which are automatically handled by the server
0803: if (ignoredReferenceTypes.contains(ref.getType())) {
0804: continue;
0805: }
0806:
0807: // skip destinations with a global jndi name
0808: String mappedName = ref.getMappedName();
0809: if (mappedName == null)
0810: mappedName = "";
0811: if (mappedName.startsWith("jndi:")) {
0812: continue;
0813: }
0814:
0815: String destinationId = (mappedName.length() == 0) ? ref
0816: .getName() : mappedName;
0817: destinationId = getResourceEnvId(moduleId, destinationId,
0818: ref.getType(), appResources);
0819: ref.setMappedName(destinationId);
0820: }
0821:
0822: // Message destination reference
0823: for (MessageDestinationRef ref : jndiConsumer
0824: .getMessageDestinationRef()) {
0825: // skip destinations with a global jndi name
0826: String mappedName = ref.getMappedName() + "";
0827: if (mappedName.startsWith("jndi:")) {
0828: continue;
0829: }
0830:
0831: String destinationId = (mappedName.length() == 0) ? ref
0832: .getName() : mappedName;
0833: destinationId = getResourceEnvId(moduleId, destinationId,
0834: ref.getType(), appResources);
0835: ref.setMappedName(destinationId);
0836: }
0837: }
0838:
0839: private void deploy(EjbModule ejbModule, AppResources appResources)
0840: throws OpenEJBException {
0841: OpenejbJar openejbJar;
0842: if (ejbModule.getOpenejbJar() != null) {
0843: openejbJar = ejbModule.getOpenejbJar();
0844: } else {
0845: openejbJar = new OpenejbJar();
0846: ejbModule.setOpenejbJar(openejbJar);
0847: }
0848:
0849: Map<String, EjbDeployment> deployments = openejbJar
0850: .getDeploymentsByEjbName();
0851:
0852: for (EnterpriseBean bean : ejbModule.getEjbJar()
0853: .getEnterpriseBeans()) {
0854: EjbDeployment ejbDeployment = deployments.get(bean
0855: .getEjbName());
0856: if (ejbDeployment == null) {
0857: throw new OpenEJBException(
0858: "No ejb deployment found for ejb "
0859: + bean.getEjbName());
0860: }
0861:
0862: Class<? extends ContainerInfo> containerInfoType = ConfigurationFactory
0863: .getContainerInfoType(getType(bean));
0864: if (ejbDeployment.getContainerId() == null
0865: && !skipMdb(bean)) {
0866: String containerId = getUsableContainer(
0867: containerInfoType, bean, appResources);
0868: if (containerId == null) {
0869: containerId = createContainer(containerInfoType,
0870: ejbDeployment, bean);
0871: }
0872: ejbDeployment.setContainerId(containerId);
0873: }
0874:
0875: // create the container if it doesn't exist
0876: if (!configFactory.getContainerIds().contains(
0877: ejbDeployment.getContainerId())
0878: && !skipMdb(bean)) {
0879: createContainer(containerInfoType, ejbDeployment, bean);
0880: }
0881:
0882: // Resource reference
0883: for (ResourceRef ref : bean.getResourceRef()) {
0884: processResourceRef(ref, ejbDeployment, appResources);
0885: }
0886:
0887: // Resource env reference
0888: for (JndiReference ref : bean.getResourceEnvRef()) {
0889: processResourceEnvRef(ref, ejbDeployment, appResources);
0890: }
0891:
0892: // Message destination reference
0893: for (MessageDestinationRef ref : bean
0894: .getMessageDestinationRef()) {
0895: processResourceEnvRef(ref, ejbDeployment, appResources);
0896: }
0897:
0898: // mdb message destination id
0899: if (autoCreateResources
0900: && bean instanceof MessageDrivenBean) {
0901: MessageDrivenBean mdb = (MessageDrivenBean) bean;
0902:
0903: ResourceLink resourceLink = ejbDeployment
0904: .getResourceLink("openejb/destination");
0905: if (resourceLink != null) {
0906: try {
0907: String destinationId = getResourceEnvId(bean
0908: .getEjbName(), resourceLink.getResId(),
0909: mdb.getMessageDestinationType(),
0910: appResources);
0911: resourceLink.setResId(destinationId);
0912: } catch (OpenEJBException e) {
0913: // The MDB doesn't need the auto configured "openejb/destination" env entry
0914: ejbDeployment
0915: .removeResourceLink("openejb/destination");
0916: }
0917: }
0918: }
0919:
0920: }
0921: }
0922:
0923: private String createContainer(
0924: Class<? extends ContainerInfo> containerInfoType,
0925: EjbDeployment ejbDeployment, EnterpriseBean bean)
0926: throws OpenEJBException {
0927: if (!autoCreateContainers) {
0928: throw new OpenEJBException(
0929: "A container of type "
0930: + getType(bean)
0931: + " must be declared in the configuration file for bean: "
0932: + bean.getEjbName());
0933: }
0934:
0935: // get the container info (data used to build the container)
0936: ContainerInfo containerInfo = configFactory
0937: .configureService(containerInfoType);
0938: logger.info("Auto-creating a container for bean "
0939: + ejbDeployment.getDeploymentId() + ": Container(type="
0940: + getType(bean) + ", id=" + containerInfo.id + ")");
0941:
0942: // if the is an MDB container we need to resolve the resource adapter
0943: String resourceAdapterId = containerInfo.properties
0944: .getProperty("ResourceAdapter");
0945: if (resourceAdapterId != null) {
0946: String newResourceId = getResourceId(ejbDeployment
0947: .getDeploymentId(), resourceAdapterId, null, null);
0948: if (resourceAdapterId != newResourceId) {
0949: containerInfo.properties.setProperty("ResourceAdapter",
0950: newResourceId);
0951: }
0952: }
0953:
0954: // install the container
0955: configFactory.install(containerInfo);
0956: return containerInfo.id;
0957: }
0958:
0959: private void processResourceRef(ResourceRef ref,
0960: EjbDeployment ejbDeployment, AppResources appResources)
0961: throws OpenEJBException {
0962: // skip destinations with a global jndi name
0963: String mappedName = ref.getMappedName();
0964: if (mappedName == null)
0965: mappedName = "";
0966: if ((mappedName).startsWith("jndi:")) {
0967: return;
0968: }
0969:
0970: String refName = ref.getName();
0971: String refType = ref.getType();
0972:
0973: // skip references such as URLs which are automatically handled by the server
0974: if (ignoredReferenceTypes.contains(refType)) {
0975: return;
0976: }
0977:
0978: ResourceLink link = ejbDeployment.getResourceLink(refName);
0979: if (link == null) {
0980: String id = (mappedName.length() == 0) ? ref.getName()
0981: : mappedName;
0982: id = getResourceId(ejbDeployment.getDeploymentId(), id,
0983: refType, appResources);
0984: logger.info("Auto-linking resource-ref '" + refName
0985: + "' in bean " + ejbDeployment.getDeploymentId()
0986: + " to Resource(id=" + id + ")");
0987:
0988: link = new ResourceLink();
0989: link.setResId(id);
0990: link.setResRefName(refName);
0991: ejbDeployment.addResourceLink(link);
0992: } else {
0993: String id = getResourceId(ejbDeployment.getDeploymentId(),
0994: link.getResId(), refType, appResources);
0995: link.setResId(id);
0996: link.setResRefName(refName);
0997: }
0998: }
0999:
1000: private void processResourceEnvRef(JndiReference ref,
1001: EjbDeployment ejbDeployment, AppResources appResources)
1002: throws OpenEJBException {
1003: // skip destinations with a global jndi name
1004: String mappedName = (ref.getMappedName() == null) ? "" : ref
1005: .getMappedName();
1006: if (mappedName.startsWith("jndi:")) {
1007: return;
1008: }
1009:
1010: String refName = ref.getName();
1011: String refType = ref.getType();
1012:
1013: // skip references such as SessionContext which are automatically handled by the server
1014: if (ignoredReferenceTypes.contains(refType)) {
1015: return;
1016: }
1017:
1018: ResourceLink link = ejbDeployment.getResourceLink(refName);
1019: if (link == null) {
1020:
1021: String id = (mappedName.length() == 0) ? refName
1022: : mappedName;
1023: id = getResourceEnvId(ejbDeployment.getDeploymentId(), id,
1024: refType, appResources);
1025: if (id == null) {
1026: // could be a session context ref
1027: return;
1028: }
1029: logger.info("Auto-linking resource-env-ref '" + refName
1030: + "' in bean " + ejbDeployment.getDeploymentId()
1031: + " to Resource(id=" + id + ")");
1032:
1033: link = new ResourceLink();
1034: link.setResId(id);
1035: link.setResRefName(refName);
1036: ejbDeployment.addResourceLink(link);
1037: } else {
1038: String id = getResourceEnvId(ejbDeployment
1039: .getDeploymentId(), link.getResId(), refType,
1040: appResources);
1041: link.setResId(id);
1042: link.setResRefName(refName);
1043: }
1044: }
1045:
1046: private static boolean skipMdb(Object bean) {
1047: return bean instanceof MessageDrivenBean
1048: && System.getProperty("duct tape") != null;
1049: }
1050:
1051: private static String getType(EnterpriseBean enterpriseBean)
1052: throws OpenEJBException {
1053: if (enterpriseBean instanceof org.apache.openejb.jee.EntityBean) {
1054: if (((org.apache.openejb.jee.EntityBean) enterpriseBean)
1055: .getPersistenceType() == PersistenceType.CONTAINER) {
1056: return BeanTypes.CMP_ENTITY;
1057: } else {
1058: return BeanTypes.BMP_ENTITY;
1059: }
1060: } else if (enterpriseBean instanceof org.apache.openejb.jee.SessionBean) {
1061: if (((org.apache.openejb.jee.SessionBean) enterpriseBean)
1062: .getSessionType() == SessionType.STATEFUL) {
1063: return BeanTypes.STATEFUL;
1064: } else {
1065: return BeanTypes.STATELESS;
1066: }
1067: } else if (enterpriseBean instanceof org.apache.openejb.jee.MessageDrivenBean) {
1068: return BeanTypes.MESSAGE;
1069: }
1070: throw new OpenEJBException("Unknown enterprise bean type "
1071: + enterpriseBean.getClass().getName());
1072: }
1073:
1074: private void deploy(PersistenceModule persistenceModule)
1075: throws OpenEJBException {
1076: if (!autoCreateResources) {
1077: return;
1078: }
1079:
1080: Persistence persistence = persistenceModule.getPersistence();
1081: for (PersistenceUnit unit : persistence.getPersistenceUnit()) {
1082: if (unit.getProvider() != null) {
1083: logger.info("Configuring PersistenceUnit(name="
1084: + unit.getName() + ", provider="
1085: + unit.getProvider() + ")");
1086: } else {
1087: logger.info("Configuring PersistenceUnit(name="
1088: + unit.getName() + ")");
1089: }
1090:
1091: Properties required = new Properties();
1092:
1093: // if (unit.getJtaDataSource() == null && unit.getNonJtaDataSource() == null){
1094: // unit.setJtaDataSource("JtaDataSource");
1095: // unit.setNonJtaDataSource("NonJtaDataSource");
1096: // } else if (unit.getJtaDataSource() == null){
1097: // unit.setJtaDataSource(unit.getNonJtaDataSource()+"Jta");
1098: // } else if (unit.getNonJtaDataSource() == null){
1099: // unit.setNonJtaDataSource(unit.getJtaDataSource()+"NonJta");
1100: // }
1101:
1102: unit.setJtaDataSource(normalizeResourceId(unit
1103: .getJtaDataSource()));
1104: unit.setNonJtaDataSource(normalizeResourceId(unit
1105: .getNonJtaDataSource()));
1106:
1107: required.put("JtaManaged", "true");
1108: String jtaDataSourceId = findResourceId(unit
1109: .getJtaDataSource(), "DataSource", required, null);
1110:
1111: required.put("JtaManaged", "false");
1112: String nonJtaDataSourceId = findResourceId(unit
1113: .getNonJtaDataSource(), "DataSource", required,
1114: null);
1115:
1116: if (jtaDataSourceId != null && nonJtaDataSourceId != null) {
1117: // Both DataSources were explicitly configured.
1118: setJtaDataSource(unit, jtaDataSourceId);
1119: setNonJtaDataSource(unit, nonJtaDataSourceId);
1120: continue;
1121: }
1122:
1123: //
1124: // If the jta-data-source or the non-jta-data-source link to
1125: // third party resources, then we can't do any auto config
1126: // for them. We give them what they asked for and move on.
1127: //
1128: if (jtaDataSourceId == null && nonJtaDataSourceId == null) {
1129: required.put("JtaManaged", NONE);
1130:
1131: jtaDataSourceId = findResourceId(unit
1132: .getJtaDataSource(), "DataSource", required,
1133: null);
1134: nonJtaDataSourceId = findResourceId(unit
1135: .getNonJtaDataSource(), "DataSource", required,
1136: null);
1137:
1138: if (jtaDataSourceId != null
1139: || nonJtaDataSourceId != null) {
1140: if (jtaDataSourceId != null)
1141: setJtaDataSource(unit, jtaDataSourceId);
1142: if (nonJtaDataSourceId != null)
1143: setNonJtaDataSource(unit, nonJtaDataSourceId);
1144: continue;
1145: }
1146: }
1147:
1148: // We are done with the most optimal configuration.
1149: //
1150: // If both the jta-data-source and non-jta-data-source
1151: // references were explicitly and correctly configured
1152: // to existing datasource, we wouldn't get this far.
1153: //
1154: // At this point we see if either we can't figure out
1155: // if there's an issue with their configuration or
1156: // if we can't intelligently complete their configuration.
1157:
1158: //
1159: // Do both the jta-data-source and non-jta-data-source references
1160: // point to the same datasource?
1161: //
1162: // If so, then unlink the invalid one so defaulting rules can
1163: // possibly fill in a good value.
1164: //
1165:
1166: required.put("JtaManaged", ANY);
1167: String possibleJta = findResourceId(
1168: unit.getJtaDataSource(), "DataSource", required,
1169: null);
1170: String possibleNonJta = findResourceId(unit
1171: .getNonJtaDataSource(), "DataSource", required,
1172: null);
1173: if (possibleJta != null && possibleJta == possibleNonJta) {
1174: ResourceInfo dataSource = configFactory
1175: .getResourceInfo(possibleJta);
1176:
1177: String jtaManaged = (String) dataSource.properties
1178: .get("JtaManaged");
1179:
1180: logger
1181: .warning("PeristenceUnit(name="
1182: + unit.getName()
1183: + ") invalidly refers to Resource(id="
1184: + dataSource.id
1185: + ") as both its <jta-data-source> and <non-jta-data-source>.");
1186:
1187: if ("true".equalsIgnoreCase(jtaManaged)) {
1188: nonJtaDataSourceId = null;
1189: unit.setNonJtaDataSource(null);
1190:
1191: } else if ("false".equalsIgnoreCase(jtaManaged)) {
1192: jtaDataSourceId = null;
1193: unit.setJtaDataSource(null);
1194: }
1195: }
1196:
1197: //
1198: // Do the jta-data-source and non-jta-data-source references
1199: // point to innapropriately configured Resources?
1200: //
1201: checkUnitDataSourceRefs(unit);
1202:
1203: //
1204: // Do either the jta-data-source and non-jta-data-source
1205: // references point to the explicit name of a ServiceProvider?
1206: //
1207: if (jtaDataSourceId == null && nonJtaDataSourceId == null) {
1208: jtaDataSourceId = findResourceProviderId(unit
1209: .getJtaDataSource());
1210: nonJtaDataSourceId = findResourceProviderId(unit
1211: .getNonJtaDataSource());
1212:
1213: // if one of them is not null we have a match on at least one
1214: // we can just create the second resource using the first as a template
1215: if (jtaDataSourceId != null
1216: || nonJtaDataSourceId != null) {
1217: Resource jtaResource = new Resource(
1218: jtaDataSourceId, "DataSource",
1219: jtaDataSourceId);
1220: jtaResource.getProperties().setProperty(
1221: "JtaManaged", "true");
1222:
1223: Resource nonJtaResource = new Resource(
1224: nonJtaDataSourceId, "DataSource",
1225: nonJtaDataSourceId);
1226: nonJtaResource.getProperties().setProperty(
1227: "JtaManaged", "false");
1228:
1229: if (jtaDataSourceId == null) {
1230: jtaResource.setId(nonJtaDataSourceId + "Jta");
1231: jtaResource.setProvider(nonJtaDataSourceId);
1232: } else if (nonJtaDataSourceId == null) {
1233: nonJtaResource
1234: .setId(jtaDataSourceId + "NonJta");
1235: nonJtaResource.setProvider(jtaDataSourceId);
1236: }
1237:
1238: ResourceInfo jtaResourceInfo = configFactory
1239: .configureService(jtaResource,
1240: ResourceInfo.class);
1241: ResourceInfo nonJtaResourceInfo = configFactory
1242: .configureService(nonJtaResource,
1243: ResourceInfo.class);
1244:
1245: logAutoCreateResource(jtaResourceInfo,
1246: "DataSource", unit.getName());
1247: jtaDataSourceId = installResource(unit.getName(),
1248: jtaResourceInfo);
1249:
1250: logAutoCreateResource(nonJtaResourceInfo,
1251: "DataSource", unit.getName());
1252: nonJtaDataSourceId = installResource(
1253: unit.getName(), nonJtaResourceInfo);
1254:
1255: setJtaDataSource(unit, jtaDataSourceId);
1256: setNonJtaDataSource(unit, nonJtaDataSourceId);
1257: continue;
1258: }
1259: }
1260:
1261: //
1262: // If neither of the references are valid yet, then let's take
1263: // the first valid datasource.
1264: //
1265: // We won't fill in both jta-data-source and non-jta-data-source
1266: // this way as the following code does a great job at determining
1267: // if any of the existing data sources are a good match or if
1268: // one needs to be generated.
1269: //
1270: if (jtaDataSourceId == null && nonJtaDataSourceId == null) {
1271:
1272: required.clear();
1273: required.put("JtaManaged", "true");
1274: jtaDataSourceId = firstMatching("DataSource", required,
1275: null);
1276:
1277: if (jtaDataSourceId == null) {
1278: required.clear();
1279: required.put("JtaManaged", "false");
1280: nonJtaDataSourceId = firstMatching("DataSource",
1281: required, null);
1282: }
1283: }
1284:
1285: //
1286: // Does the jta-data-source reference point an existing
1287: // Resource in the system with JtaManaged=true?
1288: //
1289: // If so, we can search for an existing datasource
1290: // configured with identical properties and use it.
1291: //
1292: // If that doesn't work, we can copy the jta-data-source
1293: // and auto-create the missing non-jta-data-source
1294: // using it as a template, applying the overrides,
1295: // and finally setting JtaManaged=false
1296: //
1297:
1298: if (jtaDataSourceId != null && nonJtaDataSourceId == null) {
1299:
1300: ResourceInfo jtaResourceInfo = configFactory
1301: .getResourceInfo(jtaDataSourceId);
1302:
1303: Properties jtaProperties = jtaResourceInfo.properties;
1304:
1305: if (jtaProperties.containsKey("JtaManaged")) {
1306:
1307: // Strategy 1: Best match search
1308:
1309: required.clear();
1310: required.put("JtaManaged", "false");
1311:
1312: for (String key : asList("JdbcDriver", "JdbcUrl")) {
1313: if (jtaProperties.containsKey(key))
1314: required.put(key, jtaProperties.get(key));
1315: }
1316:
1317: nonJtaDataSourceId = firstMatching("DataSource",
1318: required, null);
1319:
1320: // Strategy 2: Copy
1321:
1322: if (nonJtaDataSourceId == null) {
1323: ResourceInfo nonJtaResourceInfo = copy(jtaResourceInfo);
1324: nonJtaResourceInfo.id = jtaResourceInfo.id
1325: + "NonJta";
1326:
1327: Properties overrides = ConfigurationFactory
1328: .getSystemProperties(
1329: nonJtaResourceInfo.id,
1330: nonJtaResourceInfo.service);
1331: nonJtaResourceInfo.properties.putAll(overrides);
1332: nonJtaResourceInfo.properties.setProperty(
1333: "JtaManaged", "false");
1334:
1335: logAutoCreateResource(nonJtaResourceInfo,
1336: "DataSource", unit.getName());
1337: logger.info("configureService.configuring",
1338: nonJtaResourceInfo.id,
1339: nonJtaResourceInfo.service,
1340: jtaResourceInfo.id);
1341:
1342: nonJtaDataSourceId = installResource(unit
1343: .getName(), nonJtaResourceInfo);
1344: }
1345: }
1346:
1347: }
1348:
1349: //
1350: // Does the jta-data-source reference point an existing
1351: // Resource in the system with JtaManaged=false?
1352: //
1353: // If so, we can search for an existing datasource
1354: // configured with identical properties and use it.
1355: //
1356: // If that doesn't work, we can copy the jta-data-source
1357: // and auto-create the missing non-jta-data-source
1358: // using it as a template, applying the overrides,
1359: // and finally setting JtaManaged=false
1360: //
1361:
1362: if (nonJtaDataSourceId != null && jtaDataSourceId == null) {
1363:
1364: ResourceInfo nonJtaResourceInfo = configFactory
1365: .getResourceInfo(nonJtaDataSourceId);
1366:
1367: Properties nonJtaProperties = nonJtaResourceInfo.properties;
1368:
1369: if (nonJtaProperties.containsKey("JtaManaged")) {
1370:
1371: // Strategy 1: Best match search
1372:
1373: required.clear();
1374: required.put("JtaManaged", "true");
1375:
1376: for (String key : asList("JdbcDriver", "JdbcUrl")) {
1377: if (nonJtaProperties.containsKey(key))
1378: required
1379: .put(key, nonJtaProperties.get(key));
1380: }
1381:
1382: jtaDataSourceId = firstMatching("DataSource",
1383: required, null);
1384:
1385: // Strategy 2: Copy
1386:
1387: if (jtaDataSourceId == null) {
1388: ResourceInfo jtaResourceInfo = copy(nonJtaResourceInfo);
1389: jtaResourceInfo.id = nonJtaResourceInfo.id
1390: + "Jta";
1391:
1392: Properties overrides = ConfigurationFactory
1393: .getSystemProperties(
1394: jtaResourceInfo.id,
1395: jtaResourceInfo.service);
1396: jtaResourceInfo.properties.putAll(overrides);
1397: jtaResourceInfo.properties.setProperty(
1398: "JtaManaged", "true");
1399:
1400: logAutoCreateResource(jtaResourceInfo,
1401: "DataSource", unit.getName());
1402: logger.info("configureService.configuring",
1403: jtaResourceInfo.id,
1404: jtaResourceInfo.service,
1405: nonJtaResourceInfo.id);
1406:
1407: jtaDataSourceId = installResource(unit
1408: .getName(), jtaResourceInfo);
1409: }
1410: }
1411:
1412: }
1413:
1414: //
1415: // By this point if we've found anything at all, both
1416: // jta-data-source and non-jta-data-source should be
1417: // filled in (provided they aren't using a third party
1418: // data source).
1419: //
1420: // Should both references still be null
1421: // we can just take a shot in the dark and auto-create
1422: // them them both using the built-in templates for jta
1423: // and non-jta default datasources. These are supplied
1424: // via the service-jar.xml file.
1425: //
1426: if (jtaDataSourceId == null && nonJtaDataSourceId == null) {
1427: required.put("JtaManaged", "true");
1428: jtaDataSourceId = autoCreateResource("DataSource",
1429: required, unit.getName());
1430:
1431: required.put("JtaManaged", "false");
1432: nonJtaDataSourceId = autoCreateResource("DataSource",
1433: required, unit.getName());
1434: }
1435:
1436: if (jtaDataSourceId != null)
1437: setJtaDataSource(unit, jtaDataSourceId);
1438: if (nonJtaDataSourceId != null)
1439: setNonJtaDataSource(unit, nonJtaDataSourceId);
1440: }
1441: }
1442:
1443: private void setNonJtaDataSource(PersistenceUnit unit,
1444: String current) {
1445:
1446: String previous = unit.getNonJtaDataSource();
1447:
1448: if (!current.equals(previous)) {
1449:
1450: logger.info("Adjusting " + unit.getName()
1451: + " <non-jta-data-source> to '" + current + "'");
1452:
1453: }
1454:
1455: unit.setNonJtaDataSource(current);
1456: }
1457:
1458: private void setJtaDataSource(PersistenceUnit unit, String current) {
1459:
1460: String previous = unit.getJtaDataSource();
1461:
1462: if (!current.equals(previous)) {
1463:
1464: logger.info("Adjusting " + unit.getName()
1465: + " <jta-data-source> to '" + current + "'");
1466:
1467: }
1468:
1469: unit.setJtaDataSource(current);
1470: }
1471:
1472: private ResourceInfo copy(ResourceInfo a) {
1473: ResourceInfo b = new ResourceInfo();
1474: b.id = a.id;
1475: b.service = a.service;
1476: b.className = a.className;
1477: b.codebase = a.codebase;
1478: b.displayName = a.displayName;
1479: b.description = a.description;
1480: b.factoryMethod = a.factoryMethod;
1481: b.constructorArgs.addAll(a.constructorArgs);
1482: b.types.addAll(a.types);
1483: b.properties = new SuperProperties();
1484: b.properties.putAll(a.properties);
1485:
1486: return b;
1487: }
1488:
1489: private void checkUnitDataSourceRefs(PersistenceUnit unit)
1490: throws OpenEJBException {
1491: Properties required = new Properties();
1492:
1493: // check that non-jta-data-source does NOT point to a JtaManaged=true datasource
1494:
1495: required.put("JtaManaged", "true");
1496:
1497: String invalidNonJta = findResourceId(unit
1498: .getNonJtaDataSource(), "DataSource", required, null);
1499:
1500: if (invalidNonJta != null) {
1501: throw new OpenEJBException(
1502: "PeristenceUnit "
1503: + unit.getName()
1504: + " <non-jta-data-source> points to a jta managed Resource. Update Resource \""
1505: + invalidNonJta
1506: + "\" to \"JtaManaged=false\", use a different Resource, or delete the <non-jta-data-source> element and a default will be supplied if possible.");
1507: }
1508:
1509: // check that jta-data-source does NOT point to a JtaManaged=false datasource
1510:
1511: required.put("JtaManaged", "false");
1512:
1513: String invalidJta = findResourceId(unit.getJtaDataSource(),
1514: "DataSource", required, null);
1515:
1516: if (invalidJta != null) {
1517: throw new OpenEJBException(
1518: "PeristenceUnit "
1519: + unit.getName()
1520: + " <jta-data-source> points to a non jta managed Resource. Update Resource \""
1521: + invalidJta
1522: + "\" to \"JtaManaged=true\", use a different Resource, or delete the <jta-data-source> element and a default will be supplied if possible.");
1523: }
1524: }
1525:
1526: private String findResourceProviderId(String resourceId)
1527: throws OpenEJBException {
1528: if (resourceId == null)
1529: return null;
1530:
1531: if (hasServiceProvider(resourceId)) {
1532: return resourceId;
1533: }
1534:
1535: resourceId = toShortName(resourceId);
1536: if (hasServiceProvider(resourceId)) {
1537: return resourceId;
1538: }
1539:
1540: return null;
1541: }
1542:
1543: private String getResourceId(String beanName, String resourceId,
1544: String type, AppResources appResources)
1545: throws OpenEJBException {
1546: return getResourceId(beanName, resourceId, type, null,
1547: appResources);
1548: }
1549:
1550: private String getResourceId(String beanName, String resourceId,
1551: String type, Properties required, AppResources appResources)
1552: throws OpenEJBException {
1553: resourceId = normalizeResourceId(resourceId);
1554:
1555: if (resourceId == null) {
1556: return null;
1557: }
1558:
1559: if (appResources == null)
1560: appResources = new AppResources();
1561:
1562: // skip references such as URL which are automatically handled by the server
1563: if (type != null && ignoredReferenceTypes.contains(type)) {
1564: return null;
1565: }
1566:
1567: // check for existing resource with specified resourceId and type and properties
1568: String id = findResourceId(resourceId, type, required,
1569: appResources);
1570: if (id != null)
1571: return id;
1572:
1573: // expand search to any type -- may be asking for a reference to a sub-type
1574: id = findResourceId(resourceId, null, required, appResources);
1575: if (id != null)
1576: return id;
1577:
1578: // throw an exception or log an error
1579: String shortName = toShortName(resourceId);
1580: String message = "No existing resource found while attempting to Auto-link unmapped resource-ref '"
1581: + resourceId
1582: + "' of type '"
1583: + type
1584: + "' for '"
1585: + beanName
1586: + "'. Looked for Resource(id="
1587: + resourceId
1588: + ") and Resource(id=" + shortName + ")";
1589: if (!autoCreateResources) {
1590: throw new OpenEJBException(message);
1591: }
1592: logger.debug(message);
1593:
1594: // if there is a provider with the specified name. use it
1595: if (hasServiceProvider(resourceId)) {
1596: ResourceInfo resourceInfo = configFactory.configureService(
1597: resourceId, ResourceInfo.class);
1598: return installResource(beanName, resourceInfo);
1599: } else if (hasServiceProvider(shortName)) {
1600: ResourceInfo resourceInfo = configFactory.configureService(
1601: shortName, ResourceInfo.class);
1602: return installResource(beanName, resourceInfo);
1603: }
1604:
1605: // if there are any resources of the desired type, use the first one
1606: id = firstMatching(type, required, appResources);
1607: if (id != null)
1608: return id;
1609:
1610: // Auto create a resource using the first provider that can supply a resource of the desired type
1611: return autoCreateResource(type, required, beanName);
1612: }
1613:
1614: private String autoCreateResource(String type, Properties required,
1615: String beanName) throws OpenEJBException {
1616: String resourceId;
1617: resourceId = ServiceUtils.getServiceProviderId(type, required);
1618: if (resourceId == null) {
1619: throw new OpenEJBException(
1620: "No provider available for resource-ref '"
1621: + resourceId + "' of type '" + type
1622: + "' for '" + beanName + "'.");
1623: }
1624: ResourceInfo resourceInfo = configFactory.configureService(
1625: resourceId, ResourceInfo.class);
1626:
1627: logAutoCreateResource(resourceInfo, type, beanName);
1628: return installResource(beanName, resourceInfo);
1629: }
1630:
1631: private void logAutoCreateResource(ResourceInfo resourceInfo,
1632: String type, String beanName) {
1633: logger.info("Auto-creating a Resource with id '"
1634: + resourceInfo.id + "' of type '" + type + " for '"
1635: + beanName + "'.");
1636: }
1637:
1638: private String firstMatching(String type, Properties required,
1639: AppResources appResources) {
1640: List<String> resourceIds = getResourceIds(appResources, type,
1641: required);
1642: String idd = null;
1643: if (resourceIds.size() > 0) {
1644: idd = resourceIds.get(0);
1645: }
1646: return idd;
1647: }
1648:
1649: private String findResourceId(String resourceId, String type,
1650: Properties required, AppResources appResources) {
1651: if (resourceId == null)
1652: return null;
1653:
1654: resourceId = normalizeResourceId(resourceId);
1655:
1656: // check for existing resource with specified resourceId
1657: List<String> resourceIds = getResourceIds(appResources, type,
1658: required);
1659: for (String id : resourceIds) {
1660: if (id.equalsIgnoreCase(resourceId))
1661: return id;
1662: }
1663:
1664: // check for existing resource with shortName
1665: String shortName = toShortName(resourceId);
1666: for (String id : resourceIds) {
1667: if (id.equalsIgnoreCase(shortName))
1668: return id;
1669: }
1670: return null;
1671: }
1672:
1673: private List<String> getResourceIds(AppResources appResources,
1674: String type, Properties required) {
1675: List<String> resourceIds;
1676: resourceIds = new ArrayList<String>();
1677: if (appResources != null)
1678: resourceIds.addAll(appResources.getResourceIds(type));
1679: resourceIds
1680: .addAll(configFactory.getResourceIds(type, required));
1681: return resourceIds;
1682: }
1683:
1684: private String toShortName(String resourceId) {
1685: // check for an existing resource using the short name (everything ever the final '/')
1686: String shortName = resourceId.replaceFirst(".*/", "");
1687: return shortName;
1688: }
1689:
1690: private String normalizeResourceId(String resourceId) {
1691: if (resourceId == null)
1692: return null;
1693:
1694: // strip off "java:comp/env"
1695: if (resourceId.startsWith("java:comp/env")) {
1696: resourceId = resourceId.substring("java:comp/env".length());
1697: }
1698:
1699: // strip off "java:openejb/Resource"
1700: if (resourceId.startsWith("java:openejb/Resource")) {
1701: resourceId = resourceId.substring("java:openejb/Resource"
1702: .length());
1703: }
1704:
1705: // strip off "java:openejb/Connector"
1706: if (resourceId.startsWith("java:openejb/Connector")) {
1707: resourceId = resourceId.substring("java:openejb/Connector"
1708: .length());
1709: }
1710:
1711: return resourceId;
1712: }
1713:
1714: private String installResource(String beanName,
1715: ResourceInfo resourceInfo) throws OpenEJBException {
1716: String resourceAdapterId = resourceInfo.properties
1717: .getProperty("ResourceAdapter");
1718: if (resourceAdapterId != null) {
1719: String newResourceId = getResourceId(beanName,
1720: resourceAdapterId, null, null);
1721: if (resourceAdapterId != newResourceId) {
1722: resourceInfo.properties.setProperty("ResourceAdapter",
1723: newResourceId);
1724: }
1725: }
1726: String dataSourceId = resourceInfo.properties
1727: .getProperty("DataSource");
1728: if (dataSourceId != null) {
1729: String newResourceId = getResourceId(beanName,
1730: dataSourceId, null, null);
1731: if (dataSourceId != newResourceId) {
1732: resourceInfo.properties.setProperty("DataSource",
1733: newResourceId);
1734: }
1735: }
1736:
1737: configFactory.install(resourceInfo);
1738: return resourceInfo.id;
1739: }
1740:
1741: private String getResourceEnvId(String beanName, String resourceId,
1742: String type, AppResources appResources)
1743: throws OpenEJBException {
1744: if (resourceId == null) {
1745: return null;
1746: }
1747: if (appResources == null)
1748: appResources = new AppResources();
1749:
1750: // skip references such as URLs which are automatically handled by the server
1751: if (ignoredReferenceTypes.contains(type)) {
1752: return null;
1753: }
1754:
1755: resourceId = normalizeResourceId(resourceId);
1756:
1757: // check for existing resource with specified resourceId
1758: List<String> resourceEnvIds = getResourceIds(appResources,
1759: type, null);
1760: for (String id : resourceEnvIds) {
1761: if (id.equalsIgnoreCase(resourceId))
1762: return id;
1763: }
1764:
1765: // throw an exception or log an error
1766: String message = "No existing resource found while attempting to Auto-link unmapped resource-env-ref '"
1767: + resourceId
1768: + "' of type '"
1769: + type
1770: + "' for '"
1771: + beanName
1772: + "'. Looked for Resource(id="
1773: + resourceId
1774: + ")";
1775: if (!autoCreateResources) {
1776: throw new OpenEJBException(message);
1777: }
1778: logger.debug(message);
1779:
1780: // Auto create a resource using the first provider that can supply a resource of the desired type
1781: String providerId = ServiceUtils.getServiceProviderId(type);
1782: if (providerId == null) {
1783: // if there are any existing resources of the desired type, use the first one
1784: if (resourceEnvIds.size() > 0) {
1785: return resourceEnvIds.get(0);
1786: }
1787: throw new OpenEJBException(
1788: "No provider available for resource-env-ref '"
1789: + resourceId + "' of type '" + type
1790: + "' for '" + beanName + "'.");
1791: }
1792:
1793: Resource resource = new Resource(resourceId, null, providerId);
1794: resource.getProperties().setProperty("destination", resourceId);
1795:
1796: ResourceInfo resourceInfo = configFactory.configureService(
1797: resource, ResourceInfo.class);
1798: logAutoCreateResource(resourceInfo, type, beanName);
1799: return installResource(beanName, resourceInfo);
1800: }
1801:
1802: private String getUsableContainer(
1803: Class<? extends ContainerInfo> containerInfoType,
1804: Object bean, AppResources appResources) {
1805: if (bean instanceof MessageDrivenBean) {
1806: MessageDrivenBean messageDrivenBean = (MessageDrivenBean) bean;
1807: String messagingType = messageDrivenBean.getMessagingType();
1808: List<String> containerIds = appResources.containerIdsByType
1809: .get(messagingType);
1810: if (containerIds != null && !containerIds.isEmpty()) {
1811: return containerIds.get(0);
1812: }
1813: }
1814:
1815: for (ContainerInfo containerInfo : configFactory
1816: .getContainerInfos()) {
1817: if (containerInfo.getClass().equals(containerInfoType)) {
1818: // MDBs must match message listener interface type
1819: if (bean instanceof MessageDrivenBean) {
1820: MessageDrivenBean messageDrivenBean = (MessageDrivenBean) bean;
1821: String messagingType = messageDrivenBean
1822: .getMessagingType();
1823: if (containerInfo.properties.get(
1824: "MessageListenerInterface").equals(
1825: messagingType)) {
1826: return containerInfo.id;
1827: }
1828: } else {
1829: return containerInfo.id;
1830: }
1831: }
1832: }
1833:
1834: return null;
1835: }
1836:
1837: private static class AppResources {
1838: @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
1839: private final Set<String> resourceAdapterIds = new TreeSet<String>();
1840: private final Map<String, List<String>> resourceIdsByType = new TreeMap<String, List<String>>();
1841: private final Map<String, List<String>> resourceEnvIdsByType = new TreeMap<String, List<String>>();
1842: private final Map<String, List<String>> containerIdsByType = new TreeMap<String, List<String>>();
1843:
1844: public AppResources() {
1845: }
1846:
1847: public AppResources(AppModule appModule) {
1848:
1849: //
1850: // DEVELOPERS NOTE: if you change the id generation code here, you must change
1851: // the id generation code in ConfigurationFactory.configureApplication(AppModule appModule)
1852: //
1853:
1854: for (ConnectorModule connectorModule : appModule
1855: .getResourceModules()) {
1856: Connector connector = connectorModule.getConnector();
1857:
1858: ResourceAdapter resourceAdapter = connector
1859: .getResourceAdapter();
1860: if (resourceAdapter.getResourceAdapterClass() != null) {
1861: String resourceAdapterId;
1862: if (resourceAdapter.getId() != null) {
1863: resourceAdapterId = resourceAdapter.getId();
1864: } else {
1865: resourceAdapterId = connectorModule
1866: .getModuleId()
1867: + "RA";
1868: }
1869: resourceAdapterIds.add(resourceAdapterId);
1870: }
1871:
1872: OutboundResourceAdapter outbound = resourceAdapter
1873: .getOutboundResourceAdapter();
1874: if (outbound != null) {
1875: for (ConnectionDefinition connection : outbound
1876: .getConnectionDefinition()) {
1877: String type = connection
1878: .getConnectionFactoryInterface();
1879:
1880: String resourceId;
1881: if (connection.getId() != null) {
1882: resourceId = connection.getId();
1883: } else if (outbound.getConnectionDefinition()
1884: .size() == 1) {
1885: resourceId = connectorModule.getModuleId();
1886: } else {
1887: resourceId = connectorModule.getModuleId()
1888: + "-" + type;
1889: }
1890:
1891: List<String> resourceIds = resourceIdsByType
1892: .get(type);
1893: if (resourceIds == null) {
1894: resourceIds = new ArrayList<String>();
1895: resourceIdsByType.put(type, resourceIds);
1896: }
1897: resourceIds.add(resourceId);
1898: }
1899: }
1900:
1901: InboundResource inbound = resourceAdapter
1902: .getInboundResourceAdapter();
1903: if (inbound != null) {
1904: for (MessageListener messageListener : inbound
1905: .getMessageAdapter().getMessageListener()) {
1906: String type = messageListener
1907: .getMessageListenerType();
1908:
1909: String containerId;
1910: if (messageListener.getId() != null) {
1911: containerId = messageListener.getId();
1912: } else if (inbound.getMessageAdapter()
1913: .getMessageListener().size() == 1) {
1914: containerId = connectorModule.getModuleId();
1915: } else {
1916: containerId = connectorModule.getModuleId()
1917: + "-" + type;
1918: }
1919:
1920: List<String> containerIds = containerIdsByType
1921: .get(type);
1922: if (containerIds == null) {
1923: containerIds = new ArrayList<String>();
1924: containerIdsByType.put(type, containerIds);
1925: }
1926: containerIds.add(containerId);
1927: }
1928: }
1929:
1930: for (AdminObject adminObject : resourceAdapter
1931: .getAdminObject()) {
1932: String type = adminObject.getAdminObjectInterface();
1933:
1934: String resourceEnvId;
1935: if (adminObject.getId() != null) {
1936: resourceEnvId = adminObject.getId();
1937: } else if (resourceAdapter.getAdminObject().size() == 1) {
1938: resourceEnvId = connectorModule.getModuleId();
1939: } else {
1940: resourceEnvId = connectorModule.getModuleId()
1941: + "-" + type;
1942: }
1943:
1944: List<String> resourceEnvIds = resourceEnvIdsByType
1945: .get(type);
1946: if (resourceEnvIds == null) {
1947: resourceEnvIds = new ArrayList<String>();
1948: resourceEnvIdsByType.put(type, resourceEnvIds);
1949: }
1950: resourceEnvIds.add(resourceEnvId);
1951: }
1952: }
1953:
1954: }
1955:
1956: public List<String> getResourceIds(String type) {
1957: if (type == null) {
1958: List<String> allResourceIds = new ArrayList<String>();
1959: for (List<String> resourceIds : resourceIdsByType
1960: .values()) {
1961: allResourceIds.addAll(resourceIds);
1962: }
1963: return allResourceIds;
1964: }
1965:
1966: List<String> resourceIds = resourceIdsByType.get(type);
1967: if (resourceIds != null) {
1968: return resourceIds;
1969: }
1970: return Collections.emptyList();
1971: }
1972:
1973: public List<String> getResourceEnvIds(String type) {
1974: if (type != null) {
1975: List<String> resourceIds = resourceEnvIdsByType
1976: .get(type);
1977: if (resourceIds != null) {
1978: return resourceIds;
1979: }
1980: }
1981: return Collections.emptyList();
1982: }
1983: }
1984: }
|