Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MNG-7862] The ModelLocator should always be used when locating pom.xml #1217

Merged
merged 2 commits into from
Aug 23, 2023
Merged
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
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 @@ -74,12 +74,17 @@ public String getUserProperty(String key) {

@Override
public Model getRawModel(String groupId, String artifactId) throws IllegalStateException {
return null;
throw new UnsupportedOperationException();
}

@Override
public Model getRawModel(Path p) {
return null;
throw new UnsupportedOperationException();
}

@Override
public Path locate(Path path) {
throw new UnsupportedOperationException();
}
}
}
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()) {
gnodet marked this conversation as resolved.
Show resolved Hide resolved
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,56 @@
/*
* 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>
* 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</li>
* </ul>
* If the given path points at a directory, 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.
*
* @param locator locator used to locate the pom file
* @param relPath 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);

/**
* When using a ModelSource3, the method with a {@code ModelLocator} argument should
* be used instead.
*
* @deprecated use {@link #getRelatedSource(ModelLocator, String)} instead
gnodet marked this conversation as resolved.
Show resolved Hide resolved
*/
@Deprecated
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