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 2012/11/19 11:31:26 UTC

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

Author: jukka
Date: Mon Nov 19 10:31:25 2012
New Revision: 1411118

URL: http://svn.apache.org/viewvc?rev=1411118&view=rev
Log:
TIKA-1026: ServiceLoader should respect OSGi service ranking

Keep track of also the service rank

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
    tika/trunk/tika-core/src/main/java/org/apache/tika/parser/DefaultParser.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=1411118&r1=1411117&r2=1411118&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 Nov 19 10:31:25 2012
@@ -43,14 +43,33 @@ public class ServiceLoader {
      */
     private static volatile ClassLoader contextClassLoader = null;
 
+    private static class RankedService implements Comparable<RankedService> {
+        private Object service;
+        private int rank;
+
+        public RankedService(Object service, int rank) {
+            this.service = service;
+            this.rank = rank;
+        }
+
+        public boolean isInstanceOf(Class<?> iface) {
+            return iface.isAssignableFrom(service.getClass());
+        }
+
+        public int compareTo(RankedService that) {
+            return that.rank - rank; // highest number first
+        }
+
+    }
+
     /**
      * 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>();
+    private static final Map<Object, RankedService> services =
+            new HashMap<Object, RankedService>();
 
     /**
      * Returns the context class loader of the current thread. If such
@@ -84,9 +103,9 @@ public class ServiceLoader {
         contextClassLoader = loader;
     }
 
-    static void addService(Object reference, Object service) {
+    static void addService(Object reference, Object service, int rank) {
         synchronized (services) {
-            services.put(reference, service);
+            services.put(reference, new RankedService(service, rank));
         }
     }
 
@@ -211,19 +230,23 @@ public class ServiceLoader {
      */
     @SuppressWarnings("unchecked")
     public <T> List<T> loadDynamicServiceProviders(Class<T> iface) {
-        List<T> providers = new ArrayList<T>();
-
         if (dynamic) {
             synchronized (services) {
-                for (Object service : services.values()) {
-                    if (iface.isAssignableFrom(service.getClass())) {
-                        providers.add((T) service);
+                List<RankedService> list =
+                        new ArrayList<RankedService>(services.values());
+                Collections.sort(list);
+
+                List<T> providers = new ArrayList<T>(list.size());
+                for (RankedService service : list) {
+                    if (service.isInstanceOf(iface)) {
+                        providers.add((T) service.service);
                     }
                 }
+                return providers;
             }
+        } else {
+            return new ArrayList<T>(0);
         }
-
-        return providers;
     }
 
     /**

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=1411118&r1=1411117&r2=1411118&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 Nov 19 10:31:25 2012
@@ -20,6 +20,7 @@ import org.apache.tika.detect.Detector;
 import org.apache.tika.parser.Parser;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 import org.osgi.util.tracker.ServiceTracker;
 import org.osgi.util.tracker.ServiceTrackerCustomizer;
@@ -37,17 +38,17 @@ import org.osgi.util.tracker.ServiceTrac
  */
 public class TikaActivator implements BundleActivator, ServiceTrackerCustomizer {
 
-	private ServiceTracker detectorTracker;
+    private ServiceTracker detectorTracker;
 
-	private ServiceTracker parserTracker;
+    private ServiceTracker parserTracker;
 
-	private BundleContext bundleContext;
+    private BundleContext bundleContext;
     //-----------------------------------------------------< BundleActivator >
 
     public void start(final BundleContext context) throws Exception {
-    	bundleContext = context;
+        bundleContext = context;
 
-    	detectorTracker = new ServiceTracker(context, Detector.class.getName(), this);
+        detectorTracker = new ServiceTracker(context, Detector.class.getName(), this);
         parserTracker = new ServiceTracker(context, Parser.class.getName(), this);
 
         detectorTracker.open();
@@ -55,22 +56,28 @@ public class TikaActivator implements Bu
     }
 
     public void stop(BundleContext context) throws Exception {
-    	parserTracker.close();
-    	detectorTracker.close();
+        parserTracker.close();
+        detectorTracker.close();
     }
 
-	public Object addingService(ServiceReference reference) {
+    public Object addingService(ServiceReference reference) {
+        int rank = 0;
+        Object property = reference.getProperty(Constants.SERVICE_RANKING);
+        if (property instanceof Integer) {
+            rank = (Integer) property;
+        }
+
         Object service = bundleContext.getService(reference);
-        ServiceLoader.addService(reference, service);
-		return service;
-	}
+        ServiceLoader.addService(reference, service, rank);
+        return service;
+    }
 
-	public void modifiedService(ServiceReference reference, Object service) {
-	}
+    public void modifiedService(ServiceReference reference, Object service) {
+    }
 
-	public void removedService(ServiceReference reference, Object service) {
+    public void removedService(ServiceReference reference, Object service) {
         ServiceLoader.removeService(reference);
         bundleContext.ungetService(reference);
-	}
+    }
 
 }

Modified: tika/trunk/tika-core/src/main/java/org/apache/tika/parser/DefaultParser.java
URL: http://svn.apache.org/viewvc/tika/trunk/tika-core/src/main/java/org/apache/tika/parser/DefaultParser.java?rev=1411118&r1=1411117&r2=1411118&view=diff
==============================================================================
--- tika/trunk/tika-core/src/main/java/org/apache/tika/parser/DefaultParser.java (original)
+++ tika/trunk/tika-core/src/main/java/org/apache/tika/parser/DefaultParser.java Mon Nov 19 10:31:25 2012
@@ -97,8 +97,10 @@ public class DefaultParser extends Compo
         if (loader != null) {
             // Add dynamic parser service (they always override static ones)
             MediaTypeRegistry registry = getMediaTypeRegistry();
-            for (Parser parser
-                    : loader.loadDynamicServiceProviders(Parser.class)) {
+            List<Parser> parsers =
+                    loader.loadDynamicServiceProviders(Parser.class);
+            Collections.reverse(parsers); // best parser last
+            for (Parser parser : parsers) {
                 for (MediaType type : parser.getSupportedTypes(context)) {
                     map.put(registry.normalize(type), parser);
                 }