You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tika.apache.org by ta...@apache.org on 2017/09/21 20:50:33 UTC

[tika] 02/02: TIKA-2466 Remove JAXB for easier use with Java 9 via Robert Munteanu.

This is an automated email from the ASF dual-hosted git repository.

tallison pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tika.git

commit ac259320057d8b7a8937dc5ee183b3a5c346a3bc
Author: tballison <ta...@mitre.org>
AuthorDate: Thu Sep 21 16:50:21 2017 -0400

    TIKA-2466 Remove JAXB for easier use with Java 9 via Robert Munteanu.
---
 CHANGES.txt                                        |   2 +
 .../main/java/org/apache/tika/config/Param.java    | 135 ++++++++++++---------
 .../java/org/apache/tika/config/TikaConfig.java    |   9 +-
 .../java/org/apache/tika/parser/ParseContext.java  |  31 +++++
 .../java/org/apache/tika/utils/XMLReaderUtils.java |  25 ++++
 5 files changed, 141 insertions(+), 61 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index 7ad0f99..b6eb6ab 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,7 @@
 Release 1.17 - ???
 
+  * Remove JAXB for easier use with Java 9 via Robert Munteanu (TIKA-2466).
+
   * Upgrade to POI 3.17 (TIKA-2429).
 
   * Enabling extraction of standard references from text (TIKA-2449).
diff --git a/tika-core/src/main/java/org/apache/tika/config/Param.java b/tika-core/src/main/java/org/apache/tika/config/Param.java
index b54f6be..112955b 100644
--- a/tika-core/src/main/java/org/apache/tika/config/Param.java
+++ b/tika-core/src/main/java/org/apache/tika/config/Param.java
@@ -16,15 +16,21 @@
  */
 package org.apache.tika.config;
 
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.utils.XMLReaderUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
 import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
 
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Marshaller;
-import javax.xml.bind.Unmarshaller;
-import javax.xml.bind.annotation.*;
-import javax.xml.bind.helpers.DefaultValidationEventHandler;
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Serializable;
@@ -38,18 +44,13 @@ import java.util.Map;
 
 
 /**
- * This is a JAXB serializable model class for parameters from configuration file.
+ * This is a serializable model class for parameters from configuration file.
  *
  * @param <T> value type. Should be serializable to string and have a constructor with string param
  * @since Apache Tika 1.14
  */
-@XmlRootElement()
-@XmlAccessorType(XmlAccessType.NONE)
 public class Param<T> implements Serializable {
 
-    private static final JAXBContext JAXB_CTX;
-    private static final Marshaller MARSHALLER;
-    private static final Unmarshaller UNMARSHALLER;
     private static final Map<Class<?>, String> map = new HashMap<>();
     private static final Map<String, Class<?>> reverseMap = new HashMap<>();
 
@@ -69,27 +70,14 @@ public class Param<T> implements Serializable {
         for (Map.Entry<Class<?>, String> entry : map.entrySet()) {
             reverseMap.put(entry.getValue(), entry.getKey());
         }
-        try {
-            JAXB_CTX = JAXBContext.newInstance(Param.class);
-            MARSHALLER = JAXB_CTX.createMarshaller();
-            MARSHALLER.setEventHandler(new DefaultValidationEventHandler());
-            UNMARSHALLER = JAXB_CTX.createUnmarshaller();
-            UNMARSHALLER.setEventHandler(new DefaultValidationEventHandler());
-        } catch (JAXBException e) {
-            throw new RuntimeException(e);
-        }
     }
 
-    @XmlTransient
     private Class<T> type;
 
-    @XmlAttribute(name = "name")
     private String name;
 
-    @XmlValue()
     private String value;
 
-    @XmlTransient
     private T actualValue;
 
     public Param(){
@@ -113,7 +101,6 @@ public class Param<T> implements Serializable {
         this.name = name;
     }
 
-    @XmlTransient
     public Class<T> getType() {
         return type;
     }
@@ -122,7 +109,6 @@ public class Param<T> implements Serializable {
         this.type = type;
     }
 
-    @XmlAttribute(name = "type")
     public String getTypeString(){
         if (type == null) {
             return null;
@@ -137,28 +123,14 @@ public class Param<T> implements Serializable {
         if (type == null || type.isEmpty()){
             return;
         }
-        if (reverseMap.containsKey(type)){
-            this.type = (Class<T>) reverseMap.get(type);
-        } else try {
-            this.type = (Class<T>) Class.forName(type);
-        } catch (ClassNotFoundException e) {
-            throw new RuntimeException(e);
-        }
+        
+        this.type = classFromType(type);
         this.actualValue = null;
     }
 
-    @XmlTransient
     public T getValue(){
         if (actualValue == null) {
-            try {
-                Constructor<T> constructor = type.getConstructor(String.class);
-                constructor.setAccessible(true);
-                this.actualValue = constructor.newInstance(value);
-            } catch (NoSuchMethodException e) {
-                throw new RuntimeException(type + " doesnt have a constructor that takes String arg", e);
-            } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
-                throw new RuntimeException(e);
-            }
+            actualValue = getTypedValue(type, value);
         }
         return actualValue;
     }
@@ -172,20 +144,75 @@ public class Param<T> implements Serializable {
                 '}';
     }
 
-    public void save(OutputStream stream) throws JAXBException {
-        MARSHALLER.marshal(this, stream);
+    public void save(OutputStream stream) throws TransformerException, TikaException {
+        
+        
+        DocumentBuilder builder = XMLReaderUtils.getDocumentBuilder();
+        Document doc = builder.newDocument();
+        Element paramEl = doc.createElement("param");
+        doc.appendChild(paramEl);
+        
+        save(paramEl);
+        
+        Transformer transformer = XMLReaderUtils.getTransformer();
+        transformer.transform(new DOMSource(paramEl), new StreamResult(stream));
     }
 
-    public void save(Node node) throws JAXBException {
-        MARSHALLER.marshal(this, node);
-    }
+    public void save(Node node) {
 
-    public static <T> Param<T> load(InputStream stream) throws JAXBException {
-        return (Param<T>) UNMARSHALLER.unmarshal(stream);
+        if ( !(node instanceof Element) ) {
+            throw new IllegalArgumentException("Not an Element : " + node);
+        }
+        
+        Element el = (Element) node;
+        
+        el.setAttribute("name",  getName());
+        el.setAttribute("type", getTypeString());
+        el.setTextContent(value);
+    }
+
+    public static <T> Param<T> load(InputStream stream) throws SAXException, IOException, TikaException {
+        
+        DocumentBuilder db = XMLReaderUtils.getDocumentBuilder();
+        Document document = db.parse(stream);
+        
+        return load(document.getFirstChild());
+    }
+
+    public static <T> Param<T> load(Node node)  {
+        
+        Node nameAttr = node.getAttributes().getNamedItem("name");
+        Node typeAttr = node.getAttributes().getNamedItem("type");
+        Node value = node.getFirstChild();
+        
+        Param<T> ret = new Param<T>();
+        ret.name  = nameAttr.getTextContent();
+        ret.setTypeString(typeAttr.getTextContent());
+        ret.value = value.getTextContent();
+        
+        return ret;
+    }
+    
+    private static <T> Class<T> classFromType(String type) {
+        if (reverseMap.containsKey(type)){
+            return (Class<T>) reverseMap.get(type);
+        } else try {
+            return (Class<T>) Class.forName(type);
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException(e);
+        }
     }
-
-    public static <T> Param<T> load(Node node) throws JAXBException {
-        return (Param<T>) UNMARSHALLER.unmarshal(node);
+    
+    private static <T> T getTypedValue(Class<T> type, String value) {
+        try {
+            Constructor<T> constructor = type.getConstructor(String.class);
+            constructor.setAccessible(true);
+            return constructor.newInstance(value);
+        } catch (NoSuchMethodException e) {
+            throw new RuntimeException(type + " doesnt have a constructor that takes String arg", e);
+        } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
+            throw new RuntimeException(e);
+        }        
     }
 
 }
diff --git a/tika-core/src/main/java/org/apache/tika/config/TikaConfig.java b/tika-core/src/main/java/org/apache/tika/config/TikaConfig.java
index 28ac235..9518042 100644
--- a/tika-core/src/main/java/org/apache/tika/config/TikaConfig.java
+++ b/tika-core/src/main/java/org/apache/tika/config/TikaConfig.java
@@ -17,7 +17,6 @@
 package org.apache.tika.config;
 
 import javax.imageio.spi.ServiceRegistry;
-import javax.xml.bind.JAXBException;
 import javax.xml.parsers.DocumentBuilder;
 import java.io.File;
 import java.io.IOException;
@@ -685,12 +684,8 @@ public class TikaConfig {
                         for (int i = 0; i < childNodes.getLength(); i++) {
                             Node item = childNodes.item(i);
                             if (item.getNodeType() == Node.ELEMENT_NODE){
-                                try {
-                                    Param<?> param = Param.load(item);
-                                    params.put(param.getName(), param);
-                                } catch (JAXBException e) {
-                                    throw new RuntimeException(e);
-                                }
+                                Param<?> param = Param.load(item);
+                                params.put(param.getName(), param);
                             }
                         }
                     }
diff --git a/tika-core/src/main/java/org/apache/tika/parser/ParseContext.java b/tika-core/src/main/java/org/apache/tika/parser/ParseContext.java
index 332efcd..68df47b 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/ParseContext.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/ParseContext.java
@@ -23,6 +23,14 @@ import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
 import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLResolver;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+
+import java.io.IOException;
 import java.io.Serializable;
 import java.util.HashMap;
 import java.util.Map;
@@ -217,5 +225,28 @@ public class ParseContext implements Serializable {
         }
         return XMLReaderUtils.getXMLInputFactory();
     }
+  
+    
+    /**
+     * Returns the transformer specified in this parsing context.
+     * 
+     * If a transformer is not explicitly specified, then a default transformer
+     * instance is created and returned. The default transformer instance is
+     * configured to to use
+     * {@link XMLConstants#FEATURE_SECURE_PROCESSING secure XML processing}.
+     *
+     * @since Apache Tika 1.17
+     * @return Transformer
+     * @throws TikaException when the transformer can not be created
+     */
+    public Transformer getTransformer() throws TikaException {
+        
+        Transformer transformer = get(Transformer.class);
+        if ( transformer != null ) {
+            return transformer;
+        }
+        
+        return XMLReaderUtils.getTransformer();
+    }
 
 }
diff --git a/tika-core/src/main/java/org/apache/tika/utils/XMLReaderUtils.java b/tika-core/src/main/java/org/apache/tika/utils/XMLReaderUtils.java
index 6f24708..a326f14 100644
--- a/tika-core/src/main/java/org/apache/tika/utils/XMLReaderUtils.java
+++ b/tika-core/src/main/java/org/apache/tika/utils/XMLReaderUtils.java
@@ -34,6 +34,11 @@ import javax.xml.parsers.SAXParserFactory;
 import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLResolver;
 import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+
 import java.io.IOException;
 import java.io.StringReader;
 import java.lang.reflect.Method;
@@ -236,4 +241,24 @@ public class XMLReaderUtils {
         }
     }
 
+    /**
+     * Returns a new transformer
+     * 
+     * The transformer instance is configured to to use
+     * {@link XMLConstants#FEATURE_SECURE_PROCESSING secure XML processing}.
+     *
+     * @since Apache Tika 1.17
+     * @return Transformer
+     * @throws TikaException when the transformer can not be created
+     */
+    public static Transformer getTransformer() throws TikaException {
+        try {
+            TransformerFactory transformerFactory = TransformerFactory.newInstance();
+            transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+            return transformerFactory.newTransformer();
+        } catch (TransformerConfigurationException | TransformerFactoryConfigurationError e) {
+            throw new TikaException("Transformer not available", e);
+        }        
+    }
+
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@tika.apache.org" <co...@tika.apache.org>.