Author: jukka
Date: Sun Feb 19 13:41:49 2012
New Revision: 1291001

URL: http://svn.apache.org/viewvc?rev=1291001&view=rev
Log:
TIKA-866: Invalid configuration file causes OutOfMemoryException

Fix service loading problem in tika-bundle.

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/TikaConfig.java
    
tika/trunk/tika-core/src/main/java/org/apache/tika/detect/DefaultDetector.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=1291001&r1=1291000&r2=1291001&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 
Sun Feb 19 13:41:49 2012
@@ -123,6 +123,55 @@ public class ServiceLoader {
     }
 
     /**
+     * Returns an input stream for reading the specified resource from the
+     * configured class loader.
+     *
+     * @param name resource name
+     * @return input stream, or <code>null</code> if the resource was not found
+     * @see ClassLoader#getResourceAsStream(String)
+     * @since Apache Tika 1.1
+     */
+    public InputStream getResourceAsStream(String name) {
+        if (loader != null) {
+            return loader.getResourceAsStream(name);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Loads and returns the named service class that's expected to implement
+     * the given interface.
+     *
+     * @param iface service interface
+     * @param name service class name
+     * @return service class
+     * @throws ClassNotFoundException if the service class can not be found
+     *                                or does not implement the given interface
+     * @see Class#forName(String, boolean, ClassLoader)
+     * @since Apache Tika 1.1
+     */
+    @SuppressWarnings("unchecked")
+    public <T> Class<? extends T> getServiceClass(Class<T> iface, String name)
+            throws ClassNotFoundException {
+        if (loader == null) {
+            throw new ClassNotFoundException(
+                    "Service class " + name + " is not available");
+        }
+        Class<?> klass = Class.forName(name, true, loader);
+        if (klass.isInterface()) {
+            throw new ClassNotFoundException(
+                    "Service class " + name + " is an interface");
+        } else if (!iface.isAssignableFrom(klass)) {
+            throw new ClassNotFoundException(
+                    "Service class " + name
+                    + " does not implement " + iface.getName());
+        } else {
+            return (Class<? extends T>) klass;
+        }
+    }
+
+    /**
      * Returns all the available service resources matching the
      *  given pattern, such as all instances of tika-mimetypes.xml 
      *  on the classpath, or all org.apache.tika.parser.Parser 

Modified: 
tika/trunk/tika-core/src/main/java/org/apache/tika/config/TikaConfig.java
URL: 
http://svn.apache.org/viewvc/tika/trunk/tika-core/src/main/java/org/apache/tika/config/TikaConfig.java?rev=1291001&r1=1291000&r2=1291001&view=diff
==============================================================================
--- tika/trunk/tika-core/src/main/java/org/apache/tika/config/TikaConfig.java 
(original)
+++ tika/trunk/tika-core/src/main/java/org/apache/tika/config/TikaConfig.java 
Sun Feb 19 13:41:49 2012
@@ -61,12 +61,12 @@ public class TikaConfig {
     }
 
     private static Detector getDefaultDetector(
-            MimeTypes types, ClassLoader loader) {
+            MimeTypes types, ServiceLoader loader) {
         return new DefaultDetector(types, loader);
     }
 
     private static CompositeParser getDefaultParser(
-            MimeTypes types, ClassLoader loader) {
+            MimeTypes types, ServiceLoader loader) {
         return new DefaultParser(types.getMediaTypeRegistry(), loader);
     }
 
@@ -105,11 +105,16 @@ public class TikaConfig {
     }
 
     public TikaConfig(Element element) throws TikaException, IOException {
-        this(element, ServiceLoader.getContextClassLoader());
+        this(element, new ServiceLoader());
     }
 
     public TikaConfig(Element element, ClassLoader loader)
             throws TikaException, IOException {
+        this(element, new ServiceLoader(loader));
+    }
+
+    private TikaConfig(Element element, ServiceLoader loader)
+            throws TikaException, IOException {
         this.mimeTypes = typesFromDomElement(element);
         this.detector = detectorFromDomElement(element, mimeTypes, loader);
         this.parser = parserFromDomElement(element, mimeTypes, loader);
@@ -129,9 +134,10 @@ public class TikaConfig {
      */
     public TikaConfig(ClassLoader loader)
             throws MimeTypeException, IOException {
+        ServiceLoader serviceLoader = new ServiceLoader(loader);
         this.mimeTypes = getDefaultMimeTypes();
-        this.detector = getDefaultDetector(mimeTypes, loader);
-        this.parser = getDefaultParser(mimeTypes, loader);
+        this.detector = getDefaultDetector(mimeTypes, serviceLoader);
+        this.parser = getDefaultParser(mimeTypes, serviceLoader);
     }
 
     /**
@@ -152,7 +158,7 @@ public class TikaConfig {
      * @throws TikaException if problem with MimeTypes or parsing XML config
      */
     public TikaConfig() throws TikaException, IOException {
-        ClassLoader loader = ServiceLoader.getContextClassLoader();
+        ServiceLoader loader = new ServiceLoader();
 
         String config = System.getProperty("tika.config");
         if (config == null) {
@@ -300,7 +306,7 @@ public class TikaConfig {
     }
 
     private static CompositeParser parserFromDomElement(
-            Element element, MimeTypes mimeTypes, ClassLoader loader)
+            Element element, MimeTypes mimeTypes, ServiceLoader loader)
             throws TikaException, IOException {
         List<Parser> parsers = new ArrayList<Parser>();
         NodeList nodes = element.getElementsByTagName("parser");
@@ -309,20 +315,15 @@ public class TikaConfig {
             String name = node.getAttribute("class");
 
             try {
-                Class<?> parserClass = Class.forName(name, true, loader);
+                Class<? extends Parser> parserClass =
+                        loader.getServiceClass(Parser.class, name);
                 // https://issues.apache.org/jira/browse/TIKA-866
                 if (AutoDetectParser.class.isAssignableFrom(parserClass)) {
                     throw new TikaException(
                             "AutoDetectParser not supported in a <parser>"
                             + " configuration element: " + name);
                 }
-
-                Object instance = parserClass.newInstance();
-                if (!(instance instanceof Parser)) {
-                    throw new TikaException(
-                            "Configured class is not a Tika Parser: " + name);
-                }
-                Parser parser = (Parser) instance;
+                Parser parser = parserClass.newInstance();
 
                 NodeList mimes = node.getElementsByTagName("mime");
                 if (mimes.getLength() > 0) {
@@ -343,7 +344,7 @@ public class TikaConfig {
                 parsers.add(parser);
             } catch (ClassNotFoundException e) {
                 throw new TikaException(
-                        "Configured parser class not found: " + name, e);
+                        "Unable to find a parser class: " + name, e);
             } catch (IllegalAccessException e) {
                 throw new TikaException(
                         "Unable to access a parser class: " + name, e);
@@ -361,7 +362,7 @@ public class TikaConfig {
     }
 
     private static Detector detectorFromDomElement(
-          Element element, MimeTypes mimeTypes, ClassLoader loader)
+          Element element, MimeTypes mimeTypes, ServiceLoader loader)
           throws TikaException, IOException {
        List<Detector> detectors = new ArrayList<Detector>();
        NodeList nodes = element.getElementsByTagName("detector");
@@ -370,17 +371,12 @@ public class TikaConfig {
            String name = node.getAttribute("class");
 
            try {
-               Class<?> detectorClass = Class.forName(name, true, loader);
-               Object instance = detectorClass.newInstance();
-               if (!(instance instanceof Detector)) {
-                   throw new TikaException(
-                           "Configured class is not a Tika Detector: " + name);
-               }
-               Detector detector = (Detector) instance;
-               detectors.add(detector);
+               Class<? extends Detector> detectorClass =
+                       loader.getServiceClass(Detector.class, name);
+               detectors.add(detectorClass.newInstance());
            } catch (ClassNotFoundException e) {
                throw new TikaException(
-                       "Configured detector class not found: " + name, e);
+                       "Unable to find a detector class: " + name, e);
            } catch (IllegalAccessException e) {
                throw new TikaException(
                        "Unable to access a detector class: " + name, e);

Modified: 
tika/trunk/tika-core/src/main/java/org/apache/tika/detect/DefaultDetector.java
URL: 
http://svn.apache.org/viewvc/tika/trunk/tika-core/src/main/java/org/apache/tika/detect/DefaultDetector.java?rev=1291001&r1=1291000&r2=1291001&view=diff
==============================================================================
--- 
tika/trunk/tika-core/src/main/java/org/apache/tika/detect/DefaultDetector.java 
(original)
+++ 
tika/trunk/tika-core/src/main/java/org/apache/tika/detect/DefaultDetector.java 
Sun Feb 19 13:41:49 2012
@@ -77,7 +77,7 @@ public class DefaultDetector extends Com
         return detectors;
     }
 
-    private DefaultDetector(MimeTypes types, ServiceLoader loader) {
+    public DefaultDetector(MimeTypes types, ServiceLoader loader) {
         super(types.getMediaTypeRegistry(), getDefaultDetectors(types, 
loader));
     }
 

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=1291001&r1=1291000&r2=1291001&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 
Sun Feb 19 13:41:49 2012
@@ -64,8 +64,8 @@ public class DefaultParser extends Compo
         
         return parsers;
     }
-    
-    private DefaultParser(MediaTypeRegistry registry, ServiceLoader loader) {
+
+    public DefaultParser(MediaTypeRegistry registry, ServiceLoader loader) {
         super(registry, getDefaultParsers(loader));
     }
 


Reply via email to