8157830: Errors in XSLT stylesheet are not dispatched correctly to ErrorListener
authorjoehw
Fri, 19 Jul 2019 02:40:59 +0000
changeset 55742 6e1161923897
parent 55741 880266b6e5b3
child 55743 fb2b47f0e067
8157830: Errors in XSLT stylesheet are not dispatched correctly to ErrorListener Reviewed-by: lancea
src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java
src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java
src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesHandlerImpl.java
src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java
src/java.xml/share/classes/jdk/xml/internal/ErrorHandlerProxy.java
test/jaxp/javax/xml/jaxp/unittest/transform/ErrorListenerTest.java
--- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java	Thu Jul 18 17:10:33 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java	Fri Jul 19 02:40:59 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -42,6 +42,7 @@
 import java.util.StringTokenizer;
 import javax.xml.XMLConstants;
 import javax.xml.catalog.CatalogFeatures;
+import jdk.xml.internal.ErrorHandlerProxy;
 import jdk.xml.internal.JdkXmlFeatures;
 import jdk.xml.internal.JdkXmlUtils;
 import jdk.xml.internal.SecuritySupport;
@@ -61,7 +62,7 @@
  * @author G. Todd Miller
  * @author Morten Jorgensen
  * @author Erwin Bolwidt <ejb@klomp.org>
- * @LastModified: Nov 2017
+ * @LastModified: July 2019
  */
 public class Parser implements Constants, ContentHandler {
 
@@ -98,9 +99,13 @@
 
     private boolean _overrideDefaultParser;
 
-    public Parser(XSLTC xsltc, boolean useOverrideDefaultParser) {
+    // flag indicates whether there's an user's ErrorListener
+    private boolean _hasUserErrListener;
+
+    public Parser(XSLTC xsltc, boolean useOverrideDefaultParser, boolean hasUserErrListener) {
         _xsltc = xsltc;
         _overrideDefaultParser = useOverrideDefaultParser;
+        _hasUserErrListener = hasUserErrListener;
     }
 
     public void init() {
@@ -426,6 +431,11 @@
         try {
             // Parse the input document and build the abstract syntax tree
             reader.setContentHandler(this);
+            if (_hasUserErrListener) {
+                // Set a ErrorHandler proxy to pass any parsing error on to be handled
+                // by the user's ErrorListener
+                reader.setErrorHandler(new ErrorHandlerProxy());
+            }
             reader.parse(input);
             // Find the start of the stylesheet within the tree
             return getStylesheet(_root);
--- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java	Thu Jul 18 17:10:33 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java	Fri Jul 19 02:40:59 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -58,7 +58,7 @@
  * @author G. Todd Miller
  * @author Morten Jorgensen
  * @author John Howard (johnh@schemasoft.com)
- * @LastModified: Oct 2017
+ * @LastModified: July 2019
  */
 public final class XSLTC {
 
@@ -175,10 +175,10 @@
     /**
      * XSLTC compiler constructor
      */
-    public XSLTC(JdkXmlFeatures featureManager) {
+    public XSLTC(JdkXmlFeatures featureManager, boolean hasListener) {
         _overrideDefaultParser = featureManager.getFeature(
                 JdkXmlFeatures.XmlFeature.JDK_OVERRIDE_PARSER);
-        _parser = new Parser(this, _overrideDefaultParser);
+        _parser = new Parser(this, _overrideDefaultParser, hasListener);
         _xmlFeatures = featureManager;
         _extensionClassLoader = null;
         _externalExtensionFunctions = new HashMap<>();
--- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesHandlerImpl.java	Thu Jul 18 17:10:33 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesHandlerImpl.java	Fri Jul 19 02:40:59 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -47,6 +47,7 @@
  * Implementation of a JAXP1.1 TemplatesHandler
  * @author Morten Jorgensen
  * @author Santiago Pericas-Geertsen
+ * @LastModified: July 2019
  */
 public class TemplatesHandlerImpl
     implements ContentHandler, TemplatesHandler, SourceLoader
@@ -91,14 +92,14 @@
     /**
      * Default constructor
      */
-    protected TemplatesHandlerImpl(int indentNumber,
-        TransformerFactoryImpl tfactory)
+    protected TemplatesHandlerImpl(int indentNumber, TransformerFactoryImpl tfactory,
+            boolean hasUserErrListener)
     {
         _indentNumber = indentNumber;
         _tfactory = tfactory;
 
         // Instantiate XSLTC and get reference to parser object
-        XSLTC xsltc = new XSLTC(tfactory.getJdkXmlFeatures());
+        XSLTC xsltc = new XSLTC(tfactory.getJdkXmlFeatures(), hasUserErrListener);
         if (tfactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING))
             xsltc.setSecureProcessing(true);
 
--- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java	Thu Jul 18 17:10:33 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java	Fri Jul 19 02:40:59 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -84,7 +84,7 @@
  * @author G. Todd Miller
  * @author Morten Jorgensen
  * @author Santiago Pericas-Geertsen
- * @LastModified: July 2018
+ * @LastModified: July 2019
  */
 public class TransformerFactoryImpl
     extends SAXTransformerFactory implements SourceLoader, ErrorListener
@@ -107,6 +107,9 @@
      */
     private ErrorListener _errorListener = this;
 
+    // flag indicating whether there's an user's ErrorListener
+    private boolean _hasUserErrListener;
+
     /**
      * This URIResolver is passed to all created Templates and Transformers
      */
@@ -297,6 +300,7 @@
                                         "TransformerFactory");
             throw new IllegalArgumentException(err.toString());
         }
+        _hasUserErrListener = true;
         _errorListener = listener;
     }
 
@@ -946,7 +950,7 @@
         }
 
         // Create and initialize a stylesheet compiler
-        final XSLTC xsltc = new XSLTC(_xmlFeatures);
+        final XSLTC xsltc = new XSLTC(_xmlFeatures, _hasUserErrListener);
         if (_debug) xsltc.setDebug(true);
         if (_enableInlining)
                 xsltc.setTemplateInlining(true);
@@ -1104,7 +1108,7 @@
         // through the factory instance
         buildCatalogFeatures();
         final TemplatesHandlerImpl handler =
-            new TemplatesHandlerImpl(_indentNumber, this);
+            new TemplatesHandlerImpl(_indentNumber, this, _hasUserErrListener);
         if (_uriResolver != null) {
             handler.setURIResolver(_uriResolver);
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.xml/share/classes/jdk/xml/internal/ErrorHandlerProxy.java	Fri Jul 19 02:40:59 2019 +0000
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.xml.internal;
+
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * Implements an ErrorHandler that simply passes on the Exception.
+ */
+public class ErrorHandlerProxy implements ErrorHandler {
+
+    @Override
+    public void warning(SAXParseException exception) throws SAXException {
+        throw exception;
+    }
+
+    @Override
+    public void error(SAXParseException exception) throws SAXException {
+        throw exception;
+    }
+
+    @Override
+    public void fatalError(SAXParseException exception) throws SAXException {
+        throw exception;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jaxp/javax/xml/jaxp/unittest/transform/ErrorListenerTest.java	Fri Jul 19 02:40:59 2019 +0000
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package transform;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.PrintStream;
+
+import javax.xml.transform.ErrorListener;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXSource;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.xml.sax.InputSource;
+
+/*
+ * @test
+ * @bug 8157830
+ * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
+ * @run testng/othervm transform.ErrorListenerTest
+ * @summary Verifies that ErrorListeners are handled properly
+ */
+public class ErrorListenerTest {
+
+    static final private String INVALID_STYLESHEET = "xxx";
+    static final private String SYSTEM_ID = "http://openjdk_java_net/xsl/dummy.xsl";
+
+    PrintStream original;
+
+    @BeforeClass
+    public void setUpClass() throws Exception {
+        // save the PrintStream
+        original = System.err;
+    }
+
+    @AfterClass
+    protected void tearDown() throws Exception {
+        // set back to the original
+        System.setErr(original);
+    }
+
+    /**
+     * Verifies that when an ErrorListener is registered, parser errors are passed
+     * onto the listener without other output.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void test() throws Exception {
+        InputStream is = new ByteArrayInputStream(INVALID_STYLESHEET.getBytes());
+        InputSource source = new InputSource(is);
+        source.setSystemId(SYSTEM_ID);
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        PrintStream ps = new PrintStream(baos);
+        System.setErr(ps);
+
+        TransformerFactory factory = TransformerFactory.newInstance();
+        factory.setErrorListener(new ErrListener());
+
+        try {
+            factory.newTransformer(new SAXSource(source));
+        } catch (TransformerConfigurationException e) {
+            // nothing
+        }
+
+        // all errors are handled by the ErrorListener, no other output
+        Assert.assertEquals(baos.toString(), "");
+
+    }
+
+    class ErrListener implements ErrorListener {
+
+        @Override
+        public void error(TransformerException exception)
+                throws TransformerException {
+            System.out.println("Correctly handled error: " + exception.getMessage());
+        }
+
+        @Override
+        public void fatalError(TransformerException exception)
+                throws TransformerException {
+            System.out.println("Correctly handled fatal: " + exception.getMessage());
+        }
+
+        @Override
+        public void warning(TransformerException exception)
+                throws TransformerException {
+            System.out.println("Correctly handled warning: " + exception.getMessage());
+        }
+    }
+}