changeset 49080:b8cd2fcc98e2

8038043: Xerces Update: XInclude update Reviewed-by: joehw
author aefimov
date Tue, 27 Feb 2018 12:47:58 +0000
parents 978c3036fbfc
children aef762ff9b23
files src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLVersionDetector.java src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/io/Latin1Reader.java src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/io/UTF16Reader.java src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractSAXParser.java src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/DOMParser.java src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLLocatorWrapper.java src/java.xml/share/classes/com/sun/org/apache/xerces/internal/xinclude/XIncludeHandler.java src/java.xml/share/classes/com/sun/org/apache/xerces/internal/xinclude/XIncludeTextReader.java test/jaxp/javax/xml/jaxp/unittest/common/EncodingErrorsReportingTest.java
diffstat 11 files changed, 1236 insertions(+), 113 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java	Mon Feb 26 17:18:15 2018 -0800
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java	Tue Feb 27 12:47:58 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -21,6 +21,7 @@
 
 package com.sun.org.apache.xerces.internal.impl;
 
+import com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException;
 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
 import com.sun.org.apache.xerces.internal.util.AugmentationsImpl;
 import com.sun.org.apache.xerces.internal.util.XMLAttributesIteratorImpl;
@@ -45,6 +46,7 @@
 import com.sun.xml.internal.stream.XMLBufferListener;
 import com.sun.xml.internal.stream.XMLEntityStorage;
 import com.sun.xml.internal.stream.dtd.DTDGrammarUtil;
+import java.io.CharConversionException;
 import java.io.EOFException;
 import java.io.IOException;
 import javax.xml.XMLConstants;
@@ -3075,6 +3077,20 @@
 
                 }//switch
             }
+             // encoding errors
+             catch (MalformedByteSequenceException e) {
+                 fErrorReporter.reportError(e.getDomain(), e.getKey(),
+                    e.getArguments(), XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
+                 return -1;
+             }
+             catch (CharConversionException e) {
+                fErrorReporter.reportError(
+                        XMLMessageFormatter.XML_DOMAIN,
+                        "CharConversionFailure",
+                        null,
+                        XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
+                 return -1;
+             }
             // premature end of file
             catch (EOFException e) {
                 endOfFileHook(e);
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java	Mon Feb 26 17:18:15 2018 -0800
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java	Tue Feb 27 12:47:58 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -22,6 +22,8 @@
 package com.sun.org.apache.xerces.internal.impl;
 
 import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDDescription;
+import com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException;
+import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
 import com.sun.org.apache.xerces.internal.util.NamespaceSupport;
 import com.sun.org.apache.xerces.internal.util.XMLChar;
@@ -38,6 +40,7 @@
 import com.sun.xml.internal.stream.Entity;
 import com.sun.xml.internal.stream.StaxXMLInputSource;
 import com.sun.xml.internal.stream.dtd.DTDGrammarUtil;
+import java.io.CharConversionException;
 import java.io.EOFException;
 import java.io.IOException;
 import javax.xml.stream.XMLInputFactory;
@@ -758,7 +761,19 @@
                 return XMLEvent.START_DOCUMENT;
 
             }
-
+            // encoding errors
+            catch (MalformedByteSequenceException e) {
+                fErrorReporter.reportError(e.getDomain(), e.getKey(),
+                        e.getArguments(), XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
+                return -1;
+            } catch (CharConversionException e) {
+                fErrorReporter.reportError(
+                        XMLMessageFormatter.XML_DOMAIN,
+                        "CharConversionFailure",
+                        null,
+                        XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
+                return -1;
+            }
             // premature end of file
             catch (EOFException e) {
                 reportFatalError("PrematureEOF", null);
@@ -980,6 +995,19 @@
                      */
                 }
             }
+            // encoding errors
+            catch (MalformedByteSequenceException e) {
+                fErrorReporter.reportError(e.getDomain(), e.getKey(),
+                        e.getArguments(), XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
+                return -1;
+            } catch (CharConversionException e) {
+                fErrorReporter.reportError(
+                        XMLMessageFormatter.XML_DOMAIN,
+                        "CharConversionFailure",
+                        null,
+                        XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
+                return -1;
+            }
             // premature end of file
             catch (EOFException e) {
                 reportFatalError("PrematureEOF", null);
@@ -1152,7 +1180,19 @@
                     }
                 } while (complete || again);
             }
-
+            // encoding errors
+            catch (MalformedByteSequenceException e) {
+                fErrorReporter.reportError(e.getDomain(), e.getKey(),
+                        e.getArguments(), XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
+                return false;
+            } catch (CharConversionException e) {
+                fErrorReporter.reportError(
+                        XMLMessageFormatter.XML_DOMAIN,
+                        "CharConversionFailure",
+                        null,
+                        XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
+                return false;
+            }
             // premature end of file
             catch (EOFException e) {
                 e.printStackTrace();
@@ -1416,7 +1456,18 @@
                     }
                     default: throw new XNIException("Scanner State " + fScannerState + " not Recognized ");
                 }//switch
-
+            // encoding errors
+            } catch (MalformedByteSequenceException e) {
+                fErrorReporter.reportError(e.getDomain(), e.getKey(),
+                        e.getArguments(), XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
+                return -1;
+            } catch (CharConversionException e) {
+                fErrorReporter.reportError(
+                        XMLMessageFormatter.XML_DOMAIN,
+                        "CharConversionFailure",
+                        null,
+                        XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
+                return -1;
             } catch (EOFException e) {
                 // NOTE: This is the only place we're allowed to reach
                 //       the real end of the document stream. Unless the
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLVersionDetector.java	Mon Feb 26 17:18:15 2018 -0800
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLVersionDetector.java	Tue Feb 27 12:47:58 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -20,9 +20,11 @@
 
 package com.sun.org.apache.xerces.internal.impl;
 
+import java.io.CharConversionException;
 import java.io.EOFException;
 import java.io.IOException;
 
+import com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException;
 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
 import com.sun.org.apache.xerces.internal.util.SymbolTable;
 import com.sun.org.apache.xerces.internal.xni.XMLString;
@@ -196,7 +198,21 @@
             return Constants.XML_VERSION_1_0;
             // premature end of file
         }
-        catch (EOFException e) {
+        // encoding errors
+        catch (MalformedByteSequenceException e) {
+            fErrorReporter.reportError(e.getDomain(), e.getKey(),
+                    e.getArguments(), XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
+            scanner.detectingVersion = false;
+            return Constants.XML_VERSION_1_0;
+        } catch (CharConversionException e) {
+            fErrorReporter.reportError(
+                    XMLMessageFormatter.XML_DOMAIN,
+                    "CharConversionFailure",
+                     null,
+                     XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
+            scanner.detectingVersion = false;
+            return Constants.XML_VERSION_1_0;
+        } catch (EOFException e) {
             fErrorReporter.reportError(
                 XMLMessageFormatter.XML_DOMAIN,
                 "PrematureEOF",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/io/Latin1Reader.java	Tue Feb 27 12:47:58 2018 +0000
@@ -0,0 +1,219 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.sun.org.apache.xerces.internal.impl.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+/**
+ * <p>
+ * Reader for the ISO-8859-1 encoding.</p>
+ *
+ * @xerces.internal
+ *
+ * @author Michael Glavassevich, IBM
+ *
+ * @version $Id: Latin1Reader.java 718095 2008-11-16 20:00:14Z mrglavas $
+ */
+public final class Latin1Reader
+        extends Reader {
+
+    //
+    // Constants
+    //
+    /**
+     * Default byte buffer size (2048).
+     */
+    public static final int DEFAULT_BUFFER_SIZE = 2048;
+
+    //
+    // Data
+    //
+    /**
+     * Input stream.
+     */
+    protected final InputStream fInputStream;
+
+    /**
+     * Byte buffer.
+     */
+    protected final byte[] fBuffer;
+
+    //
+    // Constructors
+    //
+    /**
+     * Constructs an ISO-8859-1 reader from the specified input stream using the
+     * default buffer size.
+     *
+     * @param inputStream The input stream.
+     */
+    public Latin1Reader(InputStream inputStream) {
+        this(inputStream, DEFAULT_BUFFER_SIZE);
+    } // <init>(InputStream)
+
+    /**
+     * Constructs an ISO-8859-1 reader from the specified input stream and
+     * buffer size.
+     *
+     * @param inputStream The input stream.
+     * @param size The initial buffer size.
+     */
+    public Latin1Reader(InputStream inputStream, int size) {
+        this(inputStream, new byte[size]);
+    } // <init>(InputStream, int)
+
+    /**
+     * Constructs an ISO-8859-1 reader from the specified input stream and
+     * buffer.
+     *
+     * @param inputStream The input stream.
+     * @param buffer The byte buffer.
+     */
+    public Latin1Reader(InputStream inputStream, byte[] buffer) {
+        fInputStream = inputStream;
+        fBuffer = buffer;
+    } // <init>(InputStream, byte[])
+
+    //
+    // Reader methods
+    //
+    /**
+     * Read a single character. This method will block until a character is
+     * available, an I/O error occurs, or the end of the stream is reached.
+     *
+     * <p>
+     * Subclasses that intend to support efficient single-character input should
+     * override this method.
+     *
+     * @return The character read, as an integer in the range 0 to 255
+     * (<tt>0x00-0xff</tt>), or -1 if the end of the stream has been reached
+     *
+     * @exception IOException If an I/O error occurs
+     */
+    public int read() throws IOException {
+        return fInputStream.read();
+    } // read():int
+
+    /**
+     * Read characters into a portion of an array. This method will block until
+     * some input is available, an I/O error occurs, or the end of the stream is
+     * reached.
+     *
+     * @param ch Destination buffer
+     * @param offset Offset at which to start storing characters
+     * @param length Maximum number of characters to read
+     *
+     * @return The number of characters read, or -1 if the end of the stream has
+     * been reached
+     *
+     * @exception IOException If an I/O error occurs
+     */
+    public int read(char ch[], int offset, int length) throws IOException {
+        if (length > fBuffer.length) {
+            length = fBuffer.length;
+        }
+        int count = fInputStream.read(fBuffer, 0, length);
+        for (int i = 0; i < count; ++i) {
+            ch[offset + i] = (char) (fBuffer[i] & 0xff);
+        }
+        return count;
+    } // read(char[],int,int)
+
+    /**
+     * Skip characters. This method will block until some characters are
+     * available, an I/O error occurs, or the end of the stream is reached.
+     *
+     * @param n The number of characters to skip
+     *
+     * @return The number of characters actually skipped
+     *
+     * @exception IOException If an I/O error occurs
+     */
+    public long skip(long n) throws IOException {
+        return fInputStream.skip(n);
+    } // skip(long):long
+
+    /**
+     * Tell whether this stream is ready to be read.
+     *
+     * @return True if the next read() is guaranteed not to block for input,
+     * false otherwise. Note that returning false does not guarantee that the
+     * next read will block.
+     *
+     * @exception IOException If an I/O error occurs
+     */
+    public boolean ready() throws IOException {
+        return false;
+    } // ready()
+
+    /**
+     * Tell whether this stream supports the mark() operation.
+     */
+    public boolean markSupported() {
+        return fInputStream.markSupported();
+    } // markSupported()
+
+    /**
+     * Mark the present position in the stream. Subsequent calls to reset() will
+     * attempt to reposition the stream to this point. Not all character-input
+     * streams support the mark() operation.
+     *
+     * @param readAheadLimit Limit on the number of characters that may be read
+     * while still preserving the mark. After reading this many characters,
+     * attempting to reset the stream may fail.
+     *
+     * @exception IOException If the stream does not support mark(), or if some
+     * other I/O error occurs
+     */
+    public void mark(int readAheadLimit) throws IOException {
+        fInputStream.mark(readAheadLimit);
+    } // mark(int)
+
+    /**
+     * Reset the stream. If the stream has been marked, then attempt to
+     * reposition it at the mark. If the stream has not been marked, then
+     * attempt to reset it in some way appropriate to the particular stream, for
+     * example by repositioning it to its starting point. Not all
+     * character-input streams support the reset() operation, and some support
+     * reset() without supporting mark().
+     *
+     * @exception IOException If the stream has not been marked, or if the mark
+     * has been invalidated, or if the stream does not support reset(), or if
+     * some other I/O error occurs
+     */
+    public void reset() throws IOException {
+        fInputStream.reset();
+    } // reset()
+
+    /**
+     * Close the stream. Once a stream has been closed, further read(), ready(),
+     * mark(), or reset() invocations will throw an IOException. Closing a
+     * previously-closed stream, however, has no effect.
+     *
+     * @exception IOException If an I/O error occurs
+     */
+    public void close() throws IOException {
+        fInputStream.close();
+    } // close()
+
+} // class Latin1Reader
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/io/UTF16Reader.java	Tue Feb 27 12:47:58 2018 +0000
@@ -0,0 +1,333 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.sun.org.apache.xerces.internal.impl.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.Locale;
+
+import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
+import com.sun.org.apache.xerces.internal.util.MessageFormatter;
+
+/**
+ * <p>
+ * A UTF-16 reader. Can also be used for UCS-2 (i.e. ISO-10646-UCS-2).</p>
+ *
+ * @xerces.internal
+ *
+ * @author Michael Glavassevich, IBM
+ *
+ * @version $Id: UTF16Reader.java 718095 2008-11-16 20:00:14Z mrglavas $
+ */
+public final class UTF16Reader
+        extends Reader {
+
+    //
+    // Constants
+    //
+    /**
+     * Default byte buffer size (4096).
+     */
+    public static final int DEFAULT_BUFFER_SIZE = 4096;
+
+    //
+    // Data
+    //
+    /**
+     * Input stream.
+     */
+    protected final InputStream fInputStream;
+
+    /**
+     * Byte buffer.
+     */
+    protected final byte[] fBuffer;
+
+    /**
+     * Endianness.
+     */
+    protected final boolean fIsBigEndian;
+
+    // message formatter; used to produce localized exception messages
+    private final MessageFormatter fFormatter;
+
+    // Locale to use for messages
+    private final Locale fLocale;
+
+    //
+    // Constructors
+    //
+    /**
+     * Constructs a UTF-16 reader from the specified input stream using the
+     * default buffer size. Primarily for testing.
+     *
+     * @param inputStream The input stream.
+     * @param isBigEndian The byte order.
+     */
+    public UTF16Reader(InputStream inputStream, boolean isBigEndian) {
+        this(inputStream, DEFAULT_BUFFER_SIZE, isBigEndian,
+                new XMLMessageFormatter(), Locale.getDefault());
+    } // <init>(InputStream, boolean)
+
+    /**
+     * Constructs a UTF-16 reader from the specified input stream using the
+     * default buffer size and the given MessageFormatter.
+     *
+     * @param inputStream The input stream.
+     * @param isBigEndian The byte order.
+     */
+    public UTF16Reader(InputStream inputStream, boolean isBigEndian,
+            MessageFormatter messageFormatter, Locale locale) {
+        this(inputStream, DEFAULT_BUFFER_SIZE, isBigEndian, messageFormatter, locale);
+    } // <init>(InputStream, boolean, MessageFormatter, Locale)
+
+    /**
+     * Constructs a UTF-16 reader from the specified input stream and buffer
+     * size and given MessageFormatter.
+     *
+     * @param inputStream The input stream.
+     * @param size The initial buffer size.
+     * @param isBigEndian The byte order.
+     * @param messageFormatter Given MessageFormatter
+     * @param locale Locale to use for messages
+     */
+    public UTF16Reader(InputStream inputStream, int size, boolean isBigEndian,
+            MessageFormatter messageFormatter, Locale locale) {
+        this(inputStream, new byte[size], isBigEndian, messageFormatter, locale);
+    } // <init>(InputStream, int, boolean, MessageFormatter, Locale)
+
+    /**
+     * Constructs a UTF-16 reader from the specified input stream, buffer and
+     * MessageFormatter.
+     *
+     * @param inputStream The input stream.
+     * @param buffer The byte buffer.
+     * @param isBigEndian The byte order.
+     * @param messageFormatter Given MessageFormatter
+     * @param locale Locale to use for messages
+     */
+    public UTF16Reader(InputStream inputStream, byte[] buffer, boolean isBigEndian,
+            MessageFormatter messageFormatter, Locale locale) {
+        fInputStream = inputStream;
+        fBuffer = buffer;
+        fIsBigEndian = isBigEndian;
+        fFormatter = messageFormatter;
+        fLocale = locale;
+    } // <init>(InputStream, byte[], boolean, MessageFormatter, Locale)
+
+    //
+    // Reader methods
+    //
+    /**
+     * Read a single character. This method will block until a character is
+     * available, an I/O error occurs, or the end of the stream is reached.
+     *
+     * <p>
+     * Subclasses that intend to support efficient single-character input should
+     * override this method.
+     *
+     * @return The character read, as an integer in the range 0 to 65535
+     * (<tt>0x00-0xffff</tt>), or -1 if the end of the stream has been reached
+     *
+     * @exception IOException If an I/O error occurs
+     */
+    public int read() throws IOException {
+        final int b0 = fInputStream.read();
+        if (b0 == -1) {
+            return -1;
+        }
+        final int b1 = fInputStream.read();
+        if (b1 == -1) {
+            expectedTwoBytes();
+        }
+        // UTF-16BE
+        if (fIsBigEndian) {
+            return (b0 << 8) | b1;
+        }
+        // UTF-16LE
+        return (b1 << 8) | b0;
+    } // read():int
+
+    /**
+     * Read characters into a portion of an array. This method will block until
+     * some input is available, an I/O error occurs, or the end of the stream is
+     * reached.
+     *
+     * @param ch Destination buffer
+     * @param offset Offset at which to start storing characters
+     * @param length Maximum number of characters to read
+     *
+     * @return The number of characters read, or -1 if the end of the stream has
+     * been reached
+     *
+     * @exception IOException If an I/O error occurs
+     */
+    public int read(char ch[], int offset, int length) throws IOException {
+        int byteLength = length << 1;
+        if (byteLength > fBuffer.length) {
+            byteLength = fBuffer.length;
+        }
+        int byteCount = fInputStream.read(fBuffer, 0, byteLength);
+        if (byteCount == -1) {
+            return -1;
+        }
+        // If an odd number of bytes were read, we still need to read one more.
+        if ((byteCount & 1) != 0) {
+            int b = fInputStream.read();
+            if (b == -1) {
+                expectedTwoBytes();
+            }
+            fBuffer[byteCount++] = (byte) b;
+        }
+        final int charCount = byteCount >> 1;
+        if (fIsBigEndian) {
+            processBE(ch, offset, charCount);
+        } else {
+            processLE(ch, offset, charCount);
+        }
+        return charCount;
+    } // read(char[],int,int)
+
+    /**
+     * Skip characters. This method will block until some characters are
+     * available, an I/O error occurs, or the end of the stream is reached.
+     *
+     * @param n The number of characters to skip
+     *
+     * @return The number of characters actually skipped
+     *
+     * @exception IOException If an I/O error occurs
+     */
+    public long skip(long n) throws IOException {
+        long bytesSkipped = fInputStream.skip(n << 1);
+        if ((bytesSkipped & 1) != 0) {
+            int b = fInputStream.read();
+            if (b == -1) {
+                expectedTwoBytes();
+            }
+            ++bytesSkipped;
+        }
+        return bytesSkipped >> 1;
+    } // skip(long):long
+
+    /**
+     * Tell whether this stream is ready to be read.
+     *
+     * @return True if the next read() is guaranteed not to block for input,
+     * false otherwise. Note that returning false does not guarantee that the
+     * next read will block.
+     *
+     * @exception IOException If an I/O error occurs
+     */
+    public boolean ready() throws IOException {
+        return false;
+    } // ready()
+
+    /**
+     * Tell whether this stream supports the mark() operation.
+     */
+    public boolean markSupported() {
+        return false;
+    } // markSupported()
+
+    /**
+     * Mark the present position in the stream. Subsequent calls to reset() will
+     * attempt to reposition the stream to this point. Not all character-input
+     * streams support the mark() operation.
+     *
+     * @param readAheadLimit Limit on the number of characters that may be read
+     * while still preserving the mark. After reading this many characters,
+     * attempting to reset the stream may fail.
+     *
+     * @exception IOException If the stream does not support mark(), or if some
+     * other I/O error occurs
+     */
+    public void mark(int readAheadLimit) throws IOException {
+        throw new IOException(fFormatter.formatMessage(fLocale, "OperationNotSupported", new Object[]{"mark()", "UTF-16"}));
+    } // mark(int)
+
+    /**
+     * Reset the stream. If the stream has been marked, then attempt to
+     * reposition it at the mark. If the stream has not been marked, then
+     * attempt to reset it in some way appropriate to the particular stream, for
+     * example by repositioning it to its starting point. Not all
+     * character-input streams support the reset() operation, and some support
+     * reset() without supporting mark().
+     *
+     * @exception IOException If the stream has not been marked, or if the mark
+     * has been invalidated, or if the stream does not support reset(), or if
+     * some other I/O error occurs
+     */
+    public void reset() throws IOException {
+    } // reset()
+
+    /**
+     * Close the stream. Once a stream has been closed, further read(), ready(),
+     * mark(), or reset() invocations will throw an IOException. Closing a
+     * previously-closed stream, however, has no effect.
+     *
+     * @exception IOException If an I/O error occurs
+     */
+    public void close() throws IOException {
+        fInputStream.close();
+    } // close()
+
+    //
+    // Private methods
+    //
+    /**
+     * Decodes UTF-16BE *
+     */
+    private void processBE(final char ch[], int offset, final int count) {
+        int curPos = 0;
+        for (int i = 0; i < count; ++i) {
+            final int b0 = fBuffer[curPos++] & 0xff;
+            final int b1 = fBuffer[curPos++] & 0xff;
+            ch[offset++] = (char) ((b0 << 8) | b1);
+        }
+    } // processBE(char[],int,int)
+
+    /**
+     * Decodes UTF-16LE *
+     */
+    private void processLE(final char ch[], int offset, final int count) {
+        int curPos = 0;
+        for (int i = 0; i < count; ++i) {
+            final int b0 = fBuffer[curPos++] & 0xff;
+            final int b1 = fBuffer[curPos++] & 0xff;
+            ch[offset++] = (char) ((b1 << 8) | b0);
+        }
+    } // processLE(char[],int,int)
+
+    /**
+     * Throws an exception for expected byte.
+     */
+    private void expectedTwoBytes()
+            throws MalformedByteSequenceException {
+        throw new MalformedByteSequenceException(fFormatter,
+                fLocale,
+                XMLMessageFormatter.XML_DOMAIN,
+                "ExpectedByte",
+                new Object[]{"2", "2"});
+    } // expectedTwoBytes()
+
+} // class UTF16Reader
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractSAXParser.java	Mon Feb 26 17:18:15 2018 -0800
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractSAXParser.java	Tue Feb 27 12:47:58 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -46,6 +46,7 @@
 import com.sun.org.apache.xerces.internal.xs.AttributePSVI;
 import com.sun.org.apache.xerces.internal.xs.ElementPSVI;
 import com.sun.org.apache.xerces.internal.xs.PSVIProvider;
+import java.io.CharConversionException;
 import java.io.IOException;
 import java.util.Locale;
 import javax.xml.XMLConstants;
@@ -1143,7 +1144,7 @@
         // wrap XNI exceptions as SAX exceptions
         catch (XMLParseException e) {
             Exception ex = e.getException();
-            if (ex == null) {
+            if (ex == null || ex instanceof CharConversionException) {
                 // must be a parser exception; mine it for locator info and throw
                 // a SAXParseException
                 LocatorImpl locatorImpl = new LocatorImpl(){
@@ -1163,7 +1164,9 @@
                 locatorImpl.setSystemId(e.getExpandedSystemId());
                 locatorImpl.setLineNumber(e.getLineNumber());
                 locatorImpl.setColumnNumber(e.getColumnNumber());
-                throw new SAXParseException(e.getMessage(), locatorImpl);
+                throw (ex == null) ?
+                        new SAXParseException(e.getMessage(), locatorImpl) :
+                        new SAXParseException(e.getMessage(), locatorImpl, ex);
             }
             if (ex instanceof SAXException) {
                 // why did we create an XMLParseException?
@@ -1216,7 +1219,7 @@
         // wrap XNI exceptions as SAX exceptions
         catch (XMLParseException e) {
             Exception ex = e.getException();
-            if (ex == null) {
+            if (ex == null || ex instanceof CharConversionException) {
                 // must be a parser exception; mine it for locator info and throw
                 // a SAXParseException
                 LocatorImpl locatorImpl = new LocatorImpl() {
@@ -1236,7 +1239,9 @@
                 locatorImpl.setSystemId(e.getExpandedSystemId());
                 locatorImpl.setLineNumber(e.getLineNumber());
                 locatorImpl.setColumnNumber(e.getColumnNumber());
-                throw new SAXParseException(e.getMessage(), locatorImpl);
+                throw (ex == null) ?
+                        new SAXParseException(e.getMessage(), locatorImpl) :
+                        new SAXParseException(e.getMessage(), locatorImpl, ex);
             }
             if (ex instanceof SAXException) {
                 // why did we create an XMLParseException?
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/DOMParser.java	Mon Feb 26 17:18:15 2018 -0800
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/DOMParser.java	Tue Feb 27 12:47:58 2018 +0000
@@ -40,6 +40,7 @@
 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
 import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException;
 import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
+import java.io.CharConversionException;
 import org.w3c.dom.Node;
 import org.xml.sax.EntityResolver;
 import org.xml.sax.ErrorHandler;
@@ -184,7 +185,7 @@
         // wrap XNI exceptions as SAX exceptions
         catch (XMLParseException e) {
             Exception ex = e.getException();
-            if (ex == null) {
+            if (ex == null || ex instanceof CharConversionException) {
                 // must be a parser exception; mine it for locator info and throw
                 // a SAXParseException
                 LocatorImpl locatorImpl = new LocatorImpl();
@@ -192,7 +193,9 @@
                 locatorImpl.setSystemId(e.getExpandedSystemId());
                 locatorImpl.setLineNumber(e.getLineNumber());
                 locatorImpl.setColumnNumber(e.getColumnNumber());
-                throw new SAXParseException(e.getMessage(), locatorImpl);
+                throw (ex == null) ?
+                        new SAXParseException(e.getMessage(), locatorImpl) :
+                        new SAXParseException(e.getMessage(), locatorImpl, ex);
             }
             if (ex instanceof SAXException) {
                 // why did we create an XMLParseException?
@@ -246,7 +249,7 @@
         // wrap XNI exceptions as SAX exceptions
         catch (XMLParseException e) {
             Exception ex = e.getException();
-            if (ex == null) {
+            if (ex == null || ex instanceof CharConversionException) {
                 // must be a parser exception; mine it for locator info and throw
                 // a SAXParseException
                 LocatorImpl locatorImpl = new LocatorImpl();
@@ -254,7 +257,9 @@
                 locatorImpl.setSystemId(e.getExpandedSystemId());
                 locatorImpl.setLineNumber(e.getLineNumber());
                 locatorImpl.setColumnNumber(e.getColumnNumber());
-                throw new SAXParseException(e.getMessage(), locatorImpl);
+                throw (ex == null) ?
+                        new SAXParseException(e.getMessage(), locatorImpl) :
+                        new SAXParseException(e.getMessage(), locatorImpl, ex);
             }
             if (ex instanceof SAXException) {
                 // why did we create an XMLParseException?
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLLocatorWrapper.java	Tue Feb 27 12:47:58 2018 +0000
@@ -0,0 +1,113 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sun.org.apache.xerces.internal.util;
+
+import com.sun.org.apache.xerces.internal.xni.XMLLocator;
+
+/**
+ * <p>A light wrapper around an <code>XMLLocator</code>.</p>
+ *
+ * @author Michael Glavassevich, IBM
+ *
+ * @version $Id: XMLLocatorWrapper.java 533423 2007-04-28 20:47:15Z mrglavas $
+ */
+public final class XMLLocatorWrapper implements XMLLocator {
+
+    private XMLLocator fLocator = null;
+
+    public XMLLocatorWrapper() {}
+
+    public void setLocator(XMLLocator locator) {
+        fLocator = locator;
+    }
+
+    public XMLLocator getLocator() {
+        return fLocator;
+    }
+
+    /*
+     * XMLLocator methods
+     */
+
+    public String getPublicId() {
+        if (fLocator != null) {
+            return fLocator.getPublicId();
+        }
+        return null;
+    }
+
+    public String getLiteralSystemId() {
+        if (fLocator != null) {
+            return fLocator.getLiteralSystemId();
+        }
+        return null;
+    }
+
+    public String getBaseSystemId() {
+        if (fLocator != null) {
+            return fLocator.getBaseSystemId();
+        }
+        return null;
+    }
+
+    public String getExpandedSystemId() {
+        if (fLocator != null) {
+            return fLocator.getExpandedSystemId();
+        }
+        return null;
+    }
+
+    public int getLineNumber() {
+        if (fLocator != null) {
+            return fLocator.getLineNumber();
+        }
+        return -1;
+    }
+
+    public int getColumnNumber() {
+        if (fLocator != null) {
+            return fLocator.getColumnNumber();
+        }
+        return -1;
+    }
+
+    public int getCharacterOffset() {
+        if (fLocator != null) {
+            return fLocator.getCharacterOffset();
+        }
+        return -1;
+    }
+
+    public String getEncoding() {
+        if (fLocator != null) {
+            return fLocator.getEncoding();
+        }
+        return null;
+    }
+
+    public String getXMLVersion() {
+        if (fLocator != null) {
+            return fLocator.getXMLVersion();
+        }
+        return null;
+    }
+}
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/xinclude/XIncludeHandler.java	Mon Feb 26 17:18:15 2018 -0800
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/xinclude/XIncludeHandler.java	Tue Feb 27 12:47:58 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -36,9 +36,9 @@
 import com.sun.org.apache.xerces.internal.util.URI;
 import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl;
 import com.sun.org.apache.xerces.internal.util.XMLChar;
+import com.sun.org.apache.xerces.internal.util.XMLLocatorWrapper;
 import com.sun.org.apache.xerces.internal.util.XMLResourceIdentifierImpl;
 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
-import com.sun.org.apache.xerces.internal.utils.ObjectFactory;
 import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
 import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
 import com.sun.org.apache.xerces.internal.xni.Augmentations;
@@ -157,8 +157,8 @@
     public final static String CURRENT_BASE_URI = "currentBaseURI";
 
     // used for adding [base URI] attributes
-    public final static String XINCLUDE_BASE = "base".intern();
-    public final static QName XML_BASE_QNAME =
+    private final static String XINCLUDE_BASE = "base".intern();
+    private final static QName XML_BASE_QNAME =
         new QName(
             XMLSymbols.PREFIX_XML,
             XINCLUDE_BASE,
@@ -166,15 +166,15 @@
             NamespaceContext.XML_URI);
 
     // used for adding [language] attributes
-    public final static String XINCLUDE_LANG = "lang".intern();
-    public final static QName XML_LANG_QNAME =
+    private final static String XINCLUDE_LANG = "lang".intern();
+    private final static QName XML_LANG_QNAME =
         new QName(
             XMLSymbols.PREFIX_XML,
             XINCLUDE_LANG,
             (XMLSymbols.PREFIX_XML + ":" + XINCLUDE_LANG).intern(),
             NamespaceContext.XML_URI);
 
-    public final static QName NEW_NS_ATTR_QNAME =
+    private final static QName NEW_NS_ATTR_QNAME =
         new QName(
             XMLSymbols.PREFIX_XMLNS,
             "",
@@ -217,6 +217,10 @@
     protected static final String XINCLUDE_FIXUP_LANGUAGE =
         Constants.XERCES_FEATURE_PREFIX + Constants.XINCLUDE_FIXUP_LANGUAGE_FEATURE;
 
+    /** Property identifier: JAXP schema language. */
+    protected static final String JAXP_SCHEMA_LANGUAGE =
+        Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE;
+
     /** Property identifier: symbol table. */
     protected static final String SYMBOL_TABLE =
         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
@@ -234,7 +238,7 @@
         Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
 
     /** property identifier: buffer size. */
-    public static final String BUFFER_SIZE =
+    protected static final String BUFFER_SIZE =
         Constants.XERCES_PROPERTY_PREFIX + Constants.BUFFER_SIZE_PROPERTY;
 
     protected static final String PARSER_SETTINGS =
@@ -292,6 +296,7 @@
     protected XPointerProcessor fXPtrProcessor = null;
 
     protected XMLLocator fDocLocation;
+    protected XMLLocatorWrapper fXIncludeLocator = new XMLLocatorWrapper();
     protected XIncludeMessageFormatter fXIncludeMessageFormatter = new XIncludeMessageFormatter();
     protected XIncludeNamespaceSupport fNamespaceContext;
     protected SymbolTable fSymbolTable;
@@ -305,17 +310,19 @@
     protected XIncludeTextReader fXInclude11TextReader;
 
     // these are needed for XML Base processing
-    protected XMLResourceIdentifier fCurrentBaseURI;
-    protected IntStack fBaseURIScope;
-    protected Stack<String> fBaseURI;
-    protected Stack<String> fLiteralSystemID;
-    protected Stack<String> fExpandedSystemID;
+    protected final XMLResourceIdentifier fCurrentBaseURI;
+    protected final IntStack fBaseURIScope;
+    protected final Stack<String> fBaseURI;
+    protected final Stack<String> fLiteralSystemID;
+    protected final Stack<String> fExpandedSystemID;
 
     // these are needed for Language Fixup
-    protected IntStack fLanguageScope;
-    protected Stack<String> fLanguageStack;
+    protected final IntStack fLanguageScope;
+    protected final Stack<String> fLanguageStack;
     protected String fCurrentLanguage;
 
+    protected String fHrefFromParent;
+
     // used for passing features on to child XIncludeHandler objects
     protected ParserConfigurationSettings fSettings;
 
@@ -361,6 +368,9 @@
     // track whether a DTD is being parsed
     private boolean fInDTD;
 
+    // tracks whether content has been reported on the child pipeline
+    boolean fHasIncludeReportedContent;
+
     // track whether the root element of the result infoset has been processed
     private boolean fSeenRootElement;
 
@@ -593,15 +603,21 @@
         copyFeatures(componentManager, fSettings);
 
         // We don't want a schema validator on the new pipeline,
-        // so if it was enabled, we set the feature to false. If
-        // the validation feature was also enabled we turn on
-        // dynamic validation, so that DTD validation is performed
-        // on the included documents only if they have a DOCTYPE.
-        // This is consistent with the behaviour on the main pipeline.
+        // so if it was enabled, we set the feature to false.
         try {
             if (componentManager.getFeature(SCHEMA_VALIDATION)) {
                 fSettings.setFeature(SCHEMA_VALIDATION, false);
-                if (componentManager.getFeature(VALIDATION)) {
+                // If the value of the JAXP 1.2 schema language property
+                // is http://www.w3.org/2001/XMLSchema we're only validating
+                // against XML schema so we disable validation on the new pipeline.
+                if (Constants.NS_XMLSCHEMA.equals(componentManager.getProperty(JAXP_SCHEMA_LANGUAGE))) {
+                    fSettings.setFeature(VALIDATION, false);
+                }
+                // If the validation feature was also enabled we turn on
+                // dynamic validation, so that DTD validation is performed
+                // on the included documents only if they have a DOCTYPE.
+                // This is consistent with the behaviour on the main pipeline.
+                else if (componentManager.getFeature(VALIDATION)) {
                     fSettings.setFeature(DYNAMIC_VALIDATION, true);
                 }
             }
@@ -776,7 +792,15 @@
 
     @Override
     public void setDocumentHandler(XMLDocumentHandler handler) {
-        fDocumentHandler = handler;
+        if (fDocumentHandler != handler) {
+            fDocumentHandler = handler;
+            if (fXIncludeChildConfig != null) {
+                fXIncludeChildConfig.setDocumentHandler(handler);
+            }
+            if (fXPointerChildConfig != null) {
+                fXPointerChildConfig.setDocumentHandler(handler);
+            }
+        }
     }
 
     @Override
@@ -806,36 +830,39 @@
         // otherwise, the locator from the root document would always be used
         fErrorReporter.setDocumentLocator(locator);
 
-        if (!isRootDocument()
-            && fParentXIncludeHandler.searchForRecursiveIncludes(locator)) {
-            reportFatalError(
-                "RecursiveInclude",
-                new Object[] { locator.getExpandedSystemId()});
-        }
-
         if (!(namespaceContext instanceof XIncludeNamespaceSupport)) {
             reportFatalError("IncompatibleNamespaceContext");
         }
         fNamespaceContext = (XIncludeNamespaceSupport)namespaceContext;
         fDocLocation = locator;
+        fXIncludeLocator.setLocator(fDocLocation);
 
         // initialize the current base URI
-        fCurrentBaseURI.setBaseSystemId(locator.getBaseSystemId());
-        fCurrentBaseURI.setExpandedSystemId(locator.getExpandedSystemId());
-        fCurrentBaseURI.setLiteralSystemId(locator.getLiteralSystemId());
+        setupCurrentBaseURI(locator);
         saveBaseURI();
         if (augs == null) {
             augs = new AugmentationsImpl();
         }
         augs.putItem(CURRENT_BASE_URI, fCurrentBaseURI);
 
+        // abort here if we detect a recursive include
+        if (!isRootDocument()) {
+            fParentXIncludeHandler.fHasIncludeReportedContent = true;
+            if (fParentXIncludeHandler.searchForRecursiveIncludes(
+                fCurrentBaseURI.getExpandedSystemId())) {
+                reportFatalError(
+                        "RecursiveInclude",
+                        new Object[] { fCurrentBaseURI.getExpandedSystemId()});
+            }
+        }
+
         // initialize the current language
         fCurrentLanguage = XMLSymbols.EMPTY_STRING;
         saveLanguage(fCurrentLanguage);
 
         if (isRootDocument() && fDocumentHandler != null) {
             fDocumentHandler.startDocument(
-                locator,
+                fXIncludeLocator,
                 encoding,
                 namespaceContext,
                 augs);
@@ -1671,7 +1698,7 @@
             catch (IOException | CatalogException e) {
                 reportResourceError(
                     "XMLResourceError",
-                    new Object[] { href, e.getMessage()});
+                    new Object[] { href, e.getMessage()}, e);
                 return false;
             }
         }
@@ -1750,6 +1777,8 @@
                         // ???
 
                     newHandler.setParent(this);
+                    newHandler.setHref(href);
+                    newHandler.setXIncludeLocator(fXIncludeLocator);
                     newHandler.setDocumentHandler(this.getDocumentHandler());
                     fXPointerChildConfig = fChildConfig;
                 } else {
@@ -1758,7 +1787,8 @@
                             Constants.XERCES_PROPERTY_PREFIX
                                 + Constants.XINCLUDE_HANDLER_PROPERTY);
 
-                        newHandler.setParent(this);
+                    newHandler.setParent(this);
+                    newHandler.setHref(href);
                     newHandler.setDocumentHandler(this.getDocumentHandler());
                     fXIncludeChildConfig = fChildConfig;
                 }
@@ -1766,7 +1796,7 @@
 
             // If an xpointer attribute is present
             if (xpointer != null ) {
-                fChildConfig = fXPointerChildConfig ;
+                fChildConfig = fXPointerChildConfig;
 
                 // Parse the XPointer expression
                 try {
@@ -1790,10 +1820,12 @@
             fNeedCopyFeatures = false;
 
             try {
+                fHasIncludeReportedContent = false;
                 fNamespaceContext.pushScope();
 
                 fChildConfig.parse(includedSource);
-                // necessary to make sure proper location is reported in errors
+                // necessary to make sure proper location is reported to the application and in errors
+                fXIncludeLocator.setLocator(fDocLocation);
                 if (fErrorReporter != null) {
                     fErrorReporter.setDocumentLocator(fDocLocation);
                 }
@@ -1811,23 +1843,32 @@
                 }
             }
             catch (XNIException e) {
-                // necessary to make sure proper location is reported in errors
+                // necessary to make sure proper location is reported to the application and in errors
+                fXIncludeLocator.setLocator(fDocLocation);
                 if (fErrorReporter != null) {
                     fErrorReporter.setDocumentLocator(fDocLocation);
                 }
                 reportFatalError("XMLParseError", new Object[] { href, e.getMessage() });
             }
             catch (IOException e) {
-                // necessary to make sure proper location is reported in errors
+                // necessary to make sure proper location is reported to the application and in errors
+                fXIncludeLocator.setLocator(fDocLocation);
                 if (fErrorReporter != null) {
                     fErrorReporter.setDocumentLocator(fDocLocation);
                 }
-                // An IOException indicates that we had trouble reading the file, not
-                // that it was an invalid XML file.  So we send a resource error, not a
-                // fatal error.
+                // If the start document event has been seen on the child pipeline it
+                // means the resource was successfully opened and we started reporting
+                // document events. If an IOException is thrown after the start document
+                // event we had a failure midstream and cannot recover.
+                if (fHasIncludeReportedContent) {
+                    throw new XNIException(e);
+                }
+                // In other circumstances an IOException indicates that we had trouble
+                // accessing or opening the file, not that it was an invalid XML file. So we
+                // send a resource error, not a fatal error.
                 reportResourceError(
                     "XMLResourceError",
-                    new Object[] { href, e.getMessage()});
+                    new Object[] { href, e.getMessage()}, e);
                 return false;
             }
             finally {
@@ -1841,6 +1882,8 @@
             XIncludeTextReader textReader = null;
 
             try {
+                fHasIncludeReportedContent = false;
+
                 // Setup the appropriate text reader.
                 if (!fIsXML11) {
                     if (fXInclude10TextReader == null) {
@@ -1866,16 +1909,22 @@
             // encoding errors
             catch (MalformedByteSequenceException ex) {
                 fErrorReporter.reportError(ex.getDomain(), ex.getKey(),
-                    ex.getArguments(), XMLErrorReporter.SEVERITY_FATAL_ERROR);
+                    ex.getArguments(), XMLErrorReporter.SEVERITY_FATAL_ERROR, ex);
             }
             catch (CharConversionException e) {
                 fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
-                    "CharConversionFailure", null, XMLErrorReporter.SEVERITY_FATAL_ERROR);
+                    "CharConversionFailure", null, XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
             }
             catch (IOException e) {
+                // If a characters event has already been sent down the pipeline it
+                // means the resource was successfully opened and that this IOException
+                // is from a failure midstream from which we cannot recover.
+                if (fHasIncludeReportedContent) {
+                    throw new XNIException(e);
+                }
                 reportResourceError(
                     "TextResourceError",
-                    new Object[] { href, e.getMessage()});
+                    new Object[] { href, e.getMessage()}, e);
                 return false;
             }
             finally {
@@ -1886,7 +1935,7 @@
                     catch (IOException e) {
                         reportResourceError(
                             "TextResourceError",
-                            new Object[] { href, e.getMessage()});
+                            new Object[] { href, e.getMessage()}, e);
                         return false;
                     }
                 }
@@ -1977,37 +2026,51 @@
         return parentLanguage != null && parentLanguage.equalsIgnoreCase(fCurrentLanguage);
     }
 
-    /**
-     * Checks if the file indicated by the given XMLLocator has already been included
-     * in the current stack.
-     * @param includedSource the source to check for inclusion
-     * @return true if the source has already been included
-     */
-    protected boolean searchForRecursiveIncludes(XMLLocator includedSource) {
-        String includedSystemId = includedSource.getExpandedSystemId();
+    private void setupCurrentBaseURI(XMLLocator locator) {
+        fCurrentBaseURI.setBaseSystemId(locator.getBaseSystemId());
+        if (locator.getLiteralSystemId() != null) {
+            fCurrentBaseURI.setLiteralSystemId(locator.getLiteralSystemId());
+        }
+        else {
+            fCurrentBaseURI.setLiteralSystemId(fHrefFromParent);
+        }
 
-        if (includedSystemId == null) {
+        String expandedSystemId = locator.getExpandedSystemId();
+        if (expandedSystemId == null) {
+            // attempt to expand it ourselves
             try {
-                includedSystemId =
+                expandedSystemId =
                     XMLEntityManager.expandSystemId(
-                        includedSource.getLiteralSystemId(),
-                        includedSource.getBaseSystemId(),
+                        fCurrentBaseURI.getLiteralSystemId(),
+                        fCurrentBaseURI.getBaseSystemId(),
                         false);
+                if (expandedSystemId == null) {
+                    expandedSystemId = fCurrentBaseURI.getLiteralSystemId();
+                }
             }
             catch (MalformedURIException e) {
                 reportFatalError("ExpandedSystemId");
             }
         }
+        fCurrentBaseURI.setExpandedSystemId(expandedSystemId);
+    }
 
-        if (includedSystemId.equals(fCurrentBaseURI.getExpandedSystemId())) {
+    /**
+     * Checks if the file indicated by the given system id has already been
+     * included in the current stack.
+     * @param includedSysId the system id to check for inclusion
+     * @return true if the source has already been included
+     */
+    protected boolean searchForRecursiveIncludes(String includedSysId) {
+        if (includedSysId.equals(fCurrentBaseURI.getExpandedSystemId())) {
             return true;
         }
-
-        if (fParentXIncludeHandler == null) {
+        else if (fParentXIncludeHandler == null) {
             return false;
         }
-        return fParentXIncludeHandler.searchForRecursiveIncludes(
-            includedSource);
+        else {
+            return fParentXIncludeHandler.searchForRecursiveIncludes(includedSysId);
+        }
     }
 
     /**
@@ -2045,7 +2108,7 @@
      * unparsed entities are processed as described in the spec, sections 4.5.1 and 4.5.2
      * </ul>
      * @param attributes
-     * @return
+     * @return the processed XMLAttributes
      */
     protected XMLAttributes processAttributes(XMLAttributes attributes) {
         if (isTopLevelIncludedItem()) {
@@ -2198,7 +2261,7 @@
             return relativeURI;
         }
         else {
-            if (relativeURI.equals("")) {
+            if (relativeURI.length() == 0) {
                 relativeURI = fCurrentBaseURI.getLiteralSystemId();
             }
 
@@ -2207,7 +2270,7 @@
                     fParentRelativeURI =
                         fParentXIncludeHandler.getRelativeBaseURI();
                 }
-                if (fParentRelativeURI.equals("")) {
+                if (fParentRelativeURI.length() == 0) {
                     return relativeURI;
                 }
 
@@ -2420,7 +2483,7 @@
      * as an ancestor of the current item.
      *
      * @param depth
-     * @return
+     * @return true if an include was seen at the given depth, false otherwise
      */
     protected boolean getSawInclude(int depth) {
         if (depth >= fSawInclude.length) {
@@ -2430,11 +2493,15 @@
     }
 
     protected void reportResourceError(String key) {
-        this.reportFatalError(key, null);
+        this.reportResourceError(key, null);
     }
 
     protected void reportResourceError(String key, Object[] args) {
-        this.reportError(key, args, XMLErrorReporter.SEVERITY_WARNING);
+        this.reportResourceError(key, args, null);
+    }
+
+    protected void reportResourceError(String key, Object[] args, Exception exception) {
+        this.reportError(key, args, XMLErrorReporter.SEVERITY_WARNING, exception);
     }
 
     protected void reportFatalError(String key) {
@@ -2442,16 +2509,21 @@
     }
 
     protected void reportFatalError(String key, Object[] args) {
-        this.reportError(key, args, XMLErrorReporter.SEVERITY_FATAL_ERROR);
+        this.reportFatalError(key, args, null);
     }
 
-    private void reportError(String key, Object[] args, short severity) {
+    protected void reportFatalError(String key, Object[] args, Exception exception) {
+        this.reportError(key, args, XMLErrorReporter.SEVERITY_FATAL_ERROR, exception);
+    }
+
+    private void reportError(String key, Object[] args, short severity, Exception exception) {
         if (fErrorReporter != null) {
             fErrorReporter.reportError(
                 XIncludeMessageFormatter.XINCLUDE_DOMAIN,
                 key,
                 args,
-                severity);
+                severity,
+                exception);
         }
         // we won't worry about when error reporter is null, since there should always be
         // at least the default error reporter
@@ -2465,6 +2537,14 @@
         fParentXIncludeHandler = parent;
     }
 
+    protected void setHref(String href) {
+       fHrefFromParent = href;
+    }
+
+    protected void setXIncludeLocator(XMLLocatorWrapper locator) {
+        fXIncludeLocator = locator;
+    }
+
     // used to know whether to pass declarations to the document handler
     protected boolean isRootDocument() {
         return fParentXIncludeHandler == null;
@@ -2849,7 +2929,7 @@
     /**
      * Saves the given language on the top of the stack.
      *
-     * @param lanaguage the language to push onto the stack.
+     * @param language the language to push onto the stack.
      */
     protected void saveLanguage(String language) {
         fLanguageScope.push(fDepth);
@@ -3013,7 +3093,7 @@
     // the second hex character if a character needs to be escaped
     private static final char gAfterEscaping2[] = new char[128];
     private static final char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7',
-                                     '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+                                           '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
     // initialize the above 3 arrays
     static {
         char[] escChs = {' ', '<', '>', '"', '{', '}', '|', '\\', '^', '`'};
@@ -3104,7 +3184,7 @@
             // for each byte
             for (i = 0; i < len; i++) {
                 b = bytes[i];
-                // for non-ascii character: make it positive, then escape
+                // for non-ASCII character: make it positive, then escape
                 if (b < 0) {
                     ch = b + 256;
                     buffer.append('%');
@@ -3123,7 +3203,7 @@
         }
 
         // If escaping happened, create a new string;
-        // otherwise, return the orginal one.
+        // otherwise, return the original one.
         if (buffer.length() != len) {
             return buffer.toString();
         }
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/xinclude/XIncludeTextReader.java	Mon Feb 26 17:18:15 2018 -0800
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/xinclude/XIncludeTextReader.java	Tue Feb 27 12:47:58 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -23,6 +23,8 @@
 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
 import com.sun.org.apache.xerces.internal.impl.io.ASCIIReader;
+import com.sun.org.apache.xerces.internal.impl.io.Latin1Reader;
+import com.sun.org.apache.xerces.internal.impl.io.UTF16Reader;
 import com.sun.org.apache.xerces.internal.impl.io.UTF8Reader;
 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
 import com.sun.org.apache.xerces.internal.util.EncodingMap;
@@ -67,7 +69,7 @@
 public class XIncludeTextReader {
 
     private Reader fReader;
-    private XIncludeHandler fHandler;
+    private final XIncludeHandler fHandler;
     private XMLInputSource fSource;
     private XMLErrorReporter fErrorReporter;
     private XMLString fTempString = new XMLString();
@@ -149,12 +151,12 @@
                 stream = new BufferedInputStream(urlCon.getInputStream());
 
                 // content type will be string like "text/xml; charset=UTF-8" or "text/xml"
-                String rawContentType = urlCon.getContentType();
+                final String rawContentType = urlCon.getContentType();
 
                 // text/xml and application/xml offer only one optional parameter
-                int index = (rawContentType != null) ? rawContentType.indexOf(';') : -1;
+                final int index = (rawContentType != null) ? rawContentType.indexOf(';') : -1;
 
-                String contentType = null;
+                final String contentType;
                 String charset = null;
                 if (index != -1) {
                     // this should be something like "text/xml"
@@ -181,14 +183,16 @@
                     }
                 }
                 else {
-                    contentType = rawContentType.trim();
+                    contentType = (rawContentType != null) ? rawContentType.trim() : "";
                 }
 
                 String detectedEncoding = null;
                 /**  The encoding of such a resource is determined by:
                     1 external encoding information, if available, otherwise
                          -- the most common type of external information is the "charset" parameter of a MIME package
-                    2 if the media type of the resource is text/xml, application/xml, or matches the conventions text/*+xml or application/*+xml as described in XML Media Types [IETF RFC 3023], the encoding is recognized as specified in XML 1.0, otherwise
+                    2 if the media type of the resource is text/xml, application/xml, or matches the conventions
+                         text/*+xml or application/*+xml as described in XML Media Types [IETF RFC 3023], the encoding
+                         is recognized as specified in XML 1.0, otherwise
                     3 the value of the encoding attribute if one exists, otherwise
                     4 UTF-8.
                  **/
@@ -225,15 +229,17 @@
             // eat the Byte Order Mark
             encoding = consumeBOM(stream, encoding);
 
-            // If the document is UTF-8 or US-ASCII use
-            // the Xerces readers for these encodings. For
-            // US-ASCII consult the encoding map since
-            // this encoding has many aliases.
+            // If the document is UTF-8, UTF-16, US-ASCII or ISO-8859-1 use
+            // the Xerces readers for these encodings. For US-ASCII and ISO-8859-1
+            // consult the encoding map since these encodings have many aliases.
             if (encoding.equals("UTF-8")) {
-                return new UTF8Reader(stream,
-                    fTempString.ch.length,
-                    fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN),
-                    fErrorReporter.getLocale() );
+                return createUTF8Reader(stream);
+            }
+            else if (encoding.equals("UTF-16BE")) {
+                return createUTF16Reader(stream, true);
+            }
+            else if (encoding.equals("UTF-16LE")) {
+                return createUTF16Reader(stream, false);
             }
 
             // Try to use a Java reader.
@@ -251,16 +257,45 @@
                     new Object[] {encoding} ) );
             }
             else if (javaEncoding.equals("ASCII")) {
-                return new ASCIIReader(stream,
-                    fTempString.ch.length,
-                    fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN),
-                    fErrorReporter.getLocale() );
+                return createASCIIReader(stream);
             }
-
+            else if (javaEncoding.equals("ISO8859_1")) {
+                return createLatin1Reader(stream);
+            }
             return new InputStreamReader(stream, javaEncoding);
         }
     }
 
+    /** Create a new UTF-8 reader from the InputStream. **/
+    private Reader createUTF8Reader(InputStream stream) {
+        return new UTF8Reader(stream,
+                fTempString.ch.length,
+                fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN),
+                fErrorReporter.getLocale());
+    }
+
+    /** Create a new UTF-16 reader from the InputStream. **/
+    private Reader createUTF16Reader(InputStream stream, boolean isBigEndian) {
+        return new UTF16Reader(stream,
+                (fTempString.ch.length << 1),
+                isBigEndian,
+                fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN),
+                fErrorReporter.getLocale());
+    }
+
+    /** Create a new ASCII reader from the InputStream. **/
+    private Reader createASCIIReader(InputStream stream) {
+        return new ASCIIReader(stream,
+                fTempString.ch.length,
+                fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN),
+                fErrorReporter.getLocale());
+    }
+
+    /** Create a new ISO-8859-1 reader from the InputStream. **/
+    private Reader createLatin1Reader(InputStream stream) {
+        return new Latin1Reader(stream, fTempString.ch.length);
+    }
+
     /**
      * XMLEntityManager cares about endian-ness, since it creates its own optimized
      * readers. Since we're just using generic Java readers for now, we're not caring
@@ -416,6 +451,7 @@
         fReader = getReader(fSource);
         fSource = null;
         int readSize = fReader.read(fTempString.ch, 0, fTempString.ch.length - 1);
+        fHandler.fHasIncludeReportedContent = true;
         while (readSize != -1) {
             for (int i = 0; i < readSize; ++i) {
                 char ch = fTempString.ch[i];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jaxp/javax/xml/jaxp/unittest/common/EncodingErrorsReportingTest.java	Tue Feb 27 12:47:58 2018 +0000
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/* @test
+ * @bug 8038043
+ * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
+ * @run testng/othervm common.EncodingErrorsReportingTest
+ * @run testng/othervm -DrunSecMngr=true common.EncodingErrorsReportingTest
+ * @summary Verifies that parsers reports location of wrong UTF-8 symbols in
+ *          XML files parsed and included via xi:include element
+ */
+package common;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.function.Function;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+@Listeners({jaxp.library.BasePolicy.class})
+public class EncodingErrorsReportingTest implements EntityResolver {
+
+    /*
+     * Test reporting of wrong UTF8 byte sequence location by SAX and DOM parsers
+     */
+    @Test(dataProvider = "invalidUTF8BytesInXml")
+    public void testMalformedByteException(Function<byte[], Exception> parseF,
+                                           byte[] xmlData, int expLine, int expColumn) {
+        // Check if data was generated without errors
+        Assert.assertNotNull(xmlData, "Error in xml test data generation");
+
+        // Execute supplier to get parse exception
+        Exception caughtEx = parseF.apply(xmlData);
+
+        // Check if exception was thrown
+        Assert.assertNotNull(caughtEx, "No caught exception");
+        boolean isSPE = caughtEx instanceof SAXParseException;
+        Assert.assertTrue(isSPE, "Caught exception is not SAXParseException");
+        SAXParseException spe = (SAXParseException) caughtEx;
+
+        // Check if cause is properly set
+        Throwable cause = spe.getCause();
+        Assert.assertNotNull(cause, "Cause is null");
+        Assert.assertEquals("com.sun.org.apache.xerces.internal" +
+                            ".impl.io.MalformedByteSequenceException",
+                            cause.getClass().getName(),
+                            "Cause is not MalformedByteSequenceException");
+
+        // Check error locator parameters
+        int column_number = spe.getColumnNumber();
+        int line_number = spe.getLineNumber();
+        Assert.assertEquals(line_number, expLine, "Wrong line number reported");
+        Assert.assertEquals(column_number, expColumn, "Wrong column number reported");
+    }
+
+    // Provider with supplier functions that process XML content with different parsers
+    @DataProvider(name = "invalidUTF8BytesInXml")
+    public Object[][] parsersResultsSupplier() {
+        return new Object[][]{
+                // Tests for invalid UTF-8 byte in xml element
+                {(Function<byte[], Exception>) this::parseWithSAX,
+                        invalidByteInXmlElement(), 3, 15},
+                {(Function<byte[], Exception>) this::parseWithDOM,
+                        invalidByteInXmlElement(), 3, 15},
+                // Tests for invalid UTF-8 byte in xml attribute
+                {(Function<byte[], Exception>) this::parseWithSAX,
+                        invalidByteInXmlAttribute(), 4, 21},
+                {(Function<byte[], Exception>) this::parseWithDOM,
+                        invalidByteInXmlAttribute(), 4, 21},
+                // Tests for invalid UTF-8 byte in xml version string
+                {(Function<byte[], Exception>) this::parseWithSAX,
+                        invalidByteInXmlVersionDecl(), 1, 16},
+                {(Function<byte[], Exception>) this::parseWithDOM,
+                        invalidByteInXmlVersionDecl(), 1, 16},
+                // Tests for invalid byte in XML file included
+                // into parsed XML file with xi:include element
+                {(Function<byte[], Exception>) this::parseSaxAndXinclude,
+                        XINCLUDE_TEST_XML.getBytes(), 5, 53},
+                {(Function<byte[], Exception>) this::parseDomAndXinclude,
+                        XINCLUDE_TEST_XML.getBytes(), 5, 53},
+        };
+    }
+
+    // Parse constructed XML with SAXParser and save the observed exception
+    private Exception parseWithSAX(byte[] data) {
+        Exception caughtEx = null;
+        try {
+            SAXParserFactory factory = SAXParserFactory.newInstance();
+            SAXParser saxParser = factory.newSAXParser();
+            InputStream inputStream = new ByteArrayInputStream(data);
+            saxParser.parse(inputStream, new DefaultHandler());
+        } catch (Exception e) {
+            caughtEx = e;
+        }
+        return caughtEx;
+    }
+
+    // Parse constructed XML with DOMParser and save the observed exception
+    private Exception parseWithDOM(byte[] data) {
+        Exception caughtEx = null;
+        try {
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+            DocumentBuilder db = dbf.newDocumentBuilder();
+            InputStream inputStream = new ByteArrayInputStream(data);
+            db.parse(inputStream);
+        } catch (Exception e) {
+            caughtEx = e;
+        }
+        return caughtEx;
+    }
+
+    // Parse XML content that includes faulty XML content with xi:include element.
+    // XML data is parsed by SAX parser
+    private Exception parseSaxAndXinclude(byte[] data) {
+        Exception caughtEx = null;
+        try {
+            // Create SAX parser factory and make it xi:include aware
+            SAXParserFactory spf = SAXParserFactory.newDefaultInstance();
+            spf.setNamespaceAware(true);
+            spf.setXIncludeAware(true);
+            // Set this test class as entity resolver
+            XMLReader reader = spf.newSAXParser().getXMLReader();
+            reader.setEntityResolver(this);
+            // Parse XML
+            InputStream inputStream = new ByteArrayInputStream(data);
+            reader.parse(new InputSource(inputStream));
+        } catch (Exception e) {
+            caughtEx = e;
+        }
+        return caughtEx;
+    }
+
+    // Parse XML content that includes faulty XML content with xi:include element.
+    // XML data is parsed by DOM parser
+    private Exception parseDomAndXinclude(byte[] data) {
+        Exception caughtEx = null;
+        try {
+            // Create DOM builder factory and make it xi:include aware
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+            dbf.setNamespaceAware(true);
+            dbf.setXIncludeAware(true);
+            DocumentBuilder db = dbf.newDocumentBuilder();
+            // Set this test class as entity resolver
+            db.setEntityResolver(this);
+            InputStream inputStream = new ByteArrayInputStream(data);
+            // Parse XML
+            db.parse(inputStream);
+        } catch (Exception e) {
+            caughtEx = e;
+        }
+        return caughtEx;
+    }
+
+    // EntityResolver method to intercept load of test XML file content and
+    // redirect it to ByteArrayInputStream
+    @Override
+    public InputSource resolveEntity(String publicId, String systemId) throws IOException, SAXException {
+        if (systemId != null && systemId.endsWith(XINCLUDE_TEST_FN)) {
+            return new InputSource(
+                    new ByteArrayInputStream(
+                            generateXmlBytes("Wrong byte is ", "here", 0xFE)
+                    )
+            );
+        }
+        return null;
+    }
+
+    // Construct XML content with invalid byte in xml element
+    private static byte[] invalidByteInXmlElement() {
+        final String prefix = "<?xml version=\"1.0\"?>\n<test>\n<bad-encoding>";
+        final String postfix = "</bad-encoding></test>";
+        return generateXmlBytes(prefix, postfix, 0xFA);
+    }
+
+    // Construct XML content with invalid byte in xml version declaration
+    private static byte[] invalidByteInXmlVersionDecl() {
+        final String prefix = "<?xml version=\"";
+        final String postfix = "1.0\"?><test><bad-encoding></bad-encoding></test>";
+        return generateXmlBytes(prefix, postfix, 0xFB);
+    }
+
+    // Construct XML content with invalid byte in xml attribute
+    private static byte[] invalidByteInXmlAttribute() {
+        final String prefix = "<?xml version=\"1.0\"?>\n<test>\n\n<bad-att attribute=\"";
+        final String postfix = "\"></bad-att></test>";
+        return generateXmlBytes(prefix, postfix, 0xFC);
+    }
+
+    // Test helper function to generate XML text with invalid UTF-8 byte inside
+    private static byte[] generateXmlBytes(String prefix, String postfix, int b) {
+        try {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            baos.write(prefix.getBytes());
+            baos.write(b);
+            baos.write(postfix.getBytes());
+            return baos.toByteArray();
+        } catch (IOException e) {
+            return null;
+        }
+    }
+
+    // XML file name to be included with xi:include directive
+    private final static String XINCLUDE_TEST_FN = "xincludeTestFile.xml";
+
+    // xi:include test XML file that includes xml content with invalid byte
+    private final static String XINCLUDE_TEST_XML =
+            "<?xml version=\"1.0\"?>\n" +
+                    "<!DOCTYPE testXInclude [\n" +
+                    "<!ENTITY xincludeTestFile \""+XINCLUDE_TEST_FN+"\">]>\n" +
+                    "<testXInclude xmlns:xi=\"http://www.w3.org/2001/XInclude\">\n" +
+                    "<xi:include href=\"&xincludeTestFile;\" parse=\"text\"/>\n" +
+                    "</testXInclude>";
+}