You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by db...@apache.org on 2008/03/04 07:33:26 UTC

svn commit: r633370 - in /openejb/trunk/openejb3/container/openejb-core/src: main/java/org/apache/openejb/config/ test/java/org/apache/openejb/config/

Author: dblevins
Date: Mon Mar  3 22:33:07 2008
New Revision: 633370

URL: http://svn.apache.org/viewvc?rev=633370&view=rev
Log:
OPENEJB-763: Auto create non-jta-data-source as a clone of jta-data-source and vice versa
As well as about 24 other tested scenarios

Added:
    openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/AutoConfigPersistenceUnitsTest.java
Modified:
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AutoConfig.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/ServiceUtils.java
    openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/AutoConfigTest.java

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java?rev=633370&r1=633369&r2=633370&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java Mon Mar  3 22:33:07 2008
@@ -426,7 +426,6 @@
                     }
                 }
 
-                logger.info("Configuring PersistenceUnit(name="+info.name+", provider="+info.provider+")");
                 // Persistence Unit Root Url
                 appInfo.persistenceUnits.add(info);
             }

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AutoConfig.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AutoConfig.java?rev=633370&r1=633369&r2=633370&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AutoConfig.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AutoConfig.java Mon Mar  3 22:33:07 2008
@@ -17,6 +17,12 @@
  */
 package org.apache.openejb.config;
 
+import static org.apache.openejb.config.ServiceUtils.NONE;
+import static org.apache.openejb.config.ServiceUtils.ANY;
+
+import static java.util.Arrays.asList;
+
+import static org.apache.openejb.config.ServiceUtils.hasServiceProvider;
 import org.apache.openejb.OpenEJBException;
 import org.apache.openejb.config.sys.Resource;
 import org.apache.openejb.assembler.classic.ContainerInfo;
@@ -51,9 +57,9 @@
 import org.apache.openejb.util.LogCategory;
 import org.apache.openejb.util.Logger;
 import org.apache.openejb.util.URISupport;
+import org.apache.openejb.util.SuperProperties;
 import static org.apache.openejb.util.Join.join;
 
-import javax.sql.DataSource;
 import javax.jms.Queue;
 import javax.jms.Topic;
 import java.util.List;
@@ -852,28 +858,359 @@
         }
 
         Persistence persistence = persistenceModule.getPersistence();
-        for (PersistenceUnit persistenceUnit : persistence.getPersistenceUnit()) {
+        for (PersistenceUnit unit : persistence.getPersistenceUnit()) {
+            if (unit.getProvider() != null){
+                logger.info("Configuring PersistenceUnit(name="+unit.getName()+", provider="+unit.getProvider()+")");
+            } else {
+                logger.info("Configuring PersistenceUnit(name="+unit.getName()+")");
+            }
+
             Properties required = new Properties();
 
+//            if (unit.getJtaDataSource() == null && unit.getNonJtaDataSource() == null){
+//                unit.setJtaDataSource("JtaDataSource");
+//                unit.setNonJtaDataSource("NonJtaDataSource");
+//            } else if (unit.getJtaDataSource() == null){
+//                unit.setJtaDataSource(unit.getNonJtaDataSource()+"Jta");
+//            } else if (unit.getNonJtaDataSource() == null){
+//                unit.setNonJtaDataSource(unit.getJtaDataSource()+"NonJta");
+//            }
+
+            unit.setJtaDataSource(normalizeResourceId(unit.getJtaDataSource()));
+            unit.setNonJtaDataSource(normalizeResourceId(unit.getNonJtaDataSource()));
+
             required.put("JtaManaged", "true");
-            String jtaDataSourceId = getResourceId(persistenceUnit.getName(), persistenceUnit.getJtaDataSource(), DataSource.class.getName(), null, required);
-            if (jtaDataSourceId != null) {
-                persistenceUnit.setJtaDataSource("java:openejb/Resource/" + jtaDataSourceId);
-            }
+            String jtaDataSourceId = findResourceId(unit.getJtaDataSource(), "DataSource", required, null);
 
             required.put("JtaManaged", "false");
-            String nonJtaDataSourceId = getResourceId(persistenceUnit.getName(), persistenceUnit.getNonJtaDataSource(), DataSource.class.getName(), null, required);
-            if (nonJtaDataSourceId != null) {
-                persistenceUnit.setNonJtaDataSource("java:openejb/Resource/" + nonJtaDataSourceId);
+            String nonJtaDataSourceId = findResourceId(unit.getNonJtaDataSource(), "DataSource", required, null);
+
+            if (jtaDataSourceId != null && nonJtaDataSourceId != null){
+                // Both DataSources were explicitly configured.
+                unit.setJtaDataSource("java:openejb/Resource/" + jtaDataSourceId);
+                unit.setNonJtaDataSource("java:openejb/Resource/" + nonJtaDataSourceId);
+                continue;
+            }
+
+            //
+            //  If the jta-data-source or the non-jta-data-source link to
+            //  third party resources, then we can't do any auto config
+            //  for them.  We give them what they asked for and move on.
+            //
+            if (jtaDataSourceId == null && nonJtaDataSourceId == null) {
+                required.put("JtaManaged", NONE);
+
+                jtaDataSourceId = findResourceId(unit.getJtaDataSource(), "DataSource", required, null);
+                nonJtaDataSourceId = findResourceId(unit.getNonJtaDataSource(), "DataSource", required, null);
+
+                if (jtaDataSourceId != null || nonJtaDataSourceId != null) {
+                    if (jtaDataSourceId != null) unit.setJtaDataSource("java:openejb/Resource/" + jtaDataSourceId);
+                    if (nonJtaDataSourceId != null) unit.setNonJtaDataSource("java:openejb/Resource/" + nonJtaDataSourceId);
+                    continue;
+                }
+            }
+
+
+            //  We are done with the most optimal configuration.
+            //
+            //  If both the jta-data-source and non-jta-data-source
+            //  references were explicitly and correctly configured
+            //  to existing datasource, we wouldn't get this far.
+            //
+            //  At this point we see if either we can't figure out
+            //  if there's an issue with their configuration or
+            //  if we can't intelligently complete their configuration.
+
+
+
+            //
+            //  Do both the jta-data-source and non-jta-data-source references
+            //  point to the same datasource?
+            //
+            //  If so, then unlink the invalid one so defaulting rules can
+            //  possibly fill in a good value.
+            //
+
+            required.put("JtaManaged", ANY);
+            String possibleJta = findResourceId(unit.getJtaDataSource(), "DataSource", required, null);
+            String possibleNonJta = findResourceId(unit.getNonJtaDataSource(), "DataSource", required, null);
+            if (possibleJta != null && possibleJta == possibleNonJta){
+                ResourceInfo dataSource = configFactory.getResourceInfo(possibleJta);
+
+                String jtaManaged = (String) dataSource.properties.get("JtaManaged");
+
+                logger.warning("PeristenceUnit(name=" + unit.getName() + ") invalidly refers to Resource(id=" + dataSource.id + ") as both its <jta-data-source> and <non-jta-data-source>.");
+
+                if ("true".equalsIgnoreCase(jtaManaged)){
+                    nonJtaDataSourceId = null;
+                    unit.setNonJtaDataSource(null);
+
+                } else if ("false".equalsIgnoreCase(jtaManaged)){
+                    jtaDataSourceId = null;
+                    unit.setJtaDataSource(null);
+                }
             }
+
+            //
+            //  Do the jta-data-source and non-jta-data-source references
+            //  point to innapropriately configured Resources?
+            //
+            checkUnitDataSourceRefs(unit);
+
+            //
+            //  Do either the jta-data-source and non-jta-data-source
+            //  references point to the explicit name of a ServiceProvider?
+            //
+            if (jtaDataSourceId == null && nonJtaDataSourceId == null){
+                jtaDataSourceId = findResourceProviderId(unit.getJtaDataSource());
+                nonJtaDataSourceId = findResourceProviderId(unit.getNonJtaDataSource());
+
+                // if one of them is not null we have a match on at least one
+                // we can just create the second resource using the first as a template
+                if (jtaDataSourceId != null || nonJtaDataSourceId != null){
+                    Resource jtaResource = new Resource(jtaDataSourceId, "DataSource", jtaDataSourceId);
+                    jtaResource.getProperties().setProperty("JtaManaged", "true");
+
+                    Resource nonJtaResource = new Resource(nonJtaDataSourceId, "DataSource", nonJtaDataSourceId);
+                    nonJtaResource.getProperties().setProperty("JtaManaged", "false");
+
+                    if (jtaDataSourceId == null){
+                        jtaResource.setId(nonJtaDataSourceId+"Jta");
+                        jtaResource.setProvider(nonJtaDataSourceId);
+                    } else if (nonJtaDataSourceId == null){
+                        nonJtaResource.setId(jtaDataSourceId+"NonJta");
+                        nonJtaResource.setProvider(jtaDataSourceId);
+                    }
+
+                    ResourceInfo jtaResourceInfo = configFactory.configureService(jtaResource, ResourceInfo.class);
+                    ResourceInfo nonJtaResourceInfo = configFactory.configureService(nonJtaResource, ResourceInfo.class);
+
+                    logAutoCreateResource(jtaResourceInfo, "DataSource", unit.getName());
+                    jtaDataSourceId = installResource(unit.getName(), jtaResourceInfo);
+
+                    logAutoCreateResource(nonJtaResourceInfo, "DataSource", unit.getName());
+                    nonJtaDataSourceId = installResource(unit.getName(), nonJtaResourceInfo);
+
+                    unit.setJtaDataSource("java:openejb/Resource/" + jtaDataSourceId);
+                    unit.setNonJtaDataSource("java:openejb/Resource/" + nonJtaDataSourceId);
+                    continue;
+                }
+            }
+
+            //
+            //  If neither of the references are valid yet, then let's take
+            //  the first valid datasource.
+            //
+            //  We won't fill in both jta-data-source and non-jta-data-source
+            //  this way as the following code does a great job at determining
+            //  if any of the existing data sources are a good match or if
+            //  one needs to be generated.
+            //
+            if (jtaDataSourceId == null && nonJtaDataSourceId == null){
+
+                required.clear();
+                required.put("JtaManaged", "true");
+                jtaDataSourceId = firstMatching("DataSource", required, null);
+
+                if (jtaDataSourceId == null){
+                    required.clear();
+                    required.put("JtaManaged", "false");
+                    nonJtaDataSourceId = firstMatching("DataSource", required, null);
+                }
+            }
+
+
+            //
+            //  Does the jta-data-source reference point an existing
+            //  Resource in the system with JtaManaged=true?
+            //
+            //  If so, we can search for an existing datasource
+            //  configured with identical properties and use it.
+            //
+            //  If that doesn't work, we can copy the jta-data-source
+            //  and auto-create the missing non-jta-data-source
+            //  using it as a template, applying the overrides,
+            //  and finally setting JtaManaged=false
+            //
+
+            if (jtaDataSourceId != null && nonJtaDataSourceId == null){
+
+                ResourceInfo jtaResourceInfo = configFactory.getResourceInfo(jtaDataSourceId);
+
+                Properties jtaProperties = jtaResourceInfo.properties;
+
+                if (jtaProperties.containsKey("JtaManaged")){
+
+                    // Strategy 1: Best match search
+
+                    required.clear();
+                    required.put("JtaManaged", "false");
+
+                    for (String key : asList("JdbcDriver", "JdbcUrl")) {
+                        if (jtaProperties.containsKey(key)) required.put(key, jtaProperties.get(key));
+                    }
+
+                    nonJtaDataSourceId = firstMatching("DataSource", required, null);
+
+                    // Strategy 2: Copy
+
+                    if (nonJtaDataSourceId == null) {
+                        ResourceInfo nonJtaResourceInfo = copy(jtaResourceInfo);
+                        nonJtaResourceInfo.id = jtaResourceInfo.id + "NonJta";
+
+                        Properties overrides = ConfigurationFactory.getSystemProperties(nonJtaResourceInfo.id, nonJtaResourceInfo.service);
+                        nonJtaResourceInfo.properties.putAll(overrides);
+                        nonJtaResourceInfo.properties.setProperty("JtaManaged", "false");
+
+                        logAutoCreateResource(nonJtaResourceInfo, "DataSource", unit.getName());
+                        logger.info("configureService.configuring", nonJtaResourceInfo.id, nonJtaResourceInfo.service, jtaResourceInfo.id);
+
+                        nonJtaDataSourceId = installResource(unit.getName(), nonJtaResourceInfo);
+                    }
+                }
+
+            }
+
+            //
+            //  Does the jta-data-source reference point an existing
+            //  Resource in the system with JtaManaged=false?
+            //
+            //  If so, we can search for an existing datasource
+            //  configured with identical properties and use it.
+            //
+            //  If that doesn't work, we can copy the jta-data-source
+            //  and auto-create the missing non-jta-data-source
+            //  using it as a template, applying the overrides,
+            //  and finally setting JtaManaged=false
+            //
+
+            if (nonJtaDataSourceId != null && jtaDataSourceId == null){
+
+                ResourceInfo nonJtaResourceInfo = configFactory.getResourceInfo(nonJtaDataSourceId);
+
+                Properties nonJtaProperties = nonJtaResourceInfo.properties;
+
+                if (nonJtaProperties.containsKey("JtaManaged")){
+
+                    // Strategy 1: Best match search
+
+                    required.clear();
+                    required.put("JtaManaged", "true");
+
+                    for (String key : asList("JdbcDriver", "JdbcUrl")) {
+                        if (nonJtaProperties.containsKey(key)) required.put(key, nonJtaProperties.get(key));
+                    }
+
+                    jtaDataSourceId = firstMatching("DataSource", required, null);
+
+                    // Strategy 2: Copy
+
+                    if (jtaDataSourceId == null) {
+                        ResourceInfo jtaResourceInfo = copy(nonJtaResourceInfo);
+                        jtaResourceInfo.id = nonJtaResourceInfo.id + "Jta";
+
+                        Properties overrides = ConfigurationFactory.getSystemProperties(jtaResourceInfo.id, jtaResourceInfo.service);
+                        jtaResourceInfo.properties.putAll(overrides);
+                        jtaResourceInfo.properties.setProperty("JtaManaged", "true");
+
+                        logAutoCreateResource(jtaResourceInfo, "DataSource", unit.getName());
+                        logger.info("configureService.configuring", jtaResourceInfo.id, jtaResourceInfo.service, nonJtaResourceInfo.id);
+
+                        jtaDataSourceId = installResource(unit.getName(), jtaResourceInfo);
+                    }
+                }
+
+            }
+
+            //
+            //  By this point if we've found anything at all, both
+            //  jta-data-source and non-jta-data-source should be
+            //  filled in (provided they aren't using a third party
+            //  data source).
+            //
+            //  Should both references still be null
+            //  we can just take a shot in the dark and auto-create
+            //  them them both using the built-in templates for jta
+            //  and non-jta default datasources.  These are supplied
+            //  via the service-jar.xml file.
+            //
+            if (jtaDataSourceId == null && nonJtaDataSourceId == null){
+                required.put("JtaManaged", "true");
+                jtaDataSourceId = autoCreateResource("DataSource", required, unit.getName());
+
+                required.put("JtaManaged", "false");
+                nonJtaDataSourceId = autoCreateResource("DataSource", required, unit.getName());
+            }
+
+            if (jtaDataSourceId != null) unit.setJtaDataSource("java:openejb/Resource/" + jtaDataSourceId);
+            if (nonJtaDataSourceId != null) unit.setNonJtaDataSource("java:openejb/Resource/" + nonJtaDataSourceId);
+        }
+    }
+
+    private ResourceInfo copy(ResourceInfo a) {
+        ResourceInfo b = new ResourceInfo();
+        b.id = a.id;
+        b.service = a.service;
+        b.className = a.className;
+        b.codebase = a.codebase;
+        b.displayName = a.displayName;
+        b.description = a.description;
+        b.factoryMethod = a.factoryMethod;
+        b.constructorArgs.addAll(a.constructorArgs);
+        b.types.addAll(a.types);
+        b.properties = new SuperProperties();
+        b.properties.putAll(a.properties);
+
+        return b;
+    }
+
+    private void checkUnitDataSourceRefs(PersistenceUnit unit) throws OpenEJBException {
+        Properties required = new Properties();
+
+        // check that non-jta-data-source does NOT point to a JtaManaged=true datasource
+
+        required.put("JtaManaged", "true");
+
+        String invalidNonJta = findResourceId(unit.getNonJtaDataSource(), "DataSource", required, null);
+
+        if (invalidNonJta != null){
+            throw new OpenEJBException("PeristenceUnit "+unit.getName()+" <non-jta-data-source> points to a jta managed Resource.  Update Resource \""+invalidNonJta +"\" to \"JtaManaged=false\", use a different Resource, or delete the <non-jta-data-source> element and a default will be supplied if possible.");
+        }
+
+
+        // check that jta-data-source does NOT point to a JtaManaged=false datasource
+
+        required.put("JtaManaged", "false");
+
+        String invalidJta = findResourceId(unit.getJtaDataSource(), "DataSource", required, null);
+
+        if (invalidJta != null){
+            throw new OpenEJBException("PeristenceUnit "+unit.getName()+" <jta-data-source> points to a non jta managed Resource.  Update Resource \""+invalidJta +"\" to \"JtaManaged=true\", use a different Resource, or delete the <jta-data-source> element and a default will be supplied if possible.");
+        }
+    }
+
+    private String findResourceProviderId(String resourceId) throws OpenEJBException {
+        if (resourceId == null) return null;
+        
+        if (hasServiceProvider(resourceId)) {
+            return resourceId;
+        }
+
+        resourceId = toShortName(resourceId);
+        if (hasServiceProvider(resourceId)) {
+            return resourceId;
         }
+
+        return null;
     }
 
     private String getResourceId(String beanName, String resourceId, String type, AppResources appResources) throws OpenEJBException {
-        return getResourceId(beanName, resourceId, type, appResources, null);
+        return getResourceId(beanName, resourceId, type, null, appResources);
     }
 
-    private String getResourceId(String beanName, String resourceId, String type, AppResources appResources, Properties required) throws OpenEJBException {
+    private String getResourceId(String beanName, String resourceId, String type, Properties required, AppResources appResources) throws OpenEJBException {
+        resourceId = normalizeResourceId(resourceId);
+
         if(resourceId == null){
             return null;
         }
@@ -885,37 +1222,18 @@
             return null;
         }
 
-        // strip off "java:comp/env"
-        if (resourceId.startsWith("java:comp/env")) {
-            resourceId = resourceId.substring("java:comp/env".length());
-        }
 
-        // check for existing resource with specified resourceId
-        List<String> resourceIds = new ArrayList<String>();
-        resourceIds.addAll(appResources.getResourceIds(type));
-        resourceIds.addAll(configFactory.getResourceIds(type, required));
-        for (String id : resourceIds) {
-            if (id.equalsIgnoreCase(resourceId)) return id;
-        }
-
-        // check for an existing resource using the short name (everything ever the final '/')
-        String shortName = resourceId.replaceFirst(".*/", "");
-        for (String id : resourceIds) {
-            if (id.equalsIgnoreCase(shortName)) return id;
-        }
+        // check for existing resource with specified resourceId and type and properties
+        String id = findResourceId(resourceId, type, required, appResources);
+        if (id != null) return id;
 
         // expand search to any type -- may be asking for a reference to a sub-type
-        List<String> allResourceIds = new ArrayList<String>();
-        allResourceIds.addAll(appResources.getResourceIds(null));
-        allResourceIds.addAll(configFactory.getResourceIds(null, required));
-        for (String id : allResourceIds) {
-            if (id.equalsIgnoreCase(resourceId)) return id;
-        }
-        for (String id : allResourceIds) {
-            if (id.equalsIgnoreCase(shortName)) return id;
-        }
+        id = findResourceId(resourceId, null, required, appResources);
+        if (id != null) return id;
+
 
         // throw an exception or log an error
+        String shortName = toShortName(resourceId);
         String message = "No existing resource found while attempting to Auto-link unmapped resource-ref '" + resourceId + "' of type '" + type  + "' for '" + beanName + "'.  Looked for Resource(id=" + resourceId + ") and Resource(id=" + shortName + ")";
         if (!autoCreateResources){
             throw new OpenEJBException(message);
@@ -923,30 +1241,101 @@
         logger.debug(message);
 
         // if there is a provider with the specified name. use it
-        if (ServiceUtils.hasServiceProvider(resourceId)) {
+        if (hasServiceProvider(resourceId)) {
             ResourceInfo resourceInfo = configFactory.configureService(resourceId, ResourceInfo.class);
             return installResource(beanName, resourceInfo);
-        } else if (ServiceUtils.hasServiceProvider(shortName)) {
+        } else if (hasServiceProvider(shortName)) {
             ResourceInfo resourceInfo = configFactory.configureService(shortName, ResourceInfo.class);
             return installResource(beanName, resourceInfo);
         }
 
         // if there are any resources of the desired type, use the first one
-        if (resourceIds.size() > 0) {
-            return resourceIds.get(0);
-        }
+        id = firstMatching(type, required, appResources);
+        if (id != null) return id;
 
         // Auto create a resource using the first provider that can supply a resource of the desired type
+        return autoCreateResource(type, required, beanName);
+    }
+
+    private String autoCreateResource(String type, Properties required, String beanName) throws OpenEJBException {
+        String resourceId;
         resourceId = ServiceUtils.getServiceProviderId(type, required);
         if (resourceId == null) {
             throw new OpenEJBException("No provider available for resource-ref '" + resourceId + "' of type '" + type + "' for '" + beanName + "'.");
         }
         ResourceInfo resourceInfo = configFactory.configureService(resourceId, ResourceInfo.class);
 
-        logger.info("Auto-creating a resource with id '" + resourceInfo.id +  "' of type '" + type  + " for '" + beanName + "'.");
+        logAutoCreateResource(resourceInfo, type, beanName);
         return installResource(beanName, resourceInfo);
     }
 
+    private void logAutoCreateResource(ResourceInfo resourceInfo, String type, String beanName) {
+        logger.info("Auto-creating a Resource with id '" + resourceInfo.id +  "' of type '" + type  + " for '" + beanName + "'.");
+    }
+
+    private String firstMatching(String type, Properties required, AppResources appResources) {
+        List<String> resourceIds = getResourceIds(appResources, type, required);
+        String idd = null;
+        if (resourceIds.size() > 0) {
+            idd = resourceIds.get(0);
+        }
+        return idd;
+    }
+
+    private String findResourceId(String resourceId, String type, Properties required, AppResources appResources) {
+        if (resourceId == null) return null;
+
+        resourceId = normalizeResourceId(resourceId);
+
+        // check for existing resource with specified resourceId
+        List<String> resourceIds = getResourceIds(appResources, type, required);
+        for (String id : resourceIds) {
+            if (id.equalsIgnoreCase(resourceId)) return id;
+        }
+
+        // check for existing resource with shortName
+        String shortName = toShortName(resourceId);
+        for (String id : resourceIds) {
+            if (id.equalsIgnoreCase(shortName)) return id;
+        }
+        return null;
+    }
+
+    private List<String> getResourceIds(AppResources appResources, String type, Properties required) {
+        List<String> resourceIds;
+        resourceIds = new ArrayList<String>();
+        if (appResources != null) resourceIds.addAll(appResources.getResourceIds(type));
+        resourceIds.addAll(configFactory.getResourceIds(type, required));
+        return resourceIds;
+    }
+
+    private String toShortName(String resourceId) {
+        // check for an existing resource using the short name (everything ever the final '/')
+        String shortName = resourceId.replaceFirst(".*/", "");
+        return shortName;
+    }
+
+    private String normalizeResourceId(String resourceId) {
+        if (resourceId == null) return null;
+
+        // strip off "java:comp/env"
+        if (resourceId.startsWith("java:comp/env")) {
+            resourceId = resourceId.substring("java:comp/env".length());
+        }
+
+        // strip off "java:openejb/Resource"
+        if (resourceId.startsWith("java:openejb/Resource")) {
+            resourceId = resourceId.substring("java:openejb/Resource".length());
+        }
+
+        // strip off "java:openejb/Connector"
+        if (resourceId.startsWith("java:openejb/Connector")) {
+            resourceId = resourceId.substring("java:openejb/Connector".length());
+        }
+
+        return resourceId;
+    }
+
     private String installResource(String beanName, ResourceInfo resourceInfo) throws OpenEJBException {
         String resourceAdapterId = resourceInfo.properties.getProperty("ResourceAdapter");
         if (resourceAdapterId != null) {
@@ -978,15 +1367,10 @@
             return null;
         }
 
-        // strip off "java:comp/env"
-        if (resourceId.startsWith("java:comp/env")) {
-            resourceId = resourceId.substring("java:comp/env".length());
-        }
+        resourceId = normalizeResourceId(resourceId);
 
         // check for existing resource with specified resourceId
-        List<String> resourceEnvIds = new ArrayList<String>();
-        resourceEnvIds.addAll(appResources.getResourceIds(type));
-        resourceEnvIds.addAll(configFactory.getResourceIds(type));
+        List<String> resourceEnvIds = getResourceIds(appResources, type, null);
         for (String id : resourceEnvIds) {
             if (id.equalsIgnoreCase(resourceId)) return id;
         }
@@ -1013,7 +1397,7 @@
         resource.getProperties().setProperty("destination", resourceId);
 
         ResourceInfo resourceInfo = configFactory.configureService(resource, ResourceInfo.class);
-        logger.info("Auto-creating a resource with id '" + resourceInfo.id +  "' of type '" + type  + " for '" + beanName + "'.");
+        logAutoCreateResource(resourceInfo, type, beanName);
         return installResource(beanName, resourceInfo);
     }
 

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java?rev=633370&r1=633369&r2=633370&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java Mon Mar  3 22:33:07 2008
@@ -748,6 +748,26 @@
         return resourceIds;
     }
 
+    protected ResourceInfo getResourceInfo(String id) {
+        OpenEjbConfiguration runningConfig = getRunningConfig();
+        if (runningConfig != null) {
+            for (ResourceInfo resourceInfo : runningConfig.facilities.resources) {
+                if (resourceInfo.id == id){
+                    return resourceInfo;
+                }
+            }
+        }
+
+        if (sys != null) {
+            for (ResourceInfo resourceInfo : sys.facilities.resources) {
+                if (resourceInfo.id == id){
+                    return resourceInfo;
+                }
+            }
+        }
+        return null;
+    }
+
     @SuppressWarnings({"UnusedDeclaration", "EmptyFinallyBlock"})
     private boolean isResourceType(String service, List<String> types, String type) {
         boolean b = false;

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/ServiceUtils.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/ServiceUtils.java?rev=633370&r1=633369&r2=633370&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/ServiceUtils.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/ServiceUtils.java Mon Mar  3 22:33:07 2008
@@ -39,6 +39,7 @@
 
 public class ServiceUtils {
     public static final String ANY = ServiceUtils.class.getName() + "@ANY";
+    public static final String NONE = ServiceUtils.class.getName() + "@NONE";
 
     /**
      * Default service provider package.  This value is choosen as follows:
@@ -165,12 +166,13 @@
         for (Map.Entry<Object, Object> entry : a.entrySet()) {
             Object value = b.get(entry.getKey());
 
-            // does b have the key?
-            if (value == null) return false;
-
-            // do the values match?
             Object expected = entry.getValue();
-            if (!expected.equals(ANY) && !expected.equals(value)) return false;
+
+            if (expected.equals(NONE)){
+                if (value != null) return false;
+            } else if (expected.equals(ANY)){
+                if (value == null) return false;
+            } else if (!expected.equals(value)) return false;
         }
         return true;
     }

Added: openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/AutoConfigPersistenceUnitsTest.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/AutoConfigPersistenceUnitsTest.java?rev=633370&view=auto
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/AutoConfigPersistenceUnitsTest.java (added)
+++ openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/AutoConfigPersistenceUnitsTest.java Mon Mar  3 22:33:07 2008
@@ -0,0 +1,980 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.openejb.config;
+
+import junit.framework.TestCase;
+import org.apache.openejb.OpenEJBException;
+import org.apache.openejb.assembler.classic.AppInfo;
+import org.apache.openejb.assembler.classic.Assembler;
+import org.apache.openejb.assembler.classic.OpenEjbConfiguration;
+import org.apache.openejb.assembler.classic.PersistenceUnitInfo;
+import org.apache.openejb.assembler.classic.ProxyFactoryInfo;
+import org.apache.openejb.assembler.classic.ResourceInfo;
+import org.apache.openejb.assembler.classic.SecurityServiceInfo;
+import org.apache.openejb.assembler.classic.TransactionServiceInfo;
+import org.apache.openejb.config.sys.Resource;
+import org.apache.openejb.jee.jpa.unit.Persistence;
+import org.apache.openejb.jee.jpa.unit.PersistenceUnit;
+import org.apache.openejb.loader.SystemInstance;
+
+import javax.naming.NamingException;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+import java.util.Properties;
+import java.util.List;
+
+/**
+ * @version $Revision: 632667 $ $Date: 2008-03-01 14:32:11 -0800 (Sat, 01 Mar 2008) $
+ */
+public class AutoConfigPersistenceUnitsTest extends TestCase {
+    private ConfigurationFactory config;
+    private Assembler assembler;
+    private List<ResourceInfo> resources;
+
+    protected void setUp() throws Exception {
+        config = new ConfigurationFactory();
+        assembler = new Assembler();
+
+        assembler.createProxyFactory(config.configureService(ProxyFactoryInfo.class));
+        assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class));
+        assembler.createSecurityService(config.configureService(SecurityServiceInfo.class));
+
+        OpenEjbConfiguration configuration = SystemInstance.get().getComponent(OpenEjbConfiguration.class);
+        resources = configuration.facilities.resources;
+    }
+
+    /**
+     * Existing data source "Orange", jta managed
+     * Existing data source "OrangeUnmanaged", not jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <jta-data-source>Orange</jta-data-source>
+     *      <non-jta-data-source>OrangeUnamanged</non-jta-data-source>
+     * </persistence-unit>
+     *
+     * This is the happy path.
+     *
+     * @throws Exception
+     */
+    public void test() throws Exception {
+
+        ResourceInfo jta = addDataSource("Orange", OrangeDriver.class, "jdbc:orange:some:stuff", true);
+        ResourceInfo nonJta = addDataSource("OrangeUnmanaged", OrangeDriver.class, "jdbc:orange:some:stuff", false);
+
+        assertSame(jta, resources.get(0));
+        assertSame(nonJta, resources.get(1));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", "Orange", "OrangeUnmanaged");
+
+        assertNotNull(unitInfo);
+
+        assertEquals("java:openejb/Resource/" + jta.id, unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + nonJta.id, unitInfo.nonJtaDataSource);
+    }
+
+    /**
+     * Existing data source "Orange", not controlled by us
+     * Existing data source "OrangeUnmanaged", also not controlled by us
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <jta-data-source>Orange</jta-data-source>
+     *      <non-jta-data-source>OrangeUnamanged</non-jta-data-source>
+     * </persistence-unit>
+     *
+     * @throws Exception
+     */
+    public void testThirdPartyDataSources() throws Exception {
+
+        ResourceInfo jta = addDataSource("Orange", OrangeDriver.class, "jdbc:orange:some:stuff", null);
+        ResourceInfo nonJta = addDataSource("OrangeUnmanaged", OrangeDriver.class, "jdbc:orange:some:stuff", null);
+
+        assertSame(jta, resources.get(0));
+        assertSame(nonJta, resources.get(1));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", "Orange", "OrangeUnmanaged");
+
+        assertNotNull(unitInfo);
+
+        assertEquals("java:openejb/Resource/" + jta.id, unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + nonJta.id, unitInfo.nonJtaDataSource);
+    }
+
+
+    /**
+     * Existing data source "Orange", not controlled by us
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <jta-data-source>Orange</jta-data-source>
+     * </persistence-unit>
+     *
+     * Here we should just let them try and get by with
+     * just the one data source.
+     *
+     * @throws Exception
+     */
+    public void testThirdPartyDataSources2() throws Exception {
+
+        ResourceInfo dataSource = addDataSource("Orange", OrangeDriver.class, "jdbc:orange:some:stuff", null);
+
+        assertSame(dataSource, resources.get(0));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", "Orange", null);
+
+        assertNotNull(unitInfo);
+
+        assertEquals("java:openejb/Resource/" + dataSource.id, unitInfo.jtaDataSource);
+        assertNull(unitInfo.nonJtaDataSource);
+    }
+
+    /**
+     * Existing data source "Orange", not controlled by us
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <non-jta-data-source>Orange</non-jta-data-source>
+     * </persistence-unit>
+     *
+     * Here we should just let them try and get by with
+     * just the one data source.
+     *
+     * @throws Exception
+     */
+    public void testThirdPartyDataSources3() throws Exception {
+
+        ResourceInfo dataSource = addDataSource("Orange", OrangeDriver.class, "jdbc:orange:some:stuff", null);
+
+        assertSame(dataSource, resources.get(0));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", null, "Orange");
+
+        assertNotNull(unitInfo);
+
+        assertNull(unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + dataSource.id, unitInfo.nonJtaDataSource);
+    }
+
+    /**
+     * Existing data source "Orange", not controlled by us
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <jta-data-source>Orange</jta-data-source>
+     *      <non-jta-data-source>Orange</non-jta-data-source>
+     * </persistence-unit>
+     *
+     * Here we should just let them try and get by with
+     * both jta and non-jta references pointed at the same
+     * data source.
+     *
+     * @throws Exception
+     */
+    public void testThirdPartyDataSources4() throws Exception {
+
+        ResourceInfo dataSource = addDataSource("Orange", OrangeDriver.class, "jdbc:orange:some:stuff", null);
+
+        assertSame(dataSource, resources.get(0));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit",  "Orange", "Orange");
+
+        assertNotNull(unitInfo);
+
+        assertEquals("java:openejb/Resource/" + dataSource.id, unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + dataSource.id, unitInfo.nonJtaDataSource);
+    }
+
+    /**
+     * Existing data source "Orange", jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <jta-data-source>Orange</jta-data-source>
+     *      <non-jta-data-source>Orange</non-jta-data-source>
+     * </persistence-unit>
+     *
+     * They used the same data source for both the
+     * jta-data-source and non-jta-data-source and we
+     * can determine the data source will not work as
+     * a non-jta-data-source
+     *
+     * We should generate the missing data source for them
+     * based on the one they supplied.
+     *
+     * @throws Exception
+     */
+    public void testSameDataSourceForBoth1() throws Exception {
+
+        ResourceInfo supplied = addDataSource("Orange", OrangeDriver.class, "jdbc:orange:some:stuff", true);
+
+        assertSame(supplied, resources.get(0));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", "Orange", "Orange");
+
+        assertNotNull(unitInfo);
+
+        ResourceInfo generated = resources.get(1);
+
+        assertEquals("java:openejb/Resource/" + supplied.id, unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + generated.id, unitInfo.nonJtaDataSource);
+
+
+        assertNotNull(generated);
+        assertEquals(supplied.id + "NonJta", generated.id);
+        assertEquals(supplied.service, generated.service);
+        assertEquals(supplied.className, generated.className);
+        assertEquals(supplied.properties.get("JdbcDriver"), generated.properties.get("JdbcDriver"));
+        assertEquals(supplied.properties.get("JdbcUrl"), generated.properties.get("JdbcUrl"));
+        assertEquals("false", generated.properties.get("JtaManaged"));
+
+    }
+
+
+    /**
+     * Existing data source "Orange", not jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <jta-data-source>Orange</jta-data-source>
+     *      <non-jta-data-source>Orange</non-jta-data-source>
+     * </persistence-unit>
+     *
+     * They used the same data source for both the
+     * jta-data-source and non-jta-data-source and we
+     * can determine the data source will not work as
+     * a jta-data-source
+     *
+     * We should generate the missing data source for them
+     * based on the one they supplied.
+     *
+     * @throws Exception
+     */
+    public void testSameDataSourceForBoth2() throws Exception {
+
+        ResourceInfo supplied = addDataSource("Orange", OrangeDriver.class, "jdbc:orange:some:stuff", false);
+
+        assertSame(supplied, resources.get(0));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", "Orange", "Orange");
+
+        assertNotNull(unitInfo);
+
+        ResourceInfo generated = resources.get(1);
+
+        assertEquals("java:openejb/Resource/" + generated.id, unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + supplied.id, unitInfo.nonJtaDataSource);
+
+
+        assertNotNull(generated);
+        assertEquals(supplied.id + "Jta", generated.id);
+        assertEquals(supplied.service, generated.service);
+        assertEquals(supplied.className, generated.className);
+        assertEquals(supplied.properties.get("JdbcDriver"), generated.properties.get("JdbcDriver"));
+        assertEquals(supplied.properties.get("JdbcUrl"), generated.properties.get("JdbcUrl"));
+        assertEquals("true", generated.properties.get("JtaManaged"));
+
+    }
+
+    /**
+     * Existing data source "OrangeOne", jta managed
+     * Existing data source "OrangeTwo", not jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <jta-data-source>OrangeOne</jta-data-source>
+     *      <non-jta-data-source>OrangeOne</non-jta-data-source>
+     * </persistence-unit>
+     *
+     * They used the same data source for both the
+     * jta-data-source and non-jta-data-source and we
+     * can determine the data source will not work as
+     * a non-jta-data-source
+     * BUT
+     * they have explicitly configured a data source
+     * that nearly matches the named datasource and
+     * would be identical to what we would auto-create
+     *
+     * @throws Exception
+     */
+    public void testSameDataSourceForBoth3() throws Exception {
+
+        ResourceInfo jta = addDataSource("OrangeOne", OrangeDriver.class, "jdbc:orange:some:stuff", true);
+        ResourceInfo nonJta = addDataSource("OrangeTwo", OrangeDriver.class, "jdbc:orange:some:stuff", false);
+
+        assertSame(jta, resources.get(0));
+        assertSame(nonJta, resources.get(1));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", "OrangeOne", "OrangeOne");
+
+        assertNotNull(unitInfo);
+
+        assertEquals("java:openejb/Resource/" + jta.id, unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + nonJta.id, unitInfo.nonJtaDataSource);
+    }
+
+    /**
+     * Existing data source "OrangeOne", jta managed
+     * Existing data source "OrangeTwo", not jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <jta-data-source>OrangeTwo</jta-data-source>
+     *      <non-jta-data-source>OrangeTwo</non-jta-data-source>
+     * </persistence-unit>
+     *
+     * They used the same data source for both the
+     * jta-data-source and non-jta-data-source and we
+     * can determine the data source will not work as
+     * a jta-data-source
+     * BUT
+     * they have explicitly configured a data source
+     * that nearly matches the named datasource and
+     * would be identical to what we would auto-create
+     *
+     * @throws Exception
+     */
+    public void testSameDataSourceForBoth4() throws Exception {
+
+        ResourceInfo jta = addDataSource("OrangeOne", OrangeDriver.class, "jdbc:orange:some:stuff", true);
+        ResourceInfo nonJta = addDataSource("OrangeTwo", OrangeDriver.class, "jdbc:orange:some:stuff", false);
+
+        assertSame(jta, resources.get(0));
+        assertSame(nonJta, resources.get(1));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", "OrangeTwo", "OrangeTwo");
+
+        assertNotNull(unitInfo);
+
+        assertEquals("java:openejb/Resource/" + jta.id, unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + nonJta.id, unitInfo.nonJtaDataSource);
+    }
+
+    /**
+     * Existing data source "Orange", jta managed
+     * Existing data source "OrangeUnmanaged", not jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <jta-data-source>java:foo/bar/baz/Orange</jta-data-source>
+     *      <non-jta-data-source>java:foo/bar/baz/OrangeUnamanged</non-jta-data-source>
+     * </persistence-unit>
+     *
+     * The datasources should be mapped correctly despite the
+     * vendor specific prefix.
+     *
+     * @throws Exception
+     */
+    public void testShortName() throws Exception {
+
+        ResourceInfo jta = addDataSource("Orange", OrangeDriver.class, "jdbc:orange:some:stuff", true);
+        ResourceInfo nonJta = addDataSource("OrangeUnmanaged", OrangeDriver.class, "jdbc:orange:some:stuff", false);
+
+        assertSame(jta, resources.get(0));
+        assertSame(nonJta, resources.get(1));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", "java:foo/bar/baz/Orange", "java:foo/bar/baz/OrangeUnmanaged");
+
+        assertNotNull(unitInfo);
+
+        assertEquals("java:openejb/Resource/" + jta.id, unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + nonJta.id, unitInfo.nonJtaDataSource);
+    }
+
+    /**
+     * Existing data source "Orange", jta managed
+     * Existing data source "OrangeUnmanaged", not jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <jta-data-source>DoesNotExist</jta-data-source>
+     *      <non-jta-data-source>AlsoDoesNotExist</non-jta-data-source>
+     * </persistence-unit>
+     *
+     * We should automatically hook them up to the configured
+     * datasources that do match
+     *
+     * @throws Exception
+     */
+    public void testInvalidRefs() throws Exception {
+
+        ResourceInfo jta = addDataSource("Orange", OrangeDriver.class, "jdbc:orange:some:stuff", true);
+        ResourceInfo nonJta = addDataSource("OrangeUnmanaged", OrangeDriver.class, "jdbc:orange:some:stuff", false);
+
+        assertSame(jta, resources.get(0));
+        assertSame(nonJta, resources.get(1));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", "DoesNotExist", "AlsoDoesNotExist");
+
+        assertNotNull(unitInfo);
+
+        assertEquals("java:openejb/Resource/" + jta.id, unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + nonJta.id, unitInfo.nonJtaDataSource);
+    }
+
+    // ---
+
+    /**
+     * Existing data source "OrangeOne", not jta managed
+     * Existing data source "OrangeTwo", not jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <jta-data-source>OrangeOne</jta-data-source>
+     *      <non-jta-data-source>OrangeTwo</non-jta-data-source>
+     * </persistence-unit>
+     *
+     * This configuration should be rejected
+     *
+     * @throws Exception
+     */
+    public void testJtaRefToContrarilyConfiguredDataSource() throws Exception {
+
+        ResourceInfo nonJta1 = addDataSource("OrangeOne", OrangeDriver.class, "jdbc:orange:some:stuff", false);
+        ResourceInfo nonJta2 = addDataSource("OrangeTwo", OrangeDriver.class, "jdbc:orange:some:stuff", false);
+
+        assertSame(nonJta1, resources.get(0));
+        assertSame(nonJta2, resources.get(1));
+
+        try {
+            addPersistenceUnit("orange-unit", "OrangeOne", "OrangeTwo");
+            fail("Configuration should be rejected");
+        } catch (OpenEJBException e) {
+            // pass
+        }
+    }
+
+    /**
+     * Existing data source "OrangeOne", not jta managed
+     * Existing data source "OrangeTwo", not jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <jta-data-source>OrangeOne</jta-data-source>
+     *      <non-jta-data-source>OrangeTwo</non-jta-data-source>
+     * </persistence-unit>
+     *
+     * This configuration should be rejected
+     *
+     * @throws Exception
+     */
+    public void testNonJtaRefToContrarilyConfiguredDataSource() throws Exception {
+
+        ResourceInfo jta1 = addDataSource("OrangeOne", OrangeDriver.class, "jdbc:orange:some:stuff", true);
+        ResourceInfo jta2 = addDataSource("OrangeTwo", OrangeDriver.class, "jdbc:orange:some:stuff", true);
+
+        assertSame(jta1, resources.get(0));
+        assertSame(jta2, resources.get(1));
+
+        try {
+            addPersistenceUnit("orange-unit", "OrangeOne", "OrangeTwo");
+            fail("Configuration should be rejected");
+        } catch (OpenEJBException e) {
+            // pass
+        }
+    }
+
+    /**
+     * Existing data source "OrangeOne", not jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <jta-data-source>OrangeOne</jta-data-source>
+     * </persistence-unit>
+     *
+     * This configuration should be rejected
+     *
+     * @throws Exception
+     */
+    public void testJtaRefToContrarilyConfiguredDataSource2() throws Exception {
+
+        ResourceInfo jta = addDataSource("OrangeOne", OrangeDriver.class, "jdbc:orange:some:stuff", false);
+
+        assertSame(jta, resources.get(0));
+
+        try {
+            addPersistenceUnit("orange-unit", "OrangeOne", null);
+            fail("Configuration should be rejected");
+        } catch (OpenEJBException e) {
+            // pass
+        }
+    }
+
+    /**
+     * Existing data source "OrangeOne", not jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <non-jta-data-source>OrangeOne</non-jta-data-source>
+     * </persistence-unit>
+     *
+     * This configuration should be rejected
+     *
+     * @throws Exception
+     */
+    public void testNonJtaRefToContrarilyConfiguredDataSource2() throws Exception {
+
+        ResourceInfo jta = addDataSource("OrangeOne", OrangeDriver.class, "jdbc:orange:some:stuff", true);
+
+        assertSame(jta, resources.get(0));
+
+        try {
+            addPersistenceUnit("orange-unit", null, "OrangeOne");
+            fail("Configuration should be rejected");
+        } catch (OpenEJBException e) {
+            // pass
+        }
+    }
+
+    // ---
+
+    /**
+     * Existing data source "Orange" not jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <non-jta-data-source>Orange</non-jta-data-source>
+     * </persistence-unit>
+     *
+     * We should generate a <jta-data-source> based on
+     * the <non-jta-data-source>
+     *
+     * @throws Exception
+     */
+    public void testMissingJtaDataSource() throws Exception {
+
+        ResourceInfo supplied = addDataSource("Orange", OrangeDriver.class, "jdbc:orange:some:stuff", false);
+        assertSame(supplied, resources.get(0));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", null, "Orange");
+
+        assertNotNull(unitInfo);
+
+        ResourceInfo generated = resources.get(1);
+
+        assertEquals("java:openejb/Resource/" + supplied.id, unitInfo.nonJtaDataSource);
+        assertEquals("java:openejb/Resource/" + generated.id, unitInfo.jtaDataSource);
+
+
+        assertNotNull(generated);
+        assertEquals(supplied.id + "Jta", generated.id);
+        assertEquals(supplied.service, generated.service);
+        assertEquals(supplied.className, generated.className);
+        assertEquals(supplied.properties.get("JdbcDriver"), generated.properties.get("JdbcDriver"));
+        assertEquals(supplied.properties.get("JdbcUrl"), generated.properties.get("JdbcUrl"));
+        assertEquals("true", generated.properties.get("JtaManaged"));
+    }
+
+    /**
+     * Existing data source "Orange" not jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <non-jta-data-source>Orange</non-jta-data-source>
+     * </persistence-unit>
+     *
+     * We should generate a <jta-data-source> based on
+     * the <non-jta-data-source>
+     *
+     * @throws Exception
+     */
+    public void testMissingNonJtaDataSource() throws Exception {
+
+        ResourceInfo supplied = addDataSource("Orange", OrangeDriver.class, "jdbc:orange:some:stuff", true);
+        assertSame(supplied, resources.get(0));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", "Orange", null);
+
+        assertNotNull(unitInfo);
+
+        ResourceInfo generated = resources.get(1);
+
+        assertEquals("java:openejb/Resource/" + supplied.id, unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + generated.id, unitInfo.nonJtaDataSource);
+
+
+        assertEquals(supplied.id + "NonJta", generated.id);
+        assertEquals(supplied.service, generated.service);
+        assertEquals(supplied.className, generated.className);
+        assertEquals(supplied.properties.get("JdbcDriver"), generated.properties.get("JdbcDriver"));
+        assertEquals(supplied.properties.get("JdbcUrl"), generated.properties.get("JdbcUrl"));
+        assertEquals("false", generated.properties.get("JtaManaged"));
+    }
+
+    // ---
+
+    /**
+     * Existing data source "Orange", not jta managed
+     * Existing data source "Lime", jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <non-jta-data-source>Orange</non-jta-data-source>
+     * </persistence-unit>
+     *
+     * We should generate a <jta-data-source> based on
+     * the <non-jta-data-source>
+     *
+     * @throws Exception
+     */
+    public void testInvalidOptionsJta() throws Exception {
+
+        ResourceInfo supplied = addDataSource("Orange", OrangeDriver.class, "jdbc:orange:some:stuff", false);
+        ResourceInfo badMatch = addDataSource("Lime", LimeDriver.class, "jdbc:lime:some:stuff", true);
+
+        assertSame(supplied, resources.get(0));
+        assertSame(badMatch, resources.get(1));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", null, "Orange");
+
+        assertNotNull(unitInfo);
+
+        ResourceInfo generated = resources.get(2);
+
+        assertEquals("java:openejb/Resource/" + generated.id, unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + supplied.id, unitInfo.nonJtaDataSource);
+
+
+        assertEquals(supplied.id + "Jta", generated.id);
+        assertEquals(supplied.service, generated.service);
+        assertEquals(supplied.className, generated.className);
+        assertEquals(supplied.properties.get("JdbcDriver"), generated.properties.get("JdbcDriver"));
+        assertEquals(supplied.properties.get("JdbcUrl"), generated.properties.get("JdbcUrl"));
+        assertEquals("true", generated.properties.get("JtaManaged"));
+    }
+
+    /**
+     * Existing data source "Orange", not jta managed
+     * Existing data source "Lime", jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <jta-data-source>Orange</jta-data-source>
+     * </persistence-unit>
+     *
+     * We should generate a <non-jta-data-source> based on
+     * the <jta-data-source>
+     *
+     * @throws Exception
+     */
+    public void testInvalidOptionsNonJta() throws Exception {
+
+        ResourceInfo supplied = addDataSource("Orange", OrangeDriver.class, "jdbc:orange:some:stuff", true);
+        ResourceInfo badMatch = addDataSource("Lime", LimeDriver.class, "jdbc:lime:some:stuff", false);
+
+        assertSame(supplied, resources.get(0));
+        assertSame(badMatch, resources.get(1));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", "Orange", null);
+
+        assertNotNull(unitInfo);
+
+
+        ResourceInfo generated = resources.get(2);
+
+        assertEquals("java:openejb/Resource/" + supplied.id, unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + generated.id, unitInfo.nonJtaDataSource);
+
+
+        assertEquals(supplied.id + "NonJta", generated.id);
+        assertEquals(supplied.service, generated.service);
+        assertEquals(supplied.className, generated.className);
+        assertEquals(supplied.properties.get("JdbcDriver"), generated.properties.get("JdbcDriver"));
+        assertEquals(supplied.properties.get("JdbcUrl"), generated.properties.get("JdbcUrl"));
+        assertEquals("false", generated.properties.get("JtaManaged"));
+    }
+
+    // ---
+
+    /**
+     * Existing data source "Orange", not jta managed
+     * Existing data source "Lime", jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <non-jta-data-source>Orange</non-jta-data-source>
+     * </persistence-unit>
+     *
+     * We should select the <jta-data-source> based on
+     * the closest match to the <non-jta-data-source>
+     *
+     * @throws Exception
+     */
+    public void testPossiblyAmbiguousJtaOptions() throws Exception {
+
+        ResourceInfo supplied = addDataSource("Orange", OrangeDriver.class, "jdbc:orange:some:stuff", false);
+        ResourceInfo badMatch = addDataSource("Lime", LimeDriver.class, "jdbc:lime:some:stuff", true);
+        ResourceInfo goodMatch = addDataSource("JtaOrange", OrangeDriver.class, "jdbc:orange:some:stuff", true);
+
+        assertSame(supplied, resources.get(0));
+        assertSame(badMatch, resources.get(1));
+        assertSame(goodMatch, resources.get(2));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", null, "Orange");
+
+        assertNotNull(unitInfo);
+
+
+        assertEquals("java:openejb/Resource/" + goodMatch.id, unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + supplied.id, unitInfo.nonJtaDataSource);
+    }
+
+    /**
+     * Existing data source "Orange", not jta managed
+     * Existing data source "Lime", jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     *      <jta-data-source>Orange</jta-data-source>
+     * </persistence-unit>
+     *
+     * We should select the <non-jta-data-source> based on
+     * the closest match to the <jta-data-source>
+     *
+     * @throws Exception
+     */
+    public void testPossiblyAmbiguousNonJtaOptions() throws Exception {
+
+        ResourceInfo supplied = addDataSource("Orange", OrangeDriver.class, "jdbc:orange:some:stuff", true);
+        ResourceInfo badMatch = addDataSource("Lime", LimeDriver.class, "jdbc:lime:some:stuff", false);
+        ResourceInfo goodMatch = addDataSource("OrangeUnmanaged", OrangeDriver.class, "jdbc:orange:some:stuff", false);
+
+        assertSame(supplied, resources.get(0));
+        assertSame(badMatch, resources.get(1));
+        assertSame(goodMatch, resources.get(2));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", "Orange", null);
+
+        assertNotNull(unitInfo);
+
+
+        assertEquals("java:openejb/Resource/" + supplied.id, unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + goodMatch.id, unitInfo.nonJtaDataSource);
+    }
+
+    // ---
+
+    /**
+     * Existing data source "Orange", not jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     * </persistence-unit>
+     *
+     * The <non-jta-data-source> should be auto linked
+     * to the Orange data source
+     *
+     * We should generate a <jta-data-source> based on
+     * the <non-jta-data-source>
+     *
+     * @throws Exception
+     */
+    public void testEmptyUnitOneAvailableNonJtaDataSource() throws Exception {
+
+        ResourceInfo supplied = addDataSource("Orange", OrangeDriver.class, "jdbc:orange:some:stuff", false);
+
+        assertSame(supplied, resources.get(0));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", null, null);
+
+        assertNotNull(unitInfo);
+
+        ResourceInfo generated = resources.get(1);
+
+        assertEquals("java:openejb/Resource/" + generated.id, unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + supplied.id, unitInfo.nonJtaDataSource);
+
+
+        assertEquals(supplied.id + "Jta", generated.id);
+        assertEquals(supplied.service, generated.service);
+        assertEquals(supplied.className, generated.className);
+        assertEquals(supplied.properties.get("JdbcDriver"), generated.properties.get("JdbcDriver"));
+        assertEquals(supplied.properties.get("JdbcUrl"), generated.properties.get("JdbcUrl"));
+        assertEquals("true", generated.properties.get("JtaManaged"));
+    }
+
+    /**
+     * Existing data source "Orange", jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     * </persistence-unit>
+     *
+     * The <jta-data-source> should be auto linked
+     * to the Orange data source
+     *
+     * We should generate a <non-jta-data-source> based on
+     * the <jta-data-source>
+     *
+     * @throws Exception
+     */
+    public void testEmptyUnitOneAvailableJtaDataSource() throws Exception {
+
+        ResourceInfo supplied = addDataSource("Orange", OrangeDriver.class, "jdbc:orange:some:stuff", true);
+
+        assertSame(supplied, resources.get(0));
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", null, null);
+
+        assertNotNull(unitInfo);
+
+
+        ResourceInfo generated = resources.get(1);
+
+        assertEquals("java:openejb/Resource/" + supplied.id, unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + generated.id, unitInfo.nonJtaDataSource);
+
+
+        assertEquals(supplied.id + "NonJta", generated.id);
+        assertEquals(supplied.service, generated.service);
+        assertEquals(supplied.className, generated.className);
+        assertEquals(supplied.properties.get("JdbcDriver"), generated.properties.get("JdbcDriver"));
+        assertEquals(supplied.properties.get("JdbcUrl"), generated.properties.get("JdbcUrl"));
+        assertEquals("false", generated.properties.get("JtaManaged"));
+    }
+
+    // ---
+
+    /**
+     * Existing data source "Orange", not jta managed
+     *
+     * Persistence xml like so:
+     *
+     * <persistence-unit name="orange-unit">
+     * </persistence-unit>
+     *
+     * The <non-jta-data-source> should be auto linked
+     * to the Orange data source
+     *
+     * We should generate a <jta-data-source> based on
+     * the <non-jta-data-source>
+     *
+     * @throws Exception
+     */
+    public void testEmptyUnitNoAvailableDataSources() throws Exception {
+
+        assertEquals(0, resources.size());
+
+        PersistenceUnitInfo unitInfo = addPersistenceUnit("orange-unit", null, null);
+
+        assertNotNull(unitInfo);
+
+        ResourceInfo jta = resources.get(0);
+        ResourceInfo nonJta = resources.get(1);
+
+        assertEquals("Default JDBC Database", jta.id);
+        assertEquals("Default Unmanaged JDBC Database", nonJta.id);
+
+        assertEquals("java:openejb/Resource/" + jta.id, unitInfo.jtaDataSource);
+        assertEquals("java:openejb/Resource/" + nonJta.id, unitInfo.nonJtaDataSource);
+    }
+
+    // --------------------------------------------------------------------------------------------
+    //  Convenience methods
+    // --------------------------------------------------------------------------------------------
+
+    private PersistenceUnitInfo addPersistenceUnit(String unitName, String jtaDataSource, String nonJtaDataSource) throws OpenEJBException, IOException, NamingException {
+        PersistenceUnit unit = new PersistenceUnit(unitName);
+        unit.setJtaDataSource(jtaDataSource);
+        unit.setNonJtaDataSource(nonJtaDataSource);
+
+        AppModule app = new AppModule(this.getClass().getClassLoader(), unitName + "-app");
+        app.getPersistenceModules().add(new PersistenceModule("root", new Persistence(unit)));
+
+        // Create app
+
+        AppInfo appInfo = config.configureApplication(app);
+        assembler.createApplication(appInfo);
+
+        // Check results
+
+        return appInfo.persistenceUnits.get(0);
+    }
+
+    private ResourceInfo addDataSource(String id, Class driver, String url, Boolean managed) throws OpenEJBException {
+        Resource resource = new Resource(id, "DataSource");
+        resource.getProperties().put("JdbcDriver", driver.getName());
+        resource.getProperties().put("JdbcUrl", url);
+        resource.getProperties().put("JtaManaged", managed + "");
+
+        ResourceInfo resourceInfo = config.configureService(resource, ResourceInfo.class);
+
+        if (managed == null){
+            // Strip out the JtaManaged property so we can mimic
+            // datasources that we don't control
+            resourceInfo.properties.remove("JtaManaged");
+        }
+
+        assembler.createResource(resourceInfo);
+        return resourceInfo;
+    }
+
+    public static class Driver implements java.sql.Driver {
+        public boolean acceptsURL(String url) throws SQLException {
+            return false;
+        }
+
+        public Connection connect(String url, Properties info) throws SQLException {
+            return null;
+        }
+
+        public int getMajorVersion() {
+            return 0;
+        }
+
+        public int getMinorVersion() {
+            return 0;
+        }
+
+        public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
+            return new DriverPropertyInfo[0];
+        }
+
+        public boolean jdbcCompliant() {
+            return false;
+        }
+    }
+
+    public static class OrangeDriver extends Driver {}
+
+    public static class LimeDriver extends Driver {}
+}

Modified: openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/AutoConfigTest.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/AutoConfigTest.java?rev=633370&r1=633369&r2=633370&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/AutoConfigTest.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/AutoConfigTest.java Mon Mar  3 22:33:07 2008
@@ -21,9 +21,16 @@
 import javax.annotation.Resource;
 import java.util.Map;
 import java.util.HashMap;
+import java.util.Properties;
+import java.sql.SQLException;
+import java.sql.Connection;
+import java.sql.DriverPropertyInfo;
+import java.net.URL;
+import java.io.File;
 
 import org.apache.openejb.core.ivm.naming.InitContextFactory;
 import org.apache.openejb.config.ConfigurationFactory;
+import org.apache.openejb.config.sys.AbstractService;
 import org.apache.openejb.assembler.classic.Assembler;
 import org.apache.openejb.assembler.classic.ProxyFactoryInfo;
 import org.apache.openejb.assembler.classic.TransactionServiceInfo;
@@ -32,8 +39,14 @@
 import org.apache.openejb.assembler.classic.EjbJarInfo;
 import org.apache.openejb.assembler.classic.EnterpriseBeanInfo;
 import org.apache.openejb.assembler.classic.ResourceReferenceInfo;
+import org.apache.openejb.assembler.classic.AppInfo;
+import org.apache.openejb.assembler.classic.PersistenceUnitInfo;
+import org.apache.openejb.assembler.classic.OpenEjbConfiguration;
 import org.apache.openejb.jee.StatelessBean;
 import org.apache.openejb.jee.EjbJar;
+import org.apache.openejb.jee.jpa.unit.Persistence;
+import org.apache.openejb.jee.jpa.unit.PersistenceUnit;
+import org.apache.openejb.loader.SystemInstance;
 
 /**
  * @version $Revision$ $Date$
@@ -80,6 +93,83 @@
         assertNotNull(info);
         assertEquals("PurpleDataSource", info.resourceID);
 
+    }
+
+    public void testJtaDataSourceAutoCreate() throws Exception {
+
+        ConfigurationFactory config = new ConfigurationFactory();
+        Assembler assembler = new Assembler();
+
+        assembler.createProxyFactory(config.configureService(ProxyFactoryInfo.class));
+        assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class));
+        assembler.createSecurityService(config.configureService(SecurityServiceInfo.class));
+
+        AbstractService resource = new org.apache.openejb.config.sys.Resource("Orange", "DataSource");
+        resource.getProperties().put("JdbcDriver", OrangeDriver.class.getName());
+        resource.getProperties().put("JdbcUrl", "jdbc:orange:some:stuff");
+        resource.getProperties().put("JtaManaged", "false");
+
+        ResourceInfo nonJtaDataSource = config.configureService(resource, ResourceInfo.class);
+        assembler.createResource(nonJtaDataSource);
+
+        // Setup app
+
+        PersistenceUnit unit = new PersistenceUnit("orange-unit");
+        unit.setNonJtaDataSource("Orange");
+
+        AppModule app = new AppModule(this.getClass().getClassLoader(), "test");
+        app.getPersistenceModules().add(new PersistenceModule("root", new Persistence(unit)));
+
+        // Create app
+
+        AppInfo appInfo = config.configureApplication(app);
+        assembler.createApplication(appInfo);
+
+        // Check results
+
+        PersistenceUnitInfo unitInfo = appInfo.persistenceUnits.get(0);
+        assertNotNull(unitInfo);
+
+        assertEquals("java:openejb/Resource/"+nonJtaDataSource.id, unitInfo.nonJtaDataSource);
+
+        OpenEjbConfiguration configuration = SystemInstance.get().getComponent(OpenEjbConfiguration.class);
+
+        ResourceInfo jtaDataSource = configuration.facilities.resources.get(1);
+        assertNotNull(jtaDataSource);
+        assertEquals(nonJtaDataSource.id+"Jta", jtaDataSource.id);
+        assertEquals(nonJtaDataSource.service, jtaDataSource.service);
+        assertEquals(nonJtaDataSource.className, jtaDataSource.className);
+        assertEquals(nonJtaDataSource.properties.get("JdbcDriver"), jtaDataSource.properties.get("JdbcDriver"));
+        assertEquals(nonJtaDataSource.properties.get("JdbcUrl"), jtaDataSource.properties.get("JdbcUrl"));
+        assertEquals("true", jtaDataSource.properties.get("JtaManaged"));
+
+        fail("");
+    }
+
+    public static class OrangeDriver implements java.sql.Driver {
+        public boolean acceptsURL(String url) throws SQLException {
+            return false;
+        }
+
+        public Connection connect(String url, Properties info) throws SQLException {
+            return null;
+        }
+
+        public int getMajorVersion() {
+            return 0;
+        }
+
+        public int getMinorVersion() {
+            return 0;
+        }
+
+        public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
+            return new DriverPropertyInfo[0];
+        }
+
+        public boolean jdbcCompliant() {
+            return false;
+        }
     }
 
     public static interface Widget {