8228854: Default ErrorListener reports warnings and errors to the console
Reviewed-by: lancea
--- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet.java Thu Sep 05 19:24:53 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet.java Thu Sep 05 17:26:38 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -54,7 +54,7 @@
* @author Morten Jorgensen
* @author G. Todd Miller
* @author John Howard, JohnH@schemasoft.com
- * @LastModified: Oct 2017
+ * @LastModified: Aug 2019
*/
public abstract class AbstractTranslet implements Translet {
@@ -558,8 +558,8 @@
throws TransletException
{
try {
- final TransletOutputHandlerFactory factory
- = TransletOutputHandlerFactory.newInstance(_overrideDefaultParser);
+ final TransletOutputHandlerFactory factory = TransletOutputHandlerFactory
+ .newInstance(_overrideDefaultParser, _msgHandler.getErrorListener());
String dirStr = new File(filename).getParent();
if ((null != dirStr) && (dirStr.length() > 0)) {
--- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/MessageHandler.java Thu Sep 05 19:24:53 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/MessageHandler.java Thu Sep 05 17:26:38 2019 +0000
@@ -1,6 +1,5 @@
/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -21,11 +20,18 @@
package com.sun.org.apache.xalan.internal.xsltc.runtime;
+import javax.xml.transform.ErrorListener;
+
/**
* @author Morten Jorgensen
+ * @LastModified: Aug 2019
*/
public class MessageHandler {
public void displayMessage(String msg) {
System.err.println(msg);
}
+
+ public ErrorListener getErrorListener() {
+ return null;
+ }
}
--- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/output/TransletOutputHandlerFactory.java Thu Sep 05 19:24:53 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/output/TransletOutputHandlerFactory.java Thu Sep 05 17:26:38 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -41,6 +41,7 @@
import com.sun.org.apache.xml.internal.serializer.ToXMLSAXHandler;
import com.sun.org.apache.xml.internal.serializer.ToXMLStream;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
+import javax.xml.transform.ErrorListener;
import org.w3c.dom.Node;
import org.xml.sax.ContentHandler;
@@ -48,7 +49,7 @@
/**
* @author Santiago Pericas-Geertsen
- * @LastModified: Oct 2017
+ * @LastModified: Aug 2019
*/
public class TransletOutputHandlerFactory {
@@ -71,16 +72,17 @@
private LexicalHandler _lexHandler = null;
private boolean _overrideDefaultParser;
+ private ErrorListener _errListener;
- static public TransletOutputHandlerFactory newInstance() {
- return new TransletOutputHandlerFactory(true);
- }
- static public TransletOutputHandlerFactory newInstance(boolean overrideDefaultParser) {
- return new TransletOutputHandlerFactory(overrideDefaultParser);
+ static public TransletOutputHandlerFactory newInstance(boolean overrideDefaultParser,
+ ErrorListener errListener) {
+ return new TransletOutputHandlerFactory(overrideDefaultParser, errListener);
}
- public TransletOutputHandlerFactory(boolean overrideDefaultParser) {
+ public TransletOutputHandlerFactory(boolean overrideDefaultParser,
+ ErrorListener errListener) {
_overrideDefaultParser = overrideDefaultParser;
+ _errListener = errListener;
}
public void setOutputType(int outputType) {
_outputType = outputType;
@@ -156,24 +158,24 @@
if (_method == null)
{
- result = new ToUnknownStream();
+ result = new ToUnknownStream(_errListener);
}
else if (_method.equalsIgnoreCase("xml"))
{
- result = new ToXMLStream();
+ result = new ToXMLStream(_errListener);
}
else if (_method.equalsIgnoreCase("html"))
{
- result = new ToHTMLStream();
+ result = new ToHTMLStream(_errListener);
}
else if (_method.equalsIgnoreCase("text"))
{
- result = new ToTextStream();
+ result = new ToTextStream(_errListener);
}
--- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java Thu Sep 05 19:24:53 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java Thu Sep 05 17:26:38 2019 +0000
@@ -74,6 +74,7 @@
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.JdkXmlUtils;
import jdk.xml.internal.SecuritySupport;
+import jdk.xml.internal.TransformErrorListener;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLFilter;
@@ -84,10 +85,10 @@
* @author G. Todd Miller
* @author Morten Jorgensen
* @author Santiago Pericas-Geertsen
- * @LastModified: July 2019
+ * @LastModified: Aug 2019
*/
public class TransformerFactoryImpl
- extends SAXTransformerFactory implements SourceLoader, ErrorListener
+ extends SAXTransformerFactory implements SourceLoader
{
// Public constants for attributes supported by the XSLTC TransformerFactory.
public final static String TRANSLET_NAME = "translet-name";
@@ -102,10 +103,15 @@
public final static String INDENT_NUMBER = "indent-number";
/**
+ * Default error listener
+ */
+ private final ErrorListener _defaultListener = new TransformErrorListener();
+
+ /**
* This error listener is used only for this factory and is not passed to
* the Templates or Transformer objects that we create.
*/
- private ErrorListener _errorListener = this;
+ private ErrorListener _errorListener = _defaultListener;
// flag indicating whether there's an user's ErrorListener
private boolean _hasUserErrListener;
@@ -1223,90 +1229,6 @@
}
/**
- * Receive notification of a recoverable error.
- * The transformer must continue to provide normal parsing events after
- * invoking this method. It should still be possible for the application
- * to process the document through to the end.
- *
- * @param e The warning information encapsulated in a transformer
- * exception.
- * @throws TransformerException if the application chooses to discontinue
- * the transformation (always does in our case).
- */
- @Override
- public void error(TransformerException e)
- throws TransformerException
- {
- Throwable wrapped = e.getException();
- if (wrapped != null) {
- System.err.println(new ErrorMsg(ErrorMsg.ERROR_PLUS_WRAPPED_MSG,
- e.getMessageAndLocation(),
- wrapped.getMessage()));
- } else {
- System.err.println(new ErrorMsg(ErrorMsg.ERROR_MSG,
- e.getMessageAndLocation()));
- }
- throw e;
- }
-
- /**
- * Receive notification of a non-recoverable error.
- * The application must assume that the transformation cannot continue
- * after the Transformer has invoked this method, and should continue
- * (if at all) only to collect addition error messages. In fact,
- * Transformers are free to stop reporting events once this method has
- * been invoked.
- *
- * @param e warning information encapsulated in a transformer
- * exception.
- * @throws TransformerException if the application chooses to discontinue
- * the transformation (always does in our case).
- */
- @Override
- public void fatalError(TransformerException e)
- throws TransformerException
- {
- Throwable wrapped = e.getException();
- if (wrapped != null) {
- System.err.println(new ErrorMsg(ErrorMsg.FATAL_ERR_PLUS_WRAPPED_MSG,
- e.getMessageAndLocation(),
- wrapped.getMessage()));
- } else {
- System.err.println(new ErrorMsg(ErrorMsg.FATAL_ERR_MSG,
- e.getMessageAndLocation()));
- }
- throw e;
- }
-
- /**
- * Receive notification of a warning.
- * Transformers can use this method to report conditions that are not
- * errors or fatal errors. The default behaviour is to take no action.
- * After invoking this method, the Transformer must continue with the
- * transformation. It should still be possible for the application to
- * process the document through to the end.
- *
- * @param e The warning information encapsulated in a transformer
- * exception.
- * @throws TransformerException if the application chooses to discontinue
- * the transformation (never does in our case).
- */
- @Override
- public void warning(TransformerException e)
- throws TransformerException
- {
- Throwable wrapped = e.getException();
- if (wrapped != null) {
- System.err.println(new ErrorMsg(ErrorMsg.WARNING_PLUS_WRAPPED_MSG,
- e.getMessageAndLocation(),
- wrapped.getMessage()));
- } else {
- System.err.println(new ErrorMsg(ErrorMsg.WARNING_MSG,
- e.getMessageAndLocation()));
- }
- }
-
- /**
* This method implements XSLTC's SourceLoader interface. It is used to
* glue a TrAX URIResolver to the XSLTC compiler's Input and Import classes.
*
--- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java Thu Sep 05 19:24:53 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java Thu Sep 05 17:26:38 2019 +0000
@@ -83,6 +83,7 @@
import javax.xml.transform.stream.StreamSource;
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.JdkXmlUtils;
+import jdk.xml.internal.TransformErrorListener;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
@@ -93,10 +94,10 @@
* @author Morten Jorgensen
* @author G. Todd Miller
* @author Santiago Pericas-Geertsen
- * @LastModified: Feb 2019
+ * @LastModified: Aug 2019
*/
public final class TransformerImpl extends Transformer
- implements DOMCache, ErrorListener
+ implements DOMCache
{
private final static String LEXICAL_HANDLER_PROPERTY =
@@ -129,9 +130,14 @@
private String _sourceSystemId = null;
/**
+ * Default error listener
+ */
+ private final ErrorListener _defaultListener = new TransformErrorListener();
+
+ /**
* An error listener for runtime errors.
*/
- private ErrorListener _errorListener = this;
+ private ErrorListener _errorListener = _defaultListener;
/**
* A reference to a URI resolver for calls to document().
@@ -250,6 +256,10 @@
}
}
}
+
+ public ErrorListener getErrorListener() {
+ return _errorListener;
+ }
}
protected TransformerImpl(Properties outputProperties, int indentNumber,
@@ -264,6 +274,9 @@
int indentNumber, TransformerFactoryImpl tfactory)
{
_translet = (AbstractTranslet) translet;
+ if (_translet != null) {
+ _translet.setMessageHandler(new MessageHandler(_errorListener));
+ }
_properties = createOutputProperties(outputProperties);
_propertiesClone = (Properties) _properties.clone();
_indentNumber = indentNumber;
@@ -400,7 +413,8 @@
// Get encoding using getProperty() to use defaults
_encoding = _properties.getProperty(OutputKeys.ENCODING);
- _tohFactory = TransletOutputHandlerFactory.newInstance(_overrideDefaultParser);
+ _tohFactory = TransletOutputHandlerFactory
+ .newInstance(_overrideDefaultParser, _errorListener);
_tohFactory.setEncoding(_encoding);
if (_method != null) {
_tohFactory.setOutputMethod(_method);
@@ -829,8 +843,8 @@
_errorListener = listener;
// Register a message handler to report xsl:messages
- if (_translet != null)
- _translet.setMessageHandler(new MessageHandler(_errorListener));
+ if (_translet != null)
+ _translet.setMessageHandler(new MessageHandler(_errorListener));
}
/**
@@ -1353,90 +1367,6 @@
}
/**
- * Receive notification of a recoverable error.
- * The transformer must continue to provide normal parsing events after
- * invoking this method. It should still be possible for the application
- * to process the document through to the end.
- *
- * @param e The warning information encapsulated in a transformer
- * exception.
- * @throws TransformerException if the application chooses to discontinue
- * the transformation (always does in our case).
- */
- @Override
- public void error(TransformerException e)
- throws TransformerException
- {
- Throwable wrapped = e.getException();
- if (wrapped != null) {
- System.err.println(new ErrorMsg(ErrorMsg.ERROR_PLUS_WRAPPED_MSG,
- e.getMessageAndLocation(),
- wrapped.getMessage()));
- } else {
- System.err.println(new ErrorMsg(ErrorMsg.ERROR_MSG,
- e.getMessageAndLocation()));
- }
- throw e;
- }
-
- /**
- * Receive notification of a non-recoverable error.
- * The application must assume that the transformation cannot continue
- * after the Transformer has invoked this method, and should continue
- * (if at all) only to collect addition error messages. In fact,
- * Transformers are free to stop reporting events once this method has
- * been invoked.
- *
- * @param e The warning information encapsulated in a transformer
- * exception.
- * @throws TransformerException if the application chooses to discontinue
- * the transformation (always does in our case).
- */
- @Override
- public void fatalError(TransformerException e)
- throws TransformerException
- {
- Throwable wrapped = e.getException();
- if (wrapped != null) {
- System.err.println(new ErrorMsg(ErrorMsg.FATAL_ERR_PLUS_WRAPPED_MSG,
- e.getMessageAndLocation(),
- wrapped.getMessage()));
- } else {
- System.err.println(new ErrorMsg(ErrorMsg.FATAL_ERR_MSG,
- e.getMessageAndLocation()));
- }
- throw e;
- }
-
- /**
- * Receive notification of a warning.
- * Transformers can use this method to report conditions that are not
- * errors or fatal errors. The default behaviour is to take no action.
- * After invoking this method, the Transformer must continue with the
- * transformation. It should still be possible for the application to
- * process the document through to the end.
- *
- * @param e The warning information encapsulated in a transformer
- * exception.
- * @throws TransformerException if the application chooses to discontinue
- * the transformation (never does in our case).
- */
- @Override
- public void warning(TransformerException e)
- throws TransformerException
- {
- Throwable wrapped = e.getException();
- if (wrapped != null) {
- System.err.println(new ErrorMsg(ErrorMsg.WARNING_PLUS_WRAPPED_MSG,
- e.getMessageAndLocation(),
- wrapped.getMessage()));
- } else {
- System.err.println(new ErrorMsg(ErrorMsg.WARNING_MSG,
- e.getMessageAndLocation()));
- }
- }
-
- /**
* This method resets the Transformer to its original configuration
* Transformer code is reset to the same state it was when it was
* created
@@ -1448,7 +1378,7 @@
_method = null;
_encoding = null;
_sourceSystemId = null;
- _errorListener = this;
+ _errorListener = _defaultListener;
_uriResolver = null;
_dom = null;
_parameters = null;
--- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/SerializerBase.java Thu Sep 05 19:24:53 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/SerializerBase.java Thu Sep 05 17:26:38 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, 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
@@ -25,7 +25,7 @@
import java.io.IOException;
import java.util.HashMap;
import java.util.Set;
-import java.util.ArrayList;
+import javax.xml.transform.ErrorListener;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.SourceLocator;
import javax.xml.transform.Transformer;
@@ -42,10 +42,12 @@
* It contains a number of common fields and methods.
*
* @xsl.usage internal
+ * @LastModified: Aug 2019
*/
public abstract class SerializerBase
implements SerializationHandler, SerializerConstants
{
+ protected ErrorListener m_errListener;
/**
* To fire off the end element trace event
--- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToHTMLStream.java Thu Sep 05 19:24:53 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToHTMLStream.java Thu Sep 05 17:26:38 2019 +0000
@@ -30,6 +30,7 @@
import com.sun.org.apache.xml.internal.serializer.utils.MsgKey;
import com.sun.org.apache.xml.internal.serializer.utils.Utils;
+import javax.xml.transform.ErrorListener;
/**
* This serializer takes a series of SAX or
@@ -40,7 +41,7 @@
* because it is used from another package.
*
* @xsl.usage internal
- * @LastModified: July 2019
+ * @LastModified: Aug 2019
*/
public final class ToHTMLStream extends ToStream
{
@@ -638,12 +639,15 @@
*/
public ToHTMLStream()
{
+ this(null);
+ }
- super();
+ public ToHTMLStream(ErrorListener l)
+ {
+ super(l);
m_charInfo = m_htmlcharInfo;
// initialize namespaces
m_prefixMap = new NamespaceMappings();
-
}
/** The name of the current element. */
--- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToStream.java Thu Sep 05 19:24:53 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToStream.java Thu Sep 05 17:26:38 2019 +0000
@@ -51,7 +51,7 @@
* serializers (xml, html, text ...) that write output to a stream.
*
* @xsl.usage internal
- * @LastModified: July 2019
+ * @LastModified: Aug 2019
*/
abstract public class ToStream extends SerializerBase {
@@ -198,7 +198,13 @@
/**
* Default constructor
*/
- public ToStream() { }
+ public ToStream() {
+ this(null);
+ }
+
+ public ToStream(ErrorListener l) {
+ m_errListener = l;
+ }
/**
* This helper method to writes out "]]>" when closing a CDATA section.
@@ -422,45 +428,30 @@
// from what it was
EncodingInfo encodingInfo = Encodings.getEncodingInfo(newEncoding);
- if (newEncoding != null && encodingInfo.name == null) {
- // We tried to get an EncodingInfo for Object for the given
- // encoding, but it came back with an internall null name
- // so the encoding is not supported by the JDK, issue a message.
- final String msg = Utils.messages.createMessage(
- MsgKey.ER_ENCODING_NOT_SUPPORTED,new Object[]{ newEncoding });
-
- final String msg2 =
- "Warning: encoding \"" + newEncoding + "\" not supported, using "
- + Encodings.DEFAULT_MIME_ENCODING;
- try {
- // Prepare to issue the warning message
- final Transformer tran = super.getTransformer();
- if (tran != null) {
- final ErrorListener errHandler = tran
- .getErrorListener();
- // Issue the warning message
- if (null != errHandler
- && m_sourceLocator != null) {
- errHandler
- .warning(new TransformerException(
- msg, m_sourceLocator));
- errHandler
- .warning(new TransformerException(
- msg2, m_sourceLocator));
- } else {
- System.out.println(msg);
- System.out.println(msg2);
- }
- } else {
- System.out.println(msg);
- System.out.println(msg2);
+ if (encodingInfo.name == null) {
+ // We tried to get an EncodingInfo for Object for the given
+ // encoding, but it came back with an internall null name
+ // so the encoding is not supported by the JDK, issue a message.
+ final String msg = Utils.messages.createMessage(
+ MsgKey.ER_ENCODING_NOT_SUPPORTED,new Object[]{ newEncoding });
+
+ final String msg2 =
+ "Warning: encoding \"" + newEncoding + "\" not supported, using "
+ + Encodings.DEFAULT_MIME_ENCODING;
+ try {
+ // refer to JDK-8229005, should throw Exception instead of warning and
+ // then falling back to the default encoding. Keep it for now.
+ if (m_errListener != null) {
+ m_errListener.warning(new TransformerException(msg, m_sourceLocator));
+ m_errListener.warning(new TransformerException(msg2, m_sourceLocator));
}
} catch (Exception e) {
}
// We said we are using UTF-8, so use it
newEncoding = Encodings.DEFAULT_MIME_ENCODING;
- val = Encodings.DEFAULT_MIME_ENCODING; // to store the modified value into the properties a little later
+ // to store the modified value into the properties a little later
+ val = Encodings.DEFAULT_MIME_ENCODING;
encodingInfo = Encodings.getEncodingInfo(newEncoding);
}
// The encoding was good, or was forced to UTF-8 above
--- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToTextStream.java Thu Sep 05 19:24:53 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToTextStream.java Thu Sep 05 17:26:38 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -24,6 +24,7 @@
import com.sun.org.apache.xml.internal.serializer.utils.MsgKey;
import com.sun.org.apache.xml.internal.serializer.utils.Utils;
+import javax.xml.transform.ErrorListener;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
@@ -33,7 +34,7 @@
* This class converts SAX or SAX-like calls to a
* serialized document for xsl:output method of "text".
* @xsl.usage internal
- * @LastModified: Sept 2018
+ * @LastModified: Aug 2019
*/
public final class ToTextStream extends ToStream
{
@@ -44,7 +45,12 @@
*/
public ToTextStream()
{
- super();
+ this(null);
+ }
+
+ public ToTextStream(ErrorListener l)
+ {
+ super(l);
}
--- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToUnknownStream.java Thu Sep 05 19:24:53 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToUnknownStream.java Thu Sep 05 17:26:38 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
@@ -26,6 +26,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
+import javax.xml.transform.ErrorListener;
import javax.xml.transform.SourceLocator;
import javax.xml.transform.Transformer;
import org.w3c.dom.Node;
@@ -48,7 +49,7 @@
*
* This class is not a public API, it is public because it is used within Xalan.
* @xsl.usage internal
- * @LastModified: Oct 2017
+ * @LastModified: Aug 2019
*/
public final class ToUnknownStream extends SerializerBase
{
@@ -116,7 +117,11 @@
* That may change later to an HTML Stream object.
*/
public ToUnknownStream() {
- m_handler = new ToXMLStream();
+ this(null);
+ }
+
+ public ToUnknownStream(ErrorListener l) {
+ m_handler = new ToXMLStream(l);
}
/**
--- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToXMLStream.java Thu Sep 05 19:24:53 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToXMLStream.java Thu Sep 05 17:26:38 2019 +0000
@@ -40,7 +40,7 @@
* be viewed as internal or package private, this is not an API.
*
* @xsl.usage internal
- * @LastModified: July 2019
+ * @LastModified: Aug 2019
*/
public final class ToXMLStream extends ToStream
{
@@ -64,12 +64,20 @@
*/
public ToXMLStream()
{
+ this(null);
+ }
+
+ /**
+ * Default constructor.
+ */
+ public ToXMLStream(ErrorListener l)
+ {
+ super(l);
m_charInfo = m_xmlcharInfo;
initCDATA();
// initialize namespaces
m_prefixMap = new NamespaceMappings();
-
}
/**
--- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/dom3/LSSerializerImpl.java Thu Sep 05 19:24:53 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/dom3/LSSerializerImpl.java Thu Sep 05 17:26:38 2019 +0000
@@ -1,6 +1,5 @@
/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -68,6 +67,7 @@
* @version $Id:
*
* @xsl.usage internal
+ * @LastModified: Aug 2019
*/
final public class LSSerializerImpl implements DOMConfiguration, LSSerializer {
@@ -220,7 +220,7 @@
// Get a serializer that seriailizes according to the properties,
// which in this case is to xml
- fXMLSerializer = new ToXMLStream();
+ fXMLSerializer = new ToXMLStream(null);
fXMLSerializer.setOutputFormat(configProps);
// Initialize Serializer
--- a/src/java.xml/share/classes/javax/xml/transform/ErrorListener.java Thu Sep 05 19:24:53 2019 +0200
+++ b/src/java.xml/share/classes/javax/xml/transform/ErrorListener.java Thu Sep 05 17:26:38 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -26,29 +26,39 @@
package javax.xml.transform;
/**
- * <p>To provide customized error handling, implement this interface and
- * use the <code>setErrorListener</code> method to register an instance of the
- * implementation with the {@link javax.xml.transform.Transformer}. The
- * <code>Transformer</code> then reports all errors and warnings through this
- * interface.</p>
+ * The listener interface used by a {@link TransformerFactory} or {@link Transformer}
+ * to notify callers of error messages that occur during a transformation process.
+ * An ErrorListener receives three levels of messages: warnings, errors and fatal
+ * errors as classified by their severity. Each of them is handled as described
+ * in their respective method.
+ *
+ * <p>
+ * An ErrorListener instance can be registered to a {@link TransformerFactory}
+ * or {@link Transformer} through
+ * the {@link TransformerFactory#setErrorListener(ErrorListener)}
+ * or {@link Transformer#setErrorListener(ErrorListener)}
+ * method to receive errors and warnings reported by the TransformerFactory
+ * or Transformer.
*
- * <p>If an application does <em>not</em> register its own custom
- * <code>ErrorListener</code>, the default <code>ErrorListener</code>
- * is used which reports all warnings and errors to <code>System.err</code>
- * and does not throw any <code>Exception</code>s.
- * Applications are <em>strongly</em> encouraged to register and use
- * <code>ErrorListener</code>s that insure proper behavior for warnings and
- * errors.</p>
+ * <p>
+ * When a listener is registered, the {@link TransformerFactory} or {@link Transformer}
+ * must use this interface to pass on all warnings and errors to the listener
+ * and let the application decide how to handle them.
+ * Note that the {@code TransformerFactory} or {@code Transformer} is not
+ * required to continue with the transformation after a call to
+ * {@link #fatalError(TransformerException exception)}.
*
- * <p>For transformation errors, a <code>Transformer</code> must use this
- * interface instead of throwing an <code>Exception</code>: it is up to the
- * application to decide whether to throw an <code>Exception</code> for
- * different types of errors and warnings. Note however that the
- * <code>Transformer</code> is not required to continue with the transformation
- * after a call to {@link #fatalError(TransformerException exception)}.</p>
+ * <p>
+ * If an application does not provide a listener, the {@link TransformerFactory}
+ * or {@link Transformer} shall create one on its own. The default {@code ErrorListener}
+ * may take no action for warnings and recoverable errors, and allow the
+ * transformation to continue.
+ * However, the {@code TransformerFactory} or {@code Transformer} may still throw
+ * {@code TransformerException} when it decides it can not continue processing.
*
- * <p><code>Transformer</code>s may use this mechanism to report XML parsing
- * errors as well as transformation errors.</p>
+ * @apiNote It is recommended that applications register and use their own
+ * {@code ErrorListener} to override the default behavior in order to ensure
+ * proper handling of warnings and errors.
*
* @since 1.4
*/
--- a/src/java.xml/share/classes/javax/xml/transform/package-info.java Thu Sep 05 19:24:53 2019 +0200
+++ b/src/java.xml/share/classes/javax/xml/transform/package-info.java Thu Sep 05 17:26:38 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -183,11 +183,6 @@
* to report errors that occur during the transformation. The <code>ErrorListener</code>
* on both objects will always be valid and non-<code>null</code>, whether set by
* the application or a default implementation provided by the processor.
- * The default implementation provided by the processor will report all warnings
- * and errors to <code>System.err</code> and does not throw any <code>Exception</code>s.
- * Applications are <em>strongly</em> encouraged to register and use
- * <code>ErrorListener</code>s that insure proper behavior for warnings and
- * errors.
*
*
* <h2>Resolution of URIs within a transformation</h2>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.xml/share/classes/jdk/xml/internal/TransformErrorListener.java Thu Sep 05 17:26:38 2019 +0000
@@ -0,0 +1,78 @@
+/*
+ * 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 javax.xml.transform.ErrorListener;
+import javax.xml.transform.TransformerException;
+
+/**
+ * Implements an ErrorListener for use by the JDK as the default ErrorListener.
+ * For compatibility, this implementation retains the behavior as was implemented
+ * by TransformerFactoryImpl and TransformerImpl where both the error and
+ * fatalError methods re-throw the exception.
+ */
+public class TransformErrorListener implements ErrorListener {
+ /**
+ * Receives notification of a warning.
+ *
+ * @param e The warning information encapsulated in a TransformerException.
+ * @throws TransformerException not thrown in this implementation
+ */
+ @Override
+ public void warning(TransformerException e)
+ throws TransformerException
+ {
+ // no op
+ }
+
+ /**
+ * Receives notification of an error.
+ * The transformer may continue the process if the error is recoverable.
+ * It may decide not to if it can not continue after the error.
+ *
+ * @param e The error information encapsulated in a TransformerException.
+ * @throws TransformerException re-throws the exception.
+ */
+ @Override
+ public void error(TransformerException e)
+ throws TransformerException
+ {
+ throw e;
+ }
+
+ /**
+ * Receives notification of a fatal error.
+ *
+ * @param e The error information encapsulated in a TransformerException.
+ * @throws TransformerException re-throws the exception.
+ */
+ @Override
+ public void fatalError(TransformerException e)
+ throws TransformerException
+ {
+ throw e;
+ }
+}
--- a/test/jaxp/javax/xml/jaxp/unittest/transform/ErrorListenerTest.java Thu Sep 05 19:24:53 2019 +0200
+++ b/test/jaxp/javax/xml/jaxp/unittest/transform/ErrorListenerTest.java Thu Sep 05 17:26:38 2019 +0000
@@ -27,92 +27,361 @@
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.PrintStream;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
import javax.xml.transform.ErrorListener;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.xml.sax.InputSource;
/*
* @test
- * @bug 8157830
+ * @bug 8157830 8228854
* @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 int SYSTEM_ERR = 1;
+ static final int SYSTEM_OUT = 2;
+ static final String ERR_STDERR = "Msg sent to stderr";
+ static final String ERR_STDOUT = "Msg sent to stdout";
static final private String INVALID_STYLESHEET = "xxx";
static final private String SYSTEM_ID = "http://openjdk_java_net/xsl/dummy.xsl";
- PrintStream original;
+ final private String INCLUDE_NOT_EXIST = "<?xml version=\"1.1\" encoding=\"UTF-8\"?>" +
+ "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">" +
+ " <xsl:import href=\"NOSUCHFILE.xsl\"/>" +
+ "</xsl:stylesheet>";
+
+ final private String VAR_UNDEFINED = "<?xml version=\"1.1\" encoding=\"ISO-8859-1\"?>" +
+ "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" +
+ " <xsl:template match=\"/\"> " +
+ " <test1><xsl:apply-templates select=\"$ids\"/></test1>" +
+ " <test2><xsl:apply-templates select=\"$dummy//ids/id\"/></test2>" +
+ " </xsl:template>" +
+ "</xsl:stylesheet>";
+ final private String XSL_DOC_FUNCTION = "<?xml version=\"1.1\" encoding=\"ISO-8859-1\"?>" +
+ "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" +
+ " <xsl:output method=\"xml\" indent=\"yes\"/>" +
+ " <xsl:variable name=\"ids\" select=\"//ids//id\"/>" +
+ " <xsl:variable name=\"dummy\" select=\"document('NOSUCHFILE.xml')\"/>" +
+ " <xsl:template match=\"/\"> " +
+ " <test1><xsl:apply-templates select=\"$ids\"/></test1>" +
+ " <test2><xsl:apply-templates select=\"$dummy//ids/id\"/></test2>" +
+ " </xsl:template>" +
+ " <xsl:template match=\"id\">" +
+ " <xsl:variable name=\"entity\" select=\"id(@value)\"/> " +
+ " <must-be-one><xsl:value-of select=\"count($entity)\"/></must-be-one>" +
+ " </xsl:template>" +
+ "</xsl:stylesheet>";
+ final private String XML_DOC_FUNCTION = "<?xml version=\"1.1\" encoding=\"ISO-8859-1\" standalone=\"no\"?>" +
+ "<organization2>" +
+ " <company id=\"xca\" count=\"2\">" +
+ " <department id=\"xda\"/>" +
+ " </company>" +
+ " <company id=\"xcb\" count=\"0\"/>" +
+ " <company id=\"xcc\" count=\"5\"/>" +
+ " <ids>" +
+ " <id value=\"xca\"/>" +
+ " <id value=\"xcb\"/>" +
+ " </ids>" +
+ "</organization2>";
+
+ PrintStream originalErr, originalOut;
+ List<String> testMsgs = new ArrayList<>();
@BeforeClass
public void setUpClass() throws Exception {
// save the PrintStream
- original = System.err;
+ originalErr = System.err;
+ originalOut = System.out;
}
@AfterClass
protected void tearDown() throws Exception {
// set back to the original
- System.setErr(original);
+ System.setErr(originalErr);
+ System.setOut(originalOut);
+ // print out test messages
+ testMsgs.stream().forEach((msg) -> {
+ System.out.println(msg);
+ });
+ }
+
+ /*
+ DataProvider: for ErrorListenner tests
+ Data: xsl, xml, setListener(true/false), output channel(stderr/stdout),
+ expected console output, expected listener output
+ */
+ @DataProvider(name = "testCreatingTransformer")
+ public Object[][] getTransformer() {
+ return new Object[][]{
+ /*
+ * Verifies that the default implementation does not print out
+ * warnings and errors to stderr.
+ */
+ {INCLUDE_NOT_EXIST, false, ""},
+ {VAR_UNDEFINED, false, ""},
+ /*
+ * Verifies that the registered listener is used.
+ */
+ {INCLUDE_NOT_EXIST, true, "NOSUCHFILE.xsl"},
+ {VAR_UNDEFINED, true, "'ids' is undefined"},
+ /*
+ * The original test for JDK8157830
+ * Verifies that when an ErrorListener is registered, parser errors
+ * are passed onto the listener without other output.
+ */
+ {INVALID_STYLESHEET, true, "Content is not allowed in prolog"},
+ };
+ }
+ /*
+ DataProvider: for ErrorListenner tests
+ Data: xsl, xml, setListener(true/false), output channel(stderr/stdout),
+ expected console output, expected listener output
+ */
+ @DataProvider(name = "testTransform")
+ public Object[][] getTransform() {
+ return new Object[][]{
+ /*
+ * Verifies that the default implementation does not print out
+ * warnings and errors to stderr.
+ */
+ {XSL_DOC_FUNCTION, XML_DOC_FUNCTION, false, ""},
+ /*
+ * Verifies that the default implementation does not print out
+ * warnings and errors to stderr.
+ */
+ {XSL_DOC_FUNCTION, XML_DOC_FUNCTION, true, "NOSUCHFILE.xml"}
+ };
+ }
+
+ /*
+ DataProvider: for ErrorListenner tests
+ Data: xsl, xml, setListener(true/false), expected listener output
+ */
+ @DataProvider(name = "testEncoding")
+ public Object[][] getData() {
+ return new Object[][]{
+ {"<foo><bar></bar></foo>", false, ""},
+ {"<foo><bar></bar></foo>", true, "'dummy' is not supported"}
+ };
+ }
+
+ /**
+ * Verifies that ErrorListeners are properly set and propagated, or the
+ * default ErrorListener does not send messages to stderr/stdout.
+ *
+ * @param xsl the stylesheet
+ * @param setListener a flag indicating whether a listener should be set
+ * @param msgL the expected listener output
+ * @throws Exception if the test fails
+ */
+ @Test(dataProvider = "testCreatingTransformer")
+ public void testTransformer(String xsl, boolean setListener, String msgL)
+ throws Exception {
+ ErrListener listener = setListener ? new ErrListener("test") : null;
+ String msgConsole = getTransformerErr("testTransformer", xsl, listener);
+ evalResult(listener, msgConsole, setListener, msgL);
}
/**
- * Verifies that when an ErrorListener is registered, parser errors are passed
- * onto the listener without other output.
+ * Verifies that ErrorListeners are properly set and propagated, or the
+ * default ErrorListener does not send messages to stderr/stdout.
+ *
+ * @param xsl the stylesheet
+ * @param xml the XML
+ * @param setListener a flag indicating whether a listener should be set
+ * @param msgL the expected listener output
+ * @throws Exception if the test fails
+ */
+ //@Test(dataProvider = "testTransform")
+ public void testTransform(String xsl, String xml, boolean setListener, String msgL)
+ throws Exception {
+ ErrListener listener = setListener ? new ErrListener("test") : null;
+ Transformer t = getTransformer("testDocFunc", xsl, listener);
+ String msgConsole = transform("testDocFunc", xml, t);
+ evalResult(listener, msgConsole, setListener, msgL);
+ }
+
+ /**
+ * Verifies that the default implementation does not print out warnings and
+ * errors to the console when an invalid encoding is set.
*
+ * @throws Exception if the test fails
+ */
+ //@Test(dataProvider = "testEncoding")
+ public void testEncoding(String xml, boolean setListener, String msgL)
+ throws Exception {
+ ErrListener listener = setListener ? new ErrListener("test") : null;
+ Transformer t = TransformerFactory.newInstance().newTransformer();
+ if (setListener) {
+ t.setErrorListener(listener);
+ }
+ t.setOutputProperty(OutputKeys.ENCODING, "dummy");
+ String msgConsole = transform("testEncoding", "<foo><bar></bar></foo>", t);
+ evalResult(listener, msgConsole, setListener, msgL);
+ }
+
+ private void evalResult(ErrListener l, String m, boolean setListener, String msgL)
+ throws Exception{
+ Assert.assertTrue(!m.contains(ERR_STDERR), "no output to stderr");
+ Assert.assertTrue(!m.contains(ERR_STDOUT), "no output to stdout");
+ if (setListener) {
+ testMsgs.add("l.errMsg=" + l.errMsg);
+ testMsgs.add("evalResult.msgL=" + msgL);
+ Assert.assertTrue(l.errMsg.contains(msgL),
+ "The registered listener shall be used.");
+ }
+ }
+
+ /**
+ * Obtains a Transformer.
+ *
+ * @param test the name of the test
+ * @param xsl the stylesheet
+ * @param setListener a flag indicating whether to set a listener
+ * @return the Transformer, null if error occurs
* @throws Exception
*/
- @Test
- public void test() throws Exception {
- InputStream is = new ByteArrayInputStream(INVALID_STYLESHEET.getBytes());
+ private Transformer getTransformer(String test, String xsl, ErrorListener listener)
+ throws Exception {
+ Transformer f = null;
+ InputSource source = new InputSource(new ByteArrayInputStream(xsl.getBytes()));
+ TransformerFactory factory = TransformerFactory.newInstance();
+ if (listener != null) {
+ factory.setErrorListener(listener);
+ }
+
+ try {
+ f = factory.newTransformer(new SAXSource(source));
+ if (listener != null) {
+ f.setErrorListener(listener);
+ }
+ } catch (TransformerConfigurationException e) {
+ testMsgs.add(test + "::catch: " + e.getMessage());
+ }
+
+ return f;
+ }
+
+ /**
+ * Attempts to capture messages sent to stderr/stdout during the creation
+ * of a Transformer.
+ *
+ * @param test the name of the test
+ * @param xsl the stylesheet
+ * @param setListener a flag indicating whether to set a listener
+ * @return message sent to stderr/stdout, null if none
+ * @throws Exception
+ */
+ private String getTransformerErr(String test, String xsl, ErrorListener listener)
+ throws Exception {
+ InputStream is = new ByteArrayInputStream(xsl.getBytes());
InputSource source = new InputSource(is);
- source.setSystemId(SYSTEM_ID);
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- PrintStream ps = new PrintStream(baos);
- System.setErr(ps);
+ ByteArrayOutputStream baos1 = setOutput(SYSTEM_ERR);
+ ByteArrayOutputStream baos2 = setOutput(SYSTEM_OUT);
TransformerFactory factory = TransformerFactory.newInstance();
- factory.setErrorListener(new ErrListener());
+ if (listener != null) {
+ factory.setErrorListener(listener);
+ }
try {
factory.newTransformer(new SAXSource(source));
} catch (TransformerConfigurationException e) {
- // nothing
+ testMsgs.add(test + "::catch: " + e.getMessage());
}
+ reset();
+ String msg = !"".equals(baos1.toString()) ? ERR_STDERR : "";
+ msg = !"".equals(baos2.toString()) ? msg + ERR_STDOUT : msg;
+ return msg;
+ }
- // all errors are handled by the ErrorListener, no other output
- Assert.assertEquals(baos.toString(), "");
+ /**
+ * Transforms an XML file. Attempts to capture stderr/stdout as the Transformer
+ * may direct messages to stdout.
+ *
+ * @param test the name of the test
+ * @param xml the XML file
+ * @param t the Transformer
+ * @param type the flag indicating which output channel to capture
+ * @return message sent to stdout, null if none
+ * @throws Exception
+ */
+ private String transform(String test, String xml, Transformer t)
+ throws Exception {
+ StreamSource source = new StreamSource(new StringReader(xml));
+ StreamResult result = new StreamResult(new StringWriter());
+ ByteArrayOutputStream baos1 = setOutput(SYSTEM_ERR);
+ ByteArrayOutputStream baos2 = setOutput(SYSTEM_OUT);
+ try {
+ t.transform(source, result);
+ } catch (Exception e) {
+ testMsgs.add(test + "::catch: " + e.getMessage());
+ }
+ reset();
+ String msg = !"".equals(baos1.toString()) ? ERR_STDERR : "";
+ msg = !"".equals(baos2.toString()) ? msg + ERR_STDOUT : msg;
+ return msg;
+ }
+ private ByteArrayOutputStream setOutput(int type) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ if (type == SYSTEM_ERR) {
+ System.setErr(ps);
+ } else {
+ System.setOut(ps);
+ }
+ return baos;
+ }
+
+ private void reset() {
+ System.setErr(originalErr);
+ System.setOut(originalOut);
}
class ErrListener implements ErrorListener {
+ String testName;
+ String errMsg = "";
+ ErrListener(String test) {
+ testName = test;
+ }
@Override
- public void error(TransformerException exception)
+ public void error(TransformerException e)
throws TransformerException {
- System.out.println("Correctly handled error: " + exception.getMessage());
+ errMsg = errMsg + "#error: " + e.getMessage();
}
@Override
- public void fatalError(TransformerException exception)
+ public void fatalError(TransformerException e)
throws TransformerException {
- System.out.println("Correctly handled fatal: " + exception.getMessage());
+ errMsg = errMsg + "#fatalError: " + e.getMessage();
}
@Override
- public void warning(TransformerException exception)
+ public void warning(TransformerException e)
throws TransformerException {
- System.out.println("Correctly handled warning: " + exception.getMessage());
+ errMsg = errMsg + "#warning: " + e.getMessage();
}
}
}