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 [4/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.jndi/src/com/ibm/osgi/jndi/DelegateContext.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/DelegateContext.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/DelegateContext.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/DelegateContext.java Thu Oct 1 17:19:13 2009
@@ -0,0 +1,273 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.osgi.jndi;
+
+import java.util.Hashtable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NameClassPair;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+
+public class DelegateContext implements Context
+{
+ private Hashtable<Object, Object> env = new Hashtable<Object, Object>();
+ private Context defaultContext;
+ private static ConcurrentMap<String, Context> urlContexts = new ConcurrentHashMap<String, Context>();
+
+ public DelegateContext(Hashtable<?, ?> theEnv)
+ {
+ env.putAll(theEnv);
+ }
+
+ public DelegateContext(Context ctx) throws NamingException
+ {
+
+ defaultContext = ctx;
+ env.putAll(ctx.getEnvironment());
+
+ }
+
+ public Object addToEnvironment(String propName, Object propVal) throws NamingException
+ {
+ Context ctx = getDefaultContext();
+
+ if (ctx != null) ctx.addToEnvironment(propName, propVal);
+
+ return env.put(propName, propVal);
+ }
+
+ public void bind(Name name, Object obj) throws NamingException
+ {
+ findContext(name).bind(name, obj);
+ }
+
+ public void bind(String name, Object obj) throws NamingException
+ {
+ findContext(name).bind(name, obj);
+ }
+
+ public void close() throws NamingException
+ {
+ if (defaultContext != null) defaultContext.close();
+ env.clear();
+ }
+
+ public Name composeName(Name name, Name prefix) throws NamingException
+ {
+ return findContext(name).composeName(name, prefix);
+ }
+
+ public String composeName(String name, String prefix) throws NamingException
+ {
+ return findContext(name).composeName(name, prefix);
+ }
+
+ public Context createSubcontext(Name name) throws NamingException
+ {
+ return findContext(name).createSubcontext(name);
+ }
+
+ public Context createSubcontext(String name) throws NamingException
+ {
+ return findContext(name).createSubcontext(name);
+ }
+
+ public void destroySubcontext(Name name) throws NamingException
+ {
+ findContext(name).destroySubcontext(name);
+ }
+
+ public void destroySubcontext(String name) throws NamingException
+ {
+ findContext(name).destroySubcontext(name);
+ }
+
+ public Hashtable<?, ?> getEnvironment() throws NamingException
+ {
+ Hashtable<Object, Object> theEnv = new Hashtable<Object, Object>();
+ theEnv.putAll(env);
+ return theEnv;
+ }
+
+ public String getNameInNamespace() throws NamingException
+ {
+ return getDefaultContext().getNameInNamespace();
+ }
+
+ public NameParser getNameParser(Name name) throws NamingException
+ {
+ return findContext(name).getNameParser(name);
+ }
+
+ public NameParser getNameParser(String name) throws NamingException
+ {
+ return findContext(name).getNameParser(name);
+ }
+
+ public NamingEnumeration<NameClassPair> list(Name name) throws NamingException
+ {
+ return findContext(name).list(name);
+ }
+
+ public NamingEnumeration<NameClassPair> list(String name) throws NamingException
+ {
+ return findContext(name).list(name);
+ }
+
+ public NamingEnumeration<Binding> listBindings(Name name) throws NamingException
+ {
+ return findContext(name).listBindings(name);
+ }
+
+ public NamingEnumeration<Binding> listBindings(String name) throws NamingException
+ {
+ return findContext(name).listBindings(name);
+ }
+
+ public Object lookup(Name name) throws NamingException
+ {
+ return findContext(name).lookup(name);
+ }
+
+ public Object lookup(String name) throws NamingException
+ {
+ return findContext(name).lookup(name);
+ }
+
+ public Object lookupLink(Name name) throws NamingException
+ {
+ return findContext(name).lookupLink(name);
+ }
+
+ public Object lookupLink(String name) throws NamingException
+ {
+ return findContext(name).lookupLink(name);
+ }
+
+ public void rebind(Name name, Object obj) throws NamingException
+ {
+ findContext(name).rebind(name, obj);
+ }
+
+ public void rebind(String name, Object obj) throws NamingException
+ {
+ findContext(name).rebind(name, obj);
+ }
+
+ public Object removeFromEnvironment(String propName) throws NamingException
+ {
+ Context ctx = getDefaultContext();
+
+ if (ctx != null) ctx.removeFromEnvironment(propName);
+
+ return env.remove(propName);
+ }
+
+ public void rename(Name oldName, Name newName) throws NamingException
+ {
+ findContext(oldName).rename(oldName, newName);
+ }
+
+ public void rename(String oldName, String newName) throws NamingException
+ {
+ findContext(oldName).rename(oldName, newName);
+ }
+
+ public void unbind(Name name) throws NamingException
+ {
+ findContext(name).unbind(name);
+ }
+
+ public void unbind(String name) throws NamingException
+ {
+ findContext(name).unbind(name);
+ }
+
+ protected Context findContext(Name name) throws NamingException
+ {
+ return findContext(name.toString());
+ }
+
+
+ protected Context findContext(String name) throws NamingException
+ {
+ Context toReturn = null;
+
+ if (name.contains(":")) {
+ toReturn = getURLContext(name);
+ } else {
+ toReturn = getDefaultContext();
+ }
+
+ if (toReturn != null)
+ {
+ String packages = System.getProperty(Context.URL_PKG_PREFIXES, null);
+
+ if (packages != null)
+ {
+ toReturn.addToEnvironment(Context.URL_PKG_PREFIXES, packages);
+ }
+ }
+
+ return toReturn;
+ }
+
+ private Context getDefaultContext() throws NamingException
+ {
+ if (defaultContext == null) {
+ defaultContext = ContextHelper.createContext(env);
+ }
+ return defaultContext;
+ }
+
+ private Context getURLContext(String name) throws NamingException
+ {
+ Context ctx = null;
+
+ int index = name.indexOf(':');
+
+ if (index != -1) {
+ String scheme = name.substring(0, index);
+
+ ctx = ContextHelper.createURLContext(scheme, env);
+ }
+
+ if (ctx == null) {
+ ctx = getDefaultContext();
+ }
+
+ return ctx;
+ }
+
+ /**
+ * This method allows the caller to set the default context if one is to hand.
+ * Normally the context would be lazily constructed upon first use, but this
+ * if one already exists when this is created it can be pushed in.
+ *
+ * @param ctx the context to use.
+ */
+ public void setDefaultContext(Context ctx)
+ {
+ defaultContext = ctx;
+ }
+
+ /**
+ * This method allows URL contexts to be pushed in. We should probably be
+ * pushing in references to the ObjectFactory for the url Object Factory, but
+ * for now lets just push the context itself in.
+ *
+ * @param url
+ * @param ctx
+ */
+ public void setURLContext(String url, Context ctx)
+ {
+ urlContexts.put(url, ctx);
+ }
+}
\ No newline at end of file
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/DelegateContextFactory.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/DelegateContextFactory.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/DelegateContextFactory.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/DelegateContextFactory.java Thu Oct 1 17:19:13 2009
@@ -0,0 +1,13 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.osgi.jndi;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+
+public interface DelegateContextFactory {
+ public Context getInitialContext(Hashtable<?, ?> envmt) throws NamingException;
+}
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/OSGiInitialContextFactoryBuilder.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/OSGiInitialContextFactoryBuilder.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/OSGiInitialContextFactoryBuilder.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/OSGiInitialContextFactoryBuilder.java Thu Oct 1 17:19:13 2009
@@ -0,0 +1,59 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.osgi.jndi;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+import javax.naming.spi.InitialContextFactoryBuilder;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+
+public class OSGiInitialContextFactoryBuilder implements InitialContextFactoryBuilder,
+ InitialContextFactory
+{
+ private BundleContext _context;
+
+ public OSGiInitialContextFactoryBuilder(BundleContext context)
+ {
+ _context = context;
+ }
+
+ public InitialContextFactory createInitialContextFactory(Hashtable<?, ?> environment)
+ throws NamingException
+ {
+ return this;
+ }
+ public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException
+ {
+ Context toReturn = null;
+
+ ServiceReference ref = _context.getServiceReference(DelegateContextFactory.class.getName());
+
+ //TODO: is the custom interface DelegateContextFactory the right way to go about things
+ // or is there a more generic way in RFC 142
+ if (ref != null) {
+ try {
+ DelegateContextFactory dcf = (DelegateContextFactory) _context.getService(ref);
+
+ if (dcf != null) {
+ toReturn = dcf.getInitialContext(environment);
+ }
+ }
+ finally {
+ _context.ungetService(ref);
+ }
+ }
+
+ if (toReturn == null) {
+ toReturn = new DelegateContext(environment);
+ }
+
+ return toReturn;
+ }
+}
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/OSGiObjectFactoryBuilder.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/OSGiObjectFactoryBuilder.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/OSGiObjectFactoryBuilder.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/OSGiObjectFactoryBuilder.java Thu Oct 1 17:19:13 2009
@@ -0,0 +1,218 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.osgi.jndi;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.RefAddr;
+import javax.naming.Reference;
+import javax.naming.Referenceable;
+import javax.naming.StringRefAddr;
+import javax.naming.spi.ObjectFactory;
+import javax.naming.spi.ObjectFactoryBuilder;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+public class OSGiObjectFactoryBuilder implements ObjectFactoryBuilder, ObjectFactory
+{
+ /** The bundle context we use for accessing the SR */
+ private static BundleContext context;
+
+ public static void setBundleContext(BundleContext ctx)
+ {
+ context = ctx;
+ }
+
+ public ObjectFactory createObjectFactory(Object obj, Hashtable<?, ?> environment)
+ throws NamingException
+ {
+ return this;
+ }
+
+ public Object getObjectInstance(Object obj, Name name, Context nameCtx,
+ Hashtable<?, ?> environment) throws Exception
+ {
+
+ Reference ref = null;
+
+ if (obj instanceof Reference) {
+ ref = (Reference) obj;
+ } else if (obj instanceof Referenceable) {
+ ref = ((Referenceable)obj).getReference();
+ }
+
+ Object result = ref;
+
+ if (ref != null) {
+ String className = ref.getFactoryClassName();
+
+ if (className != null) {
+ result = getObjectInstanceUsingClassName(obj, className, obj, name, nameCtx, environment);
+ } else {
+ result = getObjectInstanceUsingRefAddress(ref.getAll(), obj, name, nameCtx, environment);
+
+ if (result == null || result == obj) {
+ result = getObjectInstanceUsingAllObjectFactories(obj, name, nameCtx, environment);
+ }
+ }
+ }
+
+ if (result == null) result = ref;
+
+ return result;
+ }
+
+ private Object getObjectInstanceUsingAllObjectFactories(Object obj, Name name, Context nameCtx,
+ Hashtable<?, ?> environment)
+ {
+ Object result = obj;
+ try {
+ ServiceReference[] refs = context.getAllServiceReferences(ObjectFactory.class.getName(), null);
+
+ if (refs != null) {
+ for (ServiceReference ref : refs) {
+ ObjectFactory factory = (ObjectFactory) context.getService(ref);
+
+ if (factory != null) {
+ try {
+ result = factory.getObjectInstance(obj, name, nameCtx, environment);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ context.ungetService(ref);
+
+ // if the result comes back and is not null and not the reference
+ // object then we should return the result, so break out of the
+ // loop we are in.
+ if (result != null && result != obj) break;
+ }
+ }
+ }
+ } catch (InvalidSyntaxException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ if (result == null) result = obj;
+
+ return result;
+ }
+
+ private Object getObjectInstanceUsingRefAddress(Enumeration<RefAddr> addresses, Object obj, Name name,
+ Context nameCtx, Hashtable<?, ?> environment)
+ {
+ Object result = obj;
+
+ while (addresses.hasMoreElements()) {
+ RefAddr address = addresses.nextElement();
+ if (address instanceof StringRefAddr && "URL".equals(address.getType())) {
+ String urlScheme = (String)address.getContent();
+ ObjectFactory factory = null;
+ ServiceReference ref = null;
+ try {
+ ServiceReference[] services = context.getServiceReferences(ObjectFactory.class.getName(), "(|(osgi.jndi.urlScheme=" + urlScheme + ")(urlScheme=" + urlScheme + "))");
+
+ if (services != null) {
+ ref = services[0];
+ factory = (ObjectFactory) context.getService(ref);
+ }
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+
+ if (factory != null) {
+ try {
+ result = factory.getObjectInstance(obj, name, nameCtx, environment);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ if (ref != null) context.ungetService(ref);
+
+ // if the result is not null and references a different object from
+ // the obj then we have resolved the object, so we stop searching.
+ if (result != null && result != obj) break;
+ }
+ }
+
+ return result;
+ }
+
+ private Object getObjectInstanceUsingClassName(Object reference, String className, Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment)
+ {
+ Object result = obj;
+
+ ObjectFactory factory = null;
+ ServiceReference ref = null;
+
+ if (className != null) {
+ try {
+ ServiceReference[] refs = context.getAllServiceReferences(className, null);
+
+ if (refs != null) {
+ for (ServiceReference ref1 : refs) {
+ factory = (ObjectFactory) context.getService(ref1);
+
+ if (factory != null) {
+ ref = ref1;
+ break;
+ }
+ }
+ }
+ } catch (InvalidSyntaxException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ if (factory == null) {
+ try {
+ ServiceReference[] refs = context.getServiceReferences(ObjectFactoryBuilder.class.getName(), null);
+
+ if (refs != null) {
+ for (ServiceReference ofRef : refs) {
+ ObjectFactoryBuilder builder = (ObjectFactoryBuilder) context.getService(ofRef);
+ try {
+ factory = builder.createObjectFactory(reference, environment);
+ } catch (NamingException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ context.ungetService(ofRef);
+ if (factory != null) {
+ break;
+ }
+ }
+ }
+ } catch (InvalidSyntaxException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ if (factory != null) {
+ try {
+ result = factory.getObjectInstance(obj, name, nameCtx, environment);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } finally {
+ if (ref != null) context.ungetService(ref);
+ }
+ }
+
+ return result;
+ }
+}
\ No newline at end of file
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/startup/Activator.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/startup/Activator.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/startup/Activator.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jndi/src/com/ibm/osgi/jndi/startup/Activator.java Thu Oct 1 17:19:13 2009
@@ -0,0 +1,47 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.osgi.jndi.startup;
+
+import javax.naming.NamingException;
+import javax.naming.spi.NamingManager;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+import com.ibm.osgi.jndi.ContextHelper;
+import com.ibm.osgi.jndi.OSGiInitialContextFactoryBuilder;
+import com.ibm.osgi.jndi.OSGiObjectFactoryBuilder;
+
+/**
+ * The activator for this bundle makes sure the static classes in it are
+ * driven so they can do their magic stuff properly.
+ */
+public class Activator implements BundleActivator
+{
+ public void start(BundleContext context)
+ {
+ ContextHelper.setBundleContext(context);
+ OSGiObjectFactoryBuilder.setBundleContext(context);
+
+ try {
+ if (!!!NamingManager.hasInitialContextFactoryBuilder()) {
+ NamingManager.setInitialContextFactoryBuilder(new OSGiInitialContextFactoryBuilder(context));
+ }
+ } catch (NamingException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ try {
+ NamingManager.setObjectFactoryBuilder(new OSGiObjectFactoryBuilder());
+ } catch (NamingException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IllegalStateException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void stop(BundleContext context) {}
+}
\ No newline at end of file
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jndi/unittest/com/ibm/ws/eba/jndi/test/ObjectFactoryTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jndi/unittest/com/ibm/ws/eba/jndi/test/ObjectFactoryTest.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jndi/unittest/com/ibm/ws/eba/jndi/test/ObjectFactoryTest.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jndi/unittest/com/ibm/ws/eba/jndi/test/ObjectFactoryTest.java Thu Oct 1 17:19:13 2009
@@ -0,0 +1,156 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.ws.eba.jndi.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+import java.lang.reflect.Field;
+import java.util.Hashtable;
+import java.util.Properties;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.Reference;
+import javax.naming.StringRefAddr;
+import javax.naming.spi.NamingManager;
+import javax.naming.spi.ObjectFactory;
+
+import mocks.BundleContextMock;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+
+import com.ibm.aries.unittest.mocks.MethodCall;
+import com.ibm.aries.unittest.mocks.Skeleton;
+import com.ibm.osgi.jndi.ContextHelper;
+import com.ibm.osgi.jndi.OSGiObjectFactoryBuilder;
+import com.ibm.osgi.jndi.startup.Activator;
+
+public class ObjectFactoryTest
+{
+ private BundleContext bc;
+
+ /**
+ * This method does the setup .
+ * @throws NoSuchFieldException
+ * @throws SecurityException
+ * @throws IllegalAccessException
+ * @throws IllegalArgumentException
+ */
+ @Before
+ public void setup() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException
+ {
+ bc = Skeleton.newMock(new BundleContextMock(), BundleContext.class);
+ new Activator().start(bc);
+
+ Field f = ContextHelper.class.getDeclaredField("context");
+ f.setAccessible(true);
+ f.set(null, bc);
+ f = OSGiObjectFactoryBuilder.class.getDeclaredField("context");
+ f.setAccessible(true);
+ f.set(null, bc);
+
+ }
+
+ /**
+ * Make sure we clear the caches out before the next test.
+ */
+ @After
+ public void teardown()
+ {
+ new Activator().stop(bc);
+ BundleContextMock.clear();
+ }
+
+ @Test
+ public void testURLReferenceWithNoMatchingHandler() throws Exception
+ {
+ Reference ref = new Reference(null);
+ ref.add(new StringRefAddr("URL", "wibble"));
+ Object obj = NamingManager.getObjectInstance(ref, null, null, null);
+
+ assertSame("The naming manager should have returned the reference object", ref, obj);
+ }
+
+ @Test
+ public void testURLReferenceWithMatchingHandler() throws Exception
+ {
+ String testObject = "Test object";
+ ObjectFactory factory = Skeleton.newMock(ObjectFactory.class);
+ Skeleton.getSkeleton(factory).setReturnValue(new MethodCall(ObjectFactory.class, "getObjectInstance", Object.class, Name.class, Context.class, Hashtable.class), testObject);
+
+ Properties props = new Properties();
+ props.setProperty("osgi.jndi.urlScheme", "wibble");
+
+ bc.registerService(ObjectFactory.class.getName(), factory, props);
+
+ Reference ref = new Reference(null);
+ ref.add(new StringRefAddr("URL", "wibble"));
+ Object obj = NamingManager.getObjectInstance(ref, null, null, null);
+
+ assertEquals("The naming manager should have returned the test object", testObject, obj);
+ }
+
+ @Test
+ public void testReferenceWithNoClassName() throws Exception
+ {
+ String testObject = "Test object";
+ ObjectFactory factory = Skeleton.newMock(ObjectFactory.class);
+ Skeleton.getSkeleton(factory).setReturnValue(new MethodCall(ObjectFactory.class, "getObjectInstance", Object.class, Name.class, Context.class, Hashtable.class), testObject);
+
+ bc.registerService(ObjectFactory.class.getName(), factory, null);
+
+ Reference ref = new Reference(null);
+ Object obj = NamingManager.getObjectInstance(ref, null, null, null);
+
+ assertEquals("The naming manager should have returned the test object", testObject, obj);
+ }
+
+ @Test
+ public void testSpecifiedFactoryWithMatchingFactory() throws Exception
+ {
+ String testObject = "Test object";
+ ObjectFactory factory = Skeleton.newMock(ObjectFactory.class);
+ Skeleton.getSkeleton(factory).setReturnValue(new MethodCall(ObjectFactory.class, "getObjectInstance", Object.class, Name.class, Context.class, Hashtable.class), testObject);
+
+ Reference ref = new Reference("dummy.class.name", factory.getClass().getName(), "");
+
+ bc.registerService(new String[] {ObjectFactory.class.getName(), factory.getClass().getName()},
+ factory, null);
+
+ Object obj = NamingManager.getObjectInstance(ref, null, null, null);
+
+ assertEquals("The naming manager should have returned the test object", testObject, obj);
+ }
+
+ @Test
+ public void testSpecifiedFactoryWithRegisteredButNotMatchingFactory() throws Exception
+ {
+ String testObject = "Test object";
+ ObjectFactory factory = Skeleton.newMock(ObjectFactory.class);
+ Skeleton.getSkeleton(factory).setReturnValue(new MethodCall(ObjectFactory.class, "getObjectInstance", Object.class, Name.class, Context.class, Hashtable.class), testObject);
+
+ Reference ref = new Reference("dummy.class.name", "dummy.factory.class.name", "");
+
+ bc.registerService(new String[] {ObjectFactory.class.getName(), factory.getClass().getName()},
+ factory, null);
+
+ Object obj = NamingManager.getObjectInstance(ref, null, null, null);
+
+ assertSame("The naming manager should have returned the reference object", ref, obj);
+ }
+
+ @Test
+ public void testSpecifiedFactoryWithNoMatchingFactory() throws Exception
+ {
+ Reference ref = new Reference("dummy.class.name");
+
+ Object obj = NamingManager.getObjectInstance(ref, null, null, null);
+
+ assertSame("The naming manager should have returned the reference object", ref, obj);
+ }
+}
\ No newline at end of file
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/.aries
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/.aries?rev=820722&view=auto
==============================================================================
(empty)
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/.classpath
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/.classpath?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/.classpath (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/.classpath Thu Oct 1 17:19:13 2009
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" output="build/unittest/classes" path="unittest"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/unittest.framework"/>
+ <classpathentry kind="output" path="build/classes"/>
+</classpath>
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/.project
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/.project?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/.project (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/.project Thu Oct 1 17:19:13 2009
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>com.ibm.osgi.jpa.unit.manager</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/META-INF/MANIFEST.MF
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/META-INF/MANIFEST.MF?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/META-INF/MANIFEST.MF (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/META-INF/MANIFEST.MF Thu Oct 1 17:19:13 2009
@@ -0,0 +1,12 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Manager Plug-in
+Bundle-SymbolicName: com.ibm.osgi.jpa.unit.manager
+Bundle-Version: 1.0.0
+Bundle-Vendor: IBM
+Bundle-Activator: com.ibm.osgi.jpa.start.Activator
+Import-Package: com.ibm.osgi.util,
+ javax.persistence;version="[1.0.0, 2.0.0)",
+ javax.persistence.spi;version="[1.0.0, 2.0.0)",
+ org.osgi.framework;version="[1.5.0,2.0.0)"
+Export-Package: org.osgi.service.jpa;version="1.0.0";uses:="org.osgi.framework"
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/build.properties
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/build.properties?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/build.properties (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/build.properties Thu Oct 1 17:19:13 2009
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = build/classes/
+bin.includes = META-INF/,\
+ .
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/build.xml
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/build.xml?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/build.xml (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/build.xml Thu Oct 1 17:19:13 2009
@@ -0,0 +1,18 @@
+<!-- (C) Copyright IBM Corp. 2009 -->
+
+<project name="com.ibm.osgi.jpa.unit.manager" default="build" basedir=".">
+ <property name="aries.image" value="true"/>
+ <import file="../build/imports/standard_imports.xml"/>
+
+ <target name="unittest" depends="createJar, unittest.unittest"/>
+ <target name="createJar">
+ <jar destfile="${basedir}/unittest/resources/jarfile.jar" basedir="${basedir}/unittest/resources/jarfile"/>
+ <!-- put some jar files in the file1 persistence unit root for testing the parser -->
+ <copy tofile="${basedir}/unittest/resources/file1/bravoJarFile1.jar">
+ <fileset dir="${basedir}/unittest/resources" includes="jarfile.jar"/>
+ </copy>
+ <copy tofile="${basedir}/unittest/resources/file1/bravoJarFile2.jar">
+ <fileset dir="${basedir}/unittest/resources" includes="jarfile.jar"/>
+ </copy>
+ </target>
+</project>
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/provider/PersistenceProviderFactory.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/provider/PersistenceProviderFactory.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/provider/PersistenceProviderFactory.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/provider/PersistenceProviderFactory.java Thu Oct 1 17:19:13 2009
@@ -0,0 +1,68 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.osgi.jpa.provider;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.persistence.spi.PersistenceProvider;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * A factory for lazily creating PersistenceProvider Implementations
+ */
+public class PersistenceProviderFactory implements ServiceFactory
+{
+
+ /** The JPA provider's implementation class name */
+ private final String className;
+
+ /** The bundle containing the JPA provider */
+ private final Bundle providerBundle;
+
+ /** The persistence provider object */
+ private final AtomicReference<PersistenceProvider> provider = new AtomicReference<PersistenceProvider>();
+
+ /** Constructor
+ *
+ *@param b The Persistence Bundle
+ *@param providerClassName The provider's implementation class name
+ */
+ public PersistenceProviderFactory(Bundle b, String providerClassName)
+ {
+ className = providerClassName;
+ providerBundle = b;
+ }
+
+ @SuppressWarnings("unchecked")
+public PersistenceProvider getService(Bundle arg0, ServiceRegistration arg1)
+ {
+ if(provider.get() == null)
+ {
+ try {
+ Class<? extends PersistenceProvider> providerClass = providerBundle.loadClass(className);
+ provider.compareAndSet(null, providerClass.newInstance());
+ } catch (Exception e) {
+ try {
+ providerBundle.stop();
+ } catch (BundleException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+ e.printStackTrace();
+ }
+ }
+ return provider.get();
+ }
+
+ public void ungetService(Bundle arg0, ServiceRegistration arg1, Object arg2)
+ {
+ // No-op. We never want to tidy this up as it doesn't consume many
+ // resources once instantiated.
+ }
+
+}
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/provider/PersistenceProviderManager.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/provider/PersistenceProviderManager.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/provider/PersistenceProviderManager.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/provider/PersistenceProviderManager.java Thu Oct 1 17:19:13 2009
@@ -0,0 +1,153 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.osgi.jpa.provider;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.persistence.spi.PersistenceProvider;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.SynchronousBundleListener;
+
+/**
+ * This class registers PersistenceProvider implementations on behalf
+ * of JPA provider bundles.
+ */
+public class PersistenceProviderManager implements SynchronousBundleListener, BundleActivator
+{
+ /** The Service Registrations for Persistence Providers */
+ private final ConcurrentMap<Bundle, ServiceRegistration> registrations = new ConcurrentHashMap<Bundle, ServiceRegistration>();
+
+ private BundleContext ctx;
+
+ public void start(BundleContext ctx) throws Exception
+ {
+ this.ctx = ctx;
+
+ ctx.addBundleListener(this);
+ Bundle[] bundles = ctx.getBundles();
+
+ for (Bundle b : bundles) {
+ if (b.getState() == Bundle.STARTING ||
+ b.getState() == Bundle.ACTIVE) {
+ registerPotentialPersistenceProvider(b);
+ }
+ }
+ }
+
+ /**
+ * This method determines whether a bundle is a persistence
+ * provider bundle
+ *
+ * @param b
+ */
+ private void registerPotentialPersistenceProvider(Bundle b)
+ {
+ URL provider = b.getResource("META-INF/services/javax.persistence.spi.PersistenceProvider");
+
+ if (provider != null) {
+ try {
+ BufferedReader reader = null;
+ String providerClassName = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(provider.openStream()));
+ providerClassName = reader.readLine();
+ } finally {
+ if(reader != null)reader.close();
+ }
+
+ String[] classNames = new String[] {PersistenceProvider.class.getName(), providerClassName};
+ String version = b.getVersion().toString();
+
+ if(!!!alreadyRegistered(b, providerClassName))
+ {
+ PersistenceProviderFactory ppf = new PersistenceProviderFactory(b, providerClassName);
+
+ Dictionary<String, Object> props = new Hashtable<String, Object>();
+ props.put("osgi.jpa.provider.version", version);
+
+ ServiceRegistration reg = b.getBundleContext().registerService(classNames, ppf, props);
+
+ if(registrations.putIfAbsent(b,reg) != null)
+ reg.unregister();
+ }
+ } catch (IOException e) {
+ //TODO log this properly
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ /**
+ * Return true if the Bundle b has already registered a PersistenceProvider with the
+ * implementation class name providerClassName
+ * @param b
+ * @param providerClassName
+ * @return
+ */
+ private boolean alreadyRegistered(Bundle b, String providerClassName)
+ {
+ ServiceReference[] refs = b.getRegisteredServices();
+
+ boolean registered = false;
+
+ if(refs != null) {
+ Filter f;
+ try {
+ f = ctx.createFilter("(&(" + Constants.OBJECTCLASS + "=" + PersistenceProvider.class.getName() +
+ ")(" + Constants.OBJECTCLASS + "=" + providerClassName + "))");
+
+ for(ServiceReference r : refs)
+ {
+ registered = f.match(r);
+ if(registered) break;
+ }
+ } catch (InvalidSyntaxException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ return registered;
+ }
+
+ public void bundleChanged(BundleEvent event)
+ {
+ int eventType = event.getType();
+
+ if(eventType == BundleEvent.STARTING || eventType == BundleEvent.LAZY_ACTIVATION)
+ registerPotentialPersistenceProvider(event.getBundle());
+ else if (eventType == BundleEvent.STOPPING) {
+ ServiceRegistration reg = registrations.remove(event.getBundle());
+ if(reg != null)
+ reg.unregister();
+ }
+ }
+
+ /**
+ * Destroy this PersistenceProviderManager
+ */
+ public void stop(BundleContext ctx) throws Exception
+ {
+ ctx.removeBundleListener(this);
+ //We do not need to unregister the PersistenceProviders on behalf of the
+ //bundles. This will happen automatically when they shut down.
+ }
+
+}
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/start/Activator.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/start/Activator.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/start/Activator.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/start/Activator.java Thu Oct 1 17:19:13 2009
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.osgi.jpa.start;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+import com.ibm.osgi.jpa.provider.PersistenceProviderManager;
+import com.ibm.osgi.jpa.unit.PersistenceBundleManager;
+
+public class Activator implements BundleActivator
+{
+ private PersistenceProviderManager providerMgr;
+ private PersistenceBundleManager bundleMgr;
+
+ @Override
+ public void start(BundleContext ctx) throws Exception
+ {
+ try {
+ providerMgr = new PersistenceProviderManager();
+ providerMgr.start(ctx);
+ } catch (Exception e) {
+ //TODO log this error
+ e.printStackTrace();
+ }
+
+ try {
+ bundleMgr = new PersistenceBundleManager();
+ bundleMgr.start(ctx);
+ } catch (Exception e) {
+ //TODO log this error
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void stop(BundleContext ctx) throws Exception
+ {
+ Exception ex = null;
+
+ try {
+ providerMgr.stop(ctx);
+ } catch (Exception e) {
+ ex = e;
+ //TODO FFDC
+ }
+
+ try {
+ bundleMgr.stop(ctx);
+ } catch (Exception e) {
+ ex = e;
+ //TODO FFDC
+ }
+ if (ex != null) throw ex;
+ }
+}
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/PersistenceBundleManager.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/PersistenceBundleManager.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/PersistenceBundleManager.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/PersistenceBundleManager.java Thu Oct 1 17:19:13 2009
@@ -0,0 +1,424 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+
+package com.ibm.osgi.jpa.unit;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.validation.Schema;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.SynchronousBundleListener;
+import org.osgi.framework.Version;
+import org.osgi.service.jpa.PersistenceUnitInfoService;
+
+import com.ibm.osgi.jpa.unit.parsing.EarlyParserReturn;
+import com.ibm.osgi.jpa.unit.parsing.JPAHandler;
+import com.ibm.osgi.jpa.unit.parsing.SchemaLocatingHandler;
+import com.ibm.osgi.jpa.util.PersistenceBundleHelper;
+import com.ibm.osgi.jpa.util.PersistenceLocationData;
+
+import com.ibm.osgi.util.FragmentBuilder;
+
+/**
+ * This class manages the fragments that need to be added to persistence bundles, and
+ * also registers the metadata for persistence units in the service registry.
+ */
+public class PersistenceBundleManager implements SynchronousBundleListener, BundleActivator
+{
+ /** The bundle context for this bundle */
+ private BundleContext ctx = null;
+ /** A map of bundles to generated fragments */
+ private final ConcurrentMap<Bundle, Bundle> hostToFragmentMap = new ConcurrentHashMap<Bundle, Bundle>();
+ /** A map of persistence bundles to sets of persistence metadata */
+ private final ConcurrentMap<Bundle, Set<ServiceRegistration>> hostToPersistenceUnitMap = new ConcurrentHashMap<Bundle, Set<ServiceRegistration>>();
+ //TODO pull this from config
+ /** The default JPA provider to use */
+ public static final String DEFAULT_JPA_PROVIDER ="org.apache.openjpa.persistence.PersistenceProviderImpl";
+
+ public void start(BundleContext ctx)
+ {
+ this.ctx = ctx;
+ ctx.addBundleListener(this);
+ }
+
+ public void stop(BundleContext arg0) throws Exception {
+
+ ctx.removeBundleListener(this);
+ //When we stop, tidy up all the fragments and services, the
+ //fragments only get detached when the host is unresolved,
+ //so JPA can continue gracefully in active bundles
+ //if the container wishes
+ for(Bundle b : hostToFragmentMap.keySet())
+ tidyUpPersistenceBundle(b);
+ }
+
+ public void bundleChanged(BundleEvent event)
+ {
+ Bundle b = event.getBundle();
+
+ //We don't look at fragments
+ if (b.getHeaders().get(Constants.FRAGMENT_HOST) == null)
+ {
+ // We need to remove fragments that are no longer useful
+ // and register fragments for those that need them.
+ // No action is needed on UNRESOLVED (a package refresh)
+ // as the bundle hasn't changed
+ // We shouldn't process multiple events on different
+ // threads for the same bundle at the same time, but the
+ // framework should protect us from this. Testing may also show
+ // that we need to prevent this call being reentrant.
+ // We absolutely cannot lock when calling these methods as
+ // it can cause deadlocks if listeners hold locks whilst
+ // interacting with the framework in a manner that fires
+ // events.
+ switch(event.getType()) {
+ case BundleEvent.UNINSTALLED : {
+ tidyUpPersistenceBundle(b);
+ break;
+ }
+ //This case should fall through to add a new
+ //fragment after update/refresh
+ case BundleEvent.UNRESOLVED :
+ case BundleEvent.UPDATED :
+ tidyUpPersistenceBundle(b);
+ case BundleEvent.INSTALLED :
+ processBundle(b);
+ }
+ }
+ }
+
+ /**
+ * If we have generated a resources for the supplied bundle, then
+ * tidy them up.
+ * @param host
+ */
+ private void tidyUpPersistenceBundle(Bundle host)
+ {
+
+ Bundle fragment = hostToFragmentMap.remove(host);
+ Set<ServiceRegistration> services = hostToPersistenceUnitMap.remove(host);
+
+ if(services != null) {
+ for(ServiceRegistration reg : services)
+ reg.unregister();
+ }
+
+ if(fragment != null){
+ try {
+ fragment.uninstall();
+ } catch (BundleException be) {
+ //TODO log this error, then hope that we don't try to
+ //recreate the fragment before restarting the framework!
+ }
+ }
+ }
+
+ /**
+ * Process the supplied bundle for persistence units. If any are
+ * found then the bundle will be tied to a provider using a fragment
+ * @param b
+ */
+ private void processBundle(Bundle b)
+ {
+ Bundle fragment = null;
+ Collection <PersistenceLocationData> persistenceXmls = PersistenceBundleHelper.findPersistenceXmlFiles(b);
+ //If we have no persistence units then our job is done
+ if (!!!persistenceXmls.isEmpty())
+ {
+ //Get the persistence units defined, and a provider for them to use
+ Collection<PersistenceUnitImpl> parsedPersistenceUnits = parseXmlFiles(persistenceXmls, b);
+ ServiceReference providerRef = getProviderServiceReference(parsedPersistenceUnits);
+
+ //If we can't find a provider then bomb out
+ if (providerRef != null)
+ {
+ try {
+ FragmentBuilder builder = new FragmentBuilder(b, ".jpa.fragment");
+ builder.addImportsFromExports(providerRef.getBundle());
+ fragment = builder.install(ctx);
+
+
+ hostToFragmentMap.put(b, fragment);
+ // If we successfully got a fragment then
+ // set the provider reference and register the units
+ Set<ServiceRegistration> registrations = new HashSet<ServiceRegistration>();
+ Hashtable<String, Object> props = new Hashtable<String, Object>();
+
+ props.put(PersistenceUnitInfoService.PERSISTENCE_BUNDLE_SYMBOLIC_NAME, b.getSymbolicName());
+ props.put(PersistenceUnitInfoService.PERSISTENCE_BUNDLE_VERSION, b.getVersion());
+
+ for(PersistenceUnitImpl unit : parsedPersistenceUnits){
+ Hashtable<String, Object> serviceProps = new Hashtable<String, Object>(props);
+
+ String unitName = (String) unit.getPersistenceXmlMetadata().get(PersistenceUnitInfoService.UNIT_NAME);
+ if(unitName != null)
+ serviceProps.put(PersistenceUnitInfoService.PERSISTENCE_UNIT_NAME, unitName);
+
+ unit.setProviderReference(providerRef);
+ registrations.add(ctx.registerService(PersistenceUnitInfoService.class.getName(), unit, serviceProps));
+ }
+ hostToPersistenceUnitMap.put(b, registrations);
+ }
+ catch (IOException e)
+ {
+ // TODO Fragment generation failed, log the error
+ // No clean up because we didn't register the bundle yet
+ e.printStackTrace();
+ }
+ catch (BundleException be) {
+ //TODO log the failure to install the fragment, but return null
+ // to show we didn't get a fragment installed
+ // No clean up because we didn't register the bundle yet
+ }
+ }
+ }
+ }
+
+ /**
+ * Parse the persistence.xml files referenced by the URLs in the collection
+ * @param persistenceXmls
+ * @param bundle The bundle containing the persistence xml files
+ * @return A collection of parsed persistence units.
+ */
+ private Collection<PersistenceUnitImpl> parseXmlFiles(Collection<PersistenceLocationData> persistenceXmls, Bundle bundle)
+ {
+ Collection<PersistenceUnitImpl> persistenceUnits = new ArrayList<PersistenceUnitImpl>();
+ //Parse each xml file in turn
+ for(PersistenceLocationData datum : persistenceXmls) {
+ SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+ InputStream is = null;
+ try {
+ SAXParser parser = parserFactory.newSAXParser();
+ is = datum.getPersistenceXML().openStream();
+
+ try{
+ parser.parse(is, new SchemaLocatingHandler(ctx.getBundle()));
+ } catch (EarlyParserReturn epr) {
+ //This is not really an exception, but a way to work out which
+ //version of the persistence schema to use in validation
+ Schema s = epr.getSchema();
+
+ if(s != null) {
+ parserFactory.setSchema(s);
+ parserFactory.setNamespaceAware(true);
+ parser = parserFactory.newSAXParser();
+
+ //Get back to the beginning of the stream
+ is.close();
+ is = datum.getPersistenceXML().openStream();
+
+ JPAHandler handler = new JPAHandler(datum, epr.getVersion());
+ parser.parse(is, handler);
+
+ persistenceUnits.addAll(handler.getPersistenceUnits());
+ }
+ }
+ } catch (Exception e) {
+ //TODO Log this error in parsing
+ e.printStackTrace();
+ } finally {
+ if(is != null) try {
+ is.close();
+ } catch (IOException e) {
+ //TODO Log this
+ e.printStackTrace();
+ }
+ }
+ }
+ return persistenceUnits;
+ }
+
+ /**
+ * Get a persistence provider from the service registry described by the
+ * persistence units defined
+ * @param parsedPersistenceUnits
+ * @return A service reference or null if no suitable reference is available
+ */
+ private ServiceReference getProviderServiceReference(Collection<PersistenceUnitImpl> parsedPersistenceUnits)
+ {
+ Set<String> ppClassNames = new HashSet<String>();
+ Set<Filter> versionFilters = new HashSet<Filter>();
+ //Fill the set of class names and version Filters
+ for(PersistenceUnitImpl unit : parsedPersistenceUnits)
+ {
+ Map<String, Object> metadata = unit.getPersistenceXmlMetadata();
+ String provider = (String) metadata.get(PersistenceUnitInfoService.PROVIDER_CLASSNAME);
+ //get providers specified in the persistence units
+ if(provider != null && !!!provider.equals(""))
+ {
+ ppClassNames.add(provider);
+
+ Properties props = (Properties) metadata.get(PersistenceUnitInfoService.PROPERTIES);
+
+ if(props != null && props.containsKey(PersistenceUnitInfoService.JPA_PROVIDER_VERSION)) {
+
+ try {
+ Filter f = getFilter(props.getProperty(PersistenceUnitInfoService.JPA_PROVIDER_VERSION, "0.0.0"));
+ versionFilters.add(f);
+ } catch (InvalidSyntaxException e) {
+ // TODO Log error and ignore, This should never happen
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ //If we have too many provider class names specified then blow up
+ if(ppClassNames.size() > 1)
+ {
+ //TODO log this error (too many persistence providers specified)
+ } else {
+ //Get the best provider for the given filters
+ String provider = (ppClassNames.isEmpty()) ?
+ DEFAULT_JPA_PROVIDER : ppClassNames.iterator().next();
+ return getBestProvider(provider, versionFilters);
+ }
+ return null;
+ }
+
+ /**
+ * Locate the best provider for the given criteria
+ * @param providerClass
+ * @param matchingCriteria
+ * @return
+ */
+ private ServiceReference getBestProvider(String providerClass, Set<Filter> matchingCriteria)
+ {
+ ServiceReference[] array = null;
+ try {
+ array = ctx.getAllServiceReferences(providerClass, null);
+ } catch (InvalidSyntaxException e) {
+ //TODO this can never happen
+ }
+
+ if(array != null) {
+ //A linked list is faster for large numbers of ServiceReferences
+ //Note we cannot use Arrays.asList() as we need to remove items
+ //via an iterator, and this would throw UnsupportedOperationException.
+ List<ServiceReference> refs = new LinkedList<ServiceReference>();
+
+ for(ServiceReference reference : array)
+ refs.add(reference);
+
+ Iterator<ServiceReference> it = refs.iterator();
+
+ //Remove anything that doesn't match the filter
+ while(it.hasNext())
+ {
+ ServiceReference ref = it.next();
+ for(Filter f : matchingCriteria)
+ {
+ if(!!!f.match(ref)) {
+ it.remove();
+ break;
+ }
+ }
+ }
+
+ if(!!!refs.isEmpty()) {
+ //Sort the list in DESCENDING ORDER
+ Collections.sort(refs, new Comparator<ServiceReference>() {
+
+ //TODO we may wish to use Ranking, then versions for equal ranks
+ @Override
+ public int compare(ServiceReference object1, ServiceReference object2)
+ {
+ Version v1 = object1.getBundle().getVersion();
+ Version v2 = object2.getBundle().getVersion();
+ return v2.compareTo(v1);
+ }
+ });
+ return refs.get(0);
+ } else {
+ //TODO no matching providers for matching criteria
+ }
+ } else {
+ //TODO log no matching Providers for impl class
+ }
+
+ return null;
+ }
+
+ /**
+ * Create a filter for the supplied version range string
+ * @param providerVersion
+ * @return
+ * @throws InvalidSyntaxException
+ */
+ private Filter getFilter(String providerVersion)
+ throws InvalidSyntaxException
+ {
+ String toReturn = null;
+
+ //TODO NLS enable the messages in the exceptions below (Invalid version range specified...)
+ //Create a filter to match the required provider version range
+ if(providerVersion != null) {
+ if(!!!providerVersion.contains(","))
+ toReturn = ("(osgi.jpa.provider.version>=" + providerVersion + ")");
+ else {
+ String[] versionArray = providerVersion.split(",");
+
+ if(versionArray.length == 2) {
+
+ versionArray[0] = versionArray[0].trim();
+ versionArray[1] = versionArray[1].trim();
+
+ char bracket1 = versionArray[0].charAt(0);
+ char bracket2 = versionArray[1].charAt(versionArray[1].length() - 1);
+
+ String version1 = versionArray[0].substring(1);
+ String version2 = versionArray[1].substring(0, versionArray[1].length() -1);
+
+ if(version1.compareTo(version2) > 0)
+ throw new InvalidSyntaxException("Invalid version range specified. " + providerVersion, providerVersion);
+
+ String compare1 = "(osgi.jpa.provider.version>=" + version1 + ")";
+ String compare2 = "(osgi.jpa.provider.version<=" + version2 + ")";
+
+ if('(' == bracket1)
+ compare1 = compare1 + "(!(osgi.jpa.provider.version=" + version1 + "))";
+ else if('[' != bracket1) throw new InvalidSyntaxException("Invalid version range specified. " + providerVersion, providerVersion);
+
+
+ if(')' == bracket2)
+ compare2 = compare2 + "(!(osgi.jpa.provider.version=" + version2 + "))";
+ else if(']' != bracket2) throw new InvalidSyntaxException("Invalid version range specified. " + providerVersion, providerVersion);
+
+
+ toReturn = "(&" + compare1 + compare2 + ")";
+ } else throw new InvalidSyntaxException("Invalid version range specified. " + providerVersion, providerVersion);
+
+ }
+ }
+ return FrameworkUtil.createFilter(toReturn);
+ }
+}
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/PersistenceUnitImpl.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/PersistenceUnitImpl.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/PersistenceUnitImpl.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/PersistenceUnitImpl.java Thu Oct 1 17:19:13 2009
@@ -0,0 +1,229 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.osgi.jpa.unit;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.jpa.PersistenceUnitInfoService;
+
+import com.ibm.osgi.jpa.util.PersistenceLocationData;
+
+/**
+ * An implementation of PersistenceUnit for parsed persistence unit metadata
+ *
+ */
+@SuppressWarnings("unchecked")
+public class PersistenceUnitImpl implements PersistenceUnitInfoService
+{
+ /** A map to hold the metadata from the xml */
+ private final Map<String,Object> metadata = new HashMap<String, Object>();
+ /** Information about the location of this persistence unit */
+ private final PersistenceLocationData xmlLocationData;
+
+ /**
+ * The Service Reference for the provider to which this persistence
+ * unit is tied
+ */
+ private ServiceReference provider;
+
+
+ /**
+ * Create a new persistence unit with the given name, transaction type, location and
+ * defining bundle
+ *
+ * @param name may be null
+ * @param transactionType may be null
+ * @param location
+ * @param version The version of the JPA schema used in persistence.xml
+ */
+ public PersistenceUnitImpl(String name, String transactionType, PersistenceLocationData location, String version)
+ {
+ xmlLocationData = location;
+
+ metadata.put(SCHEMA_VERSION, version);
+
+ if (name != null)metadata.put(UNIT_NAME, name);
+ if (transactionType != null) metadata.put(TRANSACTION_TYPE, transactionType);
+
+ }
+
+
+ @Override
+ public Bundle getDefiningBundle()
+ {
+ return xmlLocationData.getPersistenceBundle();
+ }
+
+ @Override
+ public ServiceReference getProviderReference()
+ {
+ return provider;
+ }
+
+ @Override
+ public Map<String, Object> getPersistenceXmlMetadata()
+ {
+ Map<String, Object> data = new HashMap<String, Object>(metadata);
+ if(data.containsKey(MAPPING_FILES))
+ data.put(MAPPING_FILES, ((ArrayList) metadata.get(MAPPING_FILES)).clone());
+ if(data.containsKey(JAR_FILES))
+ data.put(JAR_FILES, ((ArrayList) metadata.get(JAR_FILES)).clone());
+ if(data.containsKey(MANAGED_CLASSES))
+ data.put(MANAGED_CLASSES, ((ArrayList) metadata.get(MANAGED_CLASSES)).clone());
+ if(data.containsKey(PROPERTIES))
+ data.put(PROPERTIES, ((Properties)metadata.get(PROPERTIES)).clone());
+
+ return data;
+ }
+
+ @Override
+ public URL getPersistenceXmlLocation()
+ {
+ return xmlLocationData.getPersistenceXML();
+ }
+
+ @Override
+ public URL getPersistenceUnitRoot()
+ {
+ return xmlLocationData.getPersistenceUnitRoot();
+ }
+
+ /**
+ * @param provider
+ */
+ public void setProviderClassName(String provider)
+ {
+ metadata.put(PROVIDER_CLASSNAME, provider);
+ }
+
+ /**
+ * @param jtaDataSource
+ */
+ public void setJtaDataSource(String jtaDataSource)
+ {
+ metadata.put(JTA_DATASOURCE, jtaDataSource);
+ }
+
+ /**
+ * @param nonJtaDataSource
+ */
+ public void setNonJtaDataSource(String nonJtaDataSource)
+ {
+ metadata.put(NON_JTA_DATASOURCE, nonJtaDataSource);
+ }
+
+ /**
+ * @param mappingFileName
+ */
+ public void addMappingFileName(String mappingFileName)
+ {
+ List<String> files = (List<String>) metadata.get(MAPPING_FILES);
+ if(files == null) {
+ files = new ArrayList<String>();
+ metadata.put(MAPPING_FILES, files);
+ }
+ files.add(mappingFileName);
+ }
+
+ /**
+ * @param jarFile
+ */
+ public void addJarFileName(String jarFile)
+ {
+ List<String> jars = (List<String>) metadata.get(JAR_FILES);
+ if(jars == null) {
+ jars = new ArrayList<String>();
+ metadata.put(JAR_FILES, jars);
+ }
+
+ jars.add(jarFile);
+ }
+
+ /**
+ * @param className
+ */
+ public void addClassName(String className)
+ {
+ List<String> classes = (List<String>) metadata.get(MANAGED_CLASSES);
+ if(classes == null) {
+ classes = new ArrayList<String>();
+ metadata.put(MANAGED_CLASSES, classes);
+ }
+ classes.add(className);
+ }
+
+ /**
+ * @param exclude
+ */
+ public void setExcludeUnlisted(boolean exclude)
+ {
+ metadata.put(EXCLUDE_UNLISTED_CLASSES, exclude);
+ }
+
+ /**
+ * @param name
+ * @param value
+ */
+ public void addProperty(String name, String value)
+ {
+ Properties props = (Properties) metadata.get(PROPERTIES);
+ if(props == null) {
+ props = new Properties();
+ metadata.put(PROPERTIES, props);
+ }
+ props.setProperty(name, value);
+ }
+
+ /**
+ * @param providerRef
+ */
+ public void setProviderReference(ServiceReference providerRef)
+ {
+ provider = providerRef;
+ }
+
+ @Override
+ public ClassLoader getClassLoader()
+ {
+ return new BundleDelegatingClassLoader(getDefiningBundle());
+ }
+
+ private static class BundleDelegatingClassLoader extends ClassLoader
+ {
+ private final Bundle bundle;
+
+ public BundleDelegatingClassLoader(Bundle b)
+ {
+ super(ClassLoader.getSystemClassLoader());
+ bundle = b;
+ }
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException
+ {
+ return bundle.loadClass(name);
+ }
+
+ @Override
+ protected URL findResource(String resName)
+ {
+ return bundle.getResource(resName);
+ }
+
+ @Override
+ protected Enumeration<URL> findResources(String resName) throws IOException
+ {
+ return bundle.getResources(resName);
+ }
+ }
+}
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/parsing/EarlyParserReturn.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/parsing/EarlyParserReturn.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/parsing/EarlyParserReturn.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/parsing/EarlyParserReturn.java Thu Oct 1 17:19:13 2009
@@ -0,0 +1,49 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.osgi.jpa.unit.parsing;
+
+import javax.xml.validation.Schema;
+
+import org.xml.sax.SAXException;
+
+/**
+ * A convenience mechanism for finding the schema to validate with
+ */
+public class EarlyParserReturn extends SAXException
+{
+ /** This class is serializable */
+ private static final long serialVersionUID = 6173561765417524327L;
+ /** The schema to use */
+ private final Schema schema;
+ /** The value of the version attribute in the xml */
+ private final String jpaVersion;
+
+ /**
+ * @return The schema that was used in the xml document
+ */
+ public Schema getSchema()
+ {
+ return schema;
+ }
+
+ /**
+ * @return The version of the JPA schema used
+ */
+ public String getVersion()
+ {
+ return jpaVersion;
+ }
+
+ /**
+ * @param s The schema used
+ * @param version The version of the schema used
+ */
+ public EarlyParserReturn(Schema s, String version)
+ {
+ schema = s;
+ jpaVersion = version;
+ }
+
+
+}
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/parsing/JPAHandler.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/parsing/JPAHandler.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/parsing/JPAHandler.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/parsing/JPAHandler.java Thu Oct 1 17:19:13 2009
@@ -0,0 +1,114 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.osgi.jpa.unit.parsing;
+
+import java.util.Collection;
+import java.util.Stack;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import com.ibm.osgi.jpa.unit.PersistenceUnitImpl;
+import com.ibm.osgi.jpa.util.PersistenceLocationData;
+
+/**
+ * This code is responsible for parsing the persistence.xml into PersistenceUnits
+ */
+public class JPAHandler extends DefaultHandler
+{
+ /** The Persistence Units that we have parsed */
+ private final Stack<PersistenceUnitImpl> persistenceUnits = new Stack<PersistenceUnitImpl>();
+ /** The name of the current element */
+ private String elementName;
+ /** The persistence xml location data */
+ private final PersistenceLocationData xmlLocationData;
+ /** The version of the persistence.xml file */
+ private final String jpaVersion;
+ /** A StringBuilder for caching the information from getCharacters */
+ private StringBuilder builder = new StringBuilder();
+
+ /**
+ * Create a new JPA Handler for the given peristence.xml
+ * @param data
+ * @param version the version of the JPA schema used in the xml
+ */
+ public JPAHandler(PersistenceLocationData data, String version){
+ xmlLocationData = data;
+ jpaVersion = version;
+ }
+
+ /**
+ * Collect up the characters, as element's characters may be split across multiple
+ * calls. Isn't SAX lovely...
+ */
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException
+ {
+ builder.append(ch, start, length);
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String name, Attributes attributes)
+ throws SAXException
+ {
+ //Do this setting first as we use it later.
+ elementName = (localName == null || "".equals(localName))? name : localName;
+
+ if("persistence-unit".equals(elementName)) {
+ persistenceUnits.push(new PersistenceUnitImpl(attributes.getValue("name"), attributes.getValue("transaction-type"), xmlLocationData, jpaVersion));
+ } else if("exclude-unlisted-classes".equals(elementName))
+ persistenceUnits.peek().setExcludeUnlisted(true);
+ else if("property".equals(elementName))
+ persistenceUnits.peek().addProperty(attributes.getValue("name"), attributes.getValue("value"));
+
+ }
+
+
+ @Override
+ public void endElement(String uri, String localName, String name) throws SAXException
+ {
+ String s = builder.toString().trim();
+ //This step is VERY important, otherwise we pollute subsequent
+ //elements
+ builder = new StringBuilder();
+
+ if("".equals(s)) return;
+
+ PersistenceUnitImpl pu = persistenceUnits.peek();
+
+ if("provider".equals(elementName))
+ pu.setProviderClassName(s);
+ else if("jta-data-source".equals(elementName))
+ pu.setJtaDataSource(s);
+ else if("non-jta-data-source".equals(elementName))
+ pu.setNonJtaDataSource(s);
+ else if("mapping-file".equals(elementName))
+ pu.addMappingFileName(s);
+ else if("jar-file".equals(elementName)) {
+ pu.addJarFileName(s);
+ } else if("class".equals(elementName))
+ pu.addClassName(s);
+ else if("exclude-unlisted-classes".equals(elementName))
+ pu.setExcludeUnlisted(Boolean.parseBoolean(s));
+ }
+
+ @Override
+ public void error(SAXParseException spe) throws SAXException
+ {
+ // We throw this exception to be caught further up and logged
+ // as an error there
+ throw spe;
+ }
+
+ /**
+ * @return The collection of persistence units that we have parsed
+ */
+ public Collection<PersistenceUnitImpl> getPersistenceUnits()
+ {
+ return persistenceUnits;
+ }
+
+}
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/parsing/SchemaLocatingHandler.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/parsing/SchemaLocatingHandler.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/parsing/SchemaLocatingHandler.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/unit/parsing/SchemaLocatingHandler.java Thu Oct 1 17:19:13 2009
@@ -0,0 +1,100 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.osgi.jpa.unit.parsing;
+
+import java.net.URL;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.xml.XMLConstants;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+
+import org.osgi.framework.Bundle;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * This parser provides a quick mechanism for determining the JPA schema level,
+ * and throws an EarlyParserReturn with the Schema to validate with
+ */
+public class SchemaLocatingHandler extends DefaultHandler
+{
+ /** The RFC 143 bundle object */
+ private final Bundle extender;
+
+ /**
+ * A static cache of schemas in use in the runtime
+ */
+ private static final ConcurrentMap<String, Schema> schemaCache = new ConcurrentHashMap<String, Schema>();
+
+ /**
+ * Create a new SchemaLocatingHandler
+ * @param bundle The bundle object for the RFC 143 bundle
+ */
+ public SchemaLocatingHandler(Bundle bundle)
+ {
+ extender = bundle;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String name, Attributes attributes)
+ throws SAXException
+ {
+
+ Schema s = null;
+ String version = null;
+ if("persistence".equals(name)) {
+ version = attributes.getValue(uri, "version");
+ s = validate(version);
+ }
+ throw new EarlyParserReturn(s, version);
+ }
+
+ /**
+ * Find the schema for the version of JPA we're using
+ * @param type The value of the version attribute in the xml
+ * @return
+ * @throws SAXException
+ */
+ private final Schema validate(String type) throws SAXException
+ {
+ Schema toReturn = (type == null)? null : schemaCache.get(type);
+
+ if(toReturn == null) {
+ toReturn = getSchema(type);
+ if(toReturn != null) schemaCache.putIfAbsent(type, toReturn);
+ }
+
+ return toReturn;
+ }
+
+ /**
+ * Locate the schema document
+ * @param type The schema version to find
+ * @return
+ * @throws SAXException
+ */
+ private final Schema getSchema(String type) throws SAXException
+ {
+ SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ URL schemaURL = null;
+ Schema schema = null;
+ if("1.0".equals(type)) {
+ try{
+ schemaURL = new URL("http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd");
+ }catch(Exception e){
+ //will not occur with fixed url above.
+ }
+ }
+ //TODO handle JPA 2.0
+ if(schemaURL != null){
+ schema = schemaFactory.newSchema(schemaURL);
+ }
+
+ return schema;
+ }
+
+}
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/util/PersistenceBundleHelper.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/util/PersistenceBundleHelper.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/util/PersistenceBundleHelper.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/util/PersistenceBundleHelper.java Thu Oct 1 17:19:13 2009
@@ -0,0 +1,122 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.osgi.jpa.util;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+
+/**
+ * This helper can be used to locate persistence.xml files in a bundle
+ */
+public class PersistenceBundleHelper
+{
+ /** The persistence xml location */
+ private static final String PERSISTENCE_XML = "META-INF/persistence.xml";
+
+ /**
+ * This method locates persistence xml files in the following
+ * locations:
+ * META-INF
+ * WEB-INF/classes
+ * the META-INF of any jar in WEB-INF/lib
+ * the META-INF of any jar on the Bundle-ClassPath
+ *
+ * Note that getEntry and getEntryPaths are used to ensure
+ * we do not transition the bundle to RESOLVED
+ *
+ * @param bundle
+ * @return
+ */
+ public static Collection<PersistenceLocationData> findPersistenceXmlFiles(Bundle bundle)
+ {
+
+ Collection<PersistenceLocationData> persistenceXmlFiles = new ArrayList<PersistenceLocationData>();
+
+ addLocationToCollectionIfFound(persistenceXmlFiles, "", bundle);
+
+ addLocationToCollectionIfFound(persistenceXmlFiles, "WEB-INF/classes", bundle);
+
+ @SuppressWarnings("unchecked")
+ Enumeration<String> webInfLibJars = bundle.getEntryPaths("WEB-INF/lib");
+
+ if(webInfLibJars != null) {
+
+ List<String> paths = Collections.list(webInfLibJars);
+ Iterator<String> it = paths.iterator();
+
+ while(it.hasNext()){
+ String s = it.next();
+ // We want to process jars in WEB-INF/lib/ so it should end
+ // .jar, and not contain any / separators after character 11
+ if(s.endsWith(".jar") && s.lastIndexOf('/') < 12) {
+ processNestedJar(bundle, persistenceXmlFiles, s);
+ }
+ }
+ }
+
+ String bundleClassPath = (String) bundle.getHeaders().get(Constants.BUNDLE_CLASSPATH);
+
+ if(bundleClassPath != null) {
+ String[] cpEntries = bundleClassPath.split(",");
+
+ for (String s : cpEntries) {
+ s = s.trim();
+ if(s.endsWith(".jar")) {
+ processNestedJar(bundle, persistenceXmlFiles, s);
+ }
+ }
+ }
+ return persistenceXmlFiles;
+ }
+
+ /**
+ * Check to see if a nested jar contains a "META-INF/persistence.xml" file
+ * and add it to the list if it does
+ *
+ * @param bundle
+ * @param persistenceXmlFiles
+ * @param jarLocation
+ */
+ private static void processNestedJar(Bundle bundle,
+ Collection<PersistenceLocationData> persistenceXmlFiles, String jarLocation)
+ {
+ URL jar = bundle.getEntry(jarLocation);
+ if(jar != null) {
+ ClassLoader cl = new URLClassLoader(new URL[] {jar});
+ URL xml = cl.getResource(PERSISTENCE_XML);
+
+ if(xml != null)
+ persistenceXmlFiles.add(new PersistenceLocationData(xml, jar, bundle));
+ }
+ }
+
+ /**
+ * This method will attempt to find an entry for a given path in a given bundle
+ * and add it to the collection if the entry exists
+ * @param collection
+ * @param rootPath
+ * @param bundle
+ */
+ private static void addLocationToCollectionIfFound(Collection<PersistenceLocationData> collection, String rootPath, Bundle bundle)
+ {
+ rootPath = (rootPath.endsWith("/")) ? rootPath : rootPath + "/";
+ URL root = bundle.getEntry(rootPath);
+ if(root != null) {
+ String xmlPath = rootPath + PERSISTENCE_XML;
+ URL xml = bundle.getEntry(xmlPath);
+ if(xml != null)
+ collection.add(new PersistenceLocationData(xml, root, bundle));
+ }
+ }
+
+}
Added: incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/util/PersistenceLocationData.java
URL: http://svn.apache.org/viewvc/incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/util/PersistenceLocationData.java?rev=820722&view=auto
==============================================================================
--- incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/util/PersistenceLocationData.java (added)
+++ incubator/aries/contrib/ibm/com.ibm.osgi.jpa.unit.manager/src/com/ibm/osgi/jpa/util/PersistenceLocationData.java Thu Oct 1 17:19:13 2009
@@ -0,0 +1,60 @@
+/*
+ * (C) Copyright IBM Corp. 2009
+ */
+package com.ibm.osgi.jpa.util;
+
+import java.net.URL;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * A bean to hold metadata about the location of a persistence.xml file
+ */
+public class PersistenceLocationData
+{
+ /** The location of the persistence.xml file */
+ private final URL persistenceXML;
+ /** The location of the persistence unit root */
+ private final URL persistenceUnitRoot;
+ /** The persistence Bundle object */
+ private final Bundle persistenceBundle;
+
+ /**
+ * Construct a new PersistenceLocationData
+ * @param persistenceXML
+ * @param persistenceUnitRoot
+ * @param persistenceBundle
+ */
+ public PersistenceLocationData(URL persistenceXML, URL persistenceUnitRoot,
+ Bundle persistenceBundle)
+ {
+ this.persistenceXML = persistenceXML;
+ this.persistenceUnitRoot = persistenceUnitRoot;
+ this.persistenceBundle = persistenceBundle;
+ }
+
+ /**
+ * @return A URL to the persistence.xml file
+ */
+ public URL getPersistenceXML()
+ {
+ return persistenceXML;
+ }
+
+ /**
+ * @return A URL to the persistence unit root
+ */
+ public URL getPersistenceUnitRoot()
+ {
+ return persistenceUnitRoot;
+ }
+
+ /**
+ * @return The Bundle that defines this persistence unit
+ */
+ public Bundle getPersistenceBundle()
+ {
+ return persistenceBundle;
+ }
+
+}