You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by dj...@apache.org on 2017/02/19 01:49:19 UTC
[02/51] [abbrv] geronimo-yoko git commit: Cache outbound connections
with reference counting.
http://git-wip-us.apache.org/repos/asf/geronimo-yoko/blob/f580371d/yoko-util/src/main/java/org/apache/yoko/util/concurrent/PNode.java
----------------------------------------------------------------------
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/PNode.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/PNode.java
new file mode 100644
index 0000000..9ee2fdf
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/PNode.java
@@ -0,0 +1,7 @@
+package org.apache.yoko.util.concurrent;
+
+interface PNode<T> {
+ NNode<T> next();
+
+ void next(NNode<T> nnode);
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/geronimo-yoko/blob/f580371d/yoko-util/src/main/java/org/apache/yoko/util/concurrent/ReferenceCountedCache.java
----------------------------------------------------------------------
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/ReferenceCountedCache.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/ReferenceCountedCache.java
new file mode 100644
index 0000000..b031a3a
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/ReferenceCountedCache.java
@@ -0,0 +1,124 @@
+package org.apache.yoko.util.concurrent;
+
+import org.apache.yoko.util.*;
+
+import java.lang.ref.ReferenceQueue;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class ReferenceCountedCache<K, V> implements Cache<K,V> {
+
+ private final ConcurrentMap<K, CountedEntry<K, V>> map = new ConcurrentHashMap<>();
+ private final Fifa<CountedEntry<K, V>> idleEntries = new ConcurrentFifo<>();
+ private volatile int threshold;
+ private volatile int sweep;
+ private final Cleaner<V> cleaner;
+ private final ReferenceQueue<Reference<V>> gcQueue;
+
+ /**
+ * Create a new cache
+ * @param cleaner the object to use to clean entries
+ * @param threshold the number of values above which to start cleaning up
+ * @param sweep the number of unused values to clear up
+ */
+ public ReferenceCountedCache(Cleaner<V> cleaner, int threshold, int sweep) {
+ this.threshold = threshold;
+ this.sweep = sweep;
+ this.cleaner = cleaner;
+ gcQueue = new ReferenceQueue<>();
+ }
+
+ @Override
+ public int size() {
+ return map.size();
+ }
+
+ @Override
+ public int idleCount() {
+ return idleEntries.size();
+ }
+
+ @Override
+ public Reference<V> get(K key) {
+ CountedEntry<K, V> entry = map.get(key);
+ if (entry == null) return null;
+ return entry == null ? null : track(entry.obtain());
+ }
+
+ @Override
+ public Reference<V> getOrCreate(K key, KeyedFactory<K, V> valueFactory) {
+ CountedEntry<K,V>.ValueReference result;
+ do {
+ CountedEntry<K, V> entry = map.get(key);
+ if (entry == null) {
+ // try putting a new entry in the map
+ CountedEntry<K, V> newEntry = new CountedEntry<>(key, idleEntries);
+ entry = map.putIfAbsent(key, newEntry);
+ if (entry == null) {
+ // this thread won the race to create the new entry
+ V value = null;
+ try {
+ value = valueFactory.create(key);
+ return track(newEntry.setValue(value));
+ } finally {
+ if (value == null) {
+ // create() threw an exception, so clean up
+ // and make sure no-one else tries to use this entry
+ newEntry.abort();
+ map.remove(key, newEntry);
+ }
+ }
+ }
+ }
+ result = entry.obtain();
+ } while (result == null); // the entry was cleared - try again
+ return track(result);
+ }
+
+ protected CountedEntry<K,V>.ValueReference track(CountedEntry<K,V>.ValueReference ref) {return ref;}
+
+ @Override
+ public final Reference<V> getOrCreate(K key, final Factory<V> factory) {
+ return getOrCreate(key, new KeyedFactory<K, V>() {
+ @Override
+ public V create(K key) {
+ return factory.create();
+ }
+ });
+ }
+
+ @Override
+ public void remove(Reference<V> ref) {remove(((CountedEntry<K,V>.ValueReference) ref).invalidateAndGetEntry());}
+
+ protected void remove(CountedEntry<K,V> entry) {if (entry != null) map.remove(entry.key, entry);}
+
+ @Override
+ public int clean() {
+ if (size() <= threshold) return 0;
+ int removed = 0;
+ while (removed < sweep) {
+ CountedEntry<K, V> e = idleEntries.peek();
+ if (e == null) break;
+ V clearedValue = e.clear();
+ if (clearedValue == null) continue;
+ if (!!!map.remove(e.key, e))
+ throw new IllegalStateException("Entry already removed");
+ cleaner.clean(clearedValue);
+ removed++;
+ }
+ return removed;
+ }
+
+ @Override
+ public Map<K, V> snapshot() {
+ Map<K, V> result = new HashMap<>();
+ for (Map.Entry<K,CountedEntry<K, V>> entry : map.entrySet()) {
+ try (Reference<V> ref = entry.getValue().obtain()){
+ result.put(entry.getKey(), ref.get());
+ } catch (NullPointerException ignored) {}
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/geronimo-yoko/blob/f580371d/yoko-util/src/main/java/org/apache/yoko/util/concurrent/StrongNode.java
----------------------------------------------------------------------
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/StrongNode.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/StrongNode.java
new file mode 100644
index 0000000..b870ca4
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/StrongNode.java
@@ -0,0 +1,29 @@
+package org.apache.yoko.util.concurrent;
+
+final class StrongNode<T> implements VNode<T> {
+ private final T value;
+ private PNode<T> prev;
+ private NNode<T> next;
+
+ StrongNode(T value) {this.value = value;}
+ public PNode<T> prev() {return prev;}
+ public NNode<T> next() {return next;}
+ public void prev(PNode<T> pnode) {prev = pnode;}
+ public void next(NNode<T> nnode) {next = nnode;}
+ public T get() {return value;}
+
+ public void insertAfter(PNode<T> pnode) {
+ NNode<T> nnode = pnode.next();
+ this.next = nnode;
+ this.prev = pnode;
+ nnode.prev(this);
+ pnode.next(this);
+ }
+
+ public void delete() {
+ this.prev.next(this.next);
+ this.next.prev(this.prev);
+ this.prev = null;
+ this.next = null;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/geronimo-yoko/blob/f580371d/yoko-util/src/main/java/org/apache/yoko/util/concurrent/VNode.java
----------------------------------------------------------------------
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/VNode.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/VNode.java
new file mode 100644
index 0000000..1aef732
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/VNode.java
@@ -0,0 +1,10 @@
+package org.apache.yoko.util.concurrent;
+
+public interface VNode<T> extends PNode<T>, NNode<T> {
+ T get();
+
+ void insertAfter(PNode<T> pnode);
+
+ void delete();
+
+}
http://git-wip-us.apache.org/repos/asf/geronimo-yoko/blob/f580371d/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakConcurrentFifo.java
----------------------------------------------------------------------
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakConcurrentFifo.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakConcurrentFifo.java
new file mode 100644
index 0000000..3dd9592
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakConcurrentFifo.java
@@ -0,0 +1,73 @@
+package org.apache.yoko.util.concurrent;
+
+import org.apache.yoko.util.KeyedFactory;
+import org.apache.yoko.util.Sequential;
+
+import java.lang.ref.ReferenceQueue;
+
+public class WeakConcurrentFifo<T> extends ConcurrentFifo<T> {
+ private final ReferenceQueue<T> refQueue = new ReferenceQueue<>();
+ private final KeyedFactory<? super T, Runnable> cleanupFactory;
+
+ WeakConcurrentFifo() {
+ this(NoOpRunnableFactory.INSTANCE);
+ }
+
+ WeakConcurrentFifo(KeyedFactory<? super T, Runnable> cleanupFactory) {
+ this.cleanupFactory = cleanupFactory;
+ }
+
+ @Override
+ public int size() {
+ cleanup();
+ return super.size();
+ }
+
+ @Override
+ public T peek() {
+ cleanup();
+ return super.peek();
+ }
+
+ @Override
+ public Place<T> put(T elem) {
+ cleanup();
+ return super.put(elem);
+ }
+
+ @Override
+ public T remove() {
+ cleanup();
+ return super.remove();
+ }
+
+ @Override
+ protected VNode<T> createNode(T elem) {
+ return new WeakNode<>(elem, refQueue, cleanupFactory.create(elem));
+ }
+
+ private void cleanup() {
+ do {
+ @SuppressWarnings("unchecked")
+ WeakNode<T> wn = (WeakNode<T>) refQueue.poll();
+ if (wn == null) return;
+ cleanup(wn);
+ } while (true);
+ }
+
+ private void cleanup(WeakNode<T> wn) {
+ RESPIN: do {
+ PNode<T> prev = wn.prev();
+ if (prev == null) return; // this node is already removed
+ synchronized (prev) {
+ if (wn.prev() != prev) continue RESPIN; // something changed!
+ synchronized (wn) {
+ wn.delete();
+ size.decrementAndGet();
+ wn.cleanup.run();
+ return;
+ }
+ }
+ } while (true);
+ }
+}
http://git-wip-us.apache.org/repos/asf/geronimo-yoko/blob/f580371d/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakCountedCache.java
----------------------------------------------------------------------
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakCountedCache.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakCountedCache.java
new file mode 100644
index 0000000..6c0dffe
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakCountedCache.java
@@ -0,0 +1,35 @@
+package org.apache.yoko.util.concurrent;
+
+import org.apache.yoko.util.KeyedFactory;
+
+public class WeakCountedCache<K, V> extends ReferenceCountedCache<K, V> {
+ private final WeakConcurrentFifo<CountedEntry<K,V>.ValueReference> referenceTracker
+ = new WeakConcurrentFifo<>(new CleanupFactory());
+
+ /**
+ * Create a new cache
+ *
+ * @param cleaner the object to use to clean entries
+ * @param threshold the number of values above which to start cleaning up
+ * @param sweep the number of unused values to clear up
+ */
+ public WeakCountedCache(Cleaner<V> cleaner, int threshold, int sweep) {
+ super(cleaner, threshold, sweep);
+ }
+
+ @Override
+ protected CountedEntry<K,V>.ValueReference track(CountedEntry<K,V>.ValueReference ref) {
+ if (ref != null)
+ referenceTracker.put(ref);
+ return ref;
+ }
+
+ private final class CleanupFactory implements KeyedFactory<CountedEntry<K,V>.ValueReference, Runnable> {
+ public Runnable create(CountedEntry<K, V>.ValueReference key) {
+ // Do NOT keep the key around, since this must only be held weakly.
+ // Instead, keep the closer task so we can clean up after the key is collected.
+ // Subsequent calls to close do nothing, so it's safe to run this multiple times.
+ return key.getCloserTask();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/geronimo-yoko/blob/f580371d/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakNode.java
----------------------------------------------------------------------
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakNode.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakNode.java
new file mode 100644
index 0000000..1235b5f
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakNode.java
@@ -0,0 +1,34 @@
+package org.apache.yoko.util.concurrent;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+final class WeakNode<T> extends WeakReference<T> implements VNode<T> {
+ final Runnable cleanup;
+ private PNode<T> prev;
+ private NNode<T> next;
+
+ WeakNode(T value, ReferenceQueue<T> q, Runnable cleanup) {
+ super(value, q);
+ this.cleanup = cleanup;
+ }
+ public PNode<T> prev() {return prev;}
+ public NNode<T> next() {return next;}
+ public void prev(PNode<T> pnode) {prev = pnode;}
+ public void next(NNode<T> nnode) {next = nnode;}
+
+ public void insertAfter(PNode<T> pnode) {
+ NNode<T> nnode = pnode.next();
+ this.next = nnode;
+ this.prev = pnode;
+ nnode.prev(this);
+ pnode.next(this);
+ }
+
+ public void delete() {
+ this.prev.next(this.next);
+ this.next.prev(this.prev);
+ this.prev = null;
+ this.next = null;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/geronimo-yoko/blob/f580371d/yoko-util/src/main/java/org/apache/yoko/util/osgi/ProviderLocator.java
----------------------------------------------------------------------
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/osgi/ProviderLocator.java b/yoko-util/src/main/java/org/apache/yoko/util/osgi/ProviderLocator.java
deleted file mode 100644
index dc8fffc..0000000
--- a/yoko-util/src/main/java/org/apache/yoko/util/osgi/ProviderLocator.java
+++ /dev/null
@@ -1,583 +0,0 @@
-/**
- * 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.yoko.util.osgi;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Properties;
-import java.util.Set;
-
-public class ProviderLocator {
- // a service tracker for the registry service
- // NB: This is declared as just Object to avoid classloading issues if we're running
- // outside of an OSGi environment.
- static private ProviderRegistry registry;
-
- private ProviderLocator() {
- // private constructor to prevent an instance from getting created.
- }
-
-
- public static void setRegistry(ProviderRegistry registry) {
- ProviderLocator.registry = registry;
- }
-
- /**
- * Locate a class by its provider id indicator. .
- *
- * @param providerId The provider id (generally, a fully qualified class name).
- *
- * @return The Class corresponding to this provider id. Returns null
- * if this is not registered or the indicated class can't be
- * loaded.
- */
- static public Class<?> locate(String providerId) {
- ProviderRegistry registry = getRegistry();
- // if no registry service available, this is a failure
- if (registry == null) {
- return null;
- }
- // get the service, if it exists. NB, if there is a service object,
- // then the extender and the interface class are available, so this cast should be
- // safe now.
-
- // the rest of the work is done by the registry
- return registry.locate(providerId);
- }
-
- /**
- * Locate all class files that match a given factory 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.
- */
- static public List<Class<?>> locateAll(String providerId) {
- Object registry = getRegistry();
-
- // if no registry service available, this is a failure
- if (registry == null) {
- return new ArrayList<Class<?>>();
- }
- // get the service, if it exists. NB, if there is a service object,
- // then the extender and the interface class are available, so this cast should be
- // safe now.
-
- // the rest of the work is done by the registry
- return ((ProviderRegistry)registry).locateAll(providerId);
- }
-
- /**
- * Utility class for locating a class with OSGi registry
- * support. Uses the thread context classloader as part of
- * the search order.
- *
- * @param className The name of the target class.
- *
- * @return The loaded class.
- * @exception ClassNotFoundException
- * Thrown if the class cannot be located.
- */
- static public Class<?> loadClass(String className) throws ClassNotFoundException {
- return loadClass(className, null, Thread.currentThread().getContextClassLoader());
- }
-
- /**
- * Utility class for locating a class with OSGi registry
- * support. Uses the thread context classloader as part of
- * the search order.
- *
- * @param className The name of the target class.
- *
- * @return The loaded class.
- * @exception ClassNotFoundException
- * Thrown if the class cannot be located.
- */
- static public Class<?> loadClass(String className, Class<?> contextClass) throws ClassNotFoundException {
- return loadClass(className, contextClass, Thread.currentThread().getContextClassLoader());
- }
-
- /**
- * Standardized utility method for performing class lookups
- * with support for OSGi registry lookups.
- *
- * @param className The name of the target class.
- * @param loader An optional class loader.
- *
- * @return The loaded class
- * @exception ClassNotFoundException
- * 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);
- } catch (ClassNotFoundException x) {
- }
- }
- if (contextClass != null) {
- loader = contextClass.getClassLoader();
- }
- // try again using the class context loader
- return Class.forName(className, true, loader);
- }
-
-
- /**
- * Get a single service instance that matches an interface
- * definition.
- *
- * @param iface The name of the required interface.
- * @param contextClass
- * The class requesting the lookup (used for class resolution).
- * @param loader A class loader to use for searching for service definitions
- * and loading classes.
- *
- * @return The service instance, or null if no matching services
- * can be found.
- * @exception Exception Thrown for any classloading or exceptions thrown
- * 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
- Object registry = getRegistry();
- if (registry != null) {
- // get the service, if it exists. NB, if there is a service object,
- // then the extender and the interface class are available, so this cast should be
- // safe now.
- // the rest of the work is done by the registry
- Object service = ((ProviderRegistry)registry).getService(iface);
- if (service != null) {
- return service;
- }
- }
-
- // try for a classpath locatable instance next. 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();
- }
- // a provider was not found
- return null;
- }
-
-
- /**
- * Locate a service class that matches an interface
- * definition.
- *
- * @param iface The name of the required interface.
- * @param contextClass
- * The class requesting the lookup (used for class resolution).
- * @param loader A class loader to use for searching for service definitions
- * and loading classes.
- *
- * @return The located class, or null if no matching services
- * can be found.
- * @exception Exception Thrown for any classloading exceptions thrown
- * trying to load the class.
- */
- static public Class<?> getServiceClass(String iface, Class<?> contextClass, ClassLoader loader) throws ClassNotFoundException {
- // 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
- Object registry = getRegistry();
- if (registry != null) {
- // get the service, if it exists. NB, if there is a service object,
- // then the extender and the interface class are available, so this cast should be
- // safe now.
-
- // If we've located stuff in the registry, then return it
- Class<?> cls = ((ProviderRegistry)registry).getServiceClass(iface);
- if (cls != null) {
- return cls;
- }
- }
-
- // 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);
- }
-
-
- /**
- * Get a list of services that match a given interface
- * name. This searches both the current class path and
- * the global repository for matches.
- *
- * @param iface The name of the required interface.
- * @param contextClass
- * The class requesting the lookup (used for class resolution).
- * @param loader A class loader to use for searching for service definitions
- * and loading classes.
- *
- * @return A list of matching services. Returns an empty list if there
- * are no matches.
- * @exception Exception Thrown for any classloading or exceptions thrown
- * trying to instantiate a service instance.
- */
- static public List<Object> getServices(String iface, Class<?> contextClass, ClassLoader loader) throws Exception {
- List<Object> services = new ArrayList<Object>();
-
- // 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.
- Object registry = getRegistry();
- if (registry != null) {
- // get the service, if it exists. NB, if there is a service object,
- // then the extender and the interface class are available, so this cast should be
- // safe now.
- // get any registered service instances now
- List<Object> globalServices = ((ProviderRegistry)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) {
- // create an instance of each of these classes
- for (Class<?> cls : classes) {
- services.add(cls.newInstance());
- }
- }
-
- // now return the merged set
- return services;
- }
-
-
- /**
- * Get a list of service class implementations that match
- * an interface name. This searches both the current class path and
- * the global repository for matches.
- *
- * @param iface The name of the required interface.
- * @param contextClass
- * The class requesting the lookup (used for class resolution).
- * @param loader A class loader to use for searching for service definitions
- * and loading classes.
- *
- * @return A list of matching provider classes. Returns an empty list if there
- * are no matches.
- * @exception Exception Thrown for any classloading exceptions thrown
- * trying to load a provider class.
- */
- static public List<Class<?>> getServiceClasses(String iface, Class<?> contextClass, ClassLoader loader) throws Exception {
- Set<Class<?>> serviceClasses = new LinkedHashSet<Class<?>>();
-
- // 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.
- Object registry = getRegistry();
- if (registry != null) {
- // get the service, if it exists. NB, if there is a service object,
- // then the extender and the interface class are available, so this cast should be
- // safe now.
- // get any registered service provider classes now
- List<Class<?>> globalServices = ((ProviderRegistry)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);
- }
-
-
- /**
- * Locate the first class name for a META-INF/services definition
- * of a given class. The first matching provider is
- * returned.
- *
- * @param iface The interface class name used for the match.
- * @param loader The classloader for locating resources.
- *
- * @return The mapped provider name, if found. Returns null if
- * no mapping is located.
- */
- static private String locateServiceClassName(String iface, Class<?> contextClass, ClassLoader loader) {
- // search first with the loader class path
- String name = locateServiceClassName(iface, loader);
- if (name != null) {
- return name;
- }
- // then with the context class, if there is one
- if (contextClass != null) {
- name = locateServiceClassName(iface, contextClass.getClassLoader());
- if (name != null) {
- return name;
- }
- }
- // not found
- return null;
- }
-
-
- /**
- * 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 {
- // we only look at resources that match the file name, using the specified loader
- String service = "META-INF/services/" + iface;
- Enumeration<URL> providers = loader.getResources(service);
-
- while (providers.hasMoreElements()) {
- List<String>providerNames = parseServiceDefinition(providers.nextElement());
- // if there is something defined here, return the first entry
- if (!providerNames.isEmpty()) {
- return providerNames.get(0);
- }
- }
- } catch (IOException e) {
- }
- }
- // not found
- return null;
- }
-
-
- /**
- * Locate the first class for a META-INF/services definition
- * of a given interface class. The first matching provider is
- * returned.
- *
- * @param iface The interface class name used for the match.
- * @param loader The classloader for locating resources.
- *
- * @return The mapped provider class, if found. Returns null if
- * no mapping is located.
- */
- static private Class<?> locateServiceClass(String iface, Class<?> contextClass, ClassLoader loader) throws ClassNotFoundException {
- String className = locateServiceClassName(iface, contextClass, loader);
- if (className == null) {
- return null;
- }
-
- // we found a name, try loading the class. This will throw an exception if there is an error
- return loadClass(className, contextClass, loader);
- }
-
-
- /**
- * Locate all class names name for a META-INF/services definition
- * of a given class.
- *
- * @param iface The interface class name used for the match.
- * @param loader The classloader for locating resources.
- *
- * @return The mapped provider name, if found. Returns null if
- * no mapping is located.
- */
- static private Collection<String> locateServiceClassNames(String iface, Class<?> contextClass, ClassLoader loader) {
- Set<String> names = new LinkedHashSet<String>();
-
- locateServiceClassNames(iface, loader, names);
- if (contextClass != null) {
- locateServiceClassNames(iface, contextClass.getClassLoader(), names);
- }
-
- return names;
- }
-
-
- /**
- * Locate all class names name for a META-INF/services definition
- * of a given class.
- *
- * @param iface The interface class name used for the match.
- * @param loader The classloader for locating resources.
- *
- * @return The mapped provider name, if found. Returns null if
- * no mapping is located.
- */
- static void locateServiceClassNames(String iface, ClassLoader loader, Set names) {
- if (loader != null) {
-
- try {
- // we only look at resources that match the file name, using the specified loader
- String service = "META-INF/services/" + iface;
- Enumeration<URL> providers = loader.getResources(service);
-
- while (providers.hasMoreElements()) {
- List<String>providerNames = parseServiceDefinition(providers.nextElement());
- // just add all of these to the list
- names.addAll(providerNames);
- }
- } catch (IOException e) {
- }
- }
- }
-
-
- /**
- * Locate all classes that map to a given provider class definition. This will
- * search both the services directories, as well as the provider classes from the
- * OSGi provider registry.
- *
- * @param iface The interface class name used for the match.
- * @param loader The classloader for locating resources.
- *
- * @return A list of all mapped classes, if found. Returns an empty list if
- * no mappings are found.
- */
- static private Collection<Class<?>> locateServiceClasses(String iface, Class<?> contextClass, ClassLoader loader) throws ClassNotFoundException {
- // get the set of names from services definitions on the classpath
- Collection<String> classNames = locateServiceClassNames(iface, contextClass, loader);
- Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
-
- // load each class and add to our return set
- for (String name : classNames) {
- classes.add(loadClass(name, contextClass, loader));
- }
- return classes;
- }
-
-
- /**
- * Parse a definition file and return the names of all included implementation classes
- * contained within the file.
- *
- * @param u The URL of the file
- *
- * @return A list of all matching classes. Returns an empty list
- * if no matches are found.
- */
- static private List<String> parseServiceDefinition(URL u) {
- final String url = u.toString();
- List<String> classes = new ArrayList<String>();
- // ignore directories
- if (url.endsWith("/")) {
- return classes;
- }
- // 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"));
- // 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
- classes.add(line);
- }
- // keep reading until the end.
- line = br.readLine();
- }
- br.close();
- } catch (IOException e) {
- // ignore errors and handle as default
- }
- return classes;
- }
-
- /**
- * Perform a service class discovery by looking for a
- * property in a target properties file located in the
- * java.home directory.
- *
- * @param path The relative path to the desired properties file.
- * @param property The name of the required property.
- *
- * @return The value of the named property within the properties file. Returns
- * null if the property doesn't exist or the properties file doesn't exist.
- */
- public static String lookupByJREPropertyFile(String path, String property) throws IOException {
- String jreDirectory = System.getProperty("java.home");
- File configurationFile = new File(jreDirectory + File.separator + path);
- if (configurationFile.exists() && configurationFile.canRead()) {
- Properties properties = new Properties();
- InputStream in = null;
- try {
- in = new FileInputStream(configurationFile);
- properties.load(in);
- return properties.getProperty(property);
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (Exception e) {
- }
- }
- }
- }
- return null;
- }
-
-
- /**
- * Retrieve the registry from the tracker if it is available,
- * all without causing the interface class to load.
- *
- * @return The registry service instance, or null if it is not
- * available for any reason.
- */
- private static ProviderRegistry getRegistry() {
- return registry;
- }
-}
http://git-wip-us.apache.org/repos/asf/geronimo-yoko/blob/f580371d/yoko-util/src/main/java/org/apache/yoko/util/osgi/ProviderRegistry.java
----------------------------------------------------------------------
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/osgi/ProviderRegistry.java b/yoko-util/src/main/java/org/apache/yoko/util/osgi/ProviderRegistry.java
deleted file mode 100644
index 8978c2f..0000000
--- a/yoko-util/src/main/java/org/apache/yoko/util/osgi/ProviderRegistry.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- * 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.yoko.util.osgi;
-
-import java.util.List;
-
-/**
- * The implementation of the factory registry used to store
- * the bundle registrations.
- */
-public interface ProviderRegistry {
- /**
- * Locate a class by its factory id indicator. .
- *
- * @param factoryId The factory id (generally, a fully qualified class name).
- *
- * @return The Class corresponding to this factory id. Returns null
- * if this is not registered or the indicated class can't be
- * loaded.
- */
- public Class<?> locate(String factoryId);
-
- /**
- * Locate all class files that match a given factory id.
- *
- * @param factoryId The target factory identifier.
- *
- * @return A List containing the class objects corresponding to the
- * factory identifier. Returns an empty list if no
- * 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);
-
-}
http://git-wip-us.apache.org/repos/asf/geronimo-yoko/blob/f580371d/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/BundleProviderLoader.java
----------------------------------------------------------------------
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/BundleProviderLoader.java b/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/BundleProviderLoader.java
deleted file mode 100644
index ec50364..0000000
--- a/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/BundleProviderLoader.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * 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.yoko.util.osgi.locator;
-
-import org.osgi.framework.Bundle;
-
-/**
- * Holder class for located services information.
- */
-public class BundleProviderLoader implements Comparable<BundleProviderLoader> {
- // the class name for this provider
- private final String providerId;
- // the mapped class name of the provider.
- private final String providerClass;
- // the hosting bundle.
- private final Bundle bundle;
-
- private final int priority;
-
- /**
- * Create a loader for this registered provider.
- *
- * @param providerId The provider ID
- * @param providerClass The mapped class name of the provider.
- * @param bundle The hosting bundle.
- * @param priority
- */
- public BundleProviderLoader(String providerId, String providerClass, Bundle bundle, int priority) {
- this.providerId = providerId;
- this.providerClass = providerClass;
- this.bundle = bundle;
- this.priority = priority;
- }
-
- /**
- * Load a provider class.
- *
- * @return The provider class from the target bundle.
- * @exception Exception
- */
- public Class<?> loadClass() throws ClassNotFoundException {
- try {
-// 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) {
-// log(LogService.LOG_DEBUG, "exception caught while creating " + this, e);
- throw e;
- } catch (Error e) {
-// log(LogService.LOG_DEBUG, "error caught while creating " + this, e);
- throw e;
- }
- }
-
-
- public String id() {
- return providerId;
- }
-
- @Override
- public String toString() {
- return "Provider interface=" + providerId + " , provider class=" + providerClass + ", bundle=" + bundle;
- }
-
- @Override
- public int hashCode() {
- return providerId.hashCode() + providerClass.hashCode() + (int)bundle.getBundleId();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof BundleProviderLoader) {
- return providerId.equals(((BundleProviderLoader)obj).providerId) &&
- providerClass.equals(((BundleProviderLoader)obj).providerClass) &&
- bundle.getBundleId() == ((BundleProviderLoader)obj).bundle.getBundleId();
- } else {
- return false;
- }
- }
-
- public int compareTo(BundleProviderLoader other) {
- return other.priority - priority;
- }
-}
http://git-wip-us.apache.org/repos/asf/geronimo-yoko/blob/f580371d/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/ProviderBean.java
----------------------------------------------------------------------
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/ProviderBean.java b/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/ProviderBean.java
deleted file mode 100644
index f2271f9..0000000
--- a/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/ProviderBean.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.yoko.util.osgi.locator;
-
-import java.util.logging.Logger;
-
-import org.osgi.framework.Bundle;
-
-/**
- * @version $Rev$ $Date$
- */
-public class ProviderBean {
- private static final Logger log = Logger.getLogger(ProviderBean.class.getName());
-
- private Register providerRegistry;
-
- private BundleProviderLoader bundleProviderLoader;
-
- public ProviderBean(String key,
- String className,
- Bundle bundle,
- Register providerRegistry) {
- this(key, className, bundle, providerRegistry, -1);
- }
-
- public ProviderBean(String key,
- String className,
- Bundle bundle,
- Register providerRegistry,
- Integer priority) {
- bundleProviderLoader = new BundleProviderLoader(key, className, bundle, priority == null? -1: priority);
- log.finer("ProviderBean: " + bundleProviderLoader);
- this.providerRegistry = providerRegistry;
- }
-
-
-
- public void start() {
- providerRegistry.registerProvider(bundleProviderLoader);
- }
-
- public void stop() {
- providerRegistry.unregisterProvider(bundleProviderLoader);
- }
-}
http://git-wip-us.apache.org/repos/asf/geronimo-yoko/blob/f580371d/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/ProviderRegistryImpl.java
----------------------------------------------------------------------
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/ProviderRegistryImpl.java b/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/ProviderRegistryImpl.java
deleted file mode 100644
index 7a1feec..0000000
--- a/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/ProviderRegistryImpl.java
+++ /dev/null
@@ -1,326 +0,0 @@
-/**
- * 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.yoko.util.osgi.locator;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import org.apache.yoko.util.osgi.ProviderLocator;
-
-/**
- * The implementation of the provider registry used to store
- * the bundle registrations.
- */
-public class ProviderRegistryImpl implements org.apache.yoko.util.osgi.ProviderRegistry, Register {
-
- private static final Logger log = Logger.getLogger(ProviderRegistryImpl.class.getName());
- // 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();
- // 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();
-
- public void start() {
- ProviderLocator.setRegistry(this);
- }
-
- public void stop() {
- ProviderLocator.setRegistry(null);
- }
-
- /**
- * Register an individual provivider item by its provider identifier.
- *
- * @param provider The loader used to resolve the provider class.
- */
- public void registerProvider(BundleProviderLoader provider) {
- log(Level.FINE, "registering provider " + provider);
- providers.register(provider);
- }
-
- /**
- * Removed a provider registration for a named provider id.
- *
- * @param provider The provider registration instance
- */
- public void unregisterProvider(BundleProviderLoader provider) {
- log(Level.FINE, "unregistering provider " + provider);
- providers.unregister(provider);
- }
-
-
- /**
- * Register an individual provivider item by its provider identifier.
- *
- * @param provider The loader used to resolve the provider class.
- */
- public void registerService(BundleProviderLoader provider) {
- log(Level.FINE, "registering service " + provider);
- serviceProviders.register(provider);
- }
-
- /**
- * Removed a provider registration for a named provider id.
- *
- * @param provider The provider registration instance
- */
- public void unregisterService(BundleProviderLoader provider) {
- log(Level.FINE, "unregistering service " + provider);
- serviceProviders.unregister(provider);
- }
-
- /**
- * Locate a class by its provider id indicator. .
- *
- * @param providerId The provider id (generally, a fully qualified class name).
- *
- * @return The Class corresponding to this provider id. Returns null
- * if this is not registered or the indicated class can't be
- * loaded.
- */
- 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) {
- e.printStackTrace();
- // 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 {
- 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 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 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) {
- List<Object> instances = new ArrayList<Object>();
- List<BundleProviderLoader> l = serviceProviders.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 List<Class<?>> getServiceClasses(String providerId) {
- List<Class<?>> classes = new ArrayList<Class<?>>();
- 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.
- }
- }
- }
- 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 ClassNotFoundException 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(Level level, String message) {
- log.log(level, message);
- }
-
- /**
- * 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 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>(2);
- registry.put(providerId, l);
- }
- l.add(provider);
- Collections.sort(l);
- }
-
- /**
- * 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) {
- log.fine("registry: " + registry);
- // 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;
- }
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/geronimo-yoko/blob/f580371d/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/Register.java
----------------------------------------------------------------------
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/Register.java b/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/Register.java
deleted file mode 100644
index 2868a93..0000000
--- a/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/Register.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.yoko.util.osgi.locator;
-
-/**
- * @version $Rev$ $Date$
- */
-public interface Register {
-
- void registerProvider(BundleProviderLoader provider);
-
- void unregisterProvider(BundleProviderLoader provider);
-
- void registerService(BundleProviderLoader provider);
-
- void unregisterService(BundleProviderLoader provider);
-
-}
http://git-wip-us.apache.org/repos/asf/geronimo-yoko/blob/f580371d/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/ServiceBean.java
----------------------------------------------------------------------
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/ServiceBean.java b/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/ServiceBean.java
deleted file mode 100644
index 8f3fcb6..0000000
--- a/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/ServiceBean.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.yoko.util.osgi.locator;
-
-import java.util.logging.Logger;
-
-import org.osgi.framework.Bundle;
-
-/**
- * @version $Rev$ $Date$
- */
-public class ServiceBean {
- private static final Logger log = Logger.getLogger(ServiceBean.class.getName());
-
- private Register providerRegistry;
-
- private BundleProviderLoader bundleProviderLoader;
-
- public ServiceBean(String key,
- String className,
- Bundle bundle,
- Register providerRegistry) {
- this(key, className, bundle, providerRegistry, -1);
- }
-
- public ServiceBean(String key,
- String className,
- Bundle bundle,
- Register providerRegistry,
- Integer priority) {
- bundleProviderLoader = new BundleProviderLoader(key, className, bundle, priority == null? -1: priority);
- log.finer("ServiceBean: " + bundleProviderLoader);
- this.providerRegistry = providerRegistry;
- }
-
-
-
- public void start() {
- providerRegistry.registerService(bundleProviderLoader);
- }
-
- public void stop() {
- providerRegistry.unregisterService(bundleProviderLoader);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/geronimo-yoko/blob/f580371d/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/activator/AbstractBundleActivator.java
----------------------------------------------------------------------
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/activator/AbstractBundleActivator.java b/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/activator/AbstractBundleActivator.java
deleted file mode 100644
index 2e82ffc..0000000
--- a/yoko-util/src/main/java/org/apache/yoko/util/osgi/locator/activator/AbstractBundleActivator.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package org.apache.yoko.util.osgi.locator.activator;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.yoko.util.osgi.locator.BundleProviderLoader;
-import org.apache.yoko.util.osgi.locator.Register;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
-
-public abstract class AbstractBundleActivator implements BundleActivator {
-
- public static class Info {
- final String id;
- final String className;
- final int priority;
-
- public Info(String id, String className, int priority) {
- super();
- this.id = id;
- this.className = className;
- this.priority = priority;
- }
-
- }
- private final Info[] providerInfo;
- private final Info[] serviceInfo;
- private ServiceTracker<Register, Register> tracker;
- private BundleContext context;
- private boolean registered;
- private final List<BundleProviderLoader> providerLoaders = new ArrayList<BundleProviderLoader>();
- private final List<BundleProviderLoader> serviceLoaders = new ArrayList<BundleProviderLoader>();
-
- public AbstractBundleActivator(Info[] providerInfo, Info[] serviceInfo) {
- this.providerInfo = providerInfo;
- this.serviceInfo = serviceInfo;
- }
-
- public void start(final BundleContext context) throws Exception {
- this.context = context;
- tracker = new ServiceTracker<Register, Register>(context, Register.class, new ServiceTrackerCustomizer<Register, Register>() {
-
- public Register addingService(ServiceReference<Register> reference) {
- Register register = context.getService(reference);
- register(register);
- return register;
- }
-
- public void modifiedService(ServiceReference<Register> reference,
- Register service) {
- // TODO Auto-generated method stub
-
- }
-
- public void removedService(ServiceReference<Register> reference,
- Register service) {
- // TODO Auto-generated method stub
-
- }
-
- });
- tracker.open();
- Register register = tracker.getService();
- if (register != null) {
- register(register);
- }
-
- }
-
- private synchronized void register(Register register) {
- if (!registered) {
- registered = true;
- Bundle bundle = context.getBundle();
- for (Info classInfo: providerInfo) {
- BundleProviderLoader loader = new BundleProviderLoader(classInfo.id, classInfo.className, bundle, classInfo.priority);
- providerLoaders.add(loader);
- register.registerProvider(loader);
- }
- for (Info classInfo: serviceInfo) {
- BundleProviderLoader loader = new BundleProviderLoader(classInfo.id, classInfo.className, bundle, classInfo.priority);
- serviceLoaders.add(loader);
- register.registerService(loader);
- }
- }
- }
-
- public void stop(BundleContext context) throws Exception {
- Register register = tracker.getService();
- tracker.close();
- synchronized (this) {
- if (register != null && registered) {
- for (BundleProviderLoader loader: providerLoaders) {
- register.unregisterProvider(loader);
- }
- for (BundleProviderLoader loader: serviceLoaders) {
- register.unregisterService(loader);
- }
- }
- }
-
- }
-
-}
http://git-wip-us.apache.org/repos/asf/geronimo-yoko/blob/f580371d/yoko-util/src/test/java/org/apache/yoko/util/concurrent/ConcurrentFifoTest.java
----------------------------------------------------------------------
diff --git a/yoko-util/src/test/java/org/apache/yoko/util/concurrent/ConcurrentFifoTest.java b/yoko-util/src/test/java/org/apache/yoko/util/concurrent/ConcurrentFifoTest.java
new file mode 100644
index 0000000..4818250
--- /dev/null
+++ b/yoko-util/src/test/java/org/apache/yoko/util/concurrent/ConcurrentFifoTest.java
@@ -0,0 +1,274 @@
+package org.apache.yoko.util.concurrent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.apache.yoko.util.Sequential;
+import org.junit.Before;
+import org.junit.Test;
+
+@SuppressWarnings("unused")
+public class ConcurrentFifoTest {
+ private static final List<String> ELEMS = new ArrayList<>();
+
+ static {
+ for (char c1 = 'A'; c1 <= 'Z'; c1++)
+ for (char c2 = 'a'; c2 <= 'z'; c2++)
+ ELEMS.add("" + c1 + c2);
+ }
+
+ ConcurrentFifo<String> fifo;
+ Set<Sequential.Place<String>> places;
+ volatile CyclicBarrier startBarrier;
+
+ @Before
+ public void setupFifo() {
+ fifo = new ConcurrentFifo<>();
+ }
+
+ @Before
+ public void setupPlaces() {
+ places = Collections.newSetFromMap(new ConcurrentHashMap<Sequential.Place<String>, Boolean>());
+ }
+
+ @Before
+ public void nullifyStartBarrier() {
+ startBarrier = null;
+ }
+
+ @Test
+ public void testPuttingStuff() throws Exception {
+ // create tasks
+ List<Adder> tasks = new ArrayList<>();
+ for (String dummy : ELEMS)
+ tasks.add(new Adder());
+
+ // run the tasks concurrently
+ List<List<String>> expectedOrders = runConcurrently(tasks);
+
+ // convert the fifo to a list
+ List<String> actualOrder = drainFifo();
+
+ assertEquals(ELEMS.size() * ELEMS.size(), actualOrder.size());
+
+ // check correct ordering per Adder:
+ // as we tally the elements in order,
+ // the number of ELEM[n] encountered
+ // should always be greater than or
+ // equal to the number of ELEM[n+1]
+ // encountered
+ TreeMap<String, Integer> tallySheet = new TreeMap<>();
+ // start with zero for every element
+ for (String elem : ELEMS) tallySheet.put(elem, 0);
+ // place known elephant in Cairo
+ tallySheet.put("", Integer.MAX_VALUE);
+ int index = -1;
+ for (String elem : actualOrder) {
+ index ++;
+ int newTally = tallySheet.get(elem) + 1;
+ tallySheet.put(elem, newTally);
+ Entry<String, Integer> lowerEntry = tallySheet.lowerEntry(elem);
+ String msg = String.format("Element out of order at index %d: %d \"%s\" found but only %d \"%s\"", index, newTally, elem, lowerEntry.getValue(), lowerEntry.getKey());
+ assertTrue(msg, lowerEntry.getValue() >= newTally);
+ }
+ }
+
+ @Test
+ public void testPickingStuff() throws Exception {
+ // pre-populate elements
+ for (String elem : ELEMS)
+ places.add(fifo.put(elem));
+
+ // create tasks
+ List<Constrictor> tasks = new ArrayList<>();
+ for (String elem : ELEMS)
+ tasks.add(new Constrictor());
+
+ // run the tasks concurrently
+ List<List<String>> removalLists = runConcurrently(tasks);
+ for (List<String> list : removalLists) if (!!!list.isEmpty()) System.out.println(list);
+
+ // convert the queue to a list
+ List<String> remainingElements = drainFifo();
+
+ // check for the right number of entries
+ assertEquals(Collections.emptyList(), remainingElements);
+
+ // check everything was removed exactly once
+ List<String> checkedRemovals = concatenate(removalLists);
+ Collections.sort(checkedRemovals);
+ assertEquals(ELEMS, checkedRemovals);
+ }
+
+ @Test
+ public void testGettingStuff() throws Exception {
+ // pre-populate elements
+ for (String elem : ELEMS)
+ places.add(fifo.put(elem));
+
+ // create tasks
+ List<Wiper> tasks = new ArrayList<>();
+ for (String elem : ELEMS)
+ tasks.add(new Wiper());
+
+ // run the tasks concurrently
+ List<List<String>> removalLists = runConcurrently(tasks);
+ for (List<String> list : removalLists) if (!!!list.isEmpty()) System.out.println(list);
+
+ // convert the queue to a list
+ List<String> remainingElements = drainFifo();
+
+ // check for the right number of entries
+ assertEquals(Collections.emptyList(), remainingElements);
+
+ // check everything was removed exactly once
+ List<String> checkedRemovals = concatenate(removalLists);
+ Collections.sort(checkedRemovals);
+ assertEquals(ELEMS, checkedRemovals);
+
+ // check no-one removed anything out of order
+ // i.e. each list of removed elements should remain unchanged by sorting
+ for (List<String> removed : removalLists)
+ assertEquals(new ArrayList<>(new TreeSet<>(removed)), removed);
+ }
+
+ @Test
+ public void testAllOpsConcurrently() throws Exception {
+ // pre-populate all the possible elements
+ for (String elem : ELEMS)
+ places.add(fifo.put(elem));
+
+ // create tasks
+ List<Callable<List<String>>> tasks = new ArrayList<>();
+ for (int i = 0; i < 1000; i++) {
+ switch (i % 4) {
+ case 0:
+ case 2:
+ tasks.add(new Adder());
+ break;
+ case 1:
+ tasks.add(new Constrictor());
+ break;
+ case 3:
+ tasks.add(new Wiper());
+ break;
+ }
+ }
+
+ List<String> added = new ArrayList<>(), removed = new ArrayList<>();
+
+ // collate additions and subtractions
+ Iterator<Callable<List<String>>> iterator = tasks.iterator();
+ for (List<String> results : runConcurrently(tasks))
+ (iterator.next() instanceof Adder ? added : removed).addAll(results);
+ added.addAll(ELEMS); // these were added up front
+ Collections.sort(added);
+ List<String> remainder = drainFifo();
+ removed.addAll(remainder);
+ Collections.sort(removed);
+
+ assertEquals(added, removed);
+
+ }
+
+ private <T> List<T> concatenate(List<List<T>> lists) {
+ List<T> result = new ArrayList<>();
+ for (List<T> list : lists)
+ result.addAll(list);
+ return result;
+ }
+
+ private List<String> drainFifo() {
+ List<String> queuedOrder = new ArrayList<>();
+ do {
+ String o = fifo.remove();
+ if (o == null) break;
+ queuedOrder.add(o);
+ } while (true);
+ return queuedOrder;
+ }
+
+ private <T> List<T> runConcurrently(List<? extends Callable<T>> tasks)
+ throws InterruptedException, ExecutionException {
+ // start all the threads
+ startBarrier = new CyclicBarrier(tasks.size());
+ ExecutorService xs = Executors.newFixedThreadPool(tasks.size());
+ try {
+ List<Future<T>> futures = new ArrayList<>();
+ for (Callable<T> task : tasks)
+ futures.add(xs.submit(task));
+
+ // collect the results
+ List<T> results = new ArrayList<>();
+ for (Future<T> future : futures)
+ results.add(future.get());
+ return results;
+ } finally {
+ xs.shutdown();
+ }
+ }
+
+ /** Adds stuff to the FIFO */
+ class Adder implements Callable<List<String>> {
+ @Override
+ public List<String> call() throws Exception {
+ List<String> added = new ArrayList<>();
+ startBarrier.await();
+ for (String elem : new ArrayList<>(ELEMS)) {
+ places.add(fifo.put(elem));
+ added.add(elem);
+ }
+ return added;
+ }
+ }
+
+ /** Constrains the FIFO by removing specific elements */
+ class Constrictor implements Callable<List<String>> {
+ @Override
+ public List<String> call() throws Exception {
+ List<String> constricted = new ArrayList<>();
+ startBarrier.await();
+ while (!!! places.isEmpty()) {
+ // get a copy of the known places in the fifo and shuffle it
+ List<Sequential.Place<String>> myPlaces = new ArrayList<>(places);
+ Collections.shuffle(myPlaces);
+ // remove everything we can
+ for (Sequential.Place<String> place : myPlaces) {
+ String elem = place.relinquish();
+ if (elem != null)
+ constricted.add(elem);
+ places.remove(place);
+ }
+ }
+ return constricted;
+ }
+ }
+
+ /** Wipes out the FIFO by getting all the elements */
+ class Wiper implements Callable<List<String>> {
+ @Override
+ public List<String> call() throws Exception {
+ List<String> wiped = new ArrayList<>();
+ startBarrier.await();
+ for (String elem = fifo.remove(); elem != null; elem = fifo.remove())
+ wiped.add(elem);
+ return wiped;
+ }
+ }
+}