elharo commented on code in PR #1205:
URL: https://github.com/apache/maven/pull/1205#discussion_r1446059983


##########
maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java:
##########
@@ -100,14 +104,39 @@ private Path getRootDirectory(Map<String, ?> options) {
         return (Path) value;
     }
 
+    private boolean getXInclude(Map<String, ?> options) {
+        Object value = (options != null) ? options.get(XINCLUDE) : null;
+        return value instanceof Boolean && (Boolean) value;
+    }
+
     private Model read(InputStream input, Path pomFile, Map<String, ?> 
options) throws IOException {
         try {
-            XMLInputFactory factory = new com.ctc.wstx.stax.WstxInputFactory();
-            
factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
-            XMLStreamReader parser = factory.createXMLStreamReader(input);
-
             InputSource source = getSource(options);
             boolean strict = isStrict(options);
+            Path rootDirectory = getRootDirectory(options);
+
+            Source xmlSource;
+            if (pomFile != null) {
+                if (input != null) {
+                    xmlSource = new StaxPathInputSource(pomFile, input);
+                } else {
+                    xmlSource = new Stax2FileSource(pomFile.toFile());
+                }
+            } else {
+                xmlSource = new StreamSource(input);
+            }
+
+            XMLStreamReader parser;
+            // We only support xml entities and xinclude when reading a file 
in strict mode
+            if (pomFile != null && strict && getXInclude(options)) {
+                parser = XInclude.xinclude(xmlSource, new 
LocalXmlResolver(rootDirectory));
+            } else {
+                XMLInputFactory factory = new 
com.ctc.wstx.stax.WstxInputFactory();
+                
factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
+                
factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);

Review Comment:
   Nothing you can do here, but this property should have been named 
SUPPORTS_EXTERNAL_ENTITIES



##########
maven-stax-xinclude/src/main/java/org/apache/maven/stax/xinclude/DOMXMLElementEvaluator.java:
##########
@@ -0,0 +1,98 @@
+/*
+ * 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.maven.stax.xinclude;
+
+import java.util.Map;
+import java.util.Objects;
+
+import com.ctc.wstx.dtd.DTDAttribute;
+import com.ctc.wstx.dtd.DTDElement;
+import com.ctc.wstx.dtd.DTDSubset;
+import com.ctc.wstx.util.PrefixedName;
+import org.w3c.dom.Element;
+
+/**
+ * This class extends the XMLElementEvaluator to support the DOM 
implementation in XMLElement.
+ * <p>
+ * This class is based upon a class of the same name in Apache Woden.
+ */
+class DOMXMLElementEvaluator extends XMLElementEvaluator<Element> {
+
+    private DTDSubset dtd;
+
+    /**
+     * Constructs a new DOMXMLElementEvaluator to evaluate a XPointer on a DOM 
Element.
+     *
+     * @param xpointer an XPointer to evaluate
+     * @param element an DOM Element to be evaluated
+     */
+    DOMXMLElementEvaluator(XPointer xpointer, Element element, DTDSubset dtd) {
+        super(xpointer, createXMLElement(element));
+        this.dtd = dtd;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see 
org.apache.woden.internal.xpointer.XMLElementEvaluator#testElementShorthand(org.apache.woden.XMLElement,
 java.lang.String)
+     */
+    public boolean testElementShorthand(XMLElement<Element> element, String 
shorthand) {
+        // Simple http://www.w3.org/TR/xml-id/ support for now until we 
support full scheme based ID's.
+        Element domElement = element.getSource();
+        String attr = 
domElement.getAttributeNS("http://www.w3.org/XML/1998/namespace";, "id");
+        if (Objects.equals(attr, shorthand)) {
+            return true;
+        }
+        if (dtd != null) {
+            Map<PrefixedName, DTDElement> map = dtd.getElementMap();
+            if (map != null) {
+                DTDElement dtdElement = map.get(new 
PrefixedName(domElement.getPrefix(), domElement.getLocalName()));
+                if (dtdElement != null) {
+                    DTDAttribute dtdAttribute = dtdElement.getIdAttribute();
+                    if (dtdAttribute != null) {
+                        attr = 
domElement.getAttribute(dtdAttribute.getName().getLocalName());
+                        if (Objects.equals(attr, shorthand)) {
+                            return true;
+                        }
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Evaluates the XPointer on the root Element and returns the resulting 
Element or null.
+     *
+     * @return an Element from the resultant evaluation of the root Element or 
null if evaluation fails

Review Comment:
   delete resultant



##########
maven-stax-xinclude/src/main/java/org/apache/maven/stax/xinclude/InvalidXPointerException.java:
##########
@@ -0,0 +1,143 @@
+/*
+ * 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.maven.stax.xinclude;
+
+/**
+ * This class represents Exceptions that can happen during parsing an XPointer 
Expression.

Review Comment:
   during --> while



##########
maven-stax-xinclude/src/main/java/org/apache/maven/stax/xinclude/ElementPointerPart.java:
##########
@@ -0,0 +1,245 @@
+/*
+ * 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.maven.stax.xinclude;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * ElementPointerPart is a class which represents the element() scheme for the 
XPointer Framework.
+ * The specification is defined at <a 
href="http://www.w3.org/TR/xptr-element/";>http://www.w3.org/TR/xptr-element/</a>
+ * <p>
+ * This class is immutable.
+ * <p>
+ * This class is based upon a class of the same name in Apache Woden.
+ */
+class ElementPointerPart implements PointerPart {
+    private final String ncname;
+    private final List<Integer> childSequence;
+
+    /**
+     * Constructs an ElementPointerPart with only an elementID NCName.
+     *
+     * @param elementID an NCName of the elementID to reference.
+     * @throws NullPointerException is a null elementID is given.
+     */
+    ElementPointerPart(String elementID) {
+        if (elementID == null) {
+            throw new NullPointerException("The elementID argument is null.");
+        }
+        this.ncname = elementID;
+        this.childSequence = null;
+    }
+
+    /**
+     * Constructs an ElementPointerPart with only a childSequence.
+     *
+     * @param childSequence a List of Integers representing the child sequence.
+     * @throws NullPointerException     if childSequence is null.
+     * @throws IllegalArgumentException if childSequence is empty or contains 
elements other than Integers.
+     */
+    ElementPointerPart(List<Integer> childSequence) {
+        if (childSequence == null) {
+            throw new NullPointerException("The childSequence argument is 
null.");
+        }
+        if (childSequence.isEmpty()) {
+            throw new IllegalArgumentException("The childSequence list is 
empty.");
+        }
+        this.ncname = null;
+        this.childSequence = childSequence;
+    }
+
+    /**
+     * Constructs an ElementPointerPart with both an NCName and a 
childSequence.
+     *
+     * @param elementID     an NCName of the elementID to reference.
+     * @param childSequence a List of Integers representing the child sequence.
+     * @throws NullPointerException     if elementID or childSequence are null.
+     * @throws IllegalArgumentException if childSequence is empty or contains 
elements other than Integers.
+     */
+    ElementPointerPart(String elementID, List<Integer> childSequence) {
+        if (elementID == null) {
+            throw new NullPointerException("The elementID argument is null.");
+        }
+        if (childSequence == null) {
+            throw new NullPointerException("The childSequence argument is 
null.");
+        }
+        if (childSequence.isEmpty()) {
+            throw new IllegalArgumentException("The childSequence list is 
empty.");
+        }
+        if (childSequence.contains(0)) {
+            throw new IllegalArgumentException("the childSequence list must 
only contain Integers bigger than 0.");
+        }
+
+        this.ncname = elementID;
+        this.childSequence = childSequence;
+    }
+
+    /**
+     * Returns the NCName for this Element PointerPart.
+     *
+     * @return an NCName if it exists in this Element PointerPart, otherwise 
null.
+     */
+    public String getNCName() {
+        return ncname;
+    }
+
+    /**
+     * Returns the child sequence of this Element PointerPart.
+     *
+     * @return an Integer[] of the child sequence for this element pointer 
part, or an empty array if none exists.
+     */
+    public List<Integer> getChildSequence() {
+        return Collections.unmodifiableList(childSequence);
+    }
+
+    /**
+     * Checks if this Element PointerPart has a NCName or not.
+     *
+     * @return a boolean, true if it has a NCName or false if not.
+     */
+    public boolean hasNCName() {
+        return ncname != null;
+    }
+
+    /**
+     * Checks if this Element PointerPart has a childSequence or not.
+     *
+     * @return a boolean, true if this has a childSequence or false if not.
+     */
+    public boolean hasChildSequence() {
+        return childSequence != null;
+    }
+
+    /*
+     *(non-Javadoc)
+     * @see org.apache.woden.xpointer.PointerPart#toString()
+     */
+    public String toString() {
+        String schemeData;
+        if (childSequence == null) {
+            schemeData = ncname.toString();
+        } else if (ncname == null) {
+            schemeData = serialiseChildSequence();
+        } else {
+            schemeData = ncname.toString() + serialiseChildSequence();
+        }
+        return "element(" + schemeData + ")";
+    }
+
+    /**
+     * Serialises the child sequence and returns it as a string.
+     *
+     * @return a String of the serialised child sequence.
+     */
+    private String serialiseChildSequence() {
+        StringBuilder buffer = new StringBuilder();
+        for (Integer child : childSequence) {
+            buffer.append("/").append(child.toString());
+        }
+        return buffer.toString();
+    }
+
+    /**
+     * Deserialises the schemaData for an ElementPointerPart and constructs a 
new ElementPointerPart from it.
+     *
+     * @param schemeData a String of the schemeaData parsed from the string 
XPointer.
+     * @return an ElementPointerPart representing the parsed schemaData.
+     * @throws IllegalArgumentException if the schemeData has invalid scheme 
syntax.
+     */
+    static ElementPointerPart parseFromString(final String schemeData) throws 
InvalidXPointerException {
+        List<Integer> childSequence;
+        String elementID = null;
+        int startChar;
+        int endChar;
+
+        // Find an NCName if it exists?
+        startChar = schemeData.indexOf("/");

Review Comment:
   declare here



##########
maven-model-builder/src/main/java/org/apache/maven/model/io/LocalXmlResolver.java:
##########
@@ -0,0 +1,85 @@
+/*
+ * 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.maven.model.io;
+
+import javax.xml.stream.XMLResolver;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.stream.StreamSource;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class LocalXmlResolver implements XMLResolver {
+
+    private final Path rootDirectory;
+
+    public LocalXmlResolver(Path rootDirectory) {
+        this.rootDirectory = rootDirectory != null ? rootDirectory.normalize() 
: null;
+    }
+
+    @Override
+    public Object resolveEntity(String publicID, String systemID, String 
baseURI, String namespace)
+            throws XMLStreamException {
+        if (rootDirectory == null) {
+            return null;
+        }
+        if (systemID == null) {
+            throw new XMLStreamException("systemID is null");
+        }
+        if (baseURI == null) {
+            throw new XMLStreamException("baseURI is null");
+        }
+        URI baseUri;
+        try {
+            baseUri = new URI(baseURI).normalize();
+        } catch (URISyntaxException e) {
+            throw new XMLStreamException("Invalid syntax for baseURI URI: " + 
baseURI, e);
+        }
+        URI sysUri;
+        try {
+            sysUri = new URI(systemID).normalize();
+        } catch (URISyntaxException e) {
+            throw new XMLStreamException("Invalid syntax for systemID URI: " + 
systemID, e);
+        }
+        if (sysUri.getScheme() != null) {
+            throw new XMLStreamException("systemID must be a relative URI: " + 
systemID);
+        }
+        Path base = Paths.get(baseUri).normalize();
+        if (!base.startsWith(rootDirectory)) {
+            return null;
+        }
+        Path sys = Paths.get(sysUri.getSchemeSpecificPart()).normalize();
+        if (sys.isAbsolute()) {
+            throw new XMLStreamException("systemID must be a relative path: " 
+ systemID);
+        }
+        Path res = base.resolveSibling(sys).normalize();

Review Comment:
   what is res? Please use a non-abbreviated name. 



##########
maven-core/src/test/java/org/apache/maven/project/ProjectBuilderTest.java:
##########
@@ -235,7 +235,7 @@ void testReadInvalidPom() throws Exception {
 
         // single project build entry point
         Exception ex = assertThrows(Exception.class, () -> 
projectBuilder.build(pomFile, configuration));
-        assertThat(ex.getMessage(), containsString("Received 
non-all-whitespace CHARACTERS or CDATA event"));
+        assertThat(ex.getMessage(), containsString("expected START_TAG or 
END_TAG, not CHARACTERS"));
 
         // multi projects build entry point
         ProjectBuildingException pex = assertThrows(

Review Comment:
   Here it looks like it does throw a subclass



##########
maven-core/src/test/java/org/apache/maven/project/ProjectBuilderTest.java:
##########
@@ -235,7 +235,7 @@ void testReadInvalidPom() throws Exception {
 
         // single project build entry point
         Exception ex = assertThrows(Exception.class, () -> 
projectBuilder.build(pomFile, configuration));
-        assertThat(ex.getMessage(), containsString("Received 
non-all-whitespace CHARACTERS or CDATA event"));
+        assertThat(ex.getMessage(), containsString("expected START_TAG or 
END_TAG, not CHARACTERS"));

Review Comment:
   Does this method really throw a plain java.lang.Exception, not a subclass? 
If it does throw a subclass, assert the subclass and ignore the message. If it 
does throw only java.lang.Exception then that's something that should be fixed, 
though not in this PR.
   
   In general asserting exception messages is brittle.



##########
maven-model-builder/src/main/java/org/apache/maven/model/io/LocalXmlResolver.java:
##########
@@ -0,0 +1,85 @@
+/*
+ * 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.maven.model.io;
+
+import javax.xml.stream.XMLResolver;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.stream.StreamSource;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class LocalXmlResolver implements XMLResolver {
+
+    private final Path rootDirectory;
+
+    public LocalXmlResolver(Path rootDirectory) {
+        this.rootDirectory = rootDirectory != null ? rootDirectory.normalize() 
: null;
+    }
+
+    @Override
+    public Object resolveEntity(String publicID, String systemID, String 
baseURI, String namespace)
+            throws XMLStreamException {
+        if (rootDirectory == null) {
+            return null;
+        }
+        if (systemID == null) {
+            throw new XMLStreamException("systemID is null");
+        }
+        if (baseURI == null) {
+            throw new XMLStreamException("baseURI is null");
+        }
+        URI baseUri;
+        try {
+            baseUri = new URI(baseURI).normalize();
+        } catch (URISyntaxException e) {
+            throw new XMLStreamException("Invalid syntax for baseURI URI: " + 
baseURI, e);
+        }
+        URI sysUri;

Review Comment:
   This is not ewhat I first thought it was. Rename systemIDUrl



##########
maven-core/src/test/java/org/apache/maven/project/ProjectBuilderTest.java:
##########
@@ -246,8 +246,7 @@ void testReadInvalidPom() throws Exception {
         assertThat(pex.getResults().get(0).getProblems().size(), 
greaterThan(0));
         assertThat(
                 pex.getResults(),
-                contains(projectBuildingResultWithProblemMessage(
-                        "Received non-all-whitespace CHARACTERS or CDATA event 
in nextTag()")));
+                contains(projectBuildingResultWithProblemMessage("expected 
START_TAG or END_TAG, not CHARACTERS")));

Review Comment:
   I wouldn't go further than asserting the message is non-null. Messages are 
informative, not part of the stable API



##########
maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java:
##########
@@ -100,14 +104,39 @@ private Path getRootDirectory(Map<String, ?> options) {
         return (Path) value;
     }
 
+    private boolean getXInclude(Map<String, ?> options) {
+        Object value = (options != null) ? options.get(XINCLUDE) : null;
+        return value instanceof Boolean && (Boolean) value;
+    }
+
     private Model read(InputStream input, Path pomFile, Map<String, ?> 
options) throws IOException {
         try {
-            XMLInputFactory factory = new com.ctc.wstx.stax.WstxInputFactory();
-            
factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
-            XMLStreamReader parser = factory.createXMLStreamReader(input);
-
             InputSource source = getSource(options);
             boolean strict = isStrict(options);
+            Path rootDirectory = getRootDirectory(options);
+
+            Source xmlSource;
+            if (pomFile != null) {
+                if (input != null) {
+                    xmlSource = new StaxPathInputSource(pomFile, input);
+                } else {
+                    xmlSource = new Stax2FileSource(pomFile.toFile());
+                }
+            } else {
+                xmlSource = new StreamSource(input);
+            }
+
+            XMLStreamReader parser;
+            // We only support xml entities and xinclude when reading a file 
in strict mode

Review Comment:
   nit: external general entities and XInclude



##########
maven-stax-xinclude/src/main/java/org/apache/maven/stax/xinclude/NCName.java:
##########
@@ -0,0 +1,176 @@
+/*
+ * 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.maven.stax.xinclude;
+
+/**
+ * This class represents the data type NCName use for XML non-colonized names.
+ */
+@SuppressWarnings("checkstyle:MagicNumber")
+class NCName {

Review Comment:
   This is a lot to reinvent and maintain for one function. Maybe we need this 
to avoid extra dependencies, but I'm sure this already exists in Xerces, XML 
Commons, or any of several other projects.



##########
maven-model-builder/src/main/java/org/apache/maven/model/io/LocalXmlResolver.java:
##########
@@ -0,0 +1,85 @@
+/*
+ * 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.maven.model.io;
+
+import javax.xml.stream.XMLResolver;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.stream.StreamSource;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class LocalXmlResolver implements XMLResolver {
+
+    private final Path rootDirectory;
+
+    public LocalXmlResolver(Path rootDirectory) {
+        this.rootDirectory = rootDirectory != null ? rootDirectory.normalize() 
: null;
+    }
+
+    @Override
+    public Object resolveEntity(String publicID, String systemID, String 
baseURI, String namespace)
+            throws XMLStreamException {
+        if (rootDirectory == null) {
+            return null;
+        }
+        if (systemID == null) {
+            throw new XMLStreamException("systemID is null");
+        }
+        if (baseURI == null) {
+            throw new XMLStreamException("baseURI is null");
+        }
+        URI baseUri;
+        try {
+            baseUri = new URI(baseURI).normalize();
+        } catch (URISyntaxException e) {
+            throw new XMLStreamException("Invalid syntax for baseURI URI: " + 
baseURI, e);
+        }
+        URI sysUri;
+        try {
+            sysUri = new URI(systemID).normalize();
+        } catch (URISyntaxException e) {
+            throw new XMLStreamException("Invalid syntax for systemID URI: " + 
systemID, e);
+        }
+        if (sysUri.getScheme() != null) {
+            throw new XMLStreamException("systemID must be a relative URI: " + 
systemID);
+        }
+        Path base = Paths.get(baseUri).normalize();
+        if (!base.startsWith(rootDirectory)) {
+            return null;
+        }
+        Path sys = Paths.get(sysUri.getSchemeSpecificPart()).normalize();
+        if (sys.isAbsolute()) {
+            throw new XMLStreamException("systemID must be a relative path: " 
+ systemID);
+        }
+        Path res = base.resolveSibling(sys).normalize();
+        if (!res.startsWith(rootDirectory)) {
+            throw new XMLStreamException("systemID cannot refer to outside 
rootDirectory: " + systemID);

Review Comment:
   refer to --> refer to a path



##########
maven-model-builder/src/main/java/org/apache/maven/model/io/ModelReader.java:
##########
@@ -45,6 +45,12 @@ public interface ModelReader {
      */
     String INPUT_SOURCE = "org.apache.maven.model.io.inputSource";
 
+    /**
+     * Name of the property used to store a boolean {@code true} if XInclude 
supports

Review Comment:
   supports --> support



##########
maven-model-builder/src/main/java/org/apache/maven/model/io/LocalXmlResolver.java:
##########
@@ -0,0 +1,85 @@
+/*
+ * 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.maven.model.io;
+
+import javax.xml.stream.XMLResolver;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.stream.StreamSource;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class LocalXmlResolver implements XMLResolver {
+
+    private final Path rootDirectory;
+
+    public LocalXmlResolver(Path rootDirectory) {
+        this.rootDirectory = rootDirectory != null ? rootDirectory.normalize() 
: null;
+    }
+
+    @Override
+    public Object resolveEntity(String publicID, String systemID, String 
baseURI, String namespace)
+            throws XMLStreamException {
+        if (rootDirectory == null) {
+            return null;
+        }
+        if (systemID == null) {
+            throw new XMLStreamException("systemID is null");
+        }
+        if (baseURI == null) {
+            throw new XMLStreamException("baseURI is null");
+        }
+        URI baseUri;
+        try {
+            baseUri = new URI(baseURI).normalize();
+        } catch (URISyntaxException e) {
+            throw new XMLStreamException("Invalid syntax for baseURI URI: " + 
baseURI, e);
+        }
+        URI sysUri;
+        try {
+            sysUri = new URI(systemID).normalize();
+        } catch (URISyntaxException e) {
+            throw new XMLStreamException("Invalid syntax for systemID URI: " + 
systemID, e);
+        }
+        if (sysUri.getScheme() != null) {
+            throw new XMLStreamException("systemID must be a relative URI: " + 
systemID);
+        }
+        Path base = Paths.get(baseUri).normalize();
+        if (!base.startsWith(rootDirectory)) {
+            return null;
+        }
+        Path sys = Paths.get(sysUri.getSchemeSpecificPart()).normalize();

Review Comment:
   sys --> systemIDPath



##########
maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java:
##########
@@ -147,4 +175,18 @@ private Model read(Reader reader, Path pomFile, 
Map<String, ?> options) throws I
             throw new IOException("Unable to transform pom", e);
         }
     }
+
+    private static class StaxPathInputSource extends Stax2FileSource {

Review Comment:
   a comment explaining the point here might be useful. Maybe this associates a 
file with an input stream that doesn't come from the file? or at least not only 
from the file? I'm not sure



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscr...@maven.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to