# HG changeset patch # User joehw # Date 1452279094 28800 # Node ID cab976ee6f2113db83ad57c96785f3714142312c # Parent 80f67512daa15cf37b4825c1c62a675d524d7c49 8144967: javax.xml.transform.Source and org.xml.sax.InputSource can be empty Reviewed-by: darcy, rriggs diff -r 80f67512daa1 -r cab976ee6f21 jaxp/src/java.xml/share/classes/javax/xml/transform/Source.java --- a/jaxp/src/java.xml/share/classes/javax/xml/transform/Source.java Wed Jul 05 21:12:04 2017 +0200 +++ b/jaxp/src/java.xml/share/classes/javax/xml/transform/Source.java Fri Jan 08 10:51:34 2016 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, 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 @@ -52,4 +52,17 @@ * if setSystemId was not called. */ public String getSystemId(); + + /** + * Indicates whether the {@code Source} object is empty. Empty means + * that there is no input available from this Source. + * + * @implSpec The default implementation of this method throws + * {@link UnsupportedOperationException}. + * + * @return true if the {@code Source} object is empty, false otherwise + */ + default boolean isEmpty() { + throw new UnsupportedOperationException("The isEmpty method is not supported."); + } } diff -r 80f67512daa1 -r cab976ee6f21 jaxp/src/java.xml/share/classes/javax/xml/transform/dom/DOMSource.java --- a/jaxp/src/java.xml/share/classes/javax/xml/transform/dom/DOMSource.java Wed Jul 05 21:12:04 2017 +0200 +++ b/jaxp/src/java.xml/share/classes/javax/xml/transform/dom/DOMSource.java Fri Jan 08 10:51:34 2016 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, 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 @@ -122,6 +122,7 @@ * * @param systemID Base URL for this DOM tree. */ + @Override public void setSystemId(String systemID) { this.systemID = systemID; } @@ -132,7 +133,25 @@ * * @return Base URL for this DOM tree. */ + @Override public String getSystemId() { return this.systemID; } + + /** + * Indicates whether the {@code DOMSource} object is empty. Empty is + * defined as follows: + *
Source
, or null
.
*/
+ @Override
public String getSystemId() {
if (inputSource == null) {
@@ -207,4 +209,22 @@
return null;
}
}
+
+ /**
+ * Indicates whether the {@code SAXSource} object is empty. Empty is
+ * defined as follows:
+ * StAXSource
.
*/
+ @Override
public String getSystemId() {
return systemId;
}
+
+ /**
+ * Indicates whether the {@code StAXSource} object is empty. Since a
+ * {@code StAXSource} object can never be empty, this method always returns
+ * false.
+ *
+ * @return unconditionally false
+ */
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
}
diff -r 80f67512daa1 -r cab976ee6f21 jaxp/src/java.xml/share/classes/javax/xml/transform/stream/StreamSource.java
--- a/jaxp/src/java.xml/share/classes/javax/xml/transform/stream/StreamSource.java Wed Jul 05 21:12:04 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/transform/stream/StreamSource.java Fri Jan 08 10:51:34 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, 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,8 +26,10 @@
package javax.xml.transform.stream;
import java.io.File;
+import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
+import javax.xml.transform.Result;
import javax.xml.transform.Source;
@@ -233,6 +235,7 @@
*
* @param systemId The system identifier as a URL string.
*/
+ @Override
public void setSystemId(String systemId) {
this.systemId = systemId;
}
@@ -243,6 +246,7 @@
* @return The system identifier that was set with setSystemId, or null
* if setSystemId was not called.
*/
+ @Override
public String getSystemId() {
return systemId;
}
@@ -259,6 +263,59 @@
this.systemId = f.toURI().toASCIIString();
}
+ /**
+ * Indicates whether the {@code StreamSource} object is empty. Empty is
+ * defined as follows:
+ * + * Note that this method will reset the byte stream if it is provided, or + * the character stream if the byte stream is not provided. + *
+ * In case of error while checking the byte or character stream, the method + * will return false to allow the XML processor to handle the error. + * + * @return true if the {@code StreamSource} object is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return (publicId == null && systemId == null && isStreamEmpty()); + } + + private boolean isStreamEmpty() { + boolean empty = true; + try { + if (inputStream != null) { + inputStream.reset(); + int bytesRead = inputStream.available(); + if (bytesRead > 0) { + return false; + } + } + + if (reader != null) { + reader.reset(); + int c = reader.read(); + reader.reset(); + if (c != -1) { + return false; + } + } + } catch (IOException ex) { + //in case of error, return false + return false; + } + + return empty; + } + ////////////////////////////////////////////////////////////////////// // Internal state. ////////////////////////////////////////////////////////////////////// diff -r 80f67512daa1 -r cab976ee6f21 jaxp/src/java.xml/share/classes/org/xml/sax/InputSource.java --- a/jaxp/src/java.xml/share/classes/org/xml/sax/InputSource.java Wed Jul 05 21:12:04 2017 +0200 +++ b/jaxp/src/java.xml/share/classes/org/xml/sax/InputSource.java Fri Jan 08 10:51:34 2016 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, 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 @@ -30,6 +30,7 @@ package org.xml.sax; +import java.io.IOException; import java.io.Reader; import java.io.InputStream; @@ -343,8 +344,57 @@ return characterStream; } + /** + * Indicates whether the {@code InputSource} object is empty. Empty is + * defined as follows: + *
+ * Note that this method will reset the byte stream if it is provided, or + * the character stream if the byte stream is not provided. + *
+ * In case of error while checking the byte or character stream, the method + * will return false to allow the XML processor to handle the error. + * + * @return true if the {@code InputSource} object is empty, false otherwise + */ + public boolean isEmpty() { + return (publicId == null && systemId == null && isStreamEmpty()); + } + private boolean isStreamEmpty() { + boolean empty = true; + try { + if (byteStream != null) { + byteStream.reset(); + int bytesRead = byteStream.available(); + if (bytesRead > 0) { + return false; + } + } + if (characterStream != null) { + characterStream.reset(); + int c = characterStream.read(); + characterStream.reset(); + if (c != -1) { + return false; + } + } + } catch (IOException ex) { + //in case of error, return false + return false; + } + + return empty; + } //////////////////////////////////////////////////////////////////// // Internal state. //////////////////////////////////////////////////////////////////// diff -r 80f67512daa1 -r cab976ee6f21 jaxp/test/javax/xml/jaxp/unittest/common/Sources.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/unittest/common/Sources.java Fri Jan 08 10:51:34 2016 -0800 @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2016, 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 common; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.stax.StAXSource; +import javax.xml.transform.stream.StreamSource; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; + +/* + * @bug 8144967 + * @summary Tests related to the javax.xml.transform.Source + * and org.xml.sax.InputSource + */ +public class Sources { + + /** + * @bug 8144967 + * Tests whether a Source object is empty + * @param source the Source object + */ + @Test(dataProvider = "emptySources") + public void testIsEmpty(Source source) { + Assert.assertTrue(source.isEmpty(), "The source is not empty"); + } + + /** + * @bug 8144967 + * Tests that the source is not empty + * @param source the Source object + */ + @Test(dataProvider = "nonEmptySources") + public void testIsNotEmpty(Source source) { + Assert.assertTrue(!source.isEmpty(), "The source is empty"); + } + + /** + * @bug 8144967 + * Tests whether an InputSource object is empty + * @param source the InputSource object + */ + @Test(dataProvider = "emptyInputSource") + public void testISIsEmpty(InputSource source) { + Assert.assertTrue(source.isEmpty(), "The source is not empty"); + } + + /* + * DataProvider: sources that are empty + */ + @DataProvider(name = "emptySources") + Object[][] getSources() throws URISyntaxException { + + return new Object[][]{ + {new DOMSource()}, + {new DOMSource(getDocument())}, + {new SAXSource()}, + {new SAXSource(new InputSource(new StringReader("")))}, + {new SAXSource(getXMLReader(), new InputSource(new StringReader("")))}, + {new StreamSource()}, + {new StreamSource(new ByteArrayInputStream("".getBytes()))}, + {new StreamSource(new StringReader(""))}, + {new StreamSource(new StringReader(""), null)}, + {new StreamSource((String) null)} + }; + } + + /* + * DataProvider: sources that are not empty + */ + @DataProvider(name = "nonEmptySources") + Object[][] getSourcesEx() throws URISyntaxException { + StAXSource ss = null; + try { + ss = new StAXSource(getXMLEventReader()); + } catch (XMLStreamException ex) {} + + return new Object[][]{ + //This will set a non-null systemId on the resulting StreamSource + {new StreamSource(new File(""))}, + //Can't tell because XMLStreamReader is a pull parser, cursor advancement + //would have been required in order to examine the reader. + {new StAXSource(getXMLStreamReader())}, + {ss} + }; + } + + /* + * DataProvider: sources that are empty + */ + @DataProvider(name = "emptyInputSource") + Object[][] getInputSources() throws URISyntaxException { + byte[] utf8Bytes = null; + try { + utf8Bytes = "".getBytes("UTF8"); + } catch (UnsupportedEncodingException ex) { + throw new RuntimeException(ex.getMessage()); + } + return new Object[][]{ + {new InputSource()}, + {new InputSource(new ByteArrayInputStream(utf8Bytes))}, + {new InputSource(new StringReader(""))}, + {new InputSource((String) null)} + }; + } + + /** + * Returns an instance of Document. + * + * @return an instance of Document. + */ + private Document getDocument() { + Document doc = null; + try { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + doc = dbf.newDocumentBuilder().newDocument(); + } catch (ParserConfigurationException ex) {} + return doc; + } + + /** + * Returns an instance of XMLReader. + * + * @return an instance of XMLReader. + */ + private XMLReader getXMLReader() { + XMLReader reader = null; + try { + reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader(); + } catch (ParserConfigurationException | SAXException ex) {} + return reader; + } + + /** + * Returns an instance of XMLStreamReader. + * + * @return an instance of XMLStreamReader. + */ + private XMLStreamReader getXMLStreamReader() { + XMLStreamReader r = null; + try { + XMLInputFactory xif = XMLInputFactory.newInstance(); + r = xif.createXMLStreamReader(new ByteArrayInputStream("".getBytes())); + } catch (XMLStreamException ex) {} + + return r; + } + + /** + * Returns an instance of XMLEventReader. + * + * @return an instance of XMLEventReader. + */ + private XMLEventReader getXMLEventReader() { + XMLEventReader r = null; + try { + r = XMLInputFactory.newInstance().createXMLEventReader( + new ByteArrayInputStream("".getBytes())); + } catch (XMLStreamException ex) {} + + return r; + } +}