diff --git a/src/main/java/org/owasp/html/AutoCloseableHtmlStreamRenderer.java b/src/main/java/org/owasp/html/AutoCloseableHtmlStreamRenderer.java deleted file mode 100644 index 69111cbc..00000000 --- a/src/main/java/org/owasp/html/AutoCloseableHtmlStreamRenderer.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.owasp.html; - -import java.io.Closeable; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import javax.annotation.WillCloseWhenClosed; - -final class AutoCloseableHtmlStreamRenderer extends HtmlStreamRenderer - // This is available on JDK6 and makes this class extend AutoCloseable. - implements Closeable { - private final Object closeable; - - private static final Class CLASS_AUTO_CLOSEABLE; - - static { - Class classAutoCloseable = null; - for (Class superInterface : Closeable.class.getInterfaces()) { - if ("java.lang.AutoCloseable".equals(superInterface.getName())) { - classAutoCloseable = superInterface; - break; - } - } - CLASS_AUTO_CLOSEABLE = classAutoCloseable; - } - - private static final Method METHOD_CLOSE; - - static { - Method methodClose = null; - if (CLASS_AUTO_CLOSEABLE != null) { - try { - methodClose = CLASS_AUTO_CLOSEABLE.getMethod("close"); - } catch (NoSuchMethodException ex) { - throw (NoSuchMethodError) new NoSuchMethodError().initCause(ex); - } - } - METHOD_CLOSE = methodClose; - } - - static boolean isAutoCloseable(Object o) { - return o instanceof Closeable - || CLASS_AUTO_CLOSEABLE != null && CLASS_AUTO_CLOSEABLE.isInstance(o); - } - - static AutoCloseableHtmlStreamRenderer createAutoCloseableHtmlStreamRenderer( - @WillCloseWhenClosed - Appendable output, Handler errorHandler, - Handler badHtmlHandler) { - return new AutoCloseableHtmlStreamRenderer( - output, errorHandler, badHtmlHandler); - } - - private AutoCloseableHtmlStreamRenderer( - @WillCloseWhenClosed - Appendable output, Handler errorHandler, - Handler badHtmlHandler) { - super(output, errorHandler, badHtmlHandler); - this.closeable = output; - } - - private static final Object[] ZERO_OBJECTS = new Object[0]; - - public void close() throws IOException { - if (isDocumentOpen()) { closeDocument(); } - closeIfAnyCloseable(closeable); - } - - static void closeIfAnyCloseable(Object closeable) throws IOException { - if (closeable instanceof Closeable) { - ((Closeable) closeable).close(); - } else if (METHOD_CLOSE != null) { - try { - METHOD_CLOSE.invoke(closeable, ZERO_OBJECTS); - } catch (IllegalAccessException ex) { - AssertionError ae = new AssertionError("close not public"); - ae.initCause(ex); - throw ae; - } catch (InvocationTargetException ex) { - Throwable tgt = ex.getTargetException(); - if (tgt instanceof IOException) { - throw (IOException) tgt; - } else if (tgt instanceof RuntimeException) { - throw (RuntimeException) tgt; - } else { - throw new AssertionError(null, tgt); - } - } - } - } -} diff --git a/src/main/java/org/owasp/html/HtmlElementTables.java b/src/main/java/org/owasp/html/HtmlElementTables.java index 8bb5cd14..7997a4bc 100644 --- a/src/main/java/org/owasp/html/HtmlElementTables.java +++ b/src/main/java/org/owasp/html/HtmlElementTables.java @@ -722,8 +722,7 @@ public enum TextContentModelBit { static final Comparator COMPARE_BY_ZEROTH = new Comparator() { public int compare(int[] a, int[] b) { - // Integer.compare is @since JDK 7 - return a[0] - b[0]; + return Integer.compare(a[0], b[0]); } }; diff --git a/src/main/java/org/owasp/html/HtmlStreamEventReceiverWrapper.java b/src/main/java/org/owasp/html/HtmlStreamEventReceiverWrapper.java index 5349ebc7..247b9313 100644 --- a/src/main/java/org/owasp/html/HtmlStreamEventReceiverWrapper.java +++ b/src/main/java/org/owasp/html/HtmlStreamEventReceiverWrapper.java @@ -1,7 +1,5 @@ package org.owasp.html; -import java.io.Closeable; -import java.io.IOException; import java.util.List; /** @@ -9,10 +7,7 @@ * be overridden to do additional work. */ public abstract class HtmlStreamEventReceiverWrapper -implements HtmlStreamEventReceiver, -// Not AutoCloseable for JDK 6 compatibility but will close AutoCloseable -// underlying streams when closed. - Closeable { +implements HtmlStreamEventReceiver, AutoCloseable { protected final HtmlStreamEventReceiver underlying; @@ -43,7 +38,9 @@ public void text(String text) { this.underlying.text(text); } - public void close() throws IOException { - AutoCloseableHtmlStreamRenderer.closeIfAnyCloseable(underlying); + public void close() throws Exception { + if (underlying instanceof AutoCloseable) { + ((AutoCloseable) underlying).close(); + } } } diff --git a/src/main/java/org/owasp/html/HtmlStreamRenderer.java b/src/main/java/org/owasp/html/HtmlStreamRenderer.java index bb14e3ee..9fdcb7d8 100644 --- a/src/main/java/org/owasp/html/HtmlStreamRenderer.java +++ b/src/main/java/org/owasp/html/HtmlStreamRenderer.java @@ -74,8 +74,8 @@ public static HtmlStreamRenderer create( if (output instanceof Closeable) { return new CloseableHtmlStreamRenderer( output, ioExHandler, badHtmlHandler); - } else if (AutoCloseableHtmlStreamRenderer.isAutoCloseable(output)) { - return AutoCloseableHtmlStreamRenderer.createAutoCloseableHtmlStreamRenderer( + } else if (output instanceof AutoCloseable) { + return new AutoCloseableHtmlStreamRenderer( output, ioExHandler, badHtmlHandler); } else { return new HtmlStreamRenderer(output, ioExHandler, badHtmlHandler); @@ -96,7 +96,7 @@ public static HtmlStreamRenderer create( return create(output, Handler.PROPAGATE, badHtmlHandler); } - protected HtmlStreamRenderer( + private HtmlStreamRenderer( Appendable output, Handler ioExHandler, Handler badHtmlHandler) { this.output = output; @@ -424,6 +424,25 @@ public void close() throws IOException { } } + static class AutoCloseableHtmlStreamRenderer extends HtmlStreamRenderer + implements AutoCloseable { + private final AutoCloseable closeable; + + @SuppressWarnings("synthetic-access") + AutoCloseableHtmlStreamRenderer( + @WillCloseWhenClosed + Appendable output, Handler errorHandler, + Handler badHtmlHandler) { + super(output, errorHandler, badHtmlHandler); + this.closeable = (AutoCloseable) output; + } + + public void close() throws Exception { + if (isDocumentOpen()) { closeDocument(); } + closeable.close(); + } + } + private static final long TAG_ENDS = 0L | (1L << '\t') | (1L << '\n') diff --git a/src/test/java/org/owasp/html/AutoCloseableHtmlStreamRendererTest.java b/src/test/java/org/owasp/html/AutoCloseableHtmlStreamRendererTest.java deleted file mode 100644 index 157d0b2e..00000000 --- a/src/test/java/org/owasp/html/AutoCloseableHtmlStreamRendererTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.owasp.html; - -import java.io.Closeable; -import java.io.IOException; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.IdentityHashMap; -import java.util.Map; - -import org.junit.Test; - -import junit.framework.TestCase; - -@SuppressWarnings("javadoc") -public class AutoCloseableHtmlStreamRendererTest extends TestCase { - - static final class SimpleCloseable implements Closeable { - boolean closed; - - public void close() throws IOException { - this.closed = true; - } - } - - - @Test - public static void testThatCloseablesAreClosed() throws IOException { - @SuppressWarnings("resource") - SimpleCloseable closeable = new SimpleCloseable(); - - assertFalse(closeable.closed); - - assertTrue(AutoCloseableHtmlStreamRenderer.isAutoCloseable(closeable)); - - assertFalse(closeable.closed); - - AutoCloseableHtmlStreamRenderer.closeIfAnyCloseable(closeable); - - assertTrue(closeable.closed); - } - - @Test - public static void testThatAutoCloseablesAreClosed() throws IOException { - // We need a way to create an AutoCloseable instance that we can compile. - // JDK6 so that our tests are portable. - Class autoCloseableClass; - try { - autoCloseableClass = Class.forName("java.lang.AutoCloseable"); - } catch (@SuppressWarnings("unused") ClassNotFoundException ex) { - // OK on JDK 6. - return; - } - - final Map closed = new IdentityHashMap(); - - Object autoCloseableProxyInstance = Proxy.newProxyInstance( - autoCloseableClass.getClassLoader(), - new Class[] { autoCloseableClass }, - new InvocationHandler() { - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - if ("close".equals(method.getName())) { - assertTrue(args == null || args.length == 0); - closed.put(proxy, true); - return null; - } else { - return method.invoke(new Object()); - } - } - }); - - assertTrue( - AutoCloseableHtmlStreamRenderer.isAutoCloseable( - autoCloseableProxyInstance)); - - assertFalse(closed.containsKey(autoCloseableProxyInstance)); - - AutoCloseableHtmlStreamRenderer.closeIfAnyCloseable( - autoCloseableProxyInstance); - - assertTrue(closed.containsKey(autoCloseableProxyInstance)); - } - -} diff --git a/src/test/java/org/owasp/html/PolicyFactoryTest.java b/src/test/java/org/owasp/html/PolicyFactoryTest.java index b5ab8e5b..43784e92 100644 --- a/src/test/java/org/owasp/html/PolicyFactoryTest.java +++ b/src/test/java/org/owasp/html/PolicyFactoryTest.java @@ -186,7 +186,7 @@ public Appendable append(char c) throws IOException { }; - HtmlStreamEventReceiver receiver = new HtmlStreamRenderer( + HtmlStreamEventReceiver receiver = HtmlStreamRenderer.create( throwingOut, ioHandler, badHtmlHandler); HtmlSanitizer.Policy policy = factory.apply( receiver, listener, context);