geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rickmcgu...@apache.org
Subject svn commit: r927071 - in /geronimo/specs/trunk/geronimo-osgi-support: geronimo-osgi-itesta/ geronimo-osgi-locator/src/main/java/org/apache/geronimo/osgi/locator/ geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/ geron...
Date Wed, 24 Mar 2010 14:27:32 GMT
Author: rickmcguire
Date: Wed Mar 24 14:27:31 2010
New Revision: 927071

URL: http://svn.apache.org/viewvc?rev=927071&view=rev
Log:
Reverse lookup order of services to allow for JRE class overrides

Modified:
    geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-itesta/pom.xml
    geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-locator/src/main/java/org/apache/geronimo/osgi/locator/ProviderLocator.java
    geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/OSGiLocatorTest.java
    geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry/src/main/java/org/apache/geronimo/osgi/registry/ProviderRegistryImpl.java

Modified: geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-itesta/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-itesta/pom.xml?rev=927071&r1=927070&r2=927071&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-itesta/pom.xml (original)
+++ geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-itesta/pom.xml Wed Mar 24 14:27:31
2010
@@ -53,6 +53,10 @@ provider resolution scenarios.
                         <Bundle-SymbolicName>${groupId}.${artifactId};singleton=true</Bundle-SymbolicName>
                         <Private-Package>org.apache.geronimo.osgi.testa</Private-Package>
                         <SPI-Provider>true</SPI-Provider>
+                        <Export-Provider>
+                            org.apache.geronimo.osgi.testa.TestTarget2,
+                            org.apache.geronimo.osgi.testa.NoClass
+                        </Export-Provider>
                     </instructions>
                 </configuration>
             </plugin>

Modified: geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-locator/src/main/java/org/apache/geronimo/osgi/locator/ProviderLocator.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-locator/src/main/java/org/apache/geronimo/osgi/locator/ProviderLocator.java?rev=927071&r1=927070&r2=927071&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-locator/src/main/java/org/apache/geronimo/osgi/locator/ProviderLocator.java
(original)
+++ geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-locator/src/main/java/org/apache/geronimo/osgi/locator/ProviderLocator.java
Wed Mar 24 14:27:31 2010
@@ -61,7 +61,7 @@ public class ProviderLocator {
             // NB:  We use the hard coded name in case the registry service has not
             // been started first.  Once this does get started, then everything should
             // resolved.
-            registryTracker = new ServiceTracker(context, "org.apache.geronimo.osgi.registry.api.ProviderRegistry",
null);
+            registryTracker = new ServiceTracker(c, "org.apache.geronimo.osgi.registry.api.ProviderRegistry",
null);
             ((ServiceTracker)registryTracker).open();
             // do this last...it helps indicate if we have an initialized registry.
             context = c;
@@ -178,6 +178,14 @@ public class ProviderLocator {
      *                   Thrown if the class cannot be loaded.
      */
     static public Class<?> loadClass(String className, Class<?>contextClass,
ClassLoader loader) throws ClassNotFoundException {
+        // ideally, this should be last.  However, some of the bundles duplicate classes
+        // found on the boot delegation, so we need to check this first to keep
+        // from picking up one of the default implementations.
+        Class cls = locate(className);
+        if (cls != null) {
+            return cls;
+        }
+
         if (loader != null) {
             try {
                 return loader.loadClass(className);
@@ -187,17 +195,8 @@ public class ProviderLocator {
         if (contextClass != null) {
             loader = contextClass.getClassLoader();
         }
-        try {
-            // try again using the class context loader
-            return Class.forName(className, true, loader);
-        } catch (ClassNotFoundException x) {
-            // last gasp, use the OSGi locator to try to find this
-            Class cls = locate(className);
-            if (cls == null) {
-                throw x;
-            }
-            return cls;
-        }
+        // try again using the class context loader
+        return Class.forName(className, true, loader);
     }
 
 
@@ -217,27 +216,31 @@ public class ProviderLocator {
      *                      trying to instantiate a service instance.
      */
     static public Object getService(String iface, Class<?> contextClass, ClassLoader
loader) throws Exception {
+        // if we are working in an OSGi environment, then process the service
+        // registry first.  Ideally, we would do this last, but because of boot delegation
+        // issues with some API implementations, we must try the OSGi version first
+        if (registryTracker != null) {
+            // get the service, if it exists.  NB:  if the tracker exists, then we
+            // were able to load the interface class in the first place, so we don't
+            // need to protect against that.
+            ProviderRegistry registry = (ProviderRegistry)((ServiceTracker)registryTracker).getService();
+            // if the service is not here, we fall through to the traditional method
+            if (registry != null) {
+                // the rest of the work is done by the registry
+                Object service = registry.getService(iface);
+                if (service != null) {
+                    return service;
+                }
+            }
+        }
         // try for a classpath locatable instance first.  If we find an appropriate class
mapping,
         // create an instance and return it.
         Class<?> cls = locateServiceClass(iface, contextClass, loader);
         if (cls != null) {
             return cls.newInstance();
         }
-
-        // if not initialized in an OSGi environment, this is a failure
-        if (registryTracker == null) {
-            return null;
-        }
-        // get the service, if it exists.  NB:  if the tracker exists, then we
-        // were able to load the interface class in the first place, so we don't
-        // need to protect against that.
-        ProviderRegistry registry = (ProviderRegistry)((ServiceTracker)registryTracker).getService();
-        // it is also a failure if the service is not there.
-        if (registry == null) {
-            return null;
-        }
-        // the rest of the work is done by the registry
-        return registry.getService(iface);
+        // a provider was not found
+        return null;
     }
 
 
@@ -257,27 +260,27 @@ public class ProviderLocator {
      *                      trying to load the class.
      */
     static public Class<?> getServiceClass(String iface, Class<?> contextClass,
ClassLoader loader) throws ClassNotFoundException {
-        // try for a classpath locatable instance first.  If we find an appropriate class
mapping,
-        // create an instance and return it.
-        Class<?> cls = locateServiceClass(iface, contextClass, loader);
-        if (cls != null) {
-            return cls;
+        // if we are working in an OSGi environment, then process the service
+        // registry first.  Ideally, we would do this last, but because of boot delegation
+        // issues with some API implementations, we must try the OSGi version first
+        if (registryTracker != null) {
+            // get the service, if it exists.  NB:  if the tracker exists, then we
+            // were able to load the interface class in the first place, so we don't
+            // need to protect against that.
+            ProviderRegistry registry = (ProviderRegistry)((ServiceTracker)registryTracker).getService();
+            // it is also a failure if the service is not there.
+            if (registry != null) {
+                // If we've located stuff in the registry, then return it
+                Class<?> cls = registry.getServiceClass(iface);
+                if (cls != null) {
+                    return cls;
+                }
+            }
         }
 
-        // if not initialized in an OSGi environment, this is a failure
-        if (registryTracker == null) {
-            return null;
-        }
-        // get the service, if it exists.  NB:  if the tracker exists, then we
-        // were able to load the interface class in the first place, so we don't
-        // need to protect against that.
-        ProviderRegistry registry = (ProviderRegistry)((ServiceTracker)registryTracker).getService();
-        // it is also a failure if the service is not there.
-        if (registry == null) {
-            return null;
-        }
-        // the rest of the work is done by the registry
-        return registry.getServiceClass(iface);
+        // try for a classpath locatable instance first.  If we find an appropriate class
mapping,
+        // create an instance and return it.
+        return locateServiceClass(iface, contextClass, loader);
     }
 
 
@@ -300,7 +303,26 @@ public class ProviderLocator {
     static public List<Object> getServices(String iface, Class<?> contextClass,
ClassLoader loader) throws Exception {
         List<Object> services = new ArrayList<Object>();
 
-        // try for a classpath locatable instance first.  If we find an appropriate class
mapping,
+        // because of boot delegation issues with some of the API implementations, it is
necessary
+        // to process the OSGi registered versions first to allow override of JRE provided
APIs.
+        // if not initialized in an OSGi environment, we're finished
+        if (registryTracker != null) {
+            // get the service, if it exists.  NB:  if the tracker exists, then we
+            // were able to load the interface class in the first place, so we don't
+            // need to protect against that.
+            ProviderRegistry registry = (ProviderRegistry)((ServiceTracker)registryTracker).getService();
+            // it is also the end if the service is not there.
+            if (registry != null) {
+                // get any registered service instances now
+                List<Object> globalServices = registry.getServices(iface);
+                // add to our list also
+                if (globalServices != null) {
+                    services.addAll(globalServices);
+                }
+            }
+        }
+
+        // try for a classpath locatable instance second.  If we find an appropriate class
mapping,
         // create an instance and return it.
         Collection<Class<?>> classes = locateServiceClasses(iface, contextClass,
loader);
         if (classes != null) {
@@ -310,25 +332,6 @@ public class ProviderLocator {
             }
         }
 
-        // if not initialized in an OSGi environment, we're finished
-        if (registryTracker == null) {
-            return services;
-        }
-        // get the service, if it exists.  NB:  if the tracker exists, then we
-        // were able to load the interface class in the first place, so we don't
-        // need to protect against that.
-        ProviderRegistry registry = (ProviderRegistry)((ServiceTracker)registryTracker).getService();
-        // it is also the end if the service is not there.
-        if (registry == null) {
-            return services;
-        }
-
-        // get any registered service instances now
-        List<Object> globalServices = registry.getServices(iface);
-        // add to our list also
-        if (globalServices != null) {
-            services.addAll(globalServices);
-        }
         // now return the merged set
         return services;
     }
@@ -352,31 +355,31 @@ public class ProviderLocator {
      */
     static public List<Class<?>> getServiceClasses(String iface, Class<?>
contextClass, ClassLoader loader) throws Exception {
         Set<Class<?>> serviceClasses = new LinkedHashSet<Class<?>>();
-        // try for a classpath locatable classes first.  If we find an appropriate class
mapping,
-        // add this to our return collection.
-        Collection<Class<?>> classes = locateServiceClasses(iface, contextClass,
loader);
-        if (classes != null) {
-            serviceClasses.addAll(classes);
-        }
 
+        // because of boot delegation issues with some of the API implementations, it is
necessary
+        // to process the OSGi registered versions first to allow override of JRE provided
APIs.
         // if not initialized in an OSGi environment, we're finished
-        if (registryTracker == null) {
-            return new ArrayList(serviceClasses);
-        }
-        // get the service, if it exists.  NB:  if the tracker exists, then we
-        // were able to load the interface class in the first place, so we don't
-        // need to protect against that.
-        ProviderRegistry registry = (ProviderRegistry)((ServiceTracker)registryTracker).getService();
-        // it is also the end if the service is not there.
-        if (registry == null) {
-            return new ArrayList(serviceClasses);
+        if (registryTracker != null) {
+            // get the service, if it exists.  NB:  if the tracker exists, then we
+            // were able to load the interface class in the first place, so we don't
+            // need to protect against that.
+            ProviderRegistry registry = (ProviderRegistry)((ServiceTracker)registryTracker).getService();
+            // it is also the end if the service is not there.
+            if (registry != null) {
+                // get any registered service provider classes now
+                List<Class<?>> globalServices = registry.getServiceClasses(iface);
+                // add to our list also
+                if (globalServices != null) {
+                    serviceClasses.addAll(globalServices);
+                }
+            }
         }
 
-        // get any registered service provider classes now
-        List<Class<?>> globalServices = registry.getServiceClasses(iface);
-        // add to our list also
-        if (globalServices != null) {
-            serviceClasses.addAll(globalServices);
+        // try for a classpath locatable classes second.  If we find an appropriate class
mapping,
+        // add this to our return collection.
+        Collection<Class<?>> classes = locateServiceClasses(iface, contextClass,
loader);
+        if (classes != null) {
+            serviceClasses.addAll(classes);
         }
         // now return the merged set
         return new ArrayList(serviceClasses);
@@ -412,6 +415,15 @@ public class ProviderLocator {
     }
 
 
+    /**
+     * Locate a classpath-define service mapping.
+     *
+     * @param iface  The required interface name.
+     * @param loader The ClassLoader instance to use to locate the service.
+     *
+     * @return The mapped class name, if one is found.  Returns null if the
+     *         mapping is not located.
+     */
     static private String locateServiceClassName(String iface, ClassLoader loader) {
         if (loader != null) {
             try {
@@ -445,7 +457,7 @@ public class ProviderLocator {
      * @return The mapped provider class, if found.  Returns null if
      *         no mapping is located.
      */
-    static public Class<?> locateServiceClass(String iface, Class<?> contextClass,
ClassLoader loader) throws ClassNotFoundException {
+    static private Class<?> locateServiceClass(String iface, Class<?> contextClass,
ClassLoader loader) throws ClassNotFoundException {
         String className = locateServiceClassName(iface, contextClass, loader);
         if (className == null) {
             return null;

Modified: geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/OSGiLocatorTest.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/OSGiLocatorTest.java?rev=927071&r1=927070&r2=927071&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/OSGiLocatorTest.java
(original)
+++ geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/OSGiLocatorTest.java
Wed Mar 24 14:27:31 2010
@@ -122,6 +122,17 @@ public class OSGiLocatorTest {
         assertEquals(1, targets.size());
         assertEquals("org.apache.geronimo.osgi.itesta.TestTargetTwo", targets.get(0).getName());
 
+        // this class is defined using the header form.  It should map back to itself.
+        target = ProviderLocator.locate("org.apache.geronimo.osgi.itesta..TestTarget2");
+        assertNotNull(target);
+        // this should return the given class instance
+        assertEquals("org.apache.geronimo.osgi.itesta.TestTarget2", target.getName());
+
+        targets = ProviderLocator.locateAll("org.apache.geronimo.osgi.itesta..TestTarget2");
+        // should return one entry and it should be the same class mapping
+        assertEquals(1, targets.size());
+        assertEquals("org.apache.geronimo.osgi.itesta.TestTarget2", targets.get(0).getName());
+
         // This is not in the provider registry, so it should just return null.
         target = ProviderLocator.locate("org.apache.geronimo.osgi.registry.itest.ClassNotFound");
         assertNull(target);
@@ -131,6 +142,11 @@ public class OSGiLocatorTest {
         target = ProviderLocator.locate("org.apache.geronimo.osgi.registry.itest.NoClass");
         assertNull(target);
 
+        // This is defined as a header, but the class cannot be loaded.  This should still
+        // return null.
+        target = ProviderLocator.locate("org.apache.geronimo.osgi.itesta..NoClass");
+        assertNull(target);
+
         // Now test some of the class loading support.  This will search the bundle classpath
first,
         // then the provider registry.  Since there is a matching local class this time,
it should
         // find that test class rather than the registered one.
@@ -167,6 +183,13 @@ public class OSGiLocatorTest {
         } catch (ClassNotFoundException e) {
         }
 
+        // this is defined with a header, but there is an error resolving the class
+        try {
+            target = ProviderLocator.loadClass("org.apache.geronimo.osgi.itesta.NoClass",
this.getClass());
+            fail("Expected ClassNotFoundException not thrown");
+        } catch (ClassNotFoundException e) {
+        }
+
 
         // this mapping defines multiple classes for the single key.  The first should be
returned for
         // a singleton request, the locate all should return in definition order
@@ -193,6 +216,10 @@ public class OSGiLocatorTest {
         assertNotNull(targets);
         assertEquals(0, targets.size());
 
+        // The returned class should now be null since there are no registered providers
+        target = ProviderLocator.locate("org.apache.geronimo.osgi.itesta.TestTarget2");
+        assertNull(target);
+
         // This is in the provider registry, but the class cannot be loaded.  This should
still
         // return null.
         target = ProviderLocator.locate("org.apache.geronimo.osgi.registry.itest.NoClass");

Modified: geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry/src/main/java/org/apache/geronimo/osgi/registry/ProviderRegistryImpl.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry/src/main/java/org/apache/geronimo/osgi/registry/ProviderRegistryImpl.java?rev=927071&r1=927070&r2=927071&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry/src/main/java/org/apache/geronimo/osgi/registry/ProviderRegistryImpl.java
(original)
+++ geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry/src/main/java/org/apache/geronimo/osgi/registry/ProviderRegistryImpl.java
Wed Mar 24 14:27:31 2010
@@ -23,8 +23,10 @@ import java.net.URL;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.osgi.framework.Bundle;
 import org.osgi.service.log.LogService;
@@ -36,6 +38,8 @@ import org.osgi.service.log.LogService;
 public class ProviderRegistryImpl implements org.apache.geronimo.osgi.registry.api.ProviderRegistry
{
     // indicates a bundle wishes to opt in to the META-INF/services registration and tracking.
     public static final String OPT_IN_HEADER = "SPI-Provider";
+    // provider classes exported via a header.
+    public static final String EXPORT_PROVIDER_HEADER = "Export-SPI-Provider";
     // our mapping between a provider id and the implementation information.  There
     // might be a one-to-many relationship between the ids and implementing classes.
     private SPIRegistry providers = new SPIRegistry();
@@ -221,7 +225,7 @@ public class ProviderRegistryImpl implem
      */
     public List<Object> getServices(String providerId) {
         List<Object> instances = new ArrayList<Object>();
-        List<BundleProviderLoader> l = providers.getLoaders(providerId);
+        List<BundleProviderLoader> l = serviceProviders.getLoaders(providerId);
         // this returns null for nothing found
         if (l != null) {
             for (BundleProviderLoader c : l) {
@@ -249,13 +253,14 @@ public class ProviderRegistryImpl implem
      */
     public List<Class<?>> getServiceClasses(String providerId) {
         List<Class<?>> classes = new ArrayList<Class<?>>();
-        List<BundleProviderLoader> l = providers.getLoaders(providerId);
+        List<BundleProviderLoader> l = serviceProviders.getLoaders(providerId);
         // this returns null for nothing found
         if (l != null) {
             for (BundleProviderLoader c : l) {
                 try {
                     classes.add(c.loadClass());
                 } catch (Exception e) {
+                    e.printStackTrace();
                     // just swallow this and proceed to the next.  The exception has
                     // already been logged.
                 }
@@ -320,17 +325,56 @@ public class ProviderRegistryImpl implem
 
         // locate and process any providers defined in the OSGI-INF/providers directory
         private void locateProviders() {
-            providers = processDefinitions("OSGI-INF/providers/");
+            // we accumulate from the headers and the providers directory.  The headers
+            // are simpler if there is no class mapping and is easier to use when
+            // converting a simple jar to a bundle.
+            Set<BundleProviderLoader> locatedProviders = new LinkedHashSet<BundleProviderLoader>();
+            List<BundleProviderLoader> headerProviders = locateHeaderProviderDefinitions();
+            if (headerProviders != null) {
+                locatedProviders.addAll(headerProviders);
+            }
+
+            List<BundleProviderLoader> directoryProviders = processDefinitions("OSGI-INF/providers/");
+            if (directoryProviders != null) {
+                directoryProviders.addAll(directoryProviders);
+            }
             // if we have anything, add to global registry
-            if (providers != null) {
+            if (!locatedProviders.isEmpty()) {
                 // process the registrations for each item
-                for (BundleProviderLoader loader: providers) {
+                for (BundleProviderLoader loader: locatedProviders) {
                     // add to the mapping table
                     registerProvider(loader);
                 }
             }
         }
 
+        /**
+         * Parse the Export-Provider: header to create a list of
+         * providers that are exported via the header syntax
+         * rather than via a provider mapping file.
+         *
+         * @return A list of providers defined on the header, or null if
+         *         no providers were exported.
+         */
+        private List<BundleProviderLoader> locateHeaderProviderDefinitions() {
+            // check the header to see if there's anything defined here.
+            String exportedProviders = (String)bundle.getHeaders().get(EXPORT_PROVIDER_HEADER);
+            if (exportedProviders == null) {
+                return null;
+            }
+
+            List<BundleProviderLoader>providers = new ArrayList<BundleProviderLoader>();
+            // split on the separator
+            String[] classNames = exportedProviders.split(",");
+
+            for (String name : classNames) {
+                name = name.trim();
+                // this is a simple mapping
+                providers.add(new BundleProviderLoader(name, name, bundle));
+            }
+            return providers;
+        }
+
         // now process any services
         private void locateServices() {
             // we only process these if there is a header indicating this
@@ -341,7 +385,7 @@ public class ProviderRegistryImpl implem
                 return;
             }
 
-            serviceProviders = processDefinitions("OSGI-INF/providers/");
+            serviceProviders = processDefinitions("META-INF/services/");
             // if we have anything, add to global registry
             if (serviceProviders != null) {
                 // process the registrations for each item
@@ -597,7 +641,7 @@ public class ProviderRegistryImpl implem
 
         @Override
         public String toString() {
-            return "Provider interface=" + providerId + " ,provider class=" + providerClass;
+            return "Provider interface=" + providerId + " , provider class=" + providerClass
+ ", bundle=" + bundle;
         }
 
         @Override



Mime
View raw message