gt:             String encoding = ex.getXmlEncoding();
context: /*
   * 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 org.apache.commons.io.input.compatibility;
  
  import java.io.BufferedInputStream;
  import java.io.BufferedReader;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.Reader;
  import java.io.StringReader;
  import java.net.HttpURLConnection;
  import java.net.URL;
  import java.net.URLConnection;
  import java.text.MessageFormat;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  
  import org.apache.commons.io.output.XmlStreamWriter;
  
  /**
   * Character stream that handles all the necessary Voodo to figure out the
   * charset encoding of the XML document within the stream.
   * <p>
   * IMPORTANT: This class is not related in any way to the org.xml.sax.XMLReader.
   * This one IS a character stream.
   * <p>
   * All this has to be done without consuming characters from the stream, if not
   * the XML parser will not recognized the document as a valid XML. This is not
   * 100% true, but it's close enough (UTF-8 BOM is not handled by all parsers
   * right now, XmlStreamReader handles it and things work in all parsers).
   * <p>
   * The XmlStreamReader class handles the charset encoding of XML documents in
   * Files, raw streams and HTTP streams by offering a wide set of constructors.
   * <p>
   * By default the charset encoding detection is lenient, the constructor with
   * the lenient flag can be used for an script (following HTTP MIME and XML
   * specifications). All this is nicely explained by Mark Pilgrim in his blog, <a
   * href="http://diveintomark.org/archives/2004/02/13/xml-media-types">
   * Determining the character encoding of a feed</a>.
   * <p>
   * Originally developed for <a href="http://rome.dev.java.net">ROME</a> under
   * Apache License 2.0.
   *
   * @version $Id: XmlStreamReader.java 1302748 2012-03-20 01:35:32Z ggregory $
   * @see XmlStreamWriter
   */
  public class XmlStreamReader extends Reader {
      private static final int BUFFER_SIZE = 4096;
  
      private static final String UTF_8 = "UTF-8";
  
      private static final String US_ASCII = "US-ASCII";
  
      private static final String UTF_16BE = "UTF-16BE";
  
      private static final String UTF_16LE = "UTF-16LE";
  
      private static final String UTF_16 = "UTF-16";
  
      private static final String EBCDIC = "CP1047";
  
      private static String staticDefaultEncoding = null;
  
      private Reader reader;
  
      private String encoding;
  
      private String defaultEncoding;
  
      /**
       * Sets the default encoding to use if none is set in HTTP content-type, XML
       * prolog and the rules based on content-type are not adequate.
       * <p>
       * If it is set to NULL the content-type based rules are used.
       * <p>
       * By default it is NULL.
       *
       * @param encoding charset encoding to default to.
       */
      public static void setDefaultEncoding(String encoding) {
          staticDefaultEncoding = encoding;
      }
  
      /**
       * Returns the default encoding to use if none is set in HTTP content-type,
       * XML prolog and the rules based on content-type are not adequate.
       * <p>
       * If it is NULL the content-type based rules are used.
       *
       * @return the default encoding to use.
       */
      public static String getDefaultEncoding() {
          return staticDefaultEncoding;
      }
  
      /**
       * Creates a Reader for a File.
       * <p>
       * It looks for the UTF-8 BOM first, if none sniffs the XML prolog charset,
       * if this is also missing defaults to UTF-8.
       * <p>
       * It does a lenient charset encoding detection, check the constructor with
       * the lenient parameter for details.
       *
       * @param file File to create a Reader from.
       * @throws IOException thrown if there is a problem reading the file.
       */
      public XmlStreamReader(File file) throws IOException {
          this(new FileInputStream(file));
      }
  
      /**
       * Creates a Reader for a raw InputStream.
       * <p>
       * It follows the same logic used for files.
       * <p>
       * It does a lenient charset encoding detection, check the constructor with
       * the lenient parameter for details.
       *
       * @param is InputStream to create a Reader from.
       * @throws IOException thrown if there is a problem reading the stream.
       */
      public XmlStreamReader(InputStream is) throws IOException {
          this(is, true);
      }
  
      /**
       * Creates a Reader for a raw InputStream.
       * <p>
       * It follows the same logic used for files.
       * <p>
       * If lenient detection is indicated and the detection above fails as per
       * specifications it then attempts the following:
       * <p>
       * If the content type was 'text/html' it replaces it with 'text/xml' and
       * tries the detection again.
       * <p>
       * Else if the XML prolog had a charset encoding that encoding is used.
       * <p>
       * Else if the content type had a charset encoding that encoding is used.
       * <p>
       * Else 'UTF-8' is used.
       * <p>
       * If lenient detection is indicated an XmlStreamReaderException is never
       * thrown.
       *
       * @param is InputStream to create a Reader from.
       * @param lenient indicates if the charset encoding detection should be
       *        relaxed.
       * @throws IOException thrown if there is a problem reading the stream.
       * @throws XmlStreamReaderException thrown if the charset encoding could not
       *         be determined according to the specs.
       */
      public XmlStreamReader(InputStream is, boolean lenient) throws IOException,
              XmlStreamReaderException {
          defaultEncoding = staticDefaultEncoding;
          try {
              doRawStream(is, lenient);
          } catch (XmlStreamReaderException ex) {
              if (!lenient) {
                  throw ex;
              } else {
                  doLenientDetection(null, ex);
              }
          }
      }
  
      /**
       * Creates a Reader using the InputStream of a URL.
       * <p>
       * If the URL is not of type HTTP and there is not 'content-type' header in
       * the fetched data it uses the same logic used for Files.
       * <p>
       * If the URL is a HTTP Url or there is a 'content-type' header in the
       * fetched data it uses the same logic used for an InputStream with
       * content-type.
       * <p>
       * It does a lenient charset encoding detection, check the constructor with
       * the lenient parameter for details.
       *
       * @param url URL to create a Reader from.
       * @throws IOException thrown if there is a problem reading the stream of
       *         the URL.
       */
      public XmlStreamReader(URL url) throws IOException {
          this(url.openConnection());
      }
  
      /**
       * Creates a Reader using the InputStream of a URLConnection.
       * <p>
       * If the URLConnection is not of type HttpURLConnection and there is not
       * 'content-type' header in the fetched data it uses the same logic used for
       * files.
       * <p>
       * If the URLConnection is a HTTP Url or there is a 'content-type' header in
       * the fetched data it uses the same logic used for an InputStream with
       * content-type.
       * <p>
       * It does a lenient charset encoding detection, check the constructor with
       * the lenient parameter for details.
       *
       * @param conn URLConnection to create a Reader from.
       * @throws IOException thrown if there is a problem reading the stream of
       *         the URLConnection.
       */
      public XmlStreamReader(URLConnection conn) throws IOException {
          defaultEncoding = staticDefaultEncoding;
          boolean lenient = true;
          if (conn instanceof HttpURLConnection) {
              try {
                  doHttpStream(conn.getInputStream(), conn.getContentType(),
                          lenient);
              } catch (XmlStreamReaderException ex) {
                  doLenientDetection(conn.getContentType(), ex);
              }
          } else if (conn.getContentType() != null) {
              try {
                  doHttpStream(conn.getInputStream(), conn.getContentType(),
                          lenient);
              } catch (XmlStreamReaderException ex) {
                  doLenientDetection(conn.getContentType(), ex);
              }
          } else {
              try {
                  doRawStream(conn.getInputStream(), lenient);
              } catch (XmlStreamReaderException ex) {
                  doLenientDetection(null, ex);
              }
          }
      }
  
      /**
       * Creates a Reader using an InputStream an the associated content-type
       * header.
       * <p>
       * First it checks if the stream has BOM. If there is not BOM checks the
       * content-type encoding. If there is not content-type encoding checks the
       * XML prolog encoding. If there is not XML prolog encoding uses the default
       * encoding mandated by the content-type MIME type.
       * <p>
       * It does a lenient charset encoding detection, check the constructor with
       * the lenient parameter for details.
       *
       * @param is InputStream to create the reader from.
       * @param httpContentType content-type header to use for the resolution of
       *        the charset encoding.
       * @throws IOException thrown if there is a problem reading the file.
       */
      public XmlStreamReader(InputStream is, String httpContentType)
              throws IOException {
          this(is, httpContentType, true);
      }
  
      /**
       * Creates a Reader using an InputStream an the associated content-type
       * header. This constructor is lenient regarding the encoding detection.
       * <p>
       * First it checks if the stream has BOM. If there is not BOM checks the
       * content-type encoding. If there is not content-type encoding checks the
       * XML prolog encoding. If there is not XML prolog encoding uses the default
       * encoding mandated by the content-type MIME type.
       * <p>
       * If lenient detection is indicated and the detection above fails as per
       * specifications it then attempts the following:
       * <p>
       * If the content type was 'text/html' it replaces it with 'text/xml' and
       * tries the detection again.
       * <p>
       * Else if the XML prolog had a charset encoding that encoding is used.
       * <p>
       * Else if the content type had a charset encoding that encoding is used.
       * <p>
       * Else 'UTF-8' is used.
       * <p>
       * If lenient detection is indicated an XmlStreamReaderException is never
       * thrown.
       *
       * @param is InputStream to create the reader from.
       * @param httpContentType content-type header to use for the resolution of
       *        the charset encoding.
       * @param lenient indicates if the charset encoding detection should be
       *        relaxed.
       * @throws IOException thrown if there is a problem reading the file.
       * @throws XmlStreamReaderException thrown if the charset encoding could not
       *         be determined according to the specs.
       */
      public XmlStreamReader(InputStream is, String httpContentType,
              boolean lenient, String defaultEncoding) throws IOException,
              XmlStreamReaderException {
          this.defaultEncoding = defaultEncoding == null ? staticDefaultEncoding
                  : defaultEncoding;
          try {
              doHttpStream(is, httpContentType, lenient);
          } catch (XmlStreamReaderException ex) {
              if (!lenient) {
                  throw ex;
              } else {
                  doLenientDetection(httpContentType, ex);
              }
          }
      }
  
      /**
       * Creates a Reader using an InputStream an the associated content-type
       * header. This constructor is lenient regarding the encoding detection.
       * <p>
       * First it checks if the stream has BOM. If there is not BOM checks the
       * content-type encoding. If there is not content-type encoding checks the
       * XML prolog encoding. If there is not XML prolog encoding uses the default
       * encoding mandated by the content-type MIME type.
       * <p>
       * If lenient detection is indicated and the detection above fails as per
       * specifications it then attempts the following:
       * <p>
       * If the content type was 'text/html' it replaces it with 'text/xml' and
       * tries the detection again.
       * <p>
       * Else if the XML prolog had a charset encoding that encoding is used.
       * <p>
       * Else if the content type had a charset encoding that encoding is used.
       * <p>
       * Else 'UTF-8' is used.
       * <p>
       * If lenient detection is indicated an XmlStreamReaderException is never
       * thrown.
       *
       * @param is InputStream to create the reader from.
       * @param httpContentType content-type header to use for the resolution of
       *        the charset encoding.
       * @param lenient indicates if the charset encoding detection should be
       *        relaxed.
       * @throws IOException thrown if there is a problem reading the file.
       * @throws XmlStreamReaderException thrown if the charset encoding could not
       *         be determined according to the specs.
       */
      public XmlStreamReader(InputStream is, String httpContentType,
              boolean lenient) throws IOException, XmlStreamReaderException {
          this(is, httpContentType, lenient, null);
      }
  
      private void doLenientDetection(String httpContentType,
              XmlStreamReaderException ex) throws IOException {
          if (httpContentType != null) {
              if (httpContentType.startsWith("text/html")) {
                  httpContentType = httpContentType.substring("text/html"
                          .length());
                  httpContentType = "text/xml" + httpContentType;
                  try {
                      doHttpStream(ex.getInputStream(), httpContentType, true);
                      ex = null;
                  } catch (XmlStreamReaderException ex2) {
                      ex = ex2;
                  }
              }
          }
          if (ex != null) {
  