You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tika.apache.org by ju...@apache.org on 2011/10/31 16:00:17 UTC

svn commit: r1195494 - in /tika/trunk/tika-core/src/main/java/org/apache/tika/config: ServiceLoader.java TikaActivator.java

Author: jukka
Date: Mon Oct 31 15:00:16 2011
New Revision: 1195494

URL: http://svn.apache.org/viewvc?rev=1195494&view=rev
Log:
TIKA-565: Improved OSGi bundling

Listen for all Parser and Detector services within an OSGi environment

Modified:
    tika/trunk/tika-core/src/main/java/org/apache/tika/config/ServiceLoader.java
    tika/trunk/tika-core/src/main/java/org/apache/tika/config/TikaActivator.java

Modified: tika/trunk/tika-core/src/main/java/org/apache/tika/config/ServiceLoader.java
URL: http://svn.apache.org/viewvc/tika/trunk/tika-core/src/main/java/org/apache/tika/config/ServiceLoader.java?rev=1195494&r1=1195493&r2=1195494&view=diff
==============================================================================
--- tika/trunk/tika-core/src/main/java/org/apache/tika/config/ServiceLoader.java (original)
+++ tika/trunk/tika-core/src/main/java/org/apache/tika/config/ServiceLoader.java Mon Oct 31 15:00:16 2011
@@ -24,8 +24,10 @@ import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Enumeration;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.regex.Pattern;
 
@@ -43,6 +45,15 @@ public class ServiceLoader {
     private static volatile ClassLoader contextClassLoader = null;
 
     /**
+     * The dynamic set of services available in an OSGi environment.
+     * Managed by the {@link TikaActivator} class and used as an additional
+     * source of service instances in the {@link #loadServiceProviders(Class)}
+     * method.
+     */
+    private static final Map<Object, Object> services =
+            new HashMap<Object, Object>();
+
+    /**
      * Returns the context class loader of the current thread. If such
      * a class loader is not available, then the loader of this class or
      * finally the system class loader is returned.
@@ -74,6 +85,18 @@ public class ServiceLoader {
         contextClassLoader = loader;
     }
 
+    static void addService(Object reference, Object service) {
+        synchronized (services) {
+            services.put(reference, service);
+        }
+    }
+
+    static Object removeService(Object reference) {
+        synchronized (services) {
+            return services.remove(reference);
+        }
+    }
+
     private final ClassLoader loader;
 
     private final LoadErrorHandler handler;
@@ -90,7 +113,7 @@ public class ServiceLoader {
     public ServiceLoader() {
         this(getContextClassLoader());
     }
-    
+
     /**
      * Returns all the available service resources matching the
      *  given pattern, such as all instances of tika-mimetypes.xml 
@@ -111,18 +134,27 @@ public class ServiceLoader {
     /**
      * Returns all the available service providers of the given type.
      *
-     * @param service service provider interface
+     * @param iface service provider interface
      * @return available service providers
      */
     @SuppressWarnings("unchecked")
-    public <T> List<T> loadServiceProviders(Class<T> service) {
+    public <T> List<T> loadServiceProviders(Class<T> iface) {
         List<T> providers = new ArrayList<T>();
 
+        synchronized (services) {
+            for (Object service : services.values()) {
+                if (iface.isAssignableFrom(service.getClass())) {
+                    providers.add((T) service);
+                }
+            }
+        }
+
         if (loader != null) {
             Set<String> names = new HashSet<String>();
 
-            String serviceName = service.getName();
-            Enumeration<URL> resources = findServiceResources("META-INF/services/" + serviceName);
+            String serviceName = iface.getName();
+            Enumeration<URL> resources =
+                    findServiceResources("META-INF/services/" + serviceName);
             for (URL resource : Collections.list(resources)) {
                 try {
                     names.addAll(getServiceClassNames(resource));
@@ -134,7 +166,7 @@ public class ServiceLoader {
             for (String name : names) {
                 try {
                     Class<?> klass = loader.loadClass(name);
-                    if (service.isAssignableFrom(klass)) {
+                    if (iface.isAssignableFrom(klass)) {
                         providers.add((T) klass.newInstance());
                     }
                 } catch (Throwable t) {

Modified: tika/trunk/tika-core/src/main/java/org/apache/tika/config/TikaActivator.java
URL: http://svn.apache.org/viewvc/tika/trunk/tika-core/src/main/java/org/apache/tika/config/TikaActivator.java?rev=1195494&r1=1195493&r2=1195494&view=diff
==============================================================================
--- tika/trunk/tika-core/src/main/java/org/apache/tika/config/TikaActivator.java (original)
+++ tika/trunk/tika-core/src/main/java/org/apache/tika/config/TikaActivator.java Mon Oct 31 15:00:16 2011
@@ -18,6 +18,9 @@ package org.apache.tika.config;
 
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
 
 /**
  * Bundle activator that adjust the class loading mechanism of the
@@ -30,15 +33,36 @@ import org.osgi.framework.BundleContext;
  *
  * @since Apache Tika 0.9
  */
-public class TikaActivator implements BundleActivator {
+public class TikaActivator
+        implements BundleActivator, ServiceListener {
+
+    private BundleContext bundleContext;
+
+    //-----------------------------------------------------< BundleActivator >
 
     public void start(BundleContext context) throws Exception {
-        ServiceLoader.setContextClassLoader(
-                TikaActivator.class.getClassLoader());
+        bundleContext = context;
+        bundleContext.addServiceListener(this,
+                "(|(objectClass=org.apache.tika.detect.Detector)"
+                + "(objectClass=org.apache.tika.parser.Parser))");
     }
 
     public void stop(BundleContext context) throws Exception {
-        ServiceLoader.setContextClassLoader(null);
+        bundleContext.removeServiceListener(this);
+    }
+
+    //-----------------------------------------------------< ServiceListener >
+
+    public synchronized void serviceChanged(ServiceEvent event) {
+        if (event.getType() == ServiceEvent.REGISTERED) {
+            ServiceReference reference = event.getServiceReference();
+            Object service = bundleContext.getService(reference);
+            ServiceLoader.addService(reference, service);
+        } else if (event.getType() == ServiceEvent.UNREGISTERING) {
+            ServiceReference reference = event.getServiceReference();
+            ServiceLoader.removeService(reference);
+            bundleContext.ungetService(reference);
+        }
     }
 
 }