Skip to content

Commit

Permalink
[MNG-7862] The ModelLocator should always be used when locating pom.xml
Browse files Browse the repository at this point in the history
  • Loading branch information
gnodet committed Aug 21, 2023
1 parent eff2fbf commit 2da261f
Show file tree
Hide file tree
Showing 13 changed files with 142 additions and 54 deletions.
2 changes: 1 addition & 1 deletion api/maven-api-model/src/main/mdo/maven.mdo
Original file line number Diff line number Diff line change
Expand Up @@ -1802,7 +1802,7 @@
]]>
</description>
<type>String</type>
<defaultValue>../pom.xml</defaultValue>
<defaultValue>..</defaultValue>
</field>
</fields>
<codeSegments>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
*/
package org.apache.maven.project;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
Expand Down Expand Up @@ -60,23 +59,6 @@ public Model get(String groupId, String artifactId, String version) {
.orElse(null);
}

/**
* Find model by path, useful when location the parent by relativePath
*
* @param path
* @return the matching model or {@code null}
* @since 4.0.0
*/
public Model get(Path path) {
final Path pomFile;
if (Files.isDirectory(path)) {
pomFile = path.resolve("pom.xml");
} else {
pomFile = path;
}
return modelsByPath.get(pomFile);
}

private String getVersion(Model model) {
String version = model.getVersion();
if (version == null && model.getParent() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,10 @@ public Model getRawModel(String groupId, String artifactId) throws IllegalStateE
public Model getRawModel(Path p) {
return null;
}

@Override
public Path locate(Path path) {
return null;
}
}
}
25 changes: 11 additions & 14 deletions maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
Original file line number Diff line number Diff line change
Expand Up @@ -1349,23 +1349,20 @@ private File determinePom(final CommandLine commandLine, final String workingDir
alternatePomFile = commandLine.getOptionValue(CLIManager.ALTERNATE_POM_FILE);
}

File current = baseDirectory;
if (alternatePomFile != null) {
File pom = resolveFile(new File(alternatePomFile), workingDirectory);
if (pom.isDirectory()) {
if (modelProcessor != null) {
pom = modelProcessor.locatePom(pom);
} else {
pom = new File(pom, "pom.xml");
}
}
current = resolveFile(new File(alternatePomFile), workingDirectory);
}

return pom;
} else if (modelProcessor != null) {
File pom = modelProcessor.locatePom(baseDirectory);
File pom;
if (current.isDirectory() && modelProcessor != null) {
pom = modelProcessor.locatePom(current);
} else {
pom = current;
}

if (pom.isFile()) {
return pom;
}
if (pom.isFile()) {
return pom;
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ protected Function<Path, Optional<RelativeProject>> getRelativePathMapper() {
return p -> Optional.ofNullable(context.getRawModel(p)).map(DefaultBuildPomXMLFilterFactory::toRelativeProject);
}

@Override
protected Function<Path, Path> getModelLocator() {
return context::locate;
}

@Override
protected BiFunction<String, String, String> getDependencyKeyToVersionMapper() {
return (g, a) -> Optional.ofNullable(context.getRawModel(g, a))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1363,7 +1363,7 @@ private ModelData readParentLocally(
DefaultModelProblemCollector problems)
throws ModelBuildingException {
final Parent parent = childModel.getParent();
final ModelSource candidateSource;
final ModelSource2 candidateSource;
final Model candidateModel;
final WorkspaceModelResolver resolver = request.getWorkspaceModelResolver();
if (resolver == null) {
Expand Down Expand Up @@ -1480,7 +1480,7 @@ private boolean rawChildVersionReferencesParent(String rawChildModelVersion) {
|| rawChildModelVersion.equals("${project.parent.version}");
}

private ModelSource getParentPomFile(Model childModel, Source source) {
private ModelSource2 getParentPomFile(Model childModel, Source source) {
if (!(source instanceof ModelSource2)) {
return null;
}
Expand All @@ -1491,7 +1491,11 @@ private ModelSource getParentPomFile(Model childModel, Source source) {
return null;
}

return ((ModelSource2) source).getRelatedSource(parentPath);
if (source instanceof ModelSource3) {
return ((ModelSource3) source).getRelatedSource(modelProcessor, parentPath);
} else {
return ((ModelSource2) source).getRelatedSource(parentPath);
}
}

private ModelData readParentExternally(
Expand Down Expand Up @@ -1866,7 +1870,7 @@ protected boolean hasFatalErrors(ModelProblemCollectorExt problems) {
* @since 4.0.0
*/
private class DefaultTransformerContextBuilder implements TransformerContextBuilder {
private final DefaultTransformerContext context = new DefaultTransformerContext();
private final DefaultTransformerContext context = new DefaultTransformerContext(modelProcessor);

private final Map<DefaultTransformerContext.GAKey, Set<Source>> mappedSources = new ConcurrentHashMap<>(64);

Expand All @@ -1882,6 +1886,11 @@ public TransformerContext initialize(ModelBuildingRequest request, ModelProblemC
// We must assume the TransformerContext was created using this.newTransformerContextBuilder()
DefaultModelProblemCollector problems = (DefaultModelProblemCollector) collector;
return new TransformerContext() {
@Override
public Path locate(Path path) {
return modelProcessor.locatePom(path.toFile()).toPath();
}

@Override
public String getUserProperty(String key) {
return context.userProperties.computeIfAbsent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@
import java.util.function.Supplier;

import org.apache.maven.model.Model;
import org.apache.maven.model.locator.ModelLocator;

/**
*
* @author Robert Scholte
* @since 4.0.0
*/
class DefaultTransformerContext implements TransformerContext {
final ModelLocator modelLocator;

final Map<String, String> userProperties = new ConcurrentHashMap<>();

final Map<Path, Holder> modelByPath = new ConcurrentHashMap<>();
Expand Down Expand Up @@ -77,6 +80,10 @@ public Model computeIfAbsent(Supplier<Model> supplier) {
}
}

DefaultTransformerContext(ModelLocator modelLocator) {
this.modelLocator = modelLocator;
}

@Override
public String getUserProperty(String key) {
return userProperties.get(key);
Expand All @@ -92,6 +99,11 @@ public Model getRawModel(String groupId, String artifactId) {
return Holder.deref(modelByGA.get(new GAKey(groupId, artifactId)));
}

@Override
public Path locate(Path path) {
return modelLocator.locatePom(path.toFile()).toPath();
}

static class GAKey {
private final String groupId;
private final String artifactId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@
import java.net.URI;

import org.apache.maven.building.FileSource;
import org.apache.maven.model.locator.ModelLocator;

/**
* Wraps an ordinary {@link File} as a model source.
*
* @author Benjamin Bentmann
*/
public class FileModelSource extends FileSource implements ModelSource2 {
public class FileModelSource extends FileSource implements ModelSource3 {

/**
* Creates a new model source backed by the specified file.
Expand All @@ -51,18 +52,17 @@ public File getPomFile() {
}

@Override
public ModelSource2 getRelatedSource(String relPath) {
public ModelSource3 getRelatedSource(ModelLocator locator, String relPath) {
relPath = relPath.replace('\\', File.separatorChar).replace('/', File.separatorChar);

File relatedPom = new File(getFile().getParentFile(), relPath);

if (relatedPom.isDirectory()) {
// TODO figure out how to reuse ModelLocator.locatePom(File) here
relatedPom = new File(relatedPom, "pom.xml");
if (relatedPom.isDirectory() && locator != null) {
relatedPom = locator.locatePom(relatedPom);
}

if (relatedPom.isFile() && relatedPom.canRead()) {
return new FileModelSource(new File(relatedPom.toURI().normalize()));
return new FileModelSource(relatedPom.toPath().normalize().toFile());
}

return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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.building;

import org.apache.maven.model.locator.ModelLocator;

/**
* Enhancement to the {@link ModelSource2} to support locating POM files using the {@link ModelLocator}
* when pointing to a directory.
*/
public interface ModelSource3 extends ModelSource2 {
/**
* Returns model source identified by a path relative to this model source POM. Implementation <strong>MUST</strong>
* be able to accept <code>relPath</code> parameter values that
* <ul>
* <li>use either / or \ file path separator</li>
* <li>have .. parent directory references</li>
* <li>point either at file or directory, in the latter case the provided {@code ModelLocator} will be used
* to find the POM file, else if no locator is provided, a file named 'pom.xml' needs to be used by the
* requested model source.</li>
* </ul>
*
* @param relPath is the path of the requested model source relative to this model source POM.
* @return related model source or <code>null</code> if no such model source.
*/
ModelSource3 getRelatedSource(ModelLocator locator, String relPath);

default ModelSource3 getRelatedSource(String relPath) {
return getRelatedSource(null, relPath);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,6 @@ public interface TransformerContext {
* @throws IllegalStateException if multiple versions of the same GA are part of the reactor
*/
Model getRawModel(String groupId, String artifactId);

Path locate(Path path);
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public final XMLStreamReader get(XMLStreamReader orgParser, Path projectFile) {
}

if (getRelativePathMapper() != null) {
parser = new ParentXMLFilter(parser, getRelativePathMapper(), projectFile.getParent());
parser = new ParentXMLFilter(parser, getRelativePathMapper(), getModelLocator(), projectFile.getParent());
}

CiFriendlyXMLFilter ciFriendlyFilter = new CiFriendlyXMLFilter(parser, consume);
Expand All @@ -77,6 +77,10 @@ protected Function<Path, Optional<RelativeProject>> getRelativePathMapper() {
return null;
}

protected Function<Path, Path> getModelLocator() {
return null;
}

protected BiFunction<String, String, String> getDependencyKeyToVersionMapper() {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class ParentXMLFilter extends NodeBufferingParser {

private final Function<Path, Optional<RelativeProject>> relativePathMapper;

private final Function<Path, Path> modelLocator;

private final Path projectPath;

private static final Pattern S_FILTER = Pattern.compile("\\s+");
Expand All @@ -55,9 +57,13 @@ class ParentXMLFilter extends NodeBufferingParser {
* @param relativePathMapper
*/
ParentXMLFilter(
XMLStreamReader delegate, Function<Path, Optional<RelativeProject>> relativePathMapper, Path projectPath) {
XMLStreamReader delegate,
Function<Path, Optional<RelativeProject>> relativePathMapper,
Function<Path, Path> modelLocator,
Path projectPath) {
super(delegate, "parent");
this.relativePathMapper = relativePathMapper;
this.modelLocator = modelLocator;
this.projectPath = projectPath;
}

Expand Down Expand Up @@ -93,7 +99,7 @@ protected void process(List<Event> buffer) {
} else if (event.event == END_ELEMENT && "parent".equals(event.name)) {
Optional<RelativeProject> resolvedParent;
if (!hasVersion && (!hasRelativePath || relativePath != null)) {
Path relPath = Paths.get(Objects.toString(relativePath, "../pom.xml"));
Path relPath = Paths.get(Objects.toString(relativePath, ".."));
resolvedParent = resolveRelativePath(relPath, groupId, artifactId);
} else {
resolvedParent = Optional.empty();
Expand Down Expand Up @@ -128,9 +134,13 @@ protected void process(List<Event> buffer) {
}

protected Optional<RelativeProject> resolveRelativePath(Path relativePath, String groupId, String artifactId) {
Path pomPath = projectPath.resolve(relativePath);
if (Files.isDirectory(pomPath)) {
pomPath = pomPath.resolve("pom.xml");
Path pomPath = projectPath.resolve(relativePath).normalize();
if (Files.isDirectory(pomPath) && modelLocator != null) {
pomPath = modelLocator.apply(pomPath);
}

if (pomPath == null || !Files.isRegularFile(pomPath)) {
return Optional.empty();
}

Optional<RelativeProject> mappedProject = relativePathMapper.apply(pomPath.normalize());
Expand Down
Loading

0 comments on commit 2da261f

Please sign in to comment.