8230094: CCE in createXMLEventWriter(Result) over an arbitrary XMLStreamWriter jdk-14+12
authorjoehw
Wed, 28 Aug 2019 19:02:51 +0000
changeset 57915 8570f22b9b6a
parent 57914 9c98f8788762
child 57916 97257da4ac8d
8230094: CCE in createXMLEventWriter(Result) over an arbitrary XMLStreamWriter Reviewed-by: lancea
src/java.xml/share/classes/com/sun/xml/internal/stream/XMLOutputFactoryImpl.java
src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLEventWriterImpl.java
test/jaxp/javax/xml/jaxp/unittest/stream/XMLStreamWriterTest/CustomImplTest.java
--- a/src/java.xml/share/classes/com/sun/xml/internal/stream/XMLOutputFactoryImpl.java	Wed Aug 28 14:37:45 2019 -0400
+++ b/src/java.xml/share/classes/com/sun/xml/internal/stream/XMLOutputFactoryImpl.java	Wed Aug 28 19:02:51 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -25,21 +25,19 @@
 
 package com.sun.xml.internal.stream;
 
-import java.io.File;
-import java.io.FileWriter;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.Writer;
-
-import javax.xml.stream.XMLOutputFactory ;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLOutputFactory;
 import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
 import javax.xml.transform.Result;
 import javax.xml.transform.dom.DOMResult;
 import javax.xml.transform.stream.StreamResult;
 import javax.xml.transform.stax.StAXResult;
 import com.sun.org.apache.xerces.internal.impl.Constants;
 import com.sun.org.apache.xerces.internal.impl.PropertyManager;
-
 import com.sun.xml.internal.stream.writers.XMLDOMWriterImpl;
 import com.sun.xml.internal.stream.writers.XMLEventWriterImpl;
 import com.sun.xml.internal.stream.writers.XMLStreamWriterImpl;
@@ -47,7 +45,7 @@
 /**
  * This class provides the implementation of XMLOutputFactory.
  *
- * @author  Neeraj Bajaj,
+ * @author Neeraj Bajaj,
  * @author k venugopal
  */
 public class XMLOutputFactoryImpl extends XMLOutputFactory {
@@ -63,31 +61,39 @@
      */
     boolean fReuseInstance = false;
 
-    /** Creates a new instance of XMLOutputFactory */
+    /**
+     * Creates a new instance of XMLOutputFactory
+     */
     public XMLOutputFactoryImpl() {
     }
 
-    public javax.xml.stream.XMLEventWriter createXMLEventWriter(java.io.OutputStream outputStream) throws javax.xml.stream.XMLStreamException {
-        return createXMLEventWriter(outputStream,  null);
+    public XMLEventWriter createXMLEventWriter(OutputStream outputStream)
+            throws XMLStreamException {
+        return createXMLEventWriter(outputStream, null);
     }
 
-    public javax.xml.stream.XMLEventWriter createXMLEventWriter(java.io.OutputStream outputStream, String encoding) throws javax.xml.stream.XMLStreamException {
+    public XMLEventWriter createXMLEventWriter(OutputStream outputStream, String encoding)
+            throws XMLStreamException {
         return new XMLEventWriterImpl(createXMLStreamWriter(outputStream, encoding));
     }
 
-    public javax.xml.stream.XMLEventWriter createXMLEventWriter(javax.xml.transform.Result result) throws javax.xml.stream.XMLStreamException {
+    public XMLEventWriter createXMLEventWriter(Result result)
+            throws XMLStreamException {
 
-        if (result instanceof StAXResult && ((StAXResult)result).getXMLEventWriter() != null)
-            return ((StAXResult)result).getXMLEventWriter();
+        if (result instanceof StAXResult && ((StAXResult) result).getXMLEventWriter() != null) {
+            return ((StAXResult) result).getXMLEventWriter();
+        }
 
         return new XMLEventWriterImpl(createXMLStreamWriter(result));
     }
 
-    public javax.xml.stream.XMLEventWriter createXMLEventWriter(java.io.Writer writer) throws javax.xml.stream.XMLStreamException {
+    public XMLEventWriter createXMLEventWriter(java.io.Writer writer)
+            throws XMLStreamException {
         return new XMLEventWriterImpl(createXMLStreamWriter(writer));
     }
 
-    public javax.xml.stream.XMLStreamWriter createXMLStreamWriter(javax.xml.transform.Result result) throws javax.xml.stream.XMLStreamException {
+    public XMLStreamWriter createXMLStreamWriter(Result result)
+            throws XMLStreamException {
 
         if (result instanceof StreamResult) {
             return createXMLStreamWriter((StreamResult) result, null);
@@ -97,57 +103,64 @@
             if (((StAXResult) result).getXMLStreamWriter() != null) {
                 return ((StAXResult) result).getXMLStreamWriter();
             } else {
-                throw new java.lang.UnsupportedOperationException("Result of type " + result + " is not supported");
+                throw new UnsupportedOperationException(
+                        "Result of type " + result + " is not supported");
             }
+        } else if (result.getSystemId() != null) {
+            //this is not correct impl of SAXResult. Keep it for now for compatibility
+            return createXMLStreamWriter(new StreamResult(result.getSystemId()));
         } else {
-            if (result.getSystemId() !=null) {
-                //this is not correct impl of SAXResult. Keep it for now for compatibility
-                return createXMLStreamWriter(new StreamResult(result.getSystemId()));
-            } else {
-                throw new java.lang.UnsupportedOperationException("Result of type " + result + " is not supported. " +
-                        "Supported result types are: DOMResult, StAXResult and StreamResult.");
-            }
+            throw new UnsupportedOperationException(
+                    "Result of type " + result + " is not supported. Supported result "
+                            + "types are: DOMResult, StAXResult and StreamResult.");
         }
 
     }
 
-    public javax.xml.stream.XMLStreamWriter createXMLStreamWriter(java.io.Writer writer) throws javax.xml.stream.XMLStreamException {
-        return createXMLStreamWriter(toStreamResult(null, writer, null) , null);
+    public XMLStreamWriter createXMLStreamWriter(java.io.Writer writer)
+            throws XMLStreamException {
+        return createXMLStreamWriter(toStreamResult(null, writer, null), null);
     }
 
-    public javax.xml.stream.XMLStreamWriter createXMLStreamWriter(java.io.OutputStream outputStream) throws javax.xml.stream.XMLStreamException {
+    public XMLStreamWriter createXMLStreamWriter(OutputStream outputStream)
+            throws XMLStreamException {
         return createXMLStreamWriter(outputStream, null);
     }
 
-    public javax.xml.stream.XMLStreamWriter createXMLStreamWriter(java.io.OutputStream outputStream, String encoding) throws javax.xml.stream.XMLStreamException {
-        return createXMLStreamWriter(toStreamResult(outputStream, null, null) , encoding);
+    public XMLStreamWriter createXMLStreamWriter(OutputStream outputStream, String encoding)
+            throws XMLStreamException {
+        return createXMLStreamWriter(toStreamResult(outputStream, null, null), encoding);
     }
 
-    public Object getProperty(String name) throws java.lang.IllegalArgumentException {
-        if(name == null){
+    public Object getProperty(String name)
+            throws IllegalArgumentException {
+        if (name == null) {
             throw new IllegalArgumentException("Property not supported");
         }
-        if(fPropertyManager.containsProperty(name))
+        if (fPropertyManager.containsProperty(name)) {
             return fPropertyManager.getProperty(name);
+        }
         throw new IllegalArgumentException("Property not supported");
     }
 
     public boolean isPropertySupported(String name) {
-        if(name == null){
-            return false ;
-        }
-        else{
+        if (name == null) {
+            return false;
+        } else {
             return fPropertyManager.containsProperty(name);
         }
     }
 
-    public void setProperty(String name, Object value) throws java.lang.IllegalArgumentException {
-        if(name == null || value == null || !fPropertyManager.containsProperty(name) ){
-            throw new IllegalArgumentException("Property "+name+"is not supported");
+    public void setProperty(String name, Object value)
+            throws IllegalArgumentException {
+        if (name == null || value == null || !fPropertyManager.containsProperty(name)) {
+            throw new IllegalArgumentException("Property " + name + "is not supported");
         }
-        if(name == Constants.REUSE_INSTANCE || name.equals(Constants.REUSE_INSTANCE)){
-            fReuseInstance = ((Boolean)value).booleanValue();
-            if(DEBUG)System.out.println("fReuseInstance is set to " + fReuseInstance);
+        if (name == Constants.REUSE_INSTANCE || name.equals(Constants.REUSE_INSTANCE)) {
+            fReuseInstance = (Boolean)value;
+            if (DEBUG) {
+                System.out.println("fReuseInstance is set to " + fReuseInstance);
+            }
 
             // TODO: XMLStreamWriters are not Thread safe,
             // don't let application think it is optimizing
@@ -157,16 +170,17 @@
                         + name
                         + " is not supported: XMLStreamWriters are not Thread safe");
             }
-        }else{//for any other property set the flag
+        } else {//for any other property set the flag
             //REVISIT: Even in this case instance can be reused, by passing PropertyManager
             fPropertyChanged = true;
         }
-        fPropertyManager.setProperty(name,value);
+        fPropertyManager.setProperty(name, value);
     }
 
-    /** StreamResult object is re-used and the values are set appropriately.
+    /**
+     * StreamResult object is re-used and the values are set appropriately.
      */
-    StreamResult toStreamResult(OutputStream os, Writer writer, String systemId){
+    StreamResult toStreamResult(OutputStream os, Writer writer, String systemId) {
         StreamResult sr = new StreamResult();
         sr.setOutputStream(os);
         sr.setWriter(writer);
@@ -174,26 +188,33 @@
         return sr;
     }
 
-    javax.xml.stream.XMLStreamWriter createXMLStreamWriter(javax.xml.transform.stream.StreamResult sr, String encoding) throws javax.xml.stream.XMLStreamException {
+    XMLStreamWriter createXMLStreamWriter(StreamResult sr, String encoding)
+            throws XMLStreamException {
         //if factory is configured to reuse the instance & this instance can be reused
         //& the setProperty() hasn't been called
-        try{
-            if(fReuseInstance && fStreamWriter != null && fStreamWriter.canReuse() && !fPropertyChanged){
+        try {
+            if (fReuseInstance && fStreamWriter != null && fStreamWriter.canReuse()
+                    && !fPropertyChanged) {
                 fStreamWriter.reset();
                 fStreamWriter.setOutput(sr, encoding);
-                if(DEBUG)System.out.println("reusing instance, object id : " + fStreamWriter);
+                if (DEBUG) {
+                    System.out.println("reusing instance, object id : " + fStreamWriter);
+                }
                 return fStreamWriter;
             }
-            return fStreamWriter = new XMLStreamWriterImpl(sr, encoding, new PropertyManager(fPropertyManager));
-        }catch(java.io.IOException io){
+            return fStreamWriter = new XMLStreamWriterImpl(sr, encoding,
+                    new PropertyManager(fPropertyManager));
+        } catch (IOException io) {
             throw new XMLStreamException(io);
         }
     }//createXMLStreamWriter(StreamResult,String)
 
     private static final boolean DEBUG = false;
 
-    /** This flag indicates the change of property. If true,
+    /**
+     * This flag indicates the change of property. If true,
      * <code>PropertyManager</code> should be passed when creating
-     * <code>XMLStreamWriterImpl</code> */
-    private boolean fPropertyChanged ;
+     * <code>XMLStreamWriterImpl</code>
+     */
+    private boolean fPropertyChanged;
 }//XMLOutputFactory
--- a/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLEventWriterImpl.java	Wed Aug 28 14:37:45 2019 -0400
+++ b/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLEventWriterImpl.java	Wed Aug 28 19:02:51 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -51,15 +51,16 @@
 public class XMLEventWriterImpl implements XMLEventWriter {
 
     //delegate everything to XMLStreamWriter..
-    private final XMLStreamWriterBase fStreamWriter;
+    private final XMLStreamWriter fStreamWriter;
     private static final boolean DEBUG = false;
 
     /**
-     *
+     * Constructs an XMLEventWriterImpl that implements the standard XMLStreamWriter
+     * interface.
      * @param streamWriter
      */
     public XMLEventWriterImpl(XMLStreamWriter streamWriter) {
-        fStreamWriter = (XMLStreamWriterBase) streamWriter;
+        fStreamWriter = streamWriter;
     }
 
     /**
@@ -98,9 +99,18 @@
                     System.out.println("Adding StartDocument = " + startDocument.toString());
                 }
                 try {
-                    fStreamWriter.writeStartDocument(startDocument.getCharacterEncodingScheme(),
-                            startDocument.getVersion(),
-                            startDocument.isStandalone(), startDocument.standaloneSet());
+                    if (XMLStreamWriterBase.class.isAssignableFrom(fStreamWriter.getClass())) {
+                        // internal impl uses the extended interface
+                        ((XMLStreamWriterBase)fStreamWriter).writeStartDocument(
+                                startDocument.getCharacterEncodingScheme(),
+                                startDocument.getVersion(),
+                                startDocument.isStandalone(),
+                                startDocument.standaloneSet());
+                    } else {
+                        fStreamWriter.writeStartDocument(
+                                startDocument.getCharacterEncodingScheme(),
+                                startDocument.getVersion());
+                    }
                 } catch (XMLStreamException e) {
                     fStreamWriter.writeStartDocument(startDocument.getVersion());
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jaxp/javax/xml/jaxp/unittest/stream/XMLStreamWriterTest/CustomImplTest.java	Wed Aug 28 19:02:51 2019 +0000
@@ -0,0 +1,234 @@
+/*
+ * 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 stream.XMLStreamWriterTest;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.stax.StAXResult;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8230094
+ * @run testng stream.XMLStreamWriterTest.CustomImplTest
+ * @summary Verifies custom implementation of the XMLStreamWriter.
+ */
+public class CustomImplTest {
+
+    @Test
+    public void testEventReader() throws Exception {
+        XMLOutputFactory.newFactory()
+                .createXMLEventWriter(new StAXResult(new StreamWriterFilter()));
+    }
+
+    static class StreamWriterFilter implements XMLStreamWriter
+    {
+        @Override
+        public void writeStartElement(String localName)
+                throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeStartElement(String namespaceURI, String localName)
+                throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeStartElement(
+                String prefix, String localName, String namespaceURI)
+                throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeEmptyElement(String namespaceURI, String localName)
+                throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeEmptyElement(
+                String prefix, String localName, String namespaceURI)
+                throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeEmptyElement(String localName)
+                throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeEndElement() throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeEndDocument() throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void close() throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void flush() throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeAttribute(String localName, String value)
+                throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeAttribute(
+                String prefix, String namespaceURI, String localName, String value)
+                throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeAttribute(
+                String namespaceURI, String localName, String value)
+                throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeNamespace(String prefix, String namespaceURI)
+                throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeDefaultNamespace(String namespaceURI)
+                throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeComment(String data) throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeProcessingInstruction(String target)
+                throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeProcessingInstruction(String target, String data)
+                throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeCData(String data) throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeDTD(String dtd) throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeEntityRef(String name) throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeStartDocument() throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeStartDocument(String version) throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeStartDocument(String encoding, String version)
+                throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeCharacters(String text) throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void writeCharacters(char[] text, int start, int len)
+                throws XMLStreamException
+        {
+        }
+
+        @Override
+        public String getPrefix(String uri) throws XMLStreamException
+        {
+            return null;
+        }
+
+        @Override
+        public void setPrefix(String prefix, String uri)
+                throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void setDefaultNamespace(String uri) throws XMLStreamException
+        {
+        }
+
+        @Override
+        public void setNamespaceContext(NamespaceContext context)
+                throws XMLStreamException
+        {
+        }
+
+        @Override
+        public NamespaceContext getNamespaceContext()
+        {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Object getProperty(String name) throws IllegalArgumentException
+        {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+}