/*
 *  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
 *
 *      https://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.ivy.plugins.parser.m2;

import org.apache.ivy.core.IvyPatternHelper;
import org.apache.ivy.core.module.descriptor.License;
import org.apache.ivy.core.module.id.ModuleId;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.plugins.repository.Resource;
import org.apache.ivy.util.XMLHelper;
import org.apache.ivy.util.url.URLHandlerRegistry;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * Provides the method to read some data out of the DOM tree of a pom file.
 */
public class PomReader {

    private static final String PROFILES_ELEMENT = "profiles";

    private static final String PACKAGING = "packaging";

    private static final String DEPENDENCY = "dependency";

    private static final String DEPENDENCIES = "dependencies";

    private static final String DEPENDENCY_MGT = "dependencyManagement";

    private static final String PROJECT = "project";

    private static final String MODEL = "model";

    private static final String GROUP_ID = "groupId";

    private static final String ARTIFACT_ID = "artifactId";

    private static final String VERSION = "version";

    private static final String DESCRIPTION = "description";

    private static final String HOMEPAGE = "url";

    private static final String LICENSES = "licenses";

    private static final String LICENSE = "license";

    private static final String LICENSE_NAME = "name";

    private static final String LICENSE_URL = "url";

    private static final String PARENT = "parent";

    private static final String SCOPE = "scope";

    private static final String CLASSIFIER = "classifier";

    private static final String OPTIONAL = "optional";

    private static final String EXCLUSIONS = "exclusions";

    private static final String EXCLUSION = "exclusion";

    private static final String DISTRIBUTION_MGT = "distributionManagement";

    private static final String RELOCATION = "relocation";

    private static final String PROPERTIES = "properties";

    private static final String PLUGINS = "plugins";

    private static final String PLUGIN = "plugin";

    private static final String TYPE = "type";

    private static final String PROFILE = "profile";

    private final Map<String, String> properties = new HashMap<>();

    private final Element projectElement;

    private final Element parentElement;

    @SuppressWarnings("deprecation")
    public PomReader(final URL descriptorURL, final Resource res) throws IOException, SAXException {
        InputStream stream = new AddDTDFilterInputStream(
                URLHandlerRegistry.getDefault().openStream(descriptorURL));
        InputSource source = new InputSource(stream);
        source.setSystemId(XMLHelper.toSystemId(descriptorURL));
        try {
            Document pomDomDoc = XMLHelper.parseToDom(source, new EntityResolver() {
                public InputSource resolveEntity(String publicId, String systemId)
                        throws SAXException, IOException {
                    if (systemId != null && systemId.endsWith("m2-entities.ent")) {
                        // IVY-921: return an InputSource for our local packaged m2-entities.ent file
                        return new InputSource(
                                PomReader.class.getResourceAsStream("m2-entities.ent"));
                    }
                    return null;
                }
            }, true, XMLHelper.ExternalResources.IGNORE);
            projectElement = pomDomDoc.getDocumentElement();
            if (!PROJECT.equals(projectElement.getNodeName())
                    && !MODEL.equals(projectElement.getNodeName())) {
                throw new SAXParseException("project must be the root tag", res.getName(),
                        res.getName(), 0, 0);
            }
            parentElement = getFirstChildElement(projectElement, PARENT);
        } finally {
            try {
                stream.close();
            } catch (IOException e) {
                // ignore
            }
        }
        // Both environment and system properties take precedence over properties set in
        // pom.xml. So we pre-populate our properties with the environment and system properties
        // here
        for (final Map.Entry<String, String> envEntry : System.getenv().entrySet()) {
            // Maven let's users use "env." prefix for environment variables
            this.setProperty("env." + envEntry.getKey(), envEntry.getValue());
        }
        // add system properties
        final Properties sysProps = System.getProperties();
        for (final String sysProp : sysProps.stringPropertyNames()) {
            this.setProperty(sysProp, sysProps.getProperty(sysProp));
        }
    }

    public boolean hasParent() {
        return parentElement != null;
    }

    /**
     * Add a property if not yet set and value is not null. This guarantees
     * that property keeps the first value that is put on it and that the
     * properties are never null.
     *
     * @param prop String
     * @param val  String
     */
    public void setProperty(String prop, String val) {
        if (!properties.containsKey(prop) && val != null) {
            properties.put(prop, val);
        }
    }

    public String getGroupId() {
        String groupId = getFirstChildText(projectElement, GROUP_ID);
        if (groupId == null) {
            groupId = getFirstChildText(parentElement, GROUP_ID);
        }
        return replaceProps(groupId);

    }

    public String getParentGroupId() {
        String groupId = getFirstChildText(parentElement, GROUP_ID);
        if (groupId == null) {
            groupId = getFirstChildText(projectElement, GROUP_ID);
        }
        return replaceProps(groupId);
    }

    public String getArtifactId() {
        String val = getFirstChildText(projectElement, ARTIFACT_ID);
        if (val == null) {
            val = getFirstChildText(parentElement, ARTIFACT_ID);
        }
        return replaceProps(val);
    }

    public String getParentArtifactId() {
        String val = getFirstChildText(parentElement, ARTIFACT_ID);
        if (val == null) {
            val = getFirstChildText(projectElement, ARTIFACT_ID);
        }
        return replaceProps(val);
    }

    public String getVersion() {
        String val = getFirstChildText(projectElement, VERSION);
        if (val == null) {
            val = getFirstChildText(parentElement, VERSION);
        }
        return replaceProps(val);
    }

    public String getParentVersion() {
        String val = getFirstChildText(parentElement, VERSION);
        if (val == null) {
            val = getFirstChildText(projectElement, VERSION);
        }
        return replaceProps(val);
    }

    public String getPackaging() {
        final String val = getFirstChildText(projectElement, PACKAGING);
        if (val == null) {
            return "jar";
        }
        return replaceProps(val);
    }

    public String getHomePage() {
        String val = getFirstChildText(projectElement, HOMEPAGE);
        if (val == null) {
            val = "";
        }
        return val;
    }

    public String getDescription() {
        String val = getFirstChildText(projectElement, DESCRIPTION);
        if (val == null) {
            val = "";
        }
        return val.trim();
    }

    public License[] getLicenses() {
        Element licenses = getFirstChildElement(projectElement, LICENSES);
        if (licenses == null) {
            return new License[0];
        }
        licenses.normalize();
        List<License> lics = new ArrayList<>();
        for (Element license : getAllChilds(licenses)) {
            if (LICENSE.equals(license.getNodeName())) {
                String name = getFirstChildText(license, LICENSE_NAME);
                String url = getFirstChildText(license, LICENSE_URL);

                if (name == null && url == null) {
                    // move to next license
                    continue;
                }

                if (name == null) {
                    // The license name is required in Ivy but not in a POM!
                    name = "Unknown License";
                }

                lics.add(new License(name, url));
            }
        }
        return lics.toArray(new License[lics.size()]);
    }

    public ModuleRevisionId getRelocation() {
        Element distrMgt = getFirstChildElement(projectElement, DISTRIBUTION_MGT);
        Element relocation = getFirstChildElement(distrMgt, RELOCATION);
        if (relocation == null) {
            return null;
        } else {
            String relocGroupId = getFirstChildText(relocation, GROUP_ID);
            if (relocGroupId == null) {
                relocGroupId = getGroupId();
            }
            String relocArtId = getFirstChildText(relocation, ARTIFACT_ID);
            if (relocArtId == null) {
                relocArtId = getArtifactId();
            }
            String relocVersion = getFirstChildText(relocation, VERSION);
            if (relocVersion == null) {
                relocVersion = getVersion();
            }
            return ModuleRevisionId.newInstance(relocGroupId, relocArtId, relocVersion);
        }
    }

    public List<PomDependencyData> getDependencies() {
        return getDependencies(projectElement);
    }

    private List<PomDependencyData> getDependencies(Element parent) {
        Element dependenciesElement = getFirstChildElement(parent, DEPENDENCIES);
        if (dependenciesElement == null) {
            return Collections.emptyList();
        }
        List<PomDependencyData> dependencies = new LinkedList<>();
        NodeList children = dependenciesElement.getChildNodes();
        for (int i = 0, sz = children.getLength(); i < sz; i++) {
            Node node = children.item(i);
            if (node instanceof Element && DEPENDENCY.equals(node.getNodeName())) {
                dependencies.add(new PomDependencyData((Element) node));
            }
        }
        return dependencies;
    }

    public List<PomDependencyMgt> getDependencyMgt() {
        return getDependencyMgt(projectElement);
    }

    private List<PomDependencyMgt> getDependencyMgt(Element parent) {
        Element dependenciesElement = getFirstChildElement(
                getFirstChildElement(parent, DEPENDENCY_MGT), DEPENDENCIES);
        if (dependenciesElement == null) {
            return Collections.emptyList();
        }
        List<PomDependencyMgt> dependencies = new LinkedList<>();
        NodeList children = dependenciesElement.getChildNodes();
        for (int i = 0, sz = children.getLength(); i < sz; i++) {
            Node node = children.item(i);
            if (node instanceof Element && DEPENDENCY.equals(node.getNodeName())) {
                dependencies.add(new PomDependencyMgtElement((Element) node));
            }
        }
        return dependencies;
    }

    public List<PomProfileElement> getProfiles() {
        Element profilesElement = getFirstChildElement(projectElement, PROFILES_ELEMENT);
        if (profilesElement == null) {
            return Collections.emptyList();
        }
        List<PomProfileElement> result = new LinkedList<>();
        NodeList children = profilesElement.getChildNodes();
        for (int i = 0, sz = children.getLength(); i < sz; i++) {
            Node node = children.item(i);
            if (node instanceof Element && PROFILE.equals(node.getNodeName())) {
                result.add(new PomProfileElement((Element) node));
            }
        }
        return result;
    }

    public class PomDependencyMgtElement implements PomDependencyMgt {
        private final Element depElement;

        public PomDependencyMgtElement(PomDependencyMgtElement copyFrom) {
            this(copyFrom.depElement);
        }

        PomDependencyMgtElement(Element depElement) {
            this.depElement = depElement;
        }

        /*
         * (non-Javadoc)
         *
         * @see org.apache.ivy.plugins.parser.m2.PomDependencyMgt#getGroupId()
         */
        public String getGroupId() {
            String val = getFirstChildText(depElement, GROUP_ID);
            return replaceProps(val);
        }

        /*
         * (non-Javadoc)
         *
         * @see org.apache.ivy.plugins.parser.m2.PomDependencyMgt#getArtifaceId()
         */
        public String getArtifactId() {
            String val = getFirstChildText(depElement, ARTIFACT_ID);
            return replaceProps(val);
        }

        /*
         * (non-Javadoc)
         *
         * @see org.apache.ivy.plugins.parser.m2.PomDependencyMgt#getVersion()
         */
        public String getVersion() {
            String val = getFirstChildText(depElement, VERSION);
            return replaceProps(val);
        }

        public String getScope() {
            String val = getFirstChildText(depElement, SCOPE);
            return replaceProps(val);
        }

        public List<ModuleId> getExcludedModules() {
            Element exclusionsElement = getFirstChildElement(depElement, EXCLUSIONS);
            if (exclusionsElement == null) {
                return Collections.emptyList();
            }
            List<ModuleId> exclusions = new LinkedList<>();
            NodeList children = exclusionsElement.getChildNodes();
            for (int i = 0, sz = children.getLength(); i < sz; i++) {
                Node node = children.item(i);
                if (node instanceof Element && EXCLUSION.equals(node.getNodeName())) {
                    String groupId = getFirstChildText((Element) node, GROUP_ID);
                    String artifactId = getFirstChildText((Element) node, ARTIFACT_ID);
                    if (groupId != null && artifactId != null) {
                        exclusions.add(ModuleId.newInstance(groupId, artifactId));
                    }
                }
            }
            return exclusions;
        }
    }

    public List<PomPluginElement> getPlugins() {
        return getPlugins(projectElement);
    }

    private List<PomPluginElement> getPlugins(Element parent) {
        Element buildElement = getFirstChildElement(parent, "build");
        Element pluginsElement = getFirstChildElement(buildElement, PLUGINS);

        if (pluginsElement == null) {
            return Collections.emptyList();
        }
        NodeList children = pluginsElement.getChildNodes();
        List<PomPluginElement> plugins = new LinkedList<>();
        for (int i = 0; i < children.getLength(); i++) {
            Node node = children.item(i);
            if (node instanceof Element && PLUGIN.equals(node.getNodeName())) {
                plugins.add(new PomPluginElement((Element) node));
            }
        }
        return plugins;
    }

    private static Map<String, String> getProperties(final Element parent) {
        final Element propsEl = getFirstChildElement(parent, PROPERTIES);
        if (propsEl == null) {
            return Collections.emptyMap();
        }
        propsEl.normalize();
        final Map<String, String> props = new HashMap<>();
        for (final Element prop : getAllChilds(propsEl)) {
            props.put(prop.getNodeName(), getTextContent(prop));
        }
        return props;
    }

    public class PomPluginElement implements PomDependencyMgt {
        private Element pluginElement;

        PomPluginElement(Element pluginElement) {
            this.pluginElement = pluginElement;
        }

        public String getGroupId() {
            String val = getFirstChildText(pluginElement, GROUP_ID);
            return replaceProps(val);
        }

        public String getArtifactId() {
            String val = getFirstChildText(pluginElement, ARTIFACT_ID);
            return replaceProps(val);
        }

        public String getVersion() {
            String val = getFirstChildText(pluginElement, VERSION);
            return replaceProps(val);
        }

        public String getScope() {
            return null; // not used
        }

        public List<ModuleId> getExcludedModules() {
            return Collections.emptyList(); // probably not used?
        }
    }

    public class PomDependencyData extends PomDependencyMgtElement {
        private final Element depElement;

        public PomDependencyData(PomDependencyData copyFrom) {
            this(copyFrom.depElement);
        }

        PomDependencyData(Element depElement) {
            super(depElement);
            this.depElement = depElement;
        }

        @Override
        public String getScope() {
            String val = getFirstChildText(depElement, SCOPE);
            return emptyIsNull(replaceProps(val));
        }

        public String getClassifier() {
            String val = getFirstChildText(depElement, CLASSIFIER);
            return emptyIsNull(replaceProps(val));
        }

        public String getType() {
            String val = getFirstChildText(depElement, TYPE);
            return emptyIsNull(replaceProps(val));
        }

        public boolean isOptional() {
            return Boolean.parseBoolean(getFirstChildText(depElement, OPTIONAL));
        }

        /**
         * We return null where certain elements within a pom don't have a value specified.
         * For example, there are pom.xml out there which just use "<classifier/>" in the dependencies.
         * (dependencies in org.seleniumhq.selenium:selenium-java:3.141.59 are one such example)
         * We do this so that callers of such elements don't have to keep repeating checks for empty value.
         * For us an empty value, for many of such elements, is really the same as that element not being specified
         *
         * @param val The value to check
         * @return
         */
        private String emptyIsNull(final String val) {
            if (val == null) {
                return null;
            }
            return val.equals("") ? null : val;
        }
    }

    public class PomProfileElement {

        private static final String VALUE = "value";

        private static final String NAME = "name";

        private static final String PROPERTY = "property";

        private static final String ID_ELEMENT = "id";

        private static final String ACTIVATION_ELEMENT = "activation";

        private static final String ACTIVE_BY_DEFAULT_ELEMENT = "activeByDefault";

        private static final String OS = "os";

        private static final String FAMILY = "family";

        private static final String VERSION = "version";

        private static final String ARCH = "arch";

        private static final String FILE = "file";

        private static final String MISSING = "missing";

        private static final String EXISTS = "exists";

        private static final String JDK = "jdk";

        private final Element profileElement;

        PomProfileElement(Element profileElement) {
            this.profileElement = profileElement;
        }

        public String getId() {
            return getFirstChildText(profileElement, ID_ELEMENT);
        }

        public boolean isActive() {
            return isActiveByDefault() || isActivatedByProperty()
                    || isActiveByOS() || isActiveByJDK() || isActiveByFile();
        }

        public boolean isActiveByDefault() {
            Element activation = getFirstChildElement(profileElement, ACTIVATION_ELEMENT);
            return Boolean.parseBoolean(getFirstChildText(activation, ACTIVE_BY_DEFAULT_ELEMENT));
        }

        public boolean isActiveByOS() {
            final Element activation = getFirstChildElement(profileElement, ACTIVATION_ELEMENT);
            if (activation == null) {
                return false;
            }
            final Element osActivation = getFirstChildElement(activation, OS);
            if (osActivation == null) {
                return false;
            }
            final String actualOS = System.getProperty("os.name");
            final String expectedOSName = getFirstChildText(osActivation, NAME);
            if (expectedOSName != null && !actualOS.equals(expectedOSName.trim())) {
                // os name is specified but doesn't match
                return false;
            }
            final String expectedOSFamily = getFirstChildText(osActivation, FAMILY);
            if (expectedOSFamily != null && !actualOS.contains(expectedOSFamily.trim())) {
                // os family is specified but doesn't match
                return false;
            }
            final String expectedOSArch = getFirstChildText(osActivation, ARCH);
            if (expectedOSArch != null && !System.getProperty("os.arch").equals(expectedOSArch.trim())) {
                // os arch is specified but doesn't match
                return false;
            }
            final String expectedOSVersion = getFirstChildText(osActivation, VERSION);
            if (expectedOSVersion != null && !System.getProperty("os.version").equals(expectedOSVersion.trim())) {
                // os version is specified but doesn't match
                return false;
            }
            // reaching here implies that either no OS match rules were specified or
            // all of the OS rules that were specified were matched. So we just check to see
            // if any rules were specified at all, in which case, we consider the profile to be activated
            // by the OS element
            return (expectedOSName != null || expectedOSFamily != null || expectedOSArch != null || expectedOSVersion != null);
        }

        public boolean isActiveByJDK() {
            final Element activation = getFirstChildElement(profileElement, ACTIVATION_ELEMENT);
            if (activation == null) {
                return false;
            }
            final String expectedJDKRange = getFirstChildText(activation, JDK);
            if (expectedJDKRange == null) {
                return false;
            }
            final boolean negate = expectedJDKRange.trim().startsWith("!");
            final String nonNegatedRange = negate ? expectedJDKRange.substring(1).trim() : expectedJDKRange.trim();
            final boolean javaVersionInRange = MavenVersionRangeParser.currentJavaVersionInRange(nonNegatedRange);
            return javaVersionInRange ^ negate;
        }

        public boolean isActiveByFile() {
            final Element activation = getFirstChildElement(profileElement, ACTIVATION_ELEMENT);
            if (activation == null) {
                return false;
            }
            final Element fileActivation = getFirstChildElement(activation, FILE);
            if (fileActivation == null) {
                return false;
            }
            final String expectedMissing = getFirstChildText(fileActivation, MISSING);
            if (expectedMissing != null && new File(expectedMissing.trim()).exists()) {
                // the file was specified and expected to be missing, but it exists
                return false;
            }
            final String expectedExists = getFirstChildText(fileActivation, EXISTS);
            if (expectedExists != null && !(new File(expectedExists.trim()).exists())) {
                // the file was specified and expected to be existing, but it doesn't
                return false;
            }
            // reaching here implies that either no file match rules were specified or
            // all of the file rules that were specified were matched. So we just check to see
            // if any rules were specified at all, in which case, we consider the profile to be activated
            // by the file element
            return (expectedMissing != null || expectedExists != null);
        }

        public boolean isActivatedByProperty() {
            Element activation = getFirstChildElement(profileElement, ACTIVATION_ELEMENT);
            Element propertyActivation = getFirstChildElement(activation, PROPERTY);
            String propertyName = getFirstChildText(propertyActivation, NAME);
            if (propertyName == null || "".equals(propertyName)) {
                return false;
            }
            boolean negate = propertyName.charAt(0) == '!';
            if (negate) {
                propertyName = propertyName.substring(1);
            }
            if ("".equals(propertyName)) {
                return false;
            }
            String propertyValue = getFirstChildText(propertyActivation, VALUE);

            final boolean matched;
            if (propertyValue == null || "".equals(propertyValue)) {
                matched = PomReader.this.properties.containsKey(propertyName);
            } else {
                matched = propertyValue.equals(PomReader.this.properties.get(propertyName));
            }
            return matched ^ negate;
        }

        public List<PomDependencyData> getDependencies() {
            return PomReader.this.getDependencies(profileElement);
        }

        public List<PomDependencyMgt> getDependencyMgt() {
            return PomReader.this.getDependencyMgt(profileElement);
        }

        public List<PomPluginElement> getPlugins() {
            return PomReader.this.getPlugins(profileElement);
        }

        public Map<String, String> getProfileProperties() {
            return PomReader.getProperties(profileElement);
        }
    }

    /**
     * @return the content of the properties tag into the pom.
     */
    public Map<String, String> getPomProperties() {
        return new HashMap<>(getProperties(projectElement));
    }

    private String replaceProps(String val) {
        if (val == null) {
            return null;
        } else {
            return IvyPatternHelper.substituteVariables(val, properties).trim();
        }
    }

    private static String getTextContent(Element element) {
        StringBuilder result = new StringBuilder();

        NodeList childNodes = element.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node child = childNodes.item(i);

            switch (child.getNodeType()) {
                case Node.CDATA_SECTION_NODE:
                case Node.TEXT_NODE:
                    result.append(child.getNodeValue());
                    break;
                default:
                    break;
            }
        }

        return result.toString();
    }

    private static String getFirstChildText(Element parentElem, String name) {
        Element node = getFirstChildElement(parentElem, name);
        if (node != null) {
            return getTextContent(node);
        } else {
            return null;
        }
    }

    private static Element getFirstChildElement(Element parentElem, String name) {
        if (parentElem == null) {
            return null;
        }
        NodeList childs = parentElem.getChildNodes();
        for (int i = 0; i < childs.getLength(); i++) {
            Node node = childs.item(i);
            if (node instanceof Element && name.equals(node.getNodeName())) {
                return (Element) node;
            }
        }
        return null;
    }

    private static List<Element> getAllChilds(Element parent) {
        List<Element> r = new LinkedList<>();
        if (parent != null) {
            NodeList childs = parent.getChildNodes();
            for (int i = 0; i < childs.getLength(); i++) {
                Node node = childs.item(i);
                if (node instanceof Element) {
                    r.add((Element) node);
                }
            }
        }
        return r;
    }

    private static final class AddDTDFilterInputStream extends FilterInputStream {
        private static final int MARK = 10000;

        private static final String DOCTYPE = "<!DOCTYPE project SYSTEM \"m2-entities.ent\">\n";

        private int count;

        private byte[] prefix = DOCTYPE.getBytes();

        private AddDTDFilterInputStream(InputStream in) throws IOException {
            super(new BufferedInputStream(in));

            this.in.mark(MARK);

            // TODO: we should really find a better solution for this...
            // maybe we could use a FilterReader instead of a FilterInputStream?
            int byte1 = this.in.read();
            int byte2 = this.in.read();
            int byte3 = this.in.read();

            if (byte1 == 239 && byte2 == 187 && byte3 == 191) {
                // skip the UTF-8 BOM
                this.in.mark(MARK);
            } else {
                this.in.reset();
            }

            int bytesToSkip = 0;
            LineNumberReader reader = new LineNumberReader(new InputStreamReader(this.in, StandardCharsets.UTF_8),
                    100);
            String firstLine = reader.readLine();
            if (firstLine != null) {
                String trimmed = firstLine.trim();
                if (trimmed.startsWith("<?xml ")) {
                    int endIndex = trimmed.indexOf("?>");
                    String xmlDecl = trimmed.substring(0, endIndex + 2);
                    prefix = (xmlDecl + "\n" + DOCTYPE).getBytes();
                    bytesToSkip = xmlDecl.getBytes().length;
                }
            } else {
                prefix = new byte[0];
            }

            this.in.reset();
            for (int i = 0; i < bytesToSkip; i++) {
                this.in.read();
            }
        }

        @Override
        public int read() throws IOException {
            if (count < prefix.length) {
                return prefix[count++];
            }

            return super.read();
        }

        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            if (b == null) {
                throw new NullPointerException();
            } else if (off < 0 || off > b.length || len < 0 || (off + len) > b.length
                    || (off + len) < 0) {
                throw new IndexOutOfBoundsException();
            } else if (len == 0) {
                return 0;
            }

            int nbrBytesCopied = 0;

            if (count < prefix.length) {
                int nbrBytesFromPrefix = Math.min(prefix.length - count, len);
                System.arraycopy(prefix, count, b, off, nbrBytesFromPrefix);
                nbrBytesCopied = nbrBytesFromPrefix;
            }

            if (nbrBytesCopied < len) {
                nbrBytesCopied += in.read(b, off + nbrBytesCopied, len - nbrBytesCopied);
            }

            count += nbrBytesCopied;
            return nbrBytesCopied;
        }
    }

}
