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

DI and API fixes #1407

Merged
merged 3 commits into from
Feb 9, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,9 @@
package org.apache.maven.api.services;

import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.apache.maven.api.Artifact;
import org.apache.maven.api.Project;
import org.apache.maven.api.RemoteRepository;
import org.apache.maven.api.Service;
import org.apache.maven.api.Session;
import java.util.*;

import org.apache.maven.api.*;
import org.apache.maven.api.annotations.Experimental;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.annotations.Nullable;
Expand Down Expand Up @@ -86,21 +79,45 @@ default void attachArtifact(Session session, Project project, String type, Path

void attachArtifact(Project project, Artifact artifact, Path path);

List<String> getCompileSourceRoots(Project project);

void addCompileSourceRoot(Project project, String sourceRoot);

List<String> getTestCompileSourceRoots(Project project);

void addTestCompileSourceRoot(Project project, String sourceRoot);

List<Resource> getResources(Project project);
/**
* Obtain an immutable list of compile source roots for the given project and scope.
* Paths are absolute.
*
* @param project the project
* @param scope the scope, i.e. usually main or test
* @return the list of compile source roots
*/
@Nonnull
List<Path> getCompileSourceRoots(@Nonnull Project project, @Nonnull ProjectScope scope);

void addResource(Project project, Resource resource);
/**
* Add a compilation source root to the given project for the given scope.
* The path will be transformed into an absolute path and added to the list for the given scope,
* if not already present.
*
* @param project the project
* @param scope the scope, i.e. usually main or test
* @param sourceRoot the new source root
*/
void addCompileSourceRoot(@Nonnull Project project, @Nonnull ProjectScope scope, @Nonnull Path sourceRoot);

List<Resource> getTestResources(Project project);
/**
* Get the list of resources for the given project and scope
*
* @param project the project
* @param scope the scope, i.e. usually main or test
* @return the list of resources
*/
List<Resource> getResources(@Nonnull Project project, @Nonnull ProjectScope scope);

void addTestResource(Project project, Resource resource);
/**
* Add a resource set to the given project for the given scope.
*
* @param project the project
* @param scope the scope, i.e. usually main or test
* @param resource the resource set to add
*/
void addResource(@Nonnull Project project, @Nonnull ProjectScope scope, @Nonnull Resource resource);

/**
* Returns an immutable list of project remote repositories (directly specified or inherited).
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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.api.services.xml;

import org.apache.maven.api.annotations.Experimental;
import org.apache.maven.api.plugin.descriptor.PluginDescriptor;

/**
* Reads and writes a {@link PluginDescriptor} object to/from XML.
*
* @since 4.0.0
*/
@Experimental
public interface PluginXmlFactory extends XmlFactory<PluginDescriptor> {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* 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.internal.impl;

import javax.inject.Named;
import javax.inject.Singleton;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;

import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.plugin.descriptor.PluginDescriptor;
import org.apache.maven.api.services.xml.*;
import org.apache.maven.plugin.descriptor.io.PluginDescriptorStaxReader;
import org.apache.maven.plugin.descriptor.io.PluginDescriptorStaxWriter;

import static org.apache.maven.internal.impl.Utils.nonNull;

@Named
@Singleton
public class DefaultPluginXmlFactory implements PluginXmlFactory {
@Override
public PluginDescriptor read(@Nonnull XmlReaderRequest request) throws XmlReaderException {
nonNull(request, "request");
Path path = request.getPath();
URL url = request.getURL();
Reader reader = request.getReader();
InputStream inputStream = request.getInputStream();
if (path == null && url == null && reader == null && inputStream == null) {
throw new IllegalArgumentException("path, url, reader or inputStream must be non null");
}
try {
PluginDescriptorStaxReader xml = new PluginDescriptorStaxReader();
xml.setAddDefaultEntities(request.isAddDefaultEntities());
if (inputStream != null) {
return xml.read(inputStream, request.isStrict());
} else if (reader != null) {
return xml.read(reader, request.isStrict());
} else if (path != null) {
try (InputStream is = Files.newInputStream(path)) {
return xml.read(is, request.isStrict());
}
} else {
try (InputStream is = url.openStream()) {
return xml.read(is, request.isStrict());
}
}
} catch (Exception e) {
throw new XmlReaderException("Unable to read model", e);
}
}

@Override
public void write(XmlWriterRequest<PluginDescriptor> request) throws XmlWriterException {
nonNull(request, "request");
PluginDescriptor content = nonNull(request.getContent(), "content");
Path path = request.getPath();
OutputStream outputStream = request.getOutputStream();
Writer writer = request.getWriter();
if (writer == null && outputStream == null && path == null) {
throw new IllegalArgumentException("writer, outputStream or path must be non null");
}
try {
if (writer != null) {
new PluginDescriptorStaxWriter().write(writer, content);
} else if (outputStream != null) {
new PluginDescriptorStaxWriter().write(outputStream, content);
} else {
try (OutputStream os = Files.newOutputStream(path)) {
new PluginDescriptorStaxWriter().write(outputStream, content);
}
}
} catch (Exception e) {
throw new XmlWriterException("Unable to write model", e);
}
}

/**
* Simply parse the given xml string.
*
* @param xml the input xml string
* @return the parsed object
* @throws XmlReaderException if an error occurs during the parsing
* @see #toXmlString(Object)
*/
public static PluginDescriptor fromXml(@Nonnull String xml) throws XmlReaderException {
return new DefaultPluginXmlFactory().fromXmlString(xml);
}

/**
* Simply converts the given content to an xml string.
*
* @param content the object to convert
* @return the xml string representation
* @throws XmlWriterException if an error occurs during the transformation
* @see #fromXmlString(String)
*/
public static String toXml(@Nonnull PluginDescriptor content) throws XmlWriterException {
return new DefaultPluginXmlFactory().toXmlString(content);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
import javax.inject.Named;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

import org.apache.maven.RepositoryUtils;
import org.apache.maven.api.*;
Expand All @@ -33,7 +35,9 @@
import org.apache.maven.project.MavenProject;
import org.eclipse.sisu.Typed;

import static java.util.stream.Collectors.toList;
import static org.apache.maven.internal.impl.Utils.map;
import static org.apache.maven.internal.impl.Utils.nonNull;

@Named
@Typed
Expand Down Expand Up @@ -86,47 +90,59 @@ public void attachArtifact(Project project, Artifact artifact, Path path) {
}

@Override
public List<String> getCompileSourceRoots(Project project) {
List<String> roots = getMavenProject(project).getCompileSourceRoots();
return Collections.unmodifiableList(roots);
}

@Override
public void addCompileSourceRoot(Project project, String sourceRoot) {
List<String> roots = getMavenProject(project).getCompileSourceRoots();
roots.add(sourceRoot);
}

@Override
public List<String> getTestCompileSourceRoots(Project project) {
List<String> roots = getMavenProject(project).getTestCompileSourceRoots();
return Collections.unmodifiableList(roots);
}

@Override
public void addTestCompileSourceRoot(Project project, String sourceRoot) {
List<String> roots = getMavenProject(project).getTestCompileSourceRoots();
roots.add(sourceRoot);
}

@Override
public List<Resource> getResources(Project project) {
return getMavenProject(project).getBuild().getDelegate().getResources();
public List<Path> getCompileSourceRoots(Project project, ProjectScope scope) {
MavenProject prj = getMavenProject(nonNull(project, "project"));
List<String> roots;
if (nonNull(scope, "scope") == ProjectScope.MAIN) {
roots = prj.getCompileSourceRoots();
} else if (scope == ProjectScope.TEST) {
roots = prj.getTestCompileSourceRoots();
} else {
throw new IllegalArgumentException("Unsupported scope " + scope);
}
return roots.stream()
.map(Paths::get)
.collect(Collectors.collectingAndThen(toList(), Collections::unmodifiableList));
}

@Override
public void addResource(Project project, Resource resource) {
getMavenProject(project).addResource(new org.apache.maven.model.Resource(resource));
public void addCompileSourceRoot(Project project, ProjectScope scope, Path sourceRoot) {
MavenProject prj = getMavenProject(nonNull(project, "project"));
String root = nonNull(sourceRoot, "sourceRoot").toAbsolutePath().toString();
if (nonNull(scope, "scope") == ProjectScope.MAIN) {
prj.addCompileSourceRoot(root);
} else if (scope == ProjectScope.TEST) {
prj.addTestCompileSourceRoot(root);
} else {
throw new IllegalArgumentException("Unsupported scope " + scope);
}
}

@Override
public List<Resource> getTestResources(Project project) {
return getMavenProject(project).getBuild().getDelegate().getTestResources();
public List<Resource> getResources(@Nonnull Project project, @Nonnull ProjectScope scope) {
Project prj = nonNull(project, "project");
if (nonNull(scope, "scope") == ProjectScope.MAIN) {
return prj.getBuild().getResources();
} else if (scope == ProjectScope.TEST) {
return prj.getBuild().getTestResources();
} else {
throw new IllegalArgumentException("Unsupported scope " + scope);
}
}

@Override
public void addTestResource(Project project, Resource resource) {
getMavenProject(project).addTestResource(new org.apache.maven.model.Resource(resource));
public void addResource(@Nonnull Project project, @Nonnull ProjectScope scope, @Nonnull Resource resource) {
// TODO: we should not modify the underlying model here, but resources should be stored
// TODO: in a separate field in the project, however, that could break v3 plugins
MavenProject prj = getMavenProject(nonNull(project, "project"));
org.apache.maven.model.Resource res = new org.apache.maven.model.Resource(nonNull(resource, "resource"));
if (nonNull(scope, "scope") == ProjectScope.MAIN) {
prj.addResource(res);
} else if (scope == ProjectScope.TEST) {
prj.addTestResource(res);
} else {
throw new IllegalArgumentException("Unsupported scope " + scope);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -526,23 +526,14 @@ private <T> T loadV4Mojo(
org.apache.maven.api.plugin.Log log = new DefaultLog(
LoggerFactory.getLogger(mojoExecution.getMojoDescriptor().getFullGoalName()));
try {
Set<String> classes = new HashSet<>();
try (InputStream is = pluginRealm.getResourceAsStream("META-INF/maven/org.apache.maven.api.di.Inject");
BufferedReader reader = new BufferedReader(new InputStreamReader(Objects.requireNonNull(is)))) {
reader.lines().forEach(classes::add);
}
Injector injector = Injector.create();
injector.discover(pluginRealm);
// Add known classes
// TODO: get those from the existing plexus scopes ?
injector.bindInstance(Session.class, sessionV4);
injector.bindInstance(Project.class, project);
injector.bindInstance(org.apache.maven.api.MojoExecution.class, execution);
injector.bindInstance(org.apache.maven.api.plugin.Log.class, log);
// Add plugin classes
for (String className : classes) {
Class<?> clazz = pluginRealm.loadClass(className);
injector.bindImplicit(clazz);
}
mojo = mojoInterface.cast(injector.getInstance(mojoDescriptor.getImplementationClass()));

} catch (Exception e) {
Expand Down
2 changes: 2 additions & 0 deletions maven-di/src/main/java/org/apache/maven/di/Injector.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ static Injector create() {
return new InjectorImpl();
}

Injector discover(ClassLoader classLoader);

Injector bindScope(Class<? extends Annotation> scopeAnnotation, Scope scope);

Injector bindImplicit(Class<?> cls);
Expand Down
Loading
Loading