Author: jukka
Date: Mon Jun  1 22:09:54 2009
New Revision: 780852

URL: http://svn.apache.org/viewvc?rev=780852&view=rev
Log:
TIKA-237: Better distinction between SAXException and TikaException

Add TaggedContentHandler wrapper class based on the design of the similar 
TaggedInputStream feature.

Added:
    
lucene/tika/trunk/tika-core/src/main/java/org/apache/tika/sax/TaggedContentHandler.java
    
lucene/tika/trunk/tika-core/src/main/java/org/apache/tika/sax/TaggedSAXException.java
Modified:
    
lucene/tika/trunk/tika-core/src/main/java/org/apache/tika/sax/ContentHandlerDecorator.java

Modified: 
lucene/tika/trunk/tika-core/src/main/java/org/apache/tika/sax/ContentHandlerDecorator.java
URL: 
http://svn.apache.org/viewvc/lucene/tika/trunk/tika-core/src/main/java/org/apache/tika/sax/ContentHandlerDecorator.java?rev=780852&r1=780851&r2=780852&view=diff
==============================================================================
--- 
lucene/tika/trunk/tika-core/src/main/java/org/apache/tika/sax/ContentHandlerDecorator.java
 (original)
+++ 
lucene/tika/trunk/tika-core/src/main/java/org/apache/tika/sax/ContentHandlerDecorator.java
 Mon Jun  1 22:09:54 2009
@@ -44,58 +44,124 @@
         this.handler = handler;
     }
 
+    @Override
     public void startPrefixMapping(String prefix, String uri)
             throws SAXException {
-        handler.startPrefixMapping(prefix, uri);
+        try {
+            handler.startPrefixMapping(prefix, uri);
+        } catch (SAXException e) {
+            handleException(e);
+        }
     }
 
+    @Override
     public void endPrefixMapping(String prefix) throws SAXException {
-        handler.endPrefixMapping(prefix);
+        try {
+            handler.endPrefixMapping(prefix);
+        } catch (SAXException e) {
+            handleException(e);
+        }
     }
 
+    @Override
     public void processingInstruction(String target, String data)
             throws SAXException {
-        handler.processingInstruction(target, data);
+        try {
+            handler.processingInstruction(target, data);
+        } catch (SAXException e) {
+            handleException(e);
+        }
     }
 
+    @Override
     public void setDocumentLocator(Locator locator) {
         handler.setDocumentLocator(locator);
     }
 
+    @Override
     public void startDocument() throws SAXException {
-        handler.startDocument();
+        try {
+            handler.startDocument();
+        } catch (SAXException e) {
+            handleException(e);
+        }
     }
 
+    @Override
     public void endDocument() throws SAXException {
-        handler.endDocument();
+        try {
+            handler.endDocument();
+        } catch (SAXException e) {
+            handleException(e);
+        }
     }
 
-    public void startElement(String uri, String localName, String name,
-            Attributes atts) throws SAXException {
-        handler.startElement(uri, localName, name, atts);
+    @Override
+    public void startElement(
+            String uri, String localName, String name, Attributes atts)
+            throws SAXException {
+        try {
+            handler.startElement(uri, localName, name, atts);
+        } catch (SAXException e) {
+            handleException(e);
+        }
     }
 
+    @Override
     public void endElement(String uri, String localName, String name)
             throws SAXException {
-        handler.endElement(uri, localName, name);
+        try {
+            handler.endElement(uri, localName, name);
+        } catch (SAXException e) {
+            handleException(e);
+        }
     }
 
+    @Override
     public void characters(char[] ch, int start, int length)
             throws SAXException {
-        handler.characters(ch, start, length);
+        try {
+            handler.characters(ch, start, length);
+        } catch (SAXException e) {
+            handleException(e);
+        }
     }
 
+    @Override
     public void ignorableWhitespace(char[] ch, int start, int length)
             throws SAXException {
-        handler.ignorableWhitespace(ch, start, length);
+        try {
+            handler.ignorableWhitespace(ch, start, length);
+        } catch (SAXException e) {
+            handleException(e);
+        }
     }
 
+    @Override
     public void skippedEntity(String name) throws SAXException {
-        handler.skippedEntity(name);
+        try {
+            handler.skippedEntity(name);
+        } catch (SAXException e) {
+            handleException(e);
+        }
     }
 
+    @Override
     public String toString() {
         return handler.toString();
     }
 
+    /**
+     * Handle any exceptions thrown by methods in this class. This method
+     * provides a single place to implement custom exception handling. The
+     * default behaviour is simply to re-throw the given exception, but
+     * subclasses can also provide alternative ways of handling the situation.
+     *
+     * @param exception the exception that was thrown
+     * @throws SAXException the exception (if any) thrown to the client
+     */
+    protected void handleException(SAXException exception) throws SAXException 
{
+        throw exception;
+    }
+
 }

Added: 
lucene/tika/trunk/tika-core/src/main/java/org/apache/tika/sax/TaggedContentHandler.java
URL: 
http://svn.apache.org/viewvc/lucene/tika/trunk/tika-core/src/main/java/org/apache/tika/sax/TaggedContentHandler.java?rev=780852&view=auto
==============================================================================
--- 
lucene/tika/trunk/tika-core/src/main/java/org/apache/tika/sax/TaggedContentHandler.java
 (added)
+++ 
lucene/tika/trunk/tika-core/src/main/java/org/apache/tika/sax/TaggedContentHandler.java
 Mon Jun  1 22:09:54 2009
@@ -0,0 +1,116 @@
+/*
+ * 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.tika.sax;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * A content handler decorator that tags potential exceptions so that the
+ * handler that caused the exception can easily be identified. This is
+ * done by using the {...@link TaggedSAXException} class to wrap all thrown
+ * {...@link SAXException}s. See below for an example of using this class.
+ * <pre>
+ * TaggedContentHandler handler = new TaggedContentHandler(...);
+ * try {
+ *     // Processing that may throw an SAXException either from this handler
+ *     // or from some other XML parsing activity
+ *     processXML(handler);
+ * } catch (SAXException e) {
+ *     if (handler.isCauseOf(e)) {
+ *         // The exception was caused by this handler.
+ *         // Use e.getCause() to get the original exception.
+ *     } else {
+ *         // The exception was caused by something else.
+ *     }
+ * }
+ * </pre>
+ * <p>
+ * Alternatively, the {...@link #throwIfCauseOf(Exception)} method can be
+ * used to let higher levels of code handle the exception caused by this
+ * stream while other processing errors are being taken care of at this
+ * lower level.
+ * <pre>
+ * TaggedContentHandler handler = new TaggedContentHandler(...);
+ * try {
+ *     processXML(handler);
+ * } catch (SAXException e) {
+ *     stream.throwIfCauseOf(e);
+ *     // ... or process the exception that was caused by something else
+ * }
+ * </pre>
+ *
+ * @see TaggedSAXException
+ */
+public class TaggedContentHandler extends ContentHandlerDecorator {
+
+    /**
+     * Creates a tagging decorator for the given content handler.
+     *
+     * @param proxy content handler to be decorated
+     */
+    public TaggedContentHandler(ContentHandler proxy) {
+        super(proxy);
+    }
+
+    /**
+     * Tests if the given exception was caused by this handler.
+     *
+     * @param exception an exception
+     * @return <code>true</code> if the exception was thrown by this handler,
+     *         <code>false</code> otherwise
+     */
+    public boolean isCauseOf(SAXException exception) {
+        if (exception instanceof TaggedSAXException) {
+            TaggedSAXException tagged = (TaggedSAXException) exception;
+            return this == tagged.getTag();
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Re-throws the original exception thrown by this handler. This method
+     * first checks whether the given exception is a {...@link 
TaggedSAXException}
+     * wrapper created by this decorator, and then unwraps and throws the
+     * original wrapped exception. Returns normally if the exception was
+     * not thrown by this handler.
+     *
+     * @param exception an exception
+     * @throws SAXException original exception, if any, thrown by this handler
+     */
+    public void throwIfCauseOf(Exception exception) throws SAXException {
+        if (exception instanceof TaggedSAXException) {
+            TaggedSAXException tagged = (TaggedSAXException) exception;
+            if (this == tagged.getTag()) {
+                throw tagged.getCause();
+            }
+        }
+    }
+
+    /**
+     * Tags any {...@link SAXException}s thrown, wrapping and re-throwing.
+     * 
+     * @param e The SAXException thrown
+     * @throws SAXException if an XML error occurs
+     */
+    @Override
+    protected void handleException(SAXException e) throws SAXException {
+        throw new TaggedSAXException(e, this);
+    }
+
+}

Added: 
lucene/tika/trunk/tika-core/src/main/java/org/apache/tika/sax/TaggedSAXException.java
URL: 
http://svn.apache.org/viewvc/lucene/tika/trunk/tika-core/src/main/java/org/apache/tika/sax/TaggedSAXException.java?rev=780852&view=auto
==============================================================================
--- 
lucene/tika/trunk/tika-core/src/main/java/org/apache/tika/sax/TaggedSAXException.java
 (added)
+++ 
lucene/tika/trunk/tika-core/src/main/java/org/apache/tika/sax/TaggedSAXException.java
 Mon Jun  1 22:09:54 2009
@@ -0,0 +1,64 @@
+/*
+ * 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.tika.sax;
+
+import org.xml.sax.SAXException;
+
+/**
+ * A {...@link SAXException} wrapper that tags the wrapped exception with
+ * a given object reference. Both the tag and the wrapped original exception
+ * can be used to determine further processing when this exception is caught.
+ */
+public class TaggedSAXException extends SAXException {
+
+    /**
+     * The object reference used to tag the exception.
+     */
+    private final Object tag;
+
+    /**
+     * Creates a tagged wrapper for the given exception.
+     *
+     * @param original the exception to be tagged
+     * @param tag tag object
+     */
+    public TaggedSAXException(SAXException original, Object tag) {
+        super(original.getMessage(), original);
+        this.tag = tag;
+    }
+
+    /**
+     * Returns the object reference used as the tag this exception.
+     *
+     * @return tag object
+     */
+    public Object getTag() {
+        return tag;
+    }
+
+    /**
+     * Returns the wrapped exception. The only difference to the overridden
+     * {...@link Throwable#getCause()} method is the narrower return type.
+     *
+     * @return wrapped exception
+     */
+    @Override
+    public SAXException getCause() {
+        return (SAXException) super.getCause();
+    }
+
+}


Reply via email to