geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rickmcgu...@apache.org
Subject svn commit: r924365 [3/3] - in /geronimo/specs/trunk: geronimo-activation_1.1_spec/src/main/java/javax/activation/ geronimo-ejb_3.1_spec/src/main/java/javax/ejb/embeddable/ geronimo-el_2.2_spec/src/main/java/javax/el/ geronimo-jacc_1.1_spec/src/main/ja...
Date Wed, 17 Mar 2010 16:52:06 GMT
Added: geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/TestTargetLocal.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/TestTargetLocal.java?rev=924365&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/TestTargetLocal.java (added)
+++ geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/TestTargetLocal.java Wed Mar 17 16:52:03 2010
@@ -0,0 +1,37 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.geronimo.osgi.registry.itest;
+
+public class TestTargetLocal {
+    public TestTargetLocal() {
+    }
+
+    @Override
+    /**
+     * The toString method is a simple means for determining
+     * which class has been instantiated without requiring
+     * interface classes to be exported by the test bundles.
+     *
+     * @return The unique identifier for this class.
+     */
+    public String toString() {
+        return "TestTarget";
+    }
+}
+

Propchange: geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/TestTargetLocal.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/TestTargetLocal.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/TestTargetLocal.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/TestTargetTwo.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/TestTargetTwo.java?rev=924365&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/TestTargetTwo.java (added)
+++ geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/TestTargetTwo.java Wed Mar 17 16:52:03 2010
@@ -0,0 +1,37 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.geronimo.osgi.registry.itest;
+
+public class TestTargetTwo {
+    public TestTargetTwo() {
+    }
+
+    @Override
+    /**
+     * The toString method is a simple means for determining
+     * which class has been instantiated without requiring
+     * interface classes to be exported by the test bundles.
+     *
+     * @return The unique identifier for this class.
+     */
+    public String toString() {
+        return "TestTargetTwo";
+    }
+}
+

Propchange: geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/TestTargetTwo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/TestTargetTwo.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry-itests/src/test/java/org/apache/geronimo/osgi/registry/itest/TestTargetTwo.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry/src/main/java/org/apache/geronimo/osgi/registry/ProviderBundleTrackerCustomizer.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry/src/main/java/org/apache/geronimo/osgi/registry/ProviderBundleTrackerCustomizer.java?rev=924365&r1=924364&r2=924365&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry/src/main/java/org/apache/geronimo/osgi/registry/ProviderBundleTrackerCustomizer.java (original)
+++ geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry/src/main/java/org/apache/geronimo/osgi/registry/ProviderBundleTrackerCustomizer.java Wed Mar 17 16:52:03 2010
@@ -64,7 +64,7 @@ public class ProviderBundleTrackerCustom
     @Override
     public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
         // have the registry process this
-        registry.removeBundle(bundle);
+        registry.removeBundle(bundle, object);
     }
 
     private void log(int level, String message) {

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=924365&r1=924364&r2=924365&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 17 16:52:03 2010
@@ -25,7 +25,6 @@ import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.Callable;
 
 import org.osgi.framework.Bundle;
 import org.osgi.service.log.LogService;
@@ -35,12 +34,14 @@ import org.osgi.service.log.LogService;
  * the bundle registrations.
  */
 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";
     // 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 Map<String, List<BundleProviderLoader>> providers = new HashMap<String, List<BundleProviderLoader>>();
-    // our list of bundles and a mapping to the set of providers that each bundle
-    // declares
-    private Map<Long, List<BundleProviderLoader>> providerBundles = new HashMap<Long, List<BundleProviderLoader>>();
+    private SPIRegistry providers = new SPIRegistry();
+    // our mapping between an interface name and a META-INF/services SPI implementation.  There
+    // might be a one-to-many relationship between the ids and implementing classes.
+    private SPIRegistry serviceProviders = new SPIRegistry();
 
     // our base Activator (used as a service source)
     private Activator activator;
@@ -63,106 +64,40 @@ public class ProviderRegistryImpl implem
      *         this bundle does not contain any providers.
      */
     public Object addBundle(Bundle bundle) {
-        // a list for accumulating providers for this bundle
-        List<BundleProviderLoader> list = new ArrayList<BundleProviderLoader>();
-        // look for services definitions in the bundle...we accumulate these as provider class
-        // definitions.
-        Enumeration e = bundle.findEntries("OSGI-INF/providers/", "*", false);
-        if (e != null) {
-            while (e.hasMoreElements()) {
-                final URL u = (URL) e.nextElement();
-                // go parse out the control file
-                parseProviderFile(u, bundle, list);
-            }
-        }
-
-        // if we have providers defined, add each to the global registry and
-        // also keep track of this in the bundle list
-        if (!list.isEmpty()) {
-            providerBundles.put(bundle.getBundleId(), list);
-            // process the registrations for each item
-            for (BundleProviderLoader loader: list) {
-                // add to the mapping table
-                register(loader);
-            }
-            // this will tell the tracker this is a bundle of interest.
-            return list ;
-        }
-        else {
-            // indicate our lack of interest here
-            return null;
-        }
+        log(LogService.LOG_DEBUG, "adding bundle " + bundle);
+        // create a tracker item for this bundle.  This will record all of the information
+        // that's relevent to this bundle
+        BundleResources tracker = new BundleResources(bundle);
+
+        // if the tracker found information of interest, return it to the
+        // BundleTracker to let it know we need to watch this one.
+        return tracker.needsTracking() ? tracker : null;
     }
 
 
     /**
-     * Parse a provider definition file and create loaders
-     * for all definitions contained within the file.
+     * Remove a bundle from the registry.
      *
-     * @param u      The URL of the file
-     * @param bundle The bundle this resides in.
-     * @param bundleProviders
-     *               The list used to accumulate the provider definitions.
-     */
-    private void parseProviderFile(URL u, Bundle bundle, List<BundleProviderLoader> bundleProviders) {
-        final String url = u.toString();
-        // ignore directories
-        if (url.endsWith("/")) {
-            return;
-        }
-        // initial size of the provider list.  If we don't add any because of parsing the
-        // lines, we can add a default one using the provider id as both key and mapped
-        // provider class.
-        int providerCount = bundleProviders.size();
-        // the identifier used for the provider is the last item in the URL.
-        final String providerId = url.substring(url.lastIndexOf("/") + 1);
-        try {
-            BufferedReader br = new BufferedReader(new InputStreamReader(u.openStream(), "UTF-8"));
-            String providerClassName = null;
-            // the file can be multiple lines long, with comments.  A single file can define multiple providers
-            // for a single key, so we might need to create multiple entries.  If the file does not contain any
-            // definition lines, then as a default, we use the providerId as an implementation class also.
-            String line = br.readLine();
-            while (line != null) {
-                // we allow comments on these lines, and a line can be all comment
-                int comment = line.indexOf('#');
-                if (comment != -1) {
-                    line = line.substring(0, comment);
-                }
-                line = line.trim();
-                // if there is nothing left on the line after stripping white space and comments, skip this
-                if (line.length() > 0) {
-                    // add this to our list
-                    bundleProviders.add(new BundleProviderLoader(providerId, line, bundle));
-                }
-                // keep reading until the end.
-                line = br.readLine();
-            }
-            br.close();
-        } catch (IOException e) {
-            // ignore errors and handle as default
-        }
-
-        // if nothing was defined inside the file, then add a default
-        if (providerCount == bundleProviders.size()) {
-            bundleProviders.add(new BundleProviderLoader(providerId, providerId, bundle));
+     * @param bundle The target bundle.
+     */
+    public void removeBundle(Bundle bundle, Object obj) {
+        log(LogService.LOG_DEBUG, "removing bundle " + bundle);
+        BundleResources tracker = (BundleResources)obj;
+        if (tracker != null) {
+            tracker.remove();
         }
     }
 
 
     /**
-     * Remove a bundle from the registry.
+     * Register an individual provivider item by its provider identifier.
      *
-     * @param bundle The target bundle.
+     * @param id      The provider id.
+     * @param provider The loader used to resolve the provider class.
      */
-    public void removeBundle(Bundle bundle) {
-        List<BundleProviderLoader> list = providerBundles.remove(bundle.getBundleId());
-        if (list != null) {
-            for (BundleProviderLoader loader : list) {
-                // unregistry the individual entry
-                unregister(loader);
-            }
-        }
+    protected void registerProvider(BundleProviderLoader provider) {
+        log(LogService.LOG_DEBUG, "registering provider " + provider);
+        providers.register(provider);
     }
 
     /**
@@ -171,16 +106,9 @@ public class ProviderRegistryImpl implem
      * @param id      The target id
      * @param provider The provider registration instance
      */
-    public synchronized void unregister(BundleProviderLoader provider) {
+    protected void unregisterProvider(BundleProviderLoader provider) {
         log(LogService.LOG_DEBUG, "unregistering provider " + provider);
-        if (providers != null) {
-            // this is stored as a list.  Just remove using the registration information
-            // This may move a different provider to the front of the list.
-            List<BundleProviderLoader> l = providers.get(provider.id());
-            if (l != null) {
-                l.remove(provider);
-            }
-        }
+        providers.unregister(provider);
     }
 
 
@@ -190,23 +118,20 @@ public class ProviderRegistryImpl implem
      * @param id      The provider id.
      * @param provider The loader used to resolve the provider class.
      */
-    public synchronized void register(BundleProviderLoader provider) {
-        log(LogService.LOG_DEBUG, "registering provider " + provider);
-        // if this is the first registration, create the mapping table
-        if (providers == null) {
-            providers = new HashMap<String, List<BundleProviderLoader>>();
-        }
-
-        String providerId = provider.id();
+    protected void registerService(BundleProviderLoader provider) {
+        log(LogService.LOG_DEBUG, "registering service " + provider);
+        serviceProviders.register(provider);
+    }
 
-        // the providers are stored as a list...we use the first one registered
-        // when asked to locate.
-        List<BundleProviderLoader> l = providers.get(providerId);
-        if (l ==  null) {
-            l = new ArrayList<BundleProviderLoader>();
-            providers.put(providerId, l);
-        }
-        l.add(provider);
+    /**
+     * Removed a provider registration for a named provider id.
+     *
+     * @param id      The target id
+     * @param provider The provider registration instance
+     */
+    protected void unregisterService(BundleProviderLoader provider) {
+        log(LogService.LOG_DEBUG, "unregistering service " + provider);
+        serviceProviders.unregister(provider);
     }
 
 
@@ -219,49 +144,150 @@ public class ProviderRegistryImpl implem
      *         if this is not registered or the indicated class can't be
      *         loaded.
      */
-    public synchronized Class<?> locate(String providerId) {
-        if (providers != null) {
-            List<BundleProviderLoader> l = providers.get(providerId);
-            if (l != null && !l.isEmpty()) {
-                // we always use the first one registered
-                BundleProviderLoader c = l.get(0);
+    public Class<?> locate(String providerId) {
+        // see if we have a registered match for this...getting just the first instance
+        BundleProviderLoader loader = providers.getLoader(providerId);
+        if (loader != null) {
+            try {
+                // try to load this.  We always return null
+                return loader.loadClass();
+            } catch (Exception e) {
+                // just swallow this and return null.  The exception has already
+                // been logged.
+            }
+        }
+        // no match to return
+        return null;
+    }
+
+    /**
+     * Locate all class files that match a given provider id.
+     *
+     * @param providerId The target provider identifier.
+     *
+     * @return A List containing the class objects corresponding to the
+     *         provider identifier.  Returns an empty list if no
+     *         matching classes can be located.
+     */
+    public List<Class<?>> locateAll(String providerId) {
+        List<Class<?>> classes = new ArrayList<Class<?>>();
+        List<BundleProviderLoader> l = providers.getLoaders(providerId);
+        // this returns null if nothing is found.
+        if (l != null) {
+            for (BundleProviderLoader c : l) {
                 try {
-                    // this loads the class from the hosting bundle.
-                    return c.call();
+                    classes.add(c.loadClass());
                 } catch (Exception e) {
-                    log(LogService.LOG_DEBUG, "Exception loading provider " + this, e);
+                    // just swallow this and proceed to the next.  The exception has
+                    // already been logged.
                 }
             }
         }
+        return classes;
+    }
+
+
+    /**
+     * Locate and instantiate an instance of a service provider
+     * defined in the META-INF/services directory of tracked bundles.
+     *
+     * @param providerId The name of the target interface class.
+     *
+     * @return The service instance.  Returns null if no service defintions
+     *         can be located.
+     * @exception Exception Any classloading or other exceptions thrown during
+     *                      the process of creating this service instance.
+     */
+    public Object getService(String providerId) throws Exception {
+        // see if we have a registered match for this...getting just the first instance
+        BundleProviderLoader loader = serviceProviders.getLoader(providerId);
+        if (loader != null) {
+            // try to load this and create an instance.  Any/all exceptions get
+            // thrown here
+            return loader.createInstance();
+        }
+        // no match to return
         return null;
     }
 
     /**
-     * Locate all class files that match a given provider id.
+     * Locate all services that match a given provider id and create instances.
      *
      * @param providerId The target provider identifier.
      *
-     * @return A List containing the class objects corresponding to the
+     * @return A List containing the instances corresponding to the
+     *         provider identifier.  Returns an empty list if no
+     *         matching classes can be located or created
+     */
+    public List<Object> getServices(String providerId) {
+        List<Object> instances = new ArrayList<Object>();
+        List<BundleProviderLoader> l = providers.getLoaders(providerId);
+        // this returns null for nothing found
+        if (l != null) {
+            for (BundleProviderLoader c : l) {
+                try {
+                    instances.add(c.createInstance());
+                } catch (Exception e) {
+                    // just swallow this and proceed to the next.  The exception has
+                    // already been logged.
+                }
+            }
+        }
+        return instances;
+    }
+
+
+    /**
+     * Locate all services that match a given provider id and return the implementation
+     * classes
+     *
+     * @param providerId The target provider identifier.
+     *
+     * @return A List containing the classes corresponding to the
      *         provider identifier.  Returns an empty list if no
      *         matching classes can be located.
      */
-    public synchronized List<Class<?>> locateAll(String providerId) {
+    public List<Class<?>> getServiceClasses(String providerId) {
         List<Class<?>> classes = new ArrayList<Class<?>>();
-        if (providers != null) {
-            List<BundleProviderLoader> l = providers.get(providerId);
-            if (l != null) {
-                for (BundleProviderLoader c : l) {
-                	try {
-                    	classes.add(c.call());
-                	} catch (Exception e) {
-                        log(LogService.LOG_DEBUG, "Exception loading " + c, e);
-                	}
-				}
+        List<BundleProviderLoader> l = providers.getLoaders(providerId);
+        // this returns null for nothing found
+        if (l != null) {
+            for (BundleProviderLoader c : l) {
+                try {
+                    classes.add(c.loadClass());
+                } catch (Exception e) {
+                    // just swallow this and proceed to the next.  The exception has
+                    // already been logged.
+                }
             }
         }
         return classes;
     }
 
+
+    /**
+     * Locate and return the class for a service provider
+     * defined in the META-INF/services directory of tracked bundles.
+     *
+     * @param providerId The name of the target interface class.
+     *
+     * @return The provider class.   Returns null if no service defintions
+     *         can be located.
+     * @exception Exception Any classloading or other exceptions thrown during
+     *                      the process of loading this service provider class.
+     */
+    public Class<?> getServiceClass(String providerId) throws ClassNotFoundException {
+        // see if we have a registered match for this...getting just the first instance
+        BundleProviderLoader loader = serviceProviders.getLoader(providerId);
+        if (loader != null) {
+            // try to load this and create an instance.  Any/all exceptions get
+            // thrown here
+            return loader.loadClass();
+        }
+        // no match to return
+        return null;
+    }
+
     private void log(int level, String message) {
         activator.log(level, message);
     }
@@ -271,10 +297,242 @@ public class ProviderRegistryImpl implem
     }
 
 
+    private class BundleResources {
+        // the bundle we're attached to.
+        private Bundle bundle;
+        // our map of providers maintained for the META-INF/services design pattern.
+        // this is an interface-to-provider instance mapping.
+        private List<BundleProviderLoader> serviceProviders;
+        // the defined mapping for provider classes...not maintained as an
+        // interface-to-provider mapping.
+        private List<BundleProviderLoader> providers;
+
+        public BundleResources(Bundle b) {
+            bundle = b;
+            // go locate any services we need
+            locateProviders();
+            locateServices();
+        }
+
+        public boolean needsTracking() {
+            return serviceProviders != null || providers != null;
+        }
+
+        // locate and process any providers defined in the OSGI-INF/providers directory
+        private void locateProviders() {
+            providers = processDefinitions("OSGI-INF/providers/");
+            // if we have anything, add to global registry
+            if (providers != null) {
+                // process the registrations for each item
+                for (BundleProviderLoader loader: providers) {
+                    // add to the mapping table
+                    registerProvider(loader);
+                }
+            }
+        }
+
+        // now process any services
+        private void locateServices() {
+            // we only process these if there is a header indicating this
+            // bundle wants to opt-in to this registration process.
+            if (bundle.getHeaders().get(OPT_IN_HEADER) == null) {
+                log(LogService.LOG_INFO, "No '" + OPT_IN_HEADER +
+                    "' Manifest header. Skipping bundle: " + bundle.getSymbolicName());
+                return;
+            }
+
+            serviceProviders = processDefinitions("OSGI-INF/providers/");
+            // if we have anything, add to global registry
+            if (serviceProviders != null) {
+                // process the registrations for each item
+                for (BundleProviderLoader loader: serviceProviders) {
+                    // add to the mapping table
+                    registerService(loader);
+                }
+            }
+        }
+
+
+        /**
+         * Remove all resources associated with this bundle from the
+         * global registry.
+         */
+        public void remove() {
+            log(LogService.LOG_DEBUG, "removing bundle " + bundle);
+            if (providers != null) {
+                for (BundleProviderLoader loader : providers) {
+                    // unregistry the individual entry
+                    unregisterProvider(loader);
+                }
+            }
+
+            if (serviceProviders != null) {
+                for (BundleProviderLoader loader : serviceProviders) {
+                    // unregistry the individual entry
+                    unregisterService(loader);
+                }
+            }
+        }
+
+
+        /**
+         * Process all of the service definition files in a given
+         * target path.  This is used to process both the
+         * META-INF/services files and the OSGI-INF/providers files.
+         *
+         * @param path   The target path location.
+         *
+         * @return The list of matching service definitions.  Returns null if
+         *         no matches were found.
+         */
+        private List<BundleProviderLoader> processDefinitions(String path) {
+            List<BundleProviderLoader> mappings = new ArrayList<BundleProviderLoader>();
+
+            // look for services definitions in the bundle...we accumulate these as provider class
+            // definitions.
+            Enumeration e = bundle.findEntries(path, "*", false);
+            if (e != null) {
+                while (e.hasMoreElements()) {
+                    final URL u = (URL) e.nextElement();
+                    // go parse out the control file
+                    parseServiceFile(u, mappings);
+                }
+            }
+            // only return this if we have something associated with this bundle
+            return mappings.isEmpty() ? null : mappings;
+        }
+
+
+        /**
+         * Parse a provider definition file and create loaders
+         * for all definitions contained within the file.
+         *
+         * @param u      The URL of the file
+         *
+         * @return A list of the defined mappings.
+         */
+        private void parseServiceFile(URL u, List<BundleProviderLoader>mappings) {
+            final String url = u.toString();
+            // ignore directories
+            if (url.endsWith("/")) {
+                return;
+            }
+
+            // the identifier used for the provider is the last item in the URL.
+            final String providerId = url.substring(url.lastIndexOf("/") + 1);
+            try {
+                BufferedReader br = new BufferedReader(new InputStreamReader(u.openStream(), "UTF-8"));
+                String providerClassName = null;
+                // the file can be multiple lines long, with comments.  A single file can define multiple providers
+                // for a single key, so we might need to create multiple entries.  If the file does not contain any
+                // definition lines, then as a default, we use the providerId as an implementation class also.
+                String line = br.readLine();
+                while (line != null) {
+                    // we allow comments on these lines, and a line can be all comment
+                    int comment = line.indexOf('#');
+                    if (comment != -1) {
+                        line = line.substring(0, comment);
+                    }
+                    line = line.trim();
+                    // if there is nothing left on the line after stripping white space and comments, skip this
+                    if (line.length() > 0) {
+                        // add this to our list
+                        mappings.add(new BundleProviderLoader(providerId, line, bundle));
+                    }
+                    // keep reading until the end.
+                    line = br.readLine();
+                }
+                br.close();
+            } catch (IOException e) {
+                // ignore errors and handle as default
+            }
+        }
+    }
+
+
+    /**
+     * Holder class for information about a given collection of
+     * id to provider mappings.  Used for both the providers and
+     * the services.
+     */
+    private class SPIRegistry {
+        private Map<String, List<BundleProviderLoader>> registry;
+
+
+        /**
+         * Register an individual provivider item by its provider identifier.
+         *
+         * @param id      The provider id.
+         * @param provider The loader used to resolve the provider class.
+         */
+        public synchronized void register(BundleProviderLoader provider) {
+            // if this is the first registration, create the mapping table
+            if (registry == null) {
+                registry = new HashMap<String, List<BundleProviderLoader>>();
+            }
+
+            String providerId = provider.id();
+
+            // the providers are stored as a list...we use the first one registered
+            // when asked to locate.
+            List<BundleProviderLoader> l = registry.get(providerId);
+            if (l ==  null) {
+                l = new ArrayList<BundleProviderLoader>();
+                registry.put(providerId, l);
+            }
+            l.add(provider);
+        }
+
+        /**
+         * Remove a provider registration for a named provider id.
+         *
+         * @param provider The provider registration instance
+         */
+        public synchronized void unregister(BundleProviderLoader provider) {
+            if (registry != null) {
+                // this is stored as a list.  Just remove using the registration information
+                // This may move a different provider to the front of the list.
+                List<BundleProviderLoader> l = registry.get(provider.id());
+                if (l != null) {
+                    l.remove(provider);
+                }
+            }
+        }
+
+
+        private synchronized BundleProviderLoader getLoader(String id) {
+            // synchronize on the registry instance
+            if (registry != null) {
+                // return the first match, if any
+                List<BundleProviderLoader> list = registry.get(id);
+                if (list != null && !list.isEmpty()) {
+                    return list.get(0);
+                }
+            }
+            // no match here
+            return null;
+        }
+
+
+        private synchronized List<BundleProviderLoader> getLoaders(String id) {
+            if (registry != null) {
+                // if we have matches, return a copy of what we currently have
+                // to create a safe local copy.
+                List<BundleProviderLoader> list = registry.get(id);
+                if (list != null && !list.isEmpty()) {
+                    return new ArrayList<BundleProviderLoader>(list);
+                }
+            }
+            // no match here
+            return null;
+        }
+    }
+
+
     /**
      * Holder class for located services information.
      */
-    private class BundleProviderLoader implements Callable<Class<?>> {
+    private class BundleProviderLoader {
         // the class name for this provider
         private final String providerId;
         // the mapped class name of the provider.
@@ -295,21 +553,44 @@ public class ProviderRegistryImpl implem
             this.bundle = bundle;
         }
 
-        public Class<?> call() throws Exception {
+        /**
+         * Load a provider class.
+         *
+         * @return The provider class from the target bundle.
+         * @exception Exception
+         */
+        public Class<?> loadClass() throws ClassNotFoundException {
             try {
-                log(LogService.LOG_DEBUG, "creating provider for: " + this);
+                log(LogService.LOG_DEBUG, "loading class for: " + this);
                 return bundle.loadClass(providerClass);
+            } catch (ClassNotFoundException e) {
+                log(LogService.LOG_DEBUG, "exception caught while loading " + this, e);
+                throw e;
+            }
+        }
+
+        /**
+         * Create an instance of the registred service.
+         *
+         * @return The created instance.  A new instance is created on each call.
+         * @exception Exception
+         */
+        public Object createInstance() throws Exception {
+            // get the class object
+            Class <?> cls = loadClass();
+            try {
+                // just create an instance using the default constructor
+                return cls.newInstance();
             } catch (Exception e) {
-                e.printStackTrace();
                 log(LogService.LOG_DEBUG, "exception caught while creating " + this, e);
                 throw e;
             } catch (Error e) {
-                e.printStackTrace();
                 log(LogService.LOG_DEBUG, "error caught while creating " + this, e);
                 throw e;
             }
         }
 
+
         public String id() {
             return providerId;
         }

Modified: geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry/src/main/java/org/apache/geronimo/osgi/registry/api/ProviderRegistry.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry/src/main/java/org/apache/geronimo/osgi/registry/api/ProviderRegistry.java?rev=924365&r1=924364&r2=924365&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry/src/main/java/org/apache/geronimo/osgi/registry/api/ProviderRegistry.java (original)
+++ geronimo/specs/trunk/geronimo-osgi-support/geronimo-osgi-registry/src/main/java/org/apache/geronimo/osgi/registry/api/ProviderRegistry.java Wed Mar 17 16:52:03 2010
@@ -44,4 +44,56 @@ public interface ProviderRegistry {
      *         matching classes can be located.
      */
     public List<Class<?>> locateAll(String factoryId);
+
+
+    /**
+     * Locate and instantiate an instance of a service provider
+     * defined in the META-INF/services directory of tracked bundles.
+     *
+     * @param providerId The name of the target interface class.
+     *
+     * @return The service instance.  Returns null if no service defintions
+     *         can be located.
+     * @exception Exception Any classloading or other exceptions thrown during
+     *                      the process of creating this service instance.
+     */
+    public Object getService(String providerId) throws Exception;
+
+    /**
+     * Locate all services that match a given provider id and create instances.
+     *
+     * @param providerId The target provider identifier.
+     *
+     * @return A List containing the instances corresponding to the
+     *         provider identifier.  Returns an empty list if no
+     *         matching classes can be located or created
+     */
+    public List<Object> getServices(String providerId);
+
+
+    /**
+     * Locate and return the class for a service provider
+     * defined in the META-INF/services directory of tracked bundles.
+     *
+     * @param providerId The name of the target interface class.
+     *
+     * @return The provider class.   Returns null if no service defintions
+     *         can be located.
+     * @exception Exception Any classloading or other exceptions thrown during
+     *                      the process of loading this service provider class.
+     */
+    public Class<?> getServiceClass(String providerId) throws ClassNotFoundException;
+
+
+    /**
+     * Locate all services that match a given provider id and return the implementation
+     * classes
+     *
+     * @param providerId The target provider identifier.
+     *
+     * @return A List containing the classes corresponding to the
+     *         provider identifier.  Returns an empty list if no
+     *         matching classes can be located.
+     */
+    public List<Class<?>> getServiceClasses(String providerId);
 }

Modified: geronimo/specs/trunk/geronimo-osgi-support/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-osgi-support/pom.xml?rev=924365&r1=924364&r2=924365&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-osgi-support/pom.xml (original)
+++ geronimo/specs/trunk/geronimo-osgi-support/pom.xml Wed Mar 17 16:52:03 2010
@@ -72,6 +72,16 @@ OSGi-specific lookup in the Geronimo spe
                 <version>${version}</version>
             </dependency>
             <dependency>
+                <groupId>org.apache.geronimo.specs</groupId>
+                <artifactId>geronimo-osgi-itesta</artifactId>
+                <version>${version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.geronimo.specs</groupId>
+                <artifactId>geronimo-osgi-itestb</artifactId>
+                <version>${version}</version>
+            </dependency>
+            <dependency>
                 <groupId>org.osgi</groupId>
                 <artifactId>org.osgi.core</artifactId>
                 <version>4.2.0</version>
@@ -178,6 +188,8 @@ OSGi-specific lookup in the Geronimo spe
     <modules>
         <module>geronimo-osgi-registry</module>
         <module>geronimo-osgi-locator</module>
+        <module>geronimo-osgi-itesta</module>
+        <module>geronimo-osgi-itestb</module>
         <module>geronimo-osgi-registry-itests</module>
         <module>geronimo-osgi-locator-itests</module>
     </modules>

Modified: geronimo/specs/trunk/geronimo-saaj_1.3_spec/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-saaj_1.3_spec/pom.xml?rev=924365&r1=924364&r2=924365&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-saaj_1.3_spec/pom.xml (original)
+++ geronimo/specs/trunk/geronimo-saaj_1.3_spec/pom.xml Wed Mar 17 16:52:03 2010
@@ -26,7 +26,7 @@
 
     <parent>
         <groupId>org.apache.geronimo.genesis</groupId>
-        <artifactId>genesis-java1.4-flava</artifactId>
+        <artifactId>genesis-java5-flava</artifactId>
         <version>2.0</version>
     </parent>
 

Modified: geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/FactoryFinder.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/FactoryFinder.java?rev=924365&r1=924364&r2=924365&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/FactoryFinder.java (original)
+++ geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/FactoryFinder.java Wed Mar 17 16:52:03 2010
@@ -39,7 +39,7 @@ class FactoryFinder {
      * @return a factory object
      * @throws SOAPException
      */
-    private static Object newInstance(String factoryClassName) throws SOAPException {
+    private static Object newInstance(String factoryClassName, ClassLoader classLoader) throws SOAPException {
         ClassLoader classloader = null;
         try {
             classloader = Thread.currentThread().getContextClassLoader();
@@ -48,7 +48,7 @@ class FactoryFinder {
         }
 
         try {
-            return ProviderLocator.loadClass(factoryClassName, classloader).newInstance();
+            return ProviderLocator.loadClass(factoryClassName, FactoryFinder.class, classloader).newInstance();
         } catch (ClassNotFoundException classnotfoundexception) {
             throw new SOAPException(
                     "Provider " + factoryClassName + " not found",
@@ -62,29 +62,6 @@ class FactoryFinder {
         }
     }
 
-    /**
-     * Instantiates a factory object given the factory's property name and the default class name.
-     *
-     * @param factoryPropertyName
-     * @param defaultFactoryClassName
-     * @return a factory object
-     * @throws SOAPException
-     */
-    static Object find(String factoryPropertyName,
-                       String defaultFactoryClassName) throws SOAPException {
-        Object factory = find(factoryPropertyName);
-        if (factory != null) {
-            return factory;
-        }
-
-        if (defaultFactoryClassName == null) {
-            throw new SOAPException(
-                    "Provider for " + factoryPropertyName + " cannot be found",
-                    null);
-        } else {
-            return newInstance(defaultFactoryClassName);
-        }
-    }
 
     /**
      * Instantiates a factory object given the factory's property name.
@@ -93,81 +70,41 @@ class FactoryFinder {
      * @return a factory object
      * @throws SOAPException
      */
-    static Object find(String factoryPropertyName) throws SOAPException {
+    static Object find(Class<?> factoryType, String defaultFactoryClassName) throws SOAPException {
+        String factoryPropertyName = factoryType.getName();
+        ClassLoader classLoader = null;
         try {
-            String factoryClassName = System.getProperty(factoryPropertyName);
-            if (factoryClassName != null) {
-                return newInstance(factoryClassName);
-            }
-        } catch (SecurityException securityexception) {
+            classLoader = Thread.currentThread().getContextClassLoader();
+        } catch (Exception exception) {
+            throw new SOAPException(exception.toString(), exception);
         }
 
         try {
-            String propertiesFileName = System.getProperty("java.home")
-                    + File.separator + "lib"
-                    + File.separator + "jaxm.properties";
-            File file = new File(propertiesFileName);
-            if (file.exists()) {
-                FileInputStream fileInput = new FileInputStream(file);
-                Properties properties = new Properties();
-                properties.load(fileInput);
-                fileInput.close();
-                String factoryClassName = properties.getProperty(
-                        factoryPropertyName);
-                return newInstance(factoryClassName);
+            // check the META-INF/services definitions, and return it if
+            // we find something.
+            Object service = ProviderLocator.getService(factoryPropertyName, FactoryFinder.class, classLoader);
+            if (service != null) {
+                return service;
             }
-        } catch (Exception exception1) {
+        } catch (Exception ex) {
         }
 
-        String factoryResource = "META-INF/services/" + factoryPropertyName;
         try {
-            InputStream inputstream = getResource(factoryResource);
-            if (inputstream != null) {
-                BufferedReader bufferedreader = new BufferedReader(
-                        new InputStreamReader(inputstream, "UTF-8"));
-                String factoryClassName = bufferedreader.readLine();
-                bufferedreader.close();
-                if ((factoryClassName != null) && !"".equals(factoryClassName)) {
-                    return newInstance(factoryClassName);
-                }
+            String factoryClassName =  ProviderLocator.lookupByJREPropertyFile("lib" + File.separator + "jaxm.properties", factoryPropertyName);
+            if (factoryClassName != null) {
+                return newInstance(factoryClassName, classLoader);
             }
-        } catch (Exception exception2) {
+        } catch (Exception ex) {
         }
 
-        return null;
-    }
-
-    /**
-     * Returns an input stream for the specified resource.
-     * <p/>
-     * <p>This method will firstly try <code>ClassLoader.getSystemResourceAsStream()</code> then the
-     * class loader of the current thread with <code>getResourceAsStream()</code> and finally
-     * attempt <code>getResourceAsStream()</code> on <code>FactoryFinder.class.getClassLoader()</code>.
-     *
-     * @param factoryResource the resource name
-     * @return an InputStream that can be used to read that resource, or <code>null</code> if the
-     *         resource could not be resolved
-     */
-    private static InputStream getResource(String factoryResource) {
-        ClassLoader classloader = null;
+        // Use the system property last
         try {
-            classloader = Thread.currentThread().getContextClassLoader();
-        } catch (SecurityException securityexception) {
-        }
-
-        InputStream inputstream;
-        if (classloader == null) {
-            inputstream =
-                    ClassLoader.getSystemResourceAsStream(factoryResource);
-        } else {
-            inputstream = classloader.getResourceAsStream(factoryResource);
-        }
-
-        if (inputstream == null) {
-            inputstream =
-                    FactoryFinder.class.getClassLoader().getResourceAsStream(
-                            factoryResource);
+            String systemProp = System.getProperty(factoryPropertyName);
+            if (systemProp != null) {
+                return newInstance(systemProp, classLoader);
+            }
+        } catch (SecurityException se) {
         }
-        return inputstream;
+        return newInstance(defaultFactoryClassName, classLoader);
     }
 }

Modified: geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/MessageFactory.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/MessageFactory.java?rev=924365&r1=924364&r2=924365&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/MessageFactory.java (original)
+++ geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/MessageFactory.java Wed Mar 17 16:52:03 2010
@@ -81,7 +81,7 @@ public abstract class MessageFactory {
      */
     public static MessageFactory newInstance() throws SOAPException {
         try {
-            MessageFactory factory = (MessageFactory)FactoryFinder.find(MESSAGE_FACTORY_PROPERTY);
+            MessageFactory factory = (MessageFactory)FactoryFinder.find(MessageFactory.class, null);
             if (factory == null) {
             	factory = newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
             }
@@ -129,7 +129,4 @@ public abstract class MessageFactory {
             throws SOAPException {
         return SAAJMetaFactory.getInstance().newMessageFactory(soapVersion);
     }
-
-    private static final String MESSAGE_FACTORY_PROPERTY =
-            "javax.xml.soap.MessageFactory";
 }

Modified: geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/SAAJMetaFactory.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/SAAJMetaFactory.java?rev=924365&r1=924364&r2=924365&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/SAAJMetaFactory.java (original)
+++ geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/SAAJMetaFactory.java Wed Mar 17 16:52:03 2010
@@ -25,7 +25,7 @@ public abstract class SAAJMetaFactory {
             throws SOAPException {
         if (instance == null) {
             try {
-                instance = (SAAJMetaFactory)FactoryFinder.find("javax.xml.soap.MetaFactory",
+                instance = (SAAJMetaFactory)FactoryFinder.find(SAAJMetaFactory.class,
                                                                "org.apache.axis2.saaj.SAAJMetaFactoryImpl");
             } catch (Exception exception) {
                 throw new SOAPException(exception.getMessage());

Modified: geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/SOAPConnectionFactory.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/SOAPConnectionFactory.java?rev=924365&r1=924364&r2=924365&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/SOAPConnectionFactory.java (original)
+++ geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/SOAPConnectionFactory.java Wed Mar 17 16:52:03 2010
@@ -42,7 +42,7 @@ public abstract class SOAPConnectionFact
             throws SOAPException, UnsupportedOperationException {
 
         try {
-            return (SOAPConnectionFactory)FactoryFinder.find(SF_PROPERTY,
+            return (SOAPConnectionFactory)FactoryFinder.find(SOAPConnectionFactory.class,
                                                              DEFAULT_SOAP_CONNECTION_FACTORY);
         } catch (Exception exception) {
             throw new SOAPException("Unable to create SOAP connection factory: "
@@ -61,7 +61,4 @@ public abstract class SOAPConnectionFact
 
     private static final String DEFAULT_SOAP_CONNECTION_FACTORY =
             "org.apache.axis2.saaj.SOAPConnectionFactoryImpl";
-
-    private static final String SF_PROPERTY =
-            "javax.xml.soap.SOAPConnectionFactory";
 }

Modified: geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/SOAPFactory.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/SOAPFactory.java?rev=924365&r1=924364&r2=924365&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/SOAPFactory.java (original)
+++ geronimo/specs/trunk/geronimo-saaj_1.3_spec/src/main/java/javax/xml/soap/SOAPFactory.java Wed Mar 17 16:52:03 2010
@@ -120,7 +120,7 @@ public abstract class SOAPFactory {
      */
     public static SOAPFactory newInstance() throws SOAPException {
         try {
-            SOAPFactory factory = (SOAPFactory)FactoryFinder.find(SOAP_FACTORY_PROPERTY);
+            return (SOAPFactory)FactoryFinder.find(SOAPFactory.class, null);
             if (factory == null) {
                 factory = newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
             }
@@ -192,7 +192,4 @@ public abstract class SOAPFactory {
     public abstract SOAPFault createFault(java.lang.String reasonText,
                                           javax.xml.namespace.QName faultCode)
             throws SOAPException;
-
-    private static final String SOAP_FACTORY_PROPERTY = "javax.xml.soap.SOAPFactory";
-
 }

Modified: geronimo/specs/trunk/geronimo-stax-api_1.0_spec/src/main/java/javax/xml/stream/FactoryLocator.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-stax-api_1.0_spec/src/main/java/javax/xml/stream/FactoryLocator.java?rev=924365&r1=924364&r2=924365&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-stax-api_1.0_spec/src/main/java/javax/xml/stream/FactoryLocator.java (original)
+++ geronimo/specs/trunk/geronimo-stax-api_1.0_spec/src/main/java/javax/xml/stream/FactoryLocator.java Wed Mar 17 16:52:03 2010
@@ -59,62 +59,58 @@ class FactoryLocator {
 
 	static Object locate(String factoryId, String altClassName,
 			ClassLoader classLoader) throws FactoryConfigurationError {
-		try {
-			String prop = System.getProperty(factoryId);
-			if (prop != null) {
-				return loadFactory(prop, classLoader);
-			}
-		} catch (Exception e) {
-		}
-
-		try {
-			String configFile = System.getProperty("java.home")
-					+ File.separator + "lib" + File.separator
-					+ "stax.properties";
-			File f = new File(configFile);
-			if (f.exists()) {
-				Properties props = new Properties();
-				props.load(new FileInputStream(f));
-				String factoryClassName = props.getProperty(factoryId);
-				return loadFactory(factoryClassName, classLoader);
-			}
-		} catch (Exception e) {
-		}
-
-		String serviceId = "META-INF/services/" + factoryId;
-		try {
-			InputStream is = null;
-
-			if (classLoader == null) {
-				is = ClassLoader.getSystemResourceAsStream(serviceId);
-			} else {
-				is = classLoader.getResourceAsStream(serviceId);
-			}
-
-			if (is != null) {
-				BufferedReader br = new BufferedReader(new InputStreamReader(
-						is, "UTF-8"));
-				String factoryClassName = br.readLine();
-				br.close();
-
-				if (factoryClassName != null && !"".equals(factoryClassName)) {
-					return loadFactory(factoryClassName, classLoader);
-				}
-			}
-		} catch (Exception ex) {
-		}
+        // NOTE:  The stax spec uses the following lookup order, which is the reverse from what is specified
+        // most of the APIs:
+        // 1. Use the javax.xml.stream.XMLInputFactory system property.
+        // 2. Use the properties file lib/xml.stream.properties in the JRE directory. This configuration
+        // file is in standard java.util.Properties format and contains the fully qualified name of the
+        // implementation class with the key being the system property defined in step 1.
+        // 3. Use the Services API (as detailed in the JAR specification), if available, to determine the
+        // classname. The Services API looks for a classname in the file META-INF/services/
+        // javax.xml.stream.XMLInputFactory in jars available to the runtime.
+        // 4. Platform default XMLInputFactory instance.
+
+
+        // Use the system property first
+        try {
+            String systemProp = System.getProperty(factoryId);
+            if (systemProp != null) {
+                return newInstance(systemProp, classLoader);
+            }
+        } catch (SecurityException se) {
+        }
+
+        try {
+            // NOTE:  The StAX spec gives this property file name as xml.stream.properties, but the javadoc and the maintenance release
+            // state this is stax.properties.
+            String factoryClassName =  ProviderLocator.lookupByJREPropertyFile("lib" + File.separator + "stax.properties", factoryId);
+            if (factoryClassName != null) {
+                return newInstance(factoryClassName, classLoader);
+            }
+        } catch (Exception ex) {
+        }
+
+        try {
+            // check the META-INF/services definitions, and return it if
+            // we find something.
+            Object service = ProviderLocator.getService(factoryId, FactoryLocator.class, classLoader);
+            if (service != null) {
+                return service;
+            }
+        } catch (Exception ex) {
+        }
 
 		if (altClassName == null) {
 			throw new FactoryConfigurationError("Unable to locate factory for "
 					+ factoryId + ".", null);
 		}
-		return loadFactory(altClassName, classLoader);
+		return newInstance(altClassName, classLoader);
 	}
 
-	private static Object loadFactory(String className, ClassLoader classLoader)
+	private static Object newInstance(String className, ClassLoader classLoader)
 			throws FactoryConfigurationError {
 		try {
-			return ProviderLocator.loadClass(className, classLoader).newInstance();
+			return ProviderLocator.loadClass(className, FactoryLocator.class, classLoader).newInstance();
 		} catch (ClassNotFoundException x) {
   			throw new FactoryConfigurationError("Requested factory "
   					+ className + " cannot be located.  Classloader ="

Modified: geronimo/specs/trunk/geronimo-validation_1.0_spec/src/main/java/javax/validation/Validation.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-validation_1.0_spec/src/main/java/javax/validation/Validation.java?rev=924365&r1=924364&r2=924365&view=diff
==============================================================================
--- geronimo/specs/trunk/geronimo-validation_1.0_spec/src/main/java/javax/validation/Validation.java (original)
+++ geronimo/specs/trunk/geronimo-validation_1.0_spec/src/main/java/javax/validation/Validation.java Wed Mar 17 16:52:03 2010
@@ -24,6 +24,7 @@ import java.net.URL;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Enumeration;
 import java.util.List;
 import java.util.Map;
@@ -182,10 +183,6 @@ public class Validation {
      * Geronimo implementation specific code.
      */
     private static class DefaultValidationProviderResolver implements ValidationProviderResolver {
-
-        private static final String SERVICES_FILENAME = "META-INF/services/" +
-            ValidationProvider.class.getName();
-
         // cache of providers per class loader
         private volatile WeakHashMap<ClassLoader, List<ValidationProvider<?>>> providerCache =
             new WeakHashMap<ClassLoader, List<ValidationProvider<?>>>();
@@ -209,52 +206,21 @@ public class Validation {
                 // need to discover and load them for this class loader
                 providers = new ArrayList<ValidationProvider<?>>();
                 try {
-                    // find all service provider files
-                    Enumeration<URL> cfgs = cl.getResources(SERVICES_FILENAME);
-                    while (cfgs.hasMoreElements()) {
-                        URL url = cfgs.nextElement();
-                        InputStream is = null;
-                        try {
-                            is = url.openStream();
-                            BufferedReader br = new BufferedReader(
-                                new InputStreamReader(is, "UTF-8"), 256);
-                            String line = br.readLine();
-                            // cfgs may contain multiple providers and/or comments
-                            while (line != null) {
-                                line = line.trim();
-                                if (!line.startsWith("#")) {
-                                    try {
-                                        Class<?> provider = null;
-                                        try {
-                                            // try loading the specified class
-                                            provider = ProviderLocator.loadClass(line, cl);
-                                        } catch (ClassNotFoundException e) {
-                                            throw new ValidationException("Failed to load provider " +
-                                                line + " configured in file " + url, e);
-                                        }
-                                        // create an instance to return
-                                        providers.add((ValidationProvider<?>) provider.newInstance());
-                                    } catch (InstantiationException e) {
-                                        throw new ValidationException("Failed to instantiate provider " +
-                                            line + " configured in file " + url, e);
-                                    } catch (IllegalAccessException e) {
-                                        throw new ValidationException("Failed to access provider " +
-                                            line + " configured in file " + url, e);
-                                    }
-                                }
-                                line = br.readLine();
-                            }
-                            is.close();
-                            is = null;
-                        } catch (IOException e) {
-                            throw new ValidationException("Error trying to read " + url, e);
-                        } finally {
-                            if (is != null)
-                                is.close();
-                        }
+                    List<Object> serviceProviders = ProviderLocator.getServices(ValidationProvider.class.getName(), this.getClass(), cl);
+                    for (Object provider : serviceProviders) {
+                        // create an instance to return
+                        providers.add((ValidationProvider<?>) provider);
                     }
-                } catch (IOException e) {
-                    throw new ValidationException("Error trying to load " + SERVICES_FILENAME, e);
+                } catch (ClassNotFoundException e) {
+                    throw new ValidationException("Failed to load provider", e);
+                } catch (InstantiationException e) {
+                    throw new ValidationException("Failed to instantiate provider", e);
+                } catch (IllegalAccessException e) {
+                    throw new ValidationException("Failed to access provider", e);
+                } catch (ClassCastException e) {
+                    throw new ValidationException("Invalid provider definition", e);
+                } catch (Exception e) {
+                    throw new ValidationException("Failed to instantiate provider", e);
                 }
 
                 // cache the discovered providers



Mime
View raw message