You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by hu...@apache.org on 2009/10/01 19:19:21 UTC

svn commit: r820722 [5/8] - in /incubator/aries/contrib: ./ ibm/ ibm/aries.image/ ibm/build/ ibm/build/buildtasks/ ibm/build/buildtasks/src/ ibm/build/buildtasks/src/com/ ibm/build/buildtasks/src/com/ibm/ ibm/build/buildtasks/src/com/ibm/aries/ ibm/bui...

Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/org/osgi/service/jpa/PersistenceUnitInfoService.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/org/osgi/service/jpa/PersistenceUnitInfoService.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/org/osgi/service/jpa/PersistenceUnitInfoService.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/org/osgi/service/jpa/PersistenceUnitInfoService.java Thu Oct  1 17:19:13 2009
@@ -0,0 +1,241 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package org.osgi.service.jpa;
+
+import java.net.URL;
+import java.util.Map;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * This interface exposes the information found or created by the JPA Extender when
+ * discovering persistence units. A service will be registered in the service
+ * registry for each persistence unit discovered.
+ */
+public interface PersistenceUnitInfoService {
+
+    /* ===============================================================
+     * Constants section
+     * ===============================================================
+     */
+    
+    /* =======================================================================
+     * The following constants are used as keys in the persistenceXmlMetadata
+     * Map and represent elements or attributes of a persistence unit in a
+     * persistence.xml file. If the elements were not specified in the
+     * persistence.xml file then the corresponding entries will not be present
+     * in the persistenceXmlMetadata Map.
+     * =======================================================================
+     */
+
+    /**
+     * The key used to store the schema version of the persistence.xml file.
+     * This entry should always be present and will always contain a value.
+     *
+     *   persistence.xml – <persistence version=...> attribute
+     *   value type - String
+     */
+    public static final String SCHEMA_VERSION =
+                                   "javax.persistence.schemaVersion";
+    
+    /**
+     * The key used to store the persistence unit name.
+     * This entry should always be present and will always contain a value.
+     *
+     *   persistence.xml – <persistence-unit name=...> attribute
+     *   value type - String
+     */
+    public static final String UNIT_NAME = "javax.persistence.unitName";
+    
+    /**
+     * The key used to store the transaction type.
+     *
+     *   persistence.xml – <persistence-unit transaction-type=...> attribute
+     *   value type - String
+     */
+    public static final String TRANSACTION_TYPE =
+                                 "javax.persistence.transactionType";
+
+    /**
+     * The key used to store the provider class name.
+     *
+     *   persistence.xml – <provider> element
+     *   value type - String
+     */
+    public static final String PROVIDER_CLASSNAME = "javax.persistence.provider";
+
+    /**
+     * The key used to store the JTA data source.
+     *
+     *   persistence.xml – <jta-data-source> element
+     *   value type - String
+     */
+    public static final String JTA_DATASOURCE = "javax.persistence.jtaDataSource";
+
+    /**
+     * The key used to store the non-JTA data source.
+     *
+     *   persistence.xml – <non-jta-data-source> element
+     *   value type - String
+     */
+    public static final String NON_JTA_DATASOURCE =
+                                 "javax.persistence.nonJtaDataSource";
+    
+    /**
+     * The key used to store the List of mapping file names.
+     *
+     *   persistence.xml – <mapping-file> elements
+     *   value type - List<String>
+     */
+    public static final String MAPPING_FILES = "javax.persistence.mappingFiles";
+    
+    /**
+     * The key used to store the List of jar file locations.
+     *
+     *   persistence.xml – <jar-file> elements
+     *   value type - List<URL>
+     */
+    public static final String JAR_FILES = "javax.persistence.jarFiles";
+    
+    /**
+     * The key used to store the List of managed class names.
+     * 
+     *   persistence.xml – <class> elements
+     *   value type - List<String>
+     */
+    public static final String MANAGED_CLASSES  =
+                                 "javax.persistence.managedClasses";
+    
+    /**
+     * The key used to store whether unlisted classes should be excluded.
+     * 
+     *   persistence.xml – <exclude-unlisted-classes> element
+     *   value type - Boolean
+     */
+    public static final String EXCLUDE_UNLISTED_CLASSES =
+                                 "javax.persistence.excludeUnlistedClasses";
+    
+    /**
+     * The key used to store the shared cache mode.
+     * 
+     *   persistence.xml – <shared-cache-mode> element
+     *   value type - String
+     */
+    public static final String SHARED_CACHE_MODE  =
+                                 "javax.persistence.sharedCacheMode";
+    
+    /**
+     * The key used to store the validation mode.
+     * 
+     *   persistence.xml – <validation-mode> element
+     *   value type - String
+     */
+    public static final String VALIDATION_MODE  =
+                                 "javax.persistence.validationMode";
+ 
+    /**
+     * The key used to store the persistence unit properties.
+     *
+     *   persistence.xml – <property> elements
+     *   value type - Properties
+     */
+    public static final String PROPERTIES = "javax.persistence.properties";
+    
+    /* ===============================================================
+     * The following constants are used as service property keys when
+     * registering this object as a service in the service registry.
+     * ===============================================================
+     */
+    
+    /**
+     * The service property key used to store the persistence unit name.
+     */
+    public static final String PERSISTENCE_UNIT_NAME =
+                                   "osgi.jpa.persistence.unit.name";
+    /**
+     * The service property key used to store the bundle symbolic name.
+     */
+    public static final String PERSISTENCE_BUNDLE_SYMBOLIC_NAME =
+                                   "osgi.jpa.persistence.bundle.name";
+    /**
+     * The service property key used to store the bundle version.
+     */
+    public static final String PERSISTENCE_BUNDLE_VERSION =
+                                   "osgi.jpa.persistence.bundle.version";
+    
+    /* ===============================================================
+     * The following properties are defined here for convenience.
+     * ===============================================================
+     */
+    
+    /**
+     * The key used to register the JPA provider version service property.
+     * It may also be used as a persistence.xml property key to specify a
+     * provider version range for the persistence unit.
+     */
+    public static final String JPA_PROVIDER_VERSION = "osgi.jpa.provider.version";
+    
+    
+    /* ===============================================================
+     * Methods section
+     * ===============================================================
+     */
+    
+    /**
+     * Expose the metadata for a particular persistence unit. The metadata is
+     * obtained by parsing the elements and attributes for the persistence unit
+     * defined in a persistence.xml file. Entries in the Map will have keys and
+     * values as defined by the constants above.  Changes to the returned Map
+     * will not be reflected in the original Map.
+     *
+     * @return A copy of the metadata Map
+     */
+    public Map<String, Object> getPersistenceXmlMetadata();
+    
+    /**
+     * A provider has been associated with this persistence unit, either because
+     * the provider was listed in the persistence.xml file, or was defaulted.
+     *
+     * @return A ServiceReference to the provider that is expected to service
+     *         this persistence unit
+     */
+    public ServiceReference getProviderReference();
+    
+    /**
+     * Return a URL that may use an OSGi-specific protocol. In order to pass the
+     * URL in a PersistenceUnitInfo, in a format the provider can use to stream
+     * over, the container may need to convert this URL to one which is file-based.
+     *
+     * @return A URL to the location of the persistence.xml file that defined this
+     * persistence unit
+     */
+    public URL getPersistenceXmlLocation();
+    
+    /**
+     * Return a URL that may use an OSGi-specific protocol. In order to pass the
+     * URL in a PersistenceUnitInfo, in a format the provider can use to stream
+     * over, the container may need to convert this URL to one which is file-based.
+     *
+     * @return A URL to the location of the persistence unit root
+     */
+    public URL getPersistenceUnitRoot();
+    
+    /**
+     * Provide a reference to the bundle in which the persistence unit was
+     * detected. The bundle may be a client bundle, or it may be a standalone
+     * persistence unit bundle.
+     *
+     * @return The bundle in which the persistence.xml file was detected
+     */
+    public Bundle getDefiningBundle();
+    
+    /**
+     * A classloader with visibility to the classes and resources in the bundle
+     * in which the persistence unit was detected.
+     *
+     * @return Classloader that can access persistence unit classes and resources
+     */
+    public ClassLoader getClassLoader();
+}
\ No newline at end of file

Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/com/ibm/osgi/jpa/test/ProviderFactoryTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/com/ibm/osgi/jpa/test/ProviderFactoryTest.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/com/ibm/osgi/jpa/test/ProviderFactoryTest.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/com/ibm/osgi/jpa/test/ProviderFactoryTest.java Thu Oct  1 17:19:13 2009
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.osgi.jpa.test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.net.MalformedURLException;
+
+import javax.persistence.spi.PersistenceProvider;
+
+import mocks.BundleContextMock;
+
+import org.junit.After;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+import com.ibm.aries.unittest.mocks.MethodCall;
+import com.ibm.aries.unittest.mocks.Skeleton;
+import com.ibm.osgi.jpa.provider.PersistenceProviderFactory;
+
+public class ProviderFactoryTest
+{
+  
+  @After
+  public void clearUp()
+  {
+    BundleContextMock.clear();
+  }
+
+  @Test
+  public void testGetService() throws MalformedURLException
+  {
+    BundleContext bc = Skeleton.newMock(new BundleContextMock(), BundleContext.class);
+    
+    Bundle providerBundle = ProviderManagerTest.getProviderBundle(bc);
+    
+    Skeleton.getSkeleton(providerBundle).setReturnValue(new MethodCall(Bundle.class, "loadClass", "no.such.Provider"), no.such.Provider.class);
+    
+    PersistenceProviderFactory factory = new PersistenceProviderFactory(providerBundle, "no.such.Provider");
+    
+    PersistenceProvider p = factory.getService(null, null);
+    
+    assertNotNull("No persistence provider returned", p);
+    
+    assertTrue("The provider was of the wrong implementation type", p instanceof no.such.Provider);
+    
+    PersistenceProvider p2 = factory.getService(null, null);
+    
+    assertSame("The two calls to getService did not return the same object",
+        p, p2);
+  }
+
+}

Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/com/ibm/osgi/jpa/test/ProviderManagerTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/com/ibm/osgi/jpa/test/ProviderManagerTest.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/com/ibm/osgi/jpa/test/ProviderManagerTest.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/com/ibm/osgi/jpa/test/ProviderManagerTest.java Thu Oct  1 17:19:13 2009
@@ -0,0 +1,137 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.osgi.jpa.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.net.MalformedURLException;
+
+import mocks.BundleContextMock;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+
+import com.ibm.aries.unittest.mocks.MethodCall;
+import com.ibm.aries.unittest.mocks.Skeleton;
+import com.ibm.osgi.jpa.provider.PersistenceProviderManager;
+
+
+public class ProviderManagerTest
+{
+
+  private static final String PROVIDER_CLASS_NAME = "no.such.Provider";
+  private PersistenceProviderManager manager;
+  private BundleContext bc;
+
+  /**
+   * Clear up the bundle context after the test.
+   */
+  @After
+  public void shutdown()
+  {
+    try {
+      manager.stop(bc);
+    } catch (Exception e) {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+    BundleContextMock.clear();
+  }
+  
+  /**
+   * Inject a bundle context into the JPAProvidersManagers
+   * @throws Exception
+   */
+  @Before
+  public void startup() throws Exception
+  {
+    manager = new PersistenceProviderManager();
+    bc = Skeleton.newMock(new BundleContextMock(), BundleContext.class);
+  }
+  
+  
+  @Test
+  public void testSpottingNewProviders() throws Exception
+  {
+    manager.start(bc);
+    
+    Bundle providerBundle = getProviderBundle(bc);
+    
+    BundleEvent be = new BundleEvent(BundleEvent.STARTING, providerBundle);
+    
+    BundleContextMock.assertNoServiceExists(PROVIDER_CLASS_NAME);
+    
+    manager.bundleChanged(be);
+    
+    BundleContextMock.assertServiceExists(PROVIDER_CLASS_NAME);
+  }
+  
+  @Test
+  public void testSpottingExistingProviders() throws Exception
+  {
+    
+    Bundle providerBundle = getProviderBundle(bc);
+ 
+    BundleContextMock bcMock =  (BundleContextMock) Skeleton.getSkeleton(bc).getTemplateObject();
+    
+    bcMock.addBundle(providerBundle);
+    
+    BundleContextMock.assertNoServiceExists(PROVIDER_CLASS_NAME);
+    
+    manager.start(bc);
+    
+    BundleContextMock.assertServiceExists(PROVIDER_CLASS_NAME);
+  }
+  
+  @Test
+  public void testNoMultipleRegistrations() throws Exception
+  {
+    testSpottingExistingProviders();
+    
+    manager.stop(bc);
+    
+    PersistenceProviderManager ppm = new PersistenceProviderManager();
+    
+    ServiceReference ref = Skeleton.newMock(ServiceReference.class);
+  
+    Skeleton skel = Skeleton.getSkeleton(bc.getBundles()[0]);
+    
+    skel.setReturnValue(new MethodCall(Bundle.class, "getRegisteredServices"), new ServiceReference[] {ref});
+ 
+    skel = Skeleton.getSkeleton(bc);
+    
+    skel.setReturnValue(new MethodCall(Filter.class, "match", ref), true);
+    
+    ppm.start(bc);
+    
+    assertEquals("Too many services were registered", 1, bc.getServiceReferences(PROVIDER_CLASS_NAME, null).length);
+    
+  }
+
+  protected static Bundle getProviderBundle(BundleContext bc) throws MalformedURLException
+  {
+    Bundle providerBundle = Skeleton.newMock(Bundle.class);
+    
+    Skeleton skel = Skeleton.getSkeleton(providerBundle);
+    
+    skel.setReturnValue(new MethodCall(Bundle.class, "getResource", "META-INF/services/javax.persistence.spi.PersistenceProvider"),
+        new File("unittest/resources/MockProvider/META-INF/services/javax.persistence.spi.PersistenceProvider").toURL());
+
+    skel.setReturnValue(new MethodCall(Bundle.class, "getVersion"), new Version("1.0.0"));
+    skel.setReturnValue(new MethodCall(Bundle.class, "getBundleContext"), bc);
+    skel.setReturnValue(new MethodCall(Bundle.class, "getState"), Bundle.ACTIVE);
+    return providerBundle;
+  }
+
+  
+  
+}

Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/com/ibm/osgi/jpa/unit/manager/test/PersistenceBundleLifecycleTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/com/ibm/osgi/jpa/unit/manager/test/PersistenceBundleLifecycleTest.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/com/ibm/osgi/jpa/unit/manager/test/PersistenceBundleLifecycleTest.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/com/ibm/osgi/jpa/unit/manager/test/PersistenceBundleLifecycleTest.java Thu Oct  1 17:19:13 2009
@@ -0,0 +1,996 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+
+
+package com.ibm.osgi.jpa.unit.manager.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.jar.Attributes;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+
+import javax.persistence.spi.PersistenceProvider;
+
+import mocks.BundleContextMock;
+import mocks.BundleMock;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.osgi.service.jpa.PersistenceUnitInfoService;
+
+import com.ibm.aries.unittest.mocks.MethodCall;
+import com.ibm.aries.unittest.mocks.Skeleton;
+import com.ibm.osgi.jpa.unit.PersistenceBundleManager;
+
+public class PersistenceBundleLifecycleTest
+{
+  private static final String FRAGMENT_SYM_NAME = "scooby.doo.jpa.fragment";
+  
+  private Bundle persistenceBundle;
+  
+  private Bundle providerBundleP100;
+  private Bundle providerBundleP101;
+  private Bundle providerBundleP110;
+  private Bundle providerBundleP111;
+  
+  private Bundle extenderBundle;
+  
+  @Before
+  public void setUp() throws Exception
+  {
+    persistenceBundle = Skeleton.newMock(new BundleMock("scooby.doo", new Hashtable<String, Object>()), Bundle.class);
+    
+    providerBundleP100 = Skeleton.newMock(new BundleMock("no.such.Provider", new Hashtable<String, Object>()), Bundle.class);
+    Skeleton skel = Skeleton.getSkeleton(providerBundleP100);
+    skel.setReturnValue(new MethodCall(Bundle.class, "getVersion"), new Version("1.0.0"));
+
+    providerBundleP101 = Skeleton.newMock(new BundleMock("no.such.Provider", new Hashtable<String, Object>()), Bundle.class);
+    skel = Skeleton.getSkeleton(providerBundleP101);
+    skel.setReturnValue(new MethodCall(Bundle.class, "getVersion"), new Version("1.0.1"));
+
+    providerBundleP110 = Skeleton.newMock(new BundleMock("no.such.Provider", new Hashtable<String, Object>()), Bundle.class);
+    skel = Skeleton.getSkeleton(providerBundleP110);
+    skel.setReturnValue(new MethodCall(Bundle.class, "getVersion"), new Version("1.1.0"));
+
+    providerBundleP111 = Skeleton.newMock(new BundleMock("no.such.Provider", new Hashtable<String, Object>()), Bundle.class);
+    skel = Skeleton.getSkeleton(providerBundleP111);
+    skel.setReturnValue(new MethodCall(Bundle.class, "getVersion"), new Version("1.1.1"));
+
+    extenderBundle = Skeleton.newMock(new BundleMock("extender", new Hashtable<String, Object>()), Bundle.class);
+    Skeleton.getSkeleton(extenderBundle).setReturnValue(new MethodCall(Bundle.class, "getResource", "schemas/persistence_1_0.xsd"), new File("unittest/resources/persistence_1_0.xsd").toURI().toURL());
+    persistenceBundle = Skeleton.newMock(new BundleMock("scooby.doo", new Hashtable<String, Object>()), Bundle.class);
+  }
+
+  @After
+  public void destroy() throws Exception
+  {
+    BundleContextMock.clear();
+  }
+  
+  @Test
+  public void testManagerStartOneExistingPersistenceBundleNoExistingProvider() throws Exception
+  {
+    //Check we don't register anything (the bundle was installed before we started)
+
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    Skeleton.getSkeleton(ctx).setReturnValue(
+        new MethodCall(BundleContext.class, "getBundles"),
+        new Bundle[] {persistenceBundle});
+    
+    setupPersistenceBundle("unittest/resources/file4/");
+    
+    mgr.start(ctx);
+    
+    BundleContextMock.assertNoServiceExists(PersistenceUnitInfoService.class.getName());
+    
+  }
+
+  @Test
+  public void testManagerStartOneExistingPersistenceBundleOneExistingProvider() throws Exception
+  {
+    //Check we don't register anything (the bundle was installed before we started)
+
+    PersistenceProvider pp = Skeleton.newMock(PersistenceProvider.class);
+    
+    Hashtable<String,String> hash1 = new Hashtable<String, String>();
+    persistenceBundle.getBundleContext().registerService(new String[] {PersistenceProvider.class.getName(), "no.such.Provider"} ,
+        pp, hash1 );
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    Skeleton.getSkeleton(ctx).setReturnValue(
+        new MethodCall(BundleContext.class, "getBundles"),
+        new Bundle[] {persistenceBundle});
+    
+    setupPersistenceBundle("unittest/resources/file4/");
+    
+    mgr.start(ctx);
+    
+    BundleContextMock.assertNoServiceExists(PersistenceUnitInfoService.class.getName());
+  }
+  
+  @Test
+  public void testManagerStopUnregistersUnits() throws Exception
+  {
+    PersistenceProvider pp = Skeleton.newMock(PersistenceProvider.class);
+    
+    Hashtable<String,String> hash1 = new Hashtable<String, String>();
+    persistenceBundle.getBundleContext().registerService(new String[] {PersistenceProvider.class.getName(), "no.such.Provider"} ,
+        pp, hash1 );
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file4/");
+    mgr.start(ctx);
+
+    testSuccessfulInstalledEvent(mgr, ctx, 1);
+    
+    mgr.stop(ctx);
+    
+    BundleContextMock.assertNoServiceExists(PersistenceUnitInfoService.class.getName());
+  }
+
+  @Test
+  public void testBundleChangedInstalledOnePreexistingProvider() throws Exception
+  {
+    //Check we correctly parse and register Persistence Units
+
+    PersistenceProvider pp = Skeleton.newMock(PersistenceProvider.class);
+    
+    Hashtable<String,String> hash1 = new Hashtable<String, String>();
+    persistenceBundle.getBundleContext().registerService(new String[] {PersistenceProvider.class.getName(), "no.such.Provider"} ,
+        pp, hash1 );
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file4/");
+    mgr.start(ctx);
+
+    testSuccessfulInstalledEvent(mgr, ctx, 1);
+  }
+  
+  @Test
+  public void testBundleChangedUninstalled() throws Exception
+  {
+    PersistenceProvider pp = Skeleton.newMock(PersistenceProvider.class);
+    
+    Hashtable<String,String> hash1 = new Hashtable<String, String>();
+    persistenceBundle.getBundleContext().registerService(new String[] {PersistenceProvider.class.getName(), "no.such.Provider"} ,
+        pp, hash1 );
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    Bundle fragment = Skeleton.newMock(Bundle.class);
+    
+    Skeleton.getSkeleton(ctx).setReturnValue(new MethodCall(BundleContext.class, "installBundle",
+        FRAGMENT_SYM_NAME, InputStream.class), fragment);
+    
+    setupPersistenceBundle("unittest/resources/file4/");
+    mgr.start(ctx);
+
+    testSuccessfulInstalledEvent(mgr, ctx, 1);
+    
+    mgr.bundleChanged(new BundleEvent(BundleEvent.UNINSTALLED, persistenceBundle));
+    
+    BundleContextMock.assertNoServiceExists(PersistenceUnitInfoService.class.getName());
+    
+    Skeleton.getSkeleton(fragment).assertCalled(new MethodCall(Bundle.class, "uninstall"));
+  }
+  
+  @Test
+  public void testBundleChangedUpdated() throws Exception
+  {
+    PersistenceProvider pp = Skeleton.newMock(PersistenceProvider.class);
+    
+    Hashtable<String,String> hash1 = new Hashtable<String, String>();
+    persistenceBundle.getBundleContext().registerService(new String[] {PersistenceProvider.class.getName(), "no.such.Provider"} ,
+        pp, hash1 );
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    Bundle fragment = Skeleton.newMock(Bundle.class);
+    
+    Skeleton.getSkeleton(ctx).setReturnValue(new MethodCall(BundleContext.class, "installBundle",
+        FRAGMENT_SYM_NAME, InputStream.class), fragment);
+    
+    setupPersistenceBundle("unittest/resources/file4/");
+    mgr.start(ctx);
+
+    testSuccessfulInstalledEvent(mgr, ctx, 1);
+    
+    Skeleton.getSkeleton(ctx).clearMethodCalls();
+    
+    mgr.bundleChanged(new BundleEvent(BundleEvent.UPDATED, persistenceBundle));
+    
+    BundleContextMock.assertServiceExists(PersistenceUnitInfoService.class.getName());
+    
+    ServiceReference[] refs = ctx.getServiceReferences(PersistenceUnitInfoService.class.getName(), null);
+    
+    assertEquals("Too many persistence units registered", 1, refs.length);
+    
+    Skeleton.getSkeleton(fragment).assertCalled(new MethodCall(Bundle.class, "uninstall"));
+    Skeleton.getSkeleton(ctx).assertCalled(new MethodCall(BundleContext.class, "installBundle",
+        FRAGMENT_SYM_NAME, InputStream.class));
+  }
+  
+  @Test
+  public void testBundleChangedUnresolved() throws Exception
+  {
+    PersistenceProvider pp = Skeleton.newMock(PersistenceProvider.class);
+    
+    Hashtable<String,String> hash1 = new Hashtable<String, String>();
+    persistenceBundle.getBundleContext().registerService(new String[] {PersistenceProvider.class.getName(), "no.such.Provider"} ,
+        pp, hash1 );
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    Bundle fragment = Skeleton.newMock(Bundle.class);
+    
+    Skeleton.getSkeleton(ctx).setReturnValue(new MethodCall(BundleContext.class, "installBundle",
+        FRAGMENT_SYM_NAME, InputStream.class), fragment);
+    
+    setupPersistenceBundle("unittest/resources/file4/");
+    mgr.start(ctx);
+
+    testSuccessfulInstalledEvent(mgr, ctx, 1);
+    
+    Skeleton.getSkeleton(ctx).clearMethodCalls();
+    
+    mgr.bundleChanged(new BundleEvent(BundleEvent.UNRESOLVED, persistenceBundle));
+    
+    BundleContextMock.assertServiceExists(PersistenceUnitInfoService.class.getName());
+    
+    ServiceReference[] refs = ctx.getServiceReferences(PersistenceUnitInfoService.class.getName(), null);
+    
+    assertEquals("Too many persistence units registered", 1, refs.length);
+    
+    Skeleton.getSkeleton(fragment).assertCalled(new MethodCall(Bundle.class, "uninstall"));
+    Skeleton.getSkeleton(ctx).assertCalled(new MethodCall(BundleContext.class, "installBundle",
+        FRAGMENT_SYM_NAME, InputStream.class));
+  }
+  
+  @Test
+  public void testBundleChangedInstalledOnePostRegisteredProvider() throws Exception
+  {
+    //Check we correctly parse and register Persistence Units
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file4/");
+    mgr.start(ctx);
+
+    BundleContextMock.assertNoServiceExists(PersistenceUnitInfoService.class.getName());
+
+    PersistenceProvider pp = Skeleton.newMock(PersistenceProvider.class);
+    
+    Hashtable<String,String> hash1 = new Hashtable<String, String>();
+    persistenceBundle.getBundleContext().registerService(new String[] {PersistenceProvider.class.getName(), "no.such.Provider"} ,
+        pp, hash1 );
+    
+    testSuccessfulInstalledEvent(mgr, ctx, 1);
+  }
+  
+  @Test
+  public void testBundleChangedInstalledNoProvider() throws Exception
+  {
+    //Check we correctly parse and register Persistence Units
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file4/");
+    mgr.start(ctx);
+
+    testUnsuccessfulInstalledEvent(mgr, ctx);
+  }
+  
+  @Test
+  public void testInstalledWithBadXML() throws Exception
+  {
+    //Check we correctly parse and register EMFactories
+
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file3/");
+    
+    mgr.start(ctx);
+    
+    testUnsuccessfulInstalledEvent(mgr, ctx);
+  }
+
+  
+  @Test
+  public void testBundleChangedStarting() throws Exception
+  {
+    //Check we correctly don't do anything on the started event
+
+    PersistenceProvider pp = Skeleton.newMock(PersistenceProvider.class);
+    
+    Hashtable<String,String> hash1 = new Hashtable<String, String>();
+    persistenceBundle.getBundleContext().registerService(new String[] {PersistenceProvider.class.getName(), "no.such.Provider"} ,
+        pp, hash1 );
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file4/");
+
+    mgr.start(ctx);
+    
+    testSuccessfulInstalledEvent(mgr, ctx, 1);
+    
+    mgr.bundleChanged(new BundleEvent(BundleEvent.STARTING, persistenceBundle));
+
+    BundleContextMock.assertServiceExists(PersistenceUnitInfoService.class.getName());
+    
+    ServiceReference[] refs = persistenceBundle.getBundleContext().getServiceReferences(PersistenceUnitInfoService.class.getName(), null);
+    
+    assertEquals("The wrong number of persistence units were registered", 1, refs.length);
+ 
+  }
+
+  @Test
+  public void testBundleChangedLazyActivation() throws Exception
+  {
+  //Check we correctly don't do anything on the LAZY event
+
+    PersistenceProvider pp = Skeleton.newMock(PersistenceProvider.class);
+    
+    Hashtable<String,String> hash1 = new Hashtable<String, String>();
+    persistenceBundle.getBundleContext().registerService(new String[] {PersistenceProvider.class.getName(), "no.such.Provider"} ,
+        pp, hash1 );
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file4/");
+
+    mgr.start(ctx);
+    
+    testSuccessfulInstalledEvent(mgr, ctx, 1);
+    
+    mgr.bundleChanged(new BundleEvent(BundleEvent.LAZY_ACTIVATION, persistenceBundle));
+
+    BundleContextMock.assertServiceExists(PersistenceUnitInfoService.class.getName());
+    
+    ServiceReference[] refs = persistenceBundle.getBundleContext().getServiceReferences(PersistenceUnitInfoService.class.getName(), null);
+    
+    assertEquals("The wrong number of persistence units were registered", 1, refs.length);
+   }
+    
+  @Test
+  public void testNoProviderInstalled() throws Exception
+  {
+    //Check we do not register a service when there is no Provider
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file5/");
+    
+    mgr.start(ctx);
+    
+    testUnsuccessfulInstalledEvent(mgr, ctx);
+  }
+
+  @Test
+  public void testdefaultProvider() throws Exception
+  {
+    //Check we correctly parse and register EMFactories
+
+    PersistenceProvider pp = Skeleton.newMock(PersistenceProvider.class);
+    
+    Hashtable<String,String> hash1 = new Hashtable<String, String>();
+    persistenceBundle.getBundleContext().registerService(new String[] {PersistenceBundleManager.DEFAULT_JPA_PROVIDER} ,
+        pp, hash1 );
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file5/");
+    
+    mgr.start(ctx);
+    
+    testSuccessfulInstalledEvent(mgr, ctx, 1);
+
+  }
+  
+  @Test
+  public void testdefaultProviderWithWAR() throws Exception
+  {
+    //Check we correctly parse and register EMFactories
+
+    PersistenceProvider pp = Skeleton.newMock(PersistenceProvider.class);
+    
+    Hashtable<String,String> hash1 = new Hashtable<String, String>();
+    persistenceBundle.getBundleContext().registerService(new String[] {PersistenceBundleManager.DEFAULT_JPA_PROVIDER} ,
+        pp, hash1 );
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    Skeleton skel = Skeleton.getSkeleton(persistenceBundle);
+    
+    skel.setReturnValue(new MethodCall(Bundle.class, "getState"), Bundle.ACTIVE);
+    
+    URL root = new File("unittest/resources/file5/").toURI().toURL();
+    URL xml = new File("unittest/resources/file5/META-INF/persistence.xml").toURI().toURL();
+    
+    skel.setReturnValue(new MethodCall(Bundle.class, "getEntry", "WEB-INF/classes/"), root);
+    skel.setReturnValue(new MethodCall(Bundle.class, "getEntry", "WEB-INF/classes/META-INF/persistence.xml"), xml);
+    skel.setReturnValue(new MethodCall(Bundle.class, "getVersion"), new Version("0.0.0"));
+
+    mgr.start(ctx);
+    
+    testSuccessfulInstalledEvent(mgr, ctx, 1);
+  }
+
+  @Test
+  public void testdefaultProviderWithWARLib() throws Exception
+  {
+    //Check we correctly parse and register EMFactories
+
+    PersistenceProvider pp = Skeleton.newMock(PersistenceProvider.class);
+    
+    Hashtable<String,String> hash1 = new Hashtable<String, String>();
+    persistenceBundle.getBundleContext().registerService(new String[] {PersistenceBundleManager.DEFAULT_JPA_PROVIDER} ,
+        pp, hash1 );
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    Skeleton skel = Skeleton.getSkeleton(persistenceBundle);
+    
+    skel.setReturnValue(new MethodCall(Bundle.class, "getState"), Bundle.ACTIVE);
+    
+    Vector<String> v = new Vector<String>();
+      v.add("WEB-INF/lib/jarfile.jar");
+    
+    skel.setReturnValue(new MethodCall(Bundle.class, "getEntryPaths", "WEB-INF/lib"), v.elements());
+    skel.setReturnValue(new MethodCall(Bundle.class, "getVersion"), new Version("0.0.0"));
+    skel.setReturnValue(new MethodCall(Bundle.class, "getEntry", "WEB-INF/lib/jarfile.jar"), new File("unittest/resources/jarfile.jar").toURI().toURL());
+
+    mgr.start(ctx);
+    
+    testSuccessfulInstalledEvent(mgr, ctx, 1);
+  }
+  
+  @Test
+  public void testdefaultProviderWithBundledJar() throws Exception
+  {
+    //Check we correctly parse and register EMFactories
+
+    PersistenceProvider pp = Skeleton.newMock(PersistenceProvider.class);
+    
+    Hashtable<String,String> hash1 = new Hashtable<String, String>();
+    persistenceBundle.getBundleContext().registerService(new String[] {PersistenceBundleManager.DEFAULT_JPA_PROVIDER} ,
+        pp, hash1 );
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    Skeleton skel = Skeleton.getSkeleton(persistenceBundle);
+    
+    skel.setReturnValue(new MethodCall(Bundle.class, "getState"), Bundle.ACTIVE);
+    
+    URL u = new File("unittest/resources/jarfile.jar").toURI().toURL();
+    
+    skel.setReturnValue(new MethodCall(Bundle.class, "getEntry", "unittest/resources/jarfile.jar"), u);
+    skel.setReturnValue(new MethodCall(Bundle.class, "getVersion"), new Version("0.0.0"));
+    persistenceBundle.getHeaders().put(Constants.BUNDLE_CLASSPATH, "., unittest/resources/jarfile.jar");
+
+    mgr.start(ctx);
+    
+    testSuccessfulInstalledEvent(mgr, ctx, 1);
+
+  }
+  
+  @Test
+  public void testSameProviders() throws Exception
+  {
+    //Check we behave correctly when two persistence units define the same
+    //provder name
+
+    PersistenceProvider pp = Skeleton.newMock(PersistenceProvider.class);
+    
+    Hashtable<String,String> hash1 = new Hashtable<String, String>();
+    persistenceBundle.getBundleContext().registerService(new String[] {PersistenceProvider.class.getName(), "no.such.Provider"} ,
+        pp, hash1 );
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file6/");
+    
+    mgr.start(ctx);
+    
+    testSuccessfulInstalledEvent(mgr, ctx, 2);
+  }
+
+  @Test
+  public void testOneWithProviderOneWithout() throws Exception
+  {
+    //Check we behave correctly when two persistence units define different
+    //provder names
+
+    PersistenceProvider pp = Skeleton.newMock(PersistenceProvider.class);
+    
+    Hashtable<String,String> hash1 = new Hashtable<String, String>();
+    persistenceBundle.getBundleContext().registerService(new String[] {PersistenceProvider.class.getName(), "no.such.Provider"} ,
+        pp, hash1 );
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file7/");
+    
+    mgr.start(ctx);
+    
+    BundleContextMock.assertNoServiceExists(PersistenceUnitInfoService.class.getName());
+    
+    mgr.bundleChanged(new BundleEvent(BundleEvent.INSTALLED, persistenceBundle));
+    
+    BundleContextMock.assertServiceExists(PersistenceUnitInfoService.class.getName());
+    
+    ServiceReference[] refs = persistenceBundle.getBundleContext().getServiceReferences(
+        PersistenceUnitInfoService.class.getName(), null);
+       
+    assertEquals("The wrong number of EMFs were registered", 2, refs.length);
+    
+    Skeleton.getSkeleton(ctx).assertCalled(new MethodCall(BundleContext.class, "installBundle",
+        FRAGMENT_SYM_NAME, InputStream.class));
+  }
+
+  @Test
+  public void testTwoProviders() throws Exception
+  {
+    //Check we correctly parse and register EMFactories
+
+    PersistenceProvider pp = Skeleton.newMock(PersistenceProvider.class);
+    
+    Hashtable<String,String> hash1 = new Hashtable<String, String>();
+    persistenceBundle.getBundleContext().registerService(new String[] {PersistenceProvider.class.getName(), "no.such.Provider"} ,
+        pp, hash1 );
+    
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    Skeleton skel = Skeleton.getSkeleton(persistenceBundle);
+    
+    skel.setReturnValue(new MethodCall(Bundle.class, "getState"), Bundle.ACTIVE);
+    
+    Vector<URL> v = new Vector<URL>();
+    v.add(new File("unittest/resources/file8/META-INF/persistence.xml").toURI().toURL());
+    
+    skel.setReturnValue(new MethodCall(Bundle.class, "findEntries", "/", "persistence.xml", true), v.elements());
+    skel.setReturnValue(new MethodCall(Bundle.class, "getVersion"), new Version("0.0.0"));
+    
+    mgr.start(ctx);
+    
+    BundleContextMock.assertNoServiceExists(PersistenceUnitInfoService.class.getName());
+    
+    mgr.bundleChanged(new BundleEvent(BundleEvent.INSTALLED, persistenceBundle));
+    
+    BundleContextMock.assertNoServiceExists(PersistenceUnitInfoService.class.getName());
+    
+    Skeleton.getSkeleton(ctx).assertNotCalled(new MethodCall(BundleContext.class, "installBundle",
+        FRAGMENT_SYM_NAME, InputStream.class));
+  }
+  
+  @Test
+  public void testpp100() throws Exception
+  {
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+     
+    PersistenceProvider pp100 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp101 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp110 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp111 = Skeleton.newMock(PersistenceProvider.class);
+    
+    registerVersionedPersistenceProviders(pp100, pp101, pp110, pp111);
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file9/");
+
+    assertCorrectPersistenceProviderUsed(mgr, ctx, pp100);
+  }
+
+  @Test
+  public void testpp101() throws Exception
+  {
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    PersistenceProvider pp100 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp101 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp110 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp111 = Skeleton.newMock(PersistenceProvider.class);
+    
+    registerVersionedPersistenceProviders(pp100, pp101, pp110, pp111);
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file10/");
+    
+    mgr.start(ctx);
+    
+    assertCorrectPersistenceProviderUsed(mgr, ctx, pp101);
+  }
+  
+  @Test
+  public void testpp101b() throws Exception
+  {
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    PersistenceProvider pp100 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp101 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp110 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp111 = Skeleton.newMock(PersistenceProvider.class);
+    
+    registerVersionedPersistenceProviders(pp100, pp101, pp110, pp111);
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file11/");
+
+    assertCorrectPersistenceProviderUsed(mgr, ctx, pp101);
+
+  }
+
+  @Test
+  public void testpp111() throws Exception
+  {
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    PersistenceProvider pp100 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp101 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp110 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp111 = Skeleton.newMock(PersistenceProvider.class);
+    
+    registerVersionedPersistenceProviders(pp100, pp101, pp110, pp111);
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file12/");
+
+    assertCorrectPersistenceProviderUsed(mgr, ctx, pp111);
+  }
+
+  @Test
+  public void testppNoMatch() throws Exception
+  {
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    PersistenceProvider pp100 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp101 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp110 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp111 = Skeleton.newMock(PersistenceProvider.class);
+    
+    registerVersionedPersistenceProviders(pp100, pp101, pp110, pp111);
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file13/");
+    
+    mgr.start(ctx);
+    
+    testUnsuccessfulInstalledEvent(mgr,ctx);
+    
+  }
+
+  @Test
+  public void testTwoProvidersMatch() throws Exception
+  {
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    PersistenceProvider pp100 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp101 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp110 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp111 = Skeleton.newMock(PersistenceProvider.class);
+    
+    registerVersionedPersistenceProviders(pp100, pp101, pp110, pp111);
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file14/");
+    
+    mgr.start(ctx);
+    assertCorrectPersistenceProviderUsed(mgr, ctx, pp101);
+  }
+
+  @Test
+  public void testTwoProvidersNoVersionMatch() throws Exception
+  {
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    PersistenceProvider pp100 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp101 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp110 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp111 = Skeleton.newMock(PersistenceProvider.class);
+    
+    registerVersionedPersistenceProviders(pp100, pp101, pp110, pp111);
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file15/");
+    
+    mgr.start(ctx);
+    
+    testUnsuccessfulInstalledEvent(mgr,ctx);
+    
+  }
+
+  @Test
+  public void testTwoProvidersExistNoCommonVersion() throws Exception
+  {
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    PersistenceProvider pp100 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp101 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp110 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp111 = Skeleton.newMock(PersistenceProvider.class);
+    
+    registerVersionedPersistenceProviders(pp100, pp101, pp110, pp111);
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file17/");
+    
+    mgr.start(ctx);
+    
+    testUnsuccessfulInstalledEvent(mgr,ctx);
+    
+  }
+  
+  @Test
+  public void testThreeProvidersNoVersionMatch() throws Exception
+  {
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    PersistenceProvider pp100 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp101 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp110 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp111 = Skeleton.newMock(PersistenceProvider.class);
+    
+    registerVersionedPersistenceProviders(pp100, pp101, pp110, pp111);
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file16/");
+   
+    mgr.start(ctx);
+    
+    testUnsuccessfulInstalledEvent(mgr,ctx);
+    
+  }
+
+  @Test
+  public void testTwoProvidersNoVersionMatchOneExists() throws Exception
+  {
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    PersistenceProvider pp100 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp101 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp110 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp111 = Skeleton.newMock(PersistenceProvider.class);
+    
+    registerVersionedPersistenceProviders(pp100, pp101, pp110, pp111);
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    setupPersistenceBundle("unittest/resources/file18/");
+
+    mgr.start(ctx);
+    
+    testUnsuccessfulInstalledEvent(mgr,ctx);
+  }
+
+  @Test
+  public void testThreeProvidersNoVersionMatchOneExists() throws Exception
+  {
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    PersistenceProvider pp100 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp101 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp110 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp111 = Skeleton.newMock(PersistenceProvider.class);
+    
+    registerVersionedPersistenceProviders(pp100, pp101, pp110, pp111);
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    Skeleton skel = Skeleton.getSkeleton(persistenceBundle);
+    
+    skel.setReturnValue(new MethodCall(Bundle.class, "getState"), Bundle.ACTIVE);
+    
+    setupPersistenceBundle("unittest/resources/file19/");
+
+    mgr.start(ctx);
+    
+    testUnsuccessfulInstalledEvent(mgr,ctx);
+    
+  }
+
+  @Test
+  public void testThreeProvidersNoVersionMatchTwoExist() throws Exception
+  {
+    PersistenceBundleManager mgr = new PersistenceBundleManager();
+    
+    PersistenceProvider pp100 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp101 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp110 = Skeleton.newMock(PersistenceProvider.class);
+    PersistenceProvider pp111 = Skeleton.newMock(PersistenceProvider.class);
+    
+    registerVersionedPersistenceProviders(pp100, pp101, pp110, pp111);
+    
+    BundleContext ctx = extenderBundle.getBundleContext();
+    
+    Skeleton skel = Skeleton.getSkeleton(persistenceBundle);
+    
+    skel.setReturnValue(new MethodCall(Bundle.class, "getState"), Bundle.ACTIVE);
+    
+    setupPersistenceBundle("unittest/resources/file20/");
+
+    mgr.start(ctx);
+
+    testUnsuccessfulInstalledEvent(mgr, ctx);
+  }
+ 
+  private void setupPersistenceBundle(String s) throws MalformedURLException
+  {
+    Skeleton skel = Skeleton.getSkeleton(persistenceBundle);
+    
+    skel.setReturnValue(new MethodCall(Bundle.class, "getState"), Bundle.ACTIVE);
+    
+    URL root = new File(s).toURI().toURL();
+    
+    URL xml = new File(s + "META-INF/persistence.xml").toURI().toURL();
+    
+    skel.setReturnValue(new MethodCall(Bundle.class, "getEntry", "/"), root);
+    skel.setReturnValue(new MethodCall(Bundle.class, "getEntry", "/META-INF/persistence.xml"), xml);
+    skel.setReturnValue(new MethodCall(Bundle.class, "getVersion"), new Version("0.0.0"));
+
+  }
+  
+  private void registerVersionedPersistenceProviders(PersistenceProvider pp100,
+      PersistenceProvider pp101, PersistenceProvider pp110,
+      PersistenceProvider pp111) {
+    Hashtable<String,String> hash1 = new Hashtable<String, String>();
+    hash1.put("osgi.jpa.provider.version", "1.0.0");
+    providerBundleP100.getBundleContext().registerService(new String[] {PersistenceProvider.class.getName(), "no.such.Provider"} ,
+        pp100, hash1 );
+    
+    hash1 = new Hashtable<String, String>();
+    hash1.put("osgi.jpa.provider.version", "1.0.1");
+    providerBundleP101.getBundleContext().registerService(new String[] {PersistenceProvider.class.getName(), "no.such.Provider"} ,
+        pp101, hash1 );
+    
+    hash1 = new Hashtable<String, String>();
+    hash1.put("osgi.jpa.provider.version", "1.1.0");
+    providerBundleP110.getBundleContext().registerService(new String[] {PersistenceProvider.class.getName(), "no.such.Provider"} ,
+        pp110, hash1 );
+    
+    hash1 = new Hashtable<String, String>();
+    hash1.put("osgi.jpa.provider.version", "1.1.1");
+    providerBundleP111.getBundleContext().registerService(new String[] {PersistenceProvider.class.getName(), "no.such.Provider"} ,
+        pp111, hash1 );
+  }
+  
+
+  private void testSuccessfulInstalledEvent(PersistenceBundleManager mgr, BundleContext ctx, int numberOfPersistenceUnits) throws InvalidSyntaxException
+  {
+    BundleContextMock.assertNoServiceExists(PersistenceUnitInfoService.class.getName());
+    
+    mgr.bundleChanged(new BundleEvent(BundleEvent.INSTALLED, persistenceBundle));
+    
+    BundleContextMock.assertServiceExists(PersistenceUnitInfoService.class.getName());
+    
+    ServiceReference[] refs = persistenceBundle.getBundleContext().getServiceReferences(PersistenceUnitInfoService.class.getName(), null);
+    
+    assertEquals("The wrong number of persistence units were registered", numberOfPersistenceUnits, refs.length);
+    
+    for(ServiceReference ref : refs) {
+      assertEquals("Incorrect properties registerered", "scooby.doo", ref.getProperty(PersistenceUnitInfoService.PERSISTENCE_BUNDLE_SYMBOLIC_NAME));
+      assertEquals("Incorrect properties registerered", Version.emptyVersion, ref.getProperty(PersistenceUnitInfoService.PERSISTENCE_BUNDLE_VERSION));
+      assertNotNull("Incorrect properties registerered", ref.getProperty(PersistenceUnitInfoService.PERSISTENCE_UNIT_NAME));
+    }
+    
+    Skeleton.getSkeleton(ctx).assertCalled(new MethodCall(BundleContext.class, "installBundle",
+        FRAGMENT_SYM_NAME, InputStream.class));
+  }
+  
+  private void testUnsuccessfulInstalledEvent(PersistenceBundleManager mgr, BundleContext ctx)
+  {
+    BundleContextMock.assertNoServiceExists(PersistenceUnitInfoService.class.getName());
+    
+    mgr.bundleChanged(new BundleEvent(BundleEvent.INSTALLED, persistenceBundle));
+    
+    BundleContextMock.assertNoServiceExists(PersistenceUnitInfoService.class.getName());
+    
+    Skeleton.getSkeleton(ctx).assertNotCalled(new MethodCall(BundleContext.class, "installBundle",
+        String.class, InputStream.class));
+  }
+  
+  private void assertCorrectPersistenceProviderUsed (PersistenceBundleManager mgr, BundleContext ctx, PersistenceProvider provider)
+  {
+    try {
+      mgr.start(ctx);
+      
+      BundleContextMock.assertNoServiceExists(PersistenceUnitInfoService.class.getName());
+      
+      mgr.bundleChanged(new BundleEvent(BundleEvent.INSTALLED, persistenceBundle));
+      
+      BundleContextMock.assertServiceExists(PersistenceUnitInfoService.class.getName());
+      ServiceReference[] refs = persistenceBundle.getBundleContext().getServiceReferences(PersistenceUnitInfoService.class.getName(), null);
+    
+      for(ServiceReference ref : refs) {
+        PersistenceUnitInfoService pu = (PersistenceUnitInfoService) persistenceBundle.getBundleContext().getService(ref);
+    
+        assertNotNull("No PersistenceUnit was registered", pu);
+    
+        Object pp = persistenceBundle.getBundleContext().getService(pu.getProviderReference());
+    
+        assertSame("The perstistnce unit was associated with the wrong persistence provider",
+        pp, provider);
+      }
+      
+      Skeleton.getSkeleton(ctx).assertCalled(new MethodCall(BundleContext.class, "installBundle",
+          FRAGMENT_SYM_NAME, InputStream.class));
+      
+    } catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+}
+

Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/com/ibm/osgi/jpa/unit/manager/test/PersistenceXMLParsingTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/com/ibm/osgi/jpa/unit/manager/test/PersistenceXMLParsingTest.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/com/ibm/osgi/jpa/unit/manager/test/PersistenceXMLParsingTest.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/com/ibm/osgi/jpa/unit/manager/test/PersistenceXMLParsingTest.java Thu Oct  1 17:19:13 2009
@@ -0,0 +1,338 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.osgi.jpa.unit.manager.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Properties;
+
+import javax.persistence.spi.PersistenceUnitTransactionType;
+import javax.xml.XMLConstants;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+
+import mocks.BundleContextMock;
+import mocks.BundleMock;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.service.jpa.PersistenceUnitInfoService;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import com.ibm.aries.unittest.mocks.Skeleton;
+import com.ibm.osgi.jpa.unit.parsing.JPAHandler;
+import com.ibm.osgi.jpa.util.PersistenceLocationData;
+
+
+public class PersistenceXMLParsingTest
+{
+
+  private Bundle persistenceBundle;
+  private SAXParser parser;
+  
+  @Before
+  public void init() throws MalformedURLException, SAXException, ParserConfigurationException
+  {
+    
+    persistenceBundle = Skeleton.newMock(new BundleMock("scooby.doo", new Hashtable<String, Object>()), Bundle.class);
+    
+    Skeleton skel = Skeleton.getSkeleton(persistenceBundle);
+    
+    SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+
+    SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+
+    Schema s = schemaFactory.newSchema(new URL("http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"));
+
+    parserFactory.setSchema(s);
+    parserFactory.setNamespaceAware(true);
+
+    parser = parserFactory.newSAXParser();
+
+  }
+  
+  @After
+  public void destroy()
+  {
+    BundleContextMock.clear();
+  }
+  
+  @Test
+  public void testFile1() throws Exception
+  {
+    InputStream is = null;
+    
+    try {
+      
+      URL xml = new File("unittest/resources/file1/META-INF/persistence.xml").toURI().toURL();
+      is = xml.openStream();
+      
+      URL root = new File("unittest/resources/file1").toURI().toURL();
+    
+      JPAHandler handler = new JPAHandler(new PersistenceLocationData(xml, root, persistenceBundle), "1.0");
+      parser.parse(is, handler);
+      
+      Collection<? extends PersistenceUnitInfoService> puinfos = handler.getPersistenceUnits();
+      assertEquals("An incorrect number of persistence units has been returned.", 4, puinfos.size());
+      
+      List<PersistenceUnitInfoService> units = getList(puinfos);
+      
+      PersistenceUnitInfoService unit = units.get(0);
+      
+      assertEquals("The schema version was incorrect", "1.0",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.SCHEMA_VERSION));
+      assertEquals("The unit name was incorrect", "alpha",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.UNIT_NAME));
+      assertNull("The transaction type was incorrect",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.TRANSACTION_TYPE));
+      assertNull("The provider class name was incorrect",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.PROVIDER_CLASSNAME));
+      assertNull("The jta datasource jndi name was wrong",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.JTA_DATASOURCE));
+      assertNull("The non jta datasource jndi name was wrong",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.NON_JTA_DATASOURCE));
+      assertNull("One or more mapping files were specified",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.MAPPING_FILES));
+      assertNull("One or more jar files were specified",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.JAR_FILES));
+      assertNull("One or more managed classes were specified",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.MANAGED_CLASSES));
+      assertNull("We should not exclude any classes",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.EXCLUDE_UNLISTED_CLASSES));
+      assertNull("The properties should never be null",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.PROPERTIES));
+      assertNotNull("The persistence.xml location was not specified", unit.getPersistenceXmlLocation());
+      assertEquals("The persistence.xml location points at the wrong file",
+          new File("unittest/resources/file1/META-INF/persistence.xml").toURI().toURL().toExternalForm(),
+          unit.getPersistenceXmlLocation().toExternalForm());
+      assertNotNull("The persistence root location was not specified", unit.getPersistenceUnitRoot());
+      assertEquals("The persistence root points at the wrong place",
+          new File("unittest/resources/file1").toURI().toURL().toExternalForm(),
+          unit.getPersistenceUnitRoot().toExternalForm());
+      assertSame("The persistence unit was associated with the wrong bundle", persistenceBundle, unit.getDefiningBundle());
+      
+
+      unit = units.get(1);
+      
+      assertEquals("The schema version was incorrect", "1.0",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.SCHEMA_VERSION));
+      assertEquals("The unit name was incorrect", "bravo",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.UNIT_NAME));
+      assertEquals("The transaction type was incorrect", PersistenceUnitTransactionType.JTA,
+          PersistenceUnitTransactionType.valueOf((String)unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.TRANSACTION_TYPE)));
+      assertEquals("The provider class name was incorrect", "bravo.persistence.provider",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.PROVIDER_CLASSNAME));
+      assertEquals("The jta datasource jndi name was wrong", "bravo/jtaDS",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.JTA_DATASOURCE));
+      assertEquals("The non jta datasource jndi name was wrong", "bravo/nonJtaDS",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.NON_JTA_DATASOURCE));
+      assertEquals("An incorrect number of mapping files were specified", 2,
+          ((Collection)unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.MAPPING_FILES)).size());
+      assertTrue("Incorrect mapping files were listed",
+          ((Collection)unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.MAPPING_FILES)).contains("bravoMappingFile1.xml")
+          && ((Collection)unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.MAPPING_FILES)).contains("bravoMappingFile2.xml"));
+      assertEquals("An incorrect number of jar files were specified", 2,
+          ((Collection)unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.JAR_FILES)).size());
+      assertTrue("Incorrect jar URLs were listed", checkJARURLs((Collection<String>)unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.JAR_FILES)));
+          
+      assertEquals("An incorrect number of managed classes were specified", 2,
+          ((Collection)unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.MANAGED_CLASSES)).size());
+      assertTrue("Incorrect managed classes were listed",
+          ((Collection)unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.MANAGED_CLASSES)).contains("bravoClass1")
+          && ((Collection)unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.MANAGED_CLASSES)).contains("bravoClass2"));
+      
+      //In the schema this defaults to false. There is a separate test (testFile1b)
+      //for the spec behaviour, which defaults to true
+      assertFalse("We should exclude any classes not listed",
+          (Boolean)unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.EXCLUDE_UNLISTED_CLASSES));
+      assertNotNull("The properties should never be null",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.PROPERTIES));
+      assertEquals("The wrong number of properties were specified", 2,
+          ((Properties)unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.PROPERTIES)).size());
+      assertEquals("The property had the wrong value", "prop.value",
+          ((Properties)unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.PROPERTIES)).getProperty("some.prop"));
+      assertEquals("The property had the wrong value", "another.prop.value",
+          ((Properties)unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.PROPERTIES)).getProperty("some.other.prop"));
+      assertNotNull("The persistence.xml location was not specified", unit.getPersistenceXmlLocation());
+      assertEquals("The persistence.xml location points at the wrong file",
+          new File("unittest/resources/file1/META-INF/persistence.xml").toURI().toURL().toExternalForm(),
+          unit.getPersistenceXmlLocation().toExternalForm());
+      assertNotNull("The persistence root location was not specified", unit.getPersistenceUnitRoot());
+      assertEquals("The persistence root points at the wrong place",
+          new File("unittest/resources/file1").toURI().toURL().toExternalForm(),
+          unit.getPersistenceUnitRoot().toExternalForm());
+      assertSame("The persistence unit was associated with the wrong bundle", persistenceBundle, unit.getDefiningBundle());
+      
+      
+      unit = units.get(2);
+      
+      assertEquals("The schema version was incorrect", "1.0",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.SCHEMA_VERSION));
+      assertEquals("The unit name was incorrect", "charlie",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.UNIT_NAME));
+      assertEquals("The transaction type was incorrect", PersistenceUnitTransactionType.RESOURCE_LOCAL,
+          PersistenceUnitTransactionType.valueOf((String)unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.TRANSACTION_TYPE)));
+      assertEquals("The provider class name was incorrect", "charlie.persistence.provider",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.PROVIDER_CLASSNAME));
+      assertNull("The jta datasource jndi name was wrong",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.JTA_DATASOURCE));
+      assertNull("The non jta datasource jndi name was wrong",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.NON_JTA_DATASOURCE));
+      assertNull("One or more mapping files were specified",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.MAPPING_FILES));
+      assertNull("One or more jar files were specified",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.JAR_FILES));
+      assertNull("One or more managed classes were specified",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.MANAGED_CLASSES));
+      assertTrue("We should not exclude any classes",
+          (Boolean)unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.EXCLUDE_UNLISTED_CLASSES));
+     assertNull("The properties should never be null",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.PROPERTIES));
+      assertNotNull("The persistence.xml location was not specified", unit.getPersistenceXmlLocation());
+      assertEquals("The persistence.xml location points at the wrong file",
+          new File("unittest/resources/file1/META-INF/persistence.xml").toURI().toURL().toExternalForm(),
+          unit.getPersistenceXmlLocation().toExternalForm());
+      assertNotNull("The persistence root location was not specified", unit.getPersistenceUnitRoot());
+      assertEquals("The persistence root points at the wrong place",
+          new File("unittest/resources/file1").toURI().toURL().toExternalForm(),
+          unit.getPersistenceUnitRoot().toExternalForm());
+      assertSame("The persistence unit was associated with the wrong bundle", persistenceBundle, unit.getDefiningBundle());
+      
+      
+      unit = units.get(3);
+      
+      assertEquals("The schema version was incorrect", "1.0",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.SCHEMA_VERSION));
+      assertEquals("The unit name was incorrect", "delta",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.UNIT_NAME));
+      assertEquals("The transaction type was incorrect", PersistenceUnitTransactionType.RESOURCE_LOCAL,
+          PersistenceUnitTransactionType.valueOf((String)unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.TRANSACTION_TYPE)));
+      assertEquals("The provider class name was incorrect", "delta.persistence.provider",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.PROVIDER_CLASSNAME));
+      assertNull("The jta datasource jndi name was wrong",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.JTA_DATASOURCE));
+      assertNull("The non jta datasource jndi name was wrong",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.NON_JTA_DATASOURCE));
+      assertNull("One or more mapping files were specified",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.MAPPING_FILES));
+      assertNull("One or more jar files were specified",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.JAR_FILES));
+      assertNull("One or more managed classes were specified",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.MANAGED_CLASSES));
+      assertFalse("We should not exclude any classes",
+          (Boolean)unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.EXCLUDE_UNLISTED_CLASSES));
+      assertNull("The properties should never be null",
+          unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.PROPERTIES));
+      assertNotNull("The persistence.xml location was not specified", unit.getPersistenceXmlLocation());
+      assertEquals("The persistence.xml location points at the wrong file",
+          new File("unittest/resources/file1/META-INF/persistence.xml").toURI().toURL().toExternalForm(),
+          unit.getPersistenceXmlLocation().toExternalForm());
+      assertNotNull("The persistence root location was not specified", unit.getPersistenceUnitRoot());
+      assertEquals("The persistence root points at the wrong place",
+          new File("unittest/resources/file1").toURI().toURL().toExternalForm(),
+          unit.getPersistenceUnitRoot().toExternalForm());
+      assertSame("The persistence unit was associated with the wrong bundle", persistenceBundle, unit.getDefiningBundle());
+
+    } finally {
+      
+      if(is != null)
+        is.close();
+    }
+    
+  }
+
+  @Test
+  public void testFile2() throws Exception
+  {
+    InputStream is = null;
+
+    try {
+      URL xml = new File("unittest/resources/file2/META-INF/persistence.xml").toURI().toURL();
+      is = xml.openStream();
+      
+      URL root = new File("unittest/resources/file2").toURI().toURL();
+    
+      JPAHandler handler = new JPAHandler(new PersistenceLocationData(xml, root, persistenceBundle), "1.0");
+      parser.parse(is, handler);
+      
+      Collection<? extends PersistenceUnitInfoService> puinfos = handler.getPersistenceUnits();
+      assertEquals("An incorrect number of persistence units has been returned.", 0, puinfos.size());
+    } finally {
+      if(is != null)
+        is.close();
+    }
+  }
+  
+  @Test(expected=SAXParseException.class)
+  public void testFile3() throws Exception
+  {
+    InputStream is = null;
+
+    try {
+      URL xml = new File("unittest/resources/file3/META-INF/persistence.xml").toURI().toURL();
+      is = xml.openStream();
+      
+      URL root = new File("unittest/resources/file3").toURI().toURL();
+    
+      JPAHandler handler = new JPAHandler(new PersistenceLocationData(xml, root, persistenceBundle), "1.0");
+      parser.parse(is, handler);
+
+      fail("Parsing should not succeed");
+    } finally {
+      if(is != null)
+        is.close();
+    }
+  }
+
+  private static List<PersistenceUnitInfoService> getList(Collection<? extends PersistenceUnitInfoService> puinfos)
+  {
+    List<PersistenceUnitInfoService> list = new ArrayList<PersistenceUnitInfoService>();
+    
+    list.addAll(puinfos);
+    
+    Collections.sort(list, new Comparator<PersistenceUnitInfoService>() {
+
+      public int compare(PersistenceUnitInfoService o1, PersistenceUnitInfoService o2)
+      {
+        return ((String)o1.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.UNIT_NAME))
+        .compareTo((String)o2.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.UNIT_NAME));
+      }
+      
+    });
+    
+    return list;
+  }
+  
+  private boolean checkJARURLs(Collection<String> collection)
+  {
+    List<String> jars = new ArrayList<String>();
+    
+    jars.add("bravoJarFile1.jar");
+    jars.add("bravoJarFile2.jar");
+    
+    return collection.containsAll(jars);
+  }
+}

Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/no/such/Provider.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/no/such/Provider.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/no/such/Provider.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/no/such/Provider.java Thu Oct  1 17:19:13 2009
@@ -0,0 +1,27 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package no.such;
+
+import java.util.Map;
+
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.spi.PersistenceProvider;
+import javax.persistence.spi.PersistenceUnitInfo;
+
+public class Provider implements PersistenceProvider
+{
+
+  public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo arg0, Map arg1)
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  public EntityManagerFactory createEntityManagerFactory(String arg0, Map arg1)
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+}

Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/MockProvider/META-INF/MANIFEST.MF
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/MockProvider/META-INF/MANIFEST.MF?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/MockProvider/META-INF/MANIFEST.MF (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/MockProvider/META-INF/MANIFEST.MF Thu Oct  1 17:19:13 2009
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Fake JPA Provider
+Bundle-SymbolicName: no.such.provider
+Bundle-Version: 1.0.0

Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/MockProvider/META-INF/services/javax.persistence.spi.PersistenceProvider
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/MockProvider/META-INF/services/javax.persistence.spi.PersistenceProvider?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/MockProvider/META-INF/services/javax.persistence.spi.PersistenceProvider (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/MockProvider/META-INF/services/javax.persistence.spi.PersistenceProvider Thu Oct  1 17:19:13 2009
@@ -0,0 +1 @@
+no.such.Provider
\ No newline at end of file

Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file1/META-INF/persistence.xml
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file1/META-INF/persistence.xml?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file1/META-INF/persistence.xml (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file1/META-INF/persistence.xml Thu Oct  1 17:19:13 2009
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
+   version="1.0">
+
+  <persistence-unit name="alpha"/>
+  
+  <persistence-unit name="bravo" transaction-type="JTA">
+    <description>Persistence unit example2 for the unittest</description>
+    <provider>bravo.persistence.provider</provider>
+    <jta-data-source>bravo/jtaDS</jta-data-source>
+    <non-jta-data-source>bravo/nonJtaDS</non-jta-data-source>
+    <mapping-file>bravoMappingFile1.xml</mapping-file>
+    <mapping-file>bravoMappingFile2.xml</mapping-file>
+    <jar-file>bravoJarFile1.jar</jar-file>
+    <jar-file>bravoJarFile2.jar</jar-file>
+    <class>bravoClass1</class>
+    <class>bravoClass2</class>
+    <exclude-unlisted-classes/>
+    <properties>
+      <property name="some.prop" value="prop.value"/>
+      <property name="some.other.prop" value="another.prop.value"/>
+    </properties>
+  </persistence-unit>
+  
+  <persistence-unit name="charlie" transaction-type="RESOURCE_LOCAL">
+    <description>Persistence unit example3 for the unittest</description>
+    <provider>charlie.persistence.provider</provider>
+    <exclude-unlisted-classes>true</exclude-unlisted-classes>
+  </persistence-unit>
+  
+  <persistence-unit name="delta" transaction-type="RESOURCE_LOCAL">
+    <description>Persistence unit example3 for the unittest</description>
+    <provider>delta.persistence.provider</provider>
+    <exclude-unlisted-classes>false</exclude-unlisted-classes>
+  </persistence-unit>
+  
+  
+</persistence>
\ No newline at end of file

Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file10/META-INF/persistence.xml
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file10/META-INF/persistence.xml?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file10/META-INF/persistence.xml (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file10/META-INF/persistence.xml Thu Oct  1 17:19:13 2009
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
+   version="1.0">
+
+  <persistence-unit name="alpha">
+  	<provider>no.such.Provider</provider>
+  	<properties>
+      <property name="osgi.jpa.provider.version" value="[1.0.0,1.0.1]"/>
+    </properties>
+  </persistence-unit>  
+  
+</persistence>
\ No newline at end of file

Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file11/META-INF/persistence.xml
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file11/META-INF/persistence.xml?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file11/META-INF/persistence.xml (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file11/META-INF/persistence.xml Thu Oct  1 17:19:13 2009
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
+   version="1.0">
+
+  <persistence-unit name="alpha">
+  	<provider>no.such.Provider</provider>
+  	<properties>
+      <property name="osgi.jpa.provider.version" value="(1.0.0,1.1.0)"/>
+    </properties>
+  </persistence-unit>  
+  
+</persistence>
\ No newline at end of file

Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file12/META-INF/persistence.xml
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file12/META-INF/persistence.xml?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file12/META-INF/persistence.xml (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file12/META-INF/persistence.xml Thu Oct  1 17:19:13 2009
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
+   version="1.0">
+
+  <persistence-unit name="alpha">
+  	<provider>no.such.Provider</provider>
+  	<properties>
+      <property name="osgi.jpa.provider.version" value="1.0.0"/>
+    </properties>
+  </persistence-unit>  
+  
+</persistence>
\ No newline at end of file

Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file13/META-INF/persistence.xml
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file13/META-INF/persistence.xml?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file13/META-INF/persistence.xml (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file13/META-INF/persistence.xml Thu Oct  1 17:19:13 2009
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
+   version="1.0">
+
+  <persistence-unit name="alpha">
+  	<provider>no.such.Provider</provider>
+  	<properties>
+      <property name="osgi.jpa.provider.version" value="(1.1.1,1.3.5)"/>
+    </properties>
+  </persistence-unit>  
+  
+</persistence>
\ No newline at end of file

Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file14/META-INF/persistence.xml
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file14/META-INF/persistence.xml?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file14/META-INF/persistence.xml (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file14/META-INF/persistence.xml Thu Oct  1 17:19:13 2009
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
+   version="1.0">
+
+  <persistence-unit name="alpha">
+  	<provider>no.such.Provider</provider>
+  	<properties>
+      <property name="osgi.jpa.provider.version" value="[1.0.0,2.0.0]"/>
+    </properties>
+  </persistence-unit>  
+  
+  <persistence-unit name="bravo">
+  	<provider>no.such.Provider</provider>
+  	<properties>
+      <property name="osgi.jpa.provider.version" value="[0.0.5,1.0.1]"/>
+    </properties>
+  </persistence-unit>
+  
+</persistence>
\ No newline at end of file

Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file15/META-INF/persistence.xml
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file15/META-INF/persistence.xml?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file15/META-INF/persistence.xml (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/unittest/resources/file15/META-INF/persistence.xml Thu Oct  1 17:19:13 2009
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
+   version="1.0">
+
+  <persistence-unit name="alpha">
+  	<provider>no.such.Provider</provider>
+  	<properties>
+      <property name="osgi.jpa.provider.version" value="[1.0.0,2.0.0]"/>
+    </properties>
+  </persistence-unit>  
+  
+  <persistence-unit name="bravo">
+  	<provider>no.such.Provider</provider>
+  	<properties>
+      <property name="osgi.jpa.provider.version" value="[0.0.5,0.9.9]"/>
+    </properties>
+  </persistence-unit>
+  
+</persistence>
\ No newline at end of file