Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public final class Features {
*/
public static final String BUILDCONSUMER = "maven.experimental.buildconsumer";

public static final String XINCLUDE = "maven.xinclude";

private Features() {}

/**
Expand All @@ -62,6 +64,18 @@ public static boolean buildConsumer(@Nullable Session session) {
return buildConsumer(session != null ? session.getUserProperties() : null);
}

public static boolean xinclude(@Nullable Properties userProperties) {
return doGet(userProperties, XINCLUDE, false);
}

public static boolean xinclude(@Nullable Map<String, String> userProperties) {
return doGet(userProperties, XINCLUDE, false);
}

public static boolean xinclude(@Nullable Session session) {
return xinclude(session != null ? session.getUserProperties() : null);
}

private static boolean doGet(Properties userProperties, String key, boolean def) {
return doGet(userProperties != null ? userProperties.get(key) : null, def);
}
Expand Down
5 changes: 5 additions & 0 deletions maven-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ under the License.
<artifactId>maven-api-xml</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-stax-xinclude</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model-builder</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
import static org.apache.maven.project.ProjectBuildingResultWithProblemMessageMatcher.projectBuildingResultWithProblemMessage;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasKey;
Expand Down Expand Up @@ -234,8 +233,8 @@ void testReadInvalidPom() throws Exception {
getContainer().lookup(org.apache.maven.project.ProjectBuilder.class);

// 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"));
ProjectBuildingException ex =
assertThrows(ProjectBuildingException.class, () -> projectBuilder.build(pomFile, configuration));

// multi projects build entry point
ProjectBuildingException pex = assertThrows(
Expand All @@ -244,10 +243,6 @@ void testReadInvalidPom() throws Exception {
assertEquals(1, pex.getResults().size());
assertNotNull(pex.getResults().get(0).getPomFile());
assertThat(pex.getResults().get(0).getProblems().size(), greaterThan(0));
assertThat(
pex.getResults(),
contains(projectBuildingResultWithProblemMessage(
"Received non-all-whitespace CHARACTERS or CDATA event in nextTag()")));
}

@Test
Expand Down
4 changes: 4 additions & 0 deletions maven-model-builder/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ under the License.
<artifactId>javax.inject</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-stax-xinclude</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.sisu</groupId>
<artifactId>org.eclipse.sisu.inject</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,7 @@ private org.apache.maven.api.model.Model doReadFileModel(
options.put(ModelProcessor.IS_STRICT, strict);
options.put(ModelProcessor.SOURCE, modelSource);
options.put(ModelReader.ROOT_DIRECTORY, request.getRootDirectory());
options.put(ModelReader.XINCLUDE, Features.xinclude(request.getUserProperties()));

InputSource source;
if (request.isLocationTracking()) {
Expand All @@ -1108,9 +1109,15 @@ private org.apache.maven.api.model.Model doReadFileModel(
}

try {
model = modelProcessor
.read(modelSource.getInputStream(), options)
.getDelegate();
if (modelSource instanceof FileModelSource) {
model = modelProcessor
.read(((FileModelSource) modelSource).getFile(), options)
.getDelegate();
} else {
model = modelProcessor
.read(modelSource.getInputStream(), options)
.getDelegate();
}
} catch (ModelParseException e) {
if (!strict) {
throw e;
Expand All @@ -1119,9 +1126,15 @@ private org.apache.maven.api.model.Model doReadFileModel(
options.put(ModelProcessor.IS_STRICT, Boolean.FALSE);

try {
model = modelProcessor
.read(modelSource.getInputStream(), options)
.getDelegate();
if (modelSource instanceof FileModelSource) {
model = modelProcessor
.read(((FileModelSource) modelSource).getFile(), options)
.getDelegate();
} else {
model = modelProcessor
.read(modelSource.getInputStream(), options)
.getDelegate();
}
} catch (ModelParseException ne) {
// still unreadable even in non-strict mode, rethrow original error
throw e;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.Objects;
Expand All @@ -39,6 +40,8 @@
import org.apache.maven.model.Model;
import org.apache.maven.model.building.ModelSourceTransformer;
import org.apache.maven.model.v4.MavenStaxReader;
import org.apache.maven.stax.xinclude.XInclude;
import org.codehaus.stax2.io.Stax2FileSource;

/**
* Handles deserialization of a model from some kind of textual format like XML.
Expand All @@ -58,13 +61,11 @@ public DefaultModelReader(ModelSourceTransformer transformer) {
public Model read(File input, Map<String, ?> options) throws IOException {
Objects.requireNonNull(input, "input cannot be null");

try (InputStream in = Files.newInputStream(input.toPath())) {
Model model = read(in, input.toPath(), options);
Model model = read(null, input, options);

model.setPomFile(input);
model.setPomFile(input);

return model;
}
return model;
}

@Override
Expand Down Expand Up @@ -100,14 +101,35 @@ private Path getRootDirectory(Map<String, ?> options) {
return (Path) 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);
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, File pomFile, Map<String, ?> options) throws IOException {
try {
InputSource source = getSource(options);
boolean strict = isStrict(options);
Path rootDirectory = getRootDirectory(options);

Source xmlSource;
if (pomFile != null) {
xmlSource = new Stax2FileSource(pomFile);
} else {
xmlSource = new StreamSource(input);
}

XMLStreamReader parser;
// We only support general external 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);
parser = factory.createXMLStreamReader(xmlSource);
}

MavenStaxReader mr = new MavenStaxReader();
mr.setAddLocationInformation(source != null);
Model model = new Model(mr.read(parser, strict, source != null ? source.toApiSource() : null));
Expand All @@ -127,7 +149,6 @@ private Model read(InputStream input, Path pomFile, Map<String, ?> options) thro
private Model read(Reader reader, 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(reader);

InputSource source = getSource(options);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* 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 systemIDUri;
try {
systemIDUri = new URI(systemID).normalize();
} catch (URISyntaxException e) {
throw new XMLStreamException("Invalid syntax for systemID URI: " + systemID, e);
}
if (systemIDUri.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 systemIDPath = Paths.get(systemIDUri.getSchemeSpecificPart()).normalize();
if (systemIDPath.isAbsolute()) {
throw new XMLStreamException("systemID must be a relative path: " + systemID);
}
Path resourcePath = base.resolveSibling(systemIDPath).normalize();
if (!resourcePath.startsWith(rootDirectory)) {
throw new XMLStreamException("systemID cannot refer to a path outside rootDirectory: " + systemID);
}
try {
return new StreamSource(
Files.newInputStream(resourcePath), resourcePath.toUri().toASCIIString());
} catch (IOException e) {
throw new XMLStreamException("Unable to create Source for " + systemID + ": " + e.getMessage(), e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 support
* is needed.
*/
String XINCLUDE = "xinclude";

/**
* Name of the property used to store the project's root directory to use with
* XInclude support.
Expand Down
Loading