diff --git a/compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/ArtifactDescriptorReaderDelegate.java b/compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/ArtifactDescriptorReaderDelegate.java index 068c697e79b3..5ccf74b589ba 100644 --- a/compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/ArtifactDescriptorReaderDelegate.java +++ b/compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/ArtifactDescriptorReaderDelegate.java @@ -96,7 +96,8 @@ public void populateResult(RepositorySystemSession session, ArtifactDescriptorRe private Dependency convert(org.apache.maven.model.Dependency dependency, ArtifactTypeRegistry stereotypes) { ArtifactType stereotype = stereotypes.get(dependency.getType()); if (stereotype == null) { - stereotype = new DefaultType(dependency.getType(), Language.NONE, dependency.getType(), null, false); + stereotype = new DefaultType(dependency.getType(), Language.NONE, dependency.getType(), null, false) + .toArtifactType(); } boolean system = dependency.getSystemPath() != null diff --git a/compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenSessionBuilderSupplier.java b/compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenSessionBuilderSupplier.java index 0ee51533211f..5d1159f09e43 100644 --- a/compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenSessionBuilderSupplier.java +++ b/compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenSessionBuilderSupplier.java @@ -25,6 +25,7 @@ import org.apache.maven.repository.internal.artifact.FatArtifactTraverser; import org.apache.maven.repository.internal.scopes.Maven4ScopeManagerConfiguration; import org.apache.maven.repository.internal.type.DefaultTypeProvider; +import org.apache.maven.repository.internal.type.TypeDeriver; import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.RepositorySystemSession.CloseableSession; import org.eclipse.aether.RepositorySystemSession.SessionBuilder; @@ -114,7 +115,8 @@ protected DependencyGraphTransformer getDependencyGraphTransformer() { new ConflictResolver( new ConfigurableVersionSelector(), new ManagedScopeSelector(getScopeManager()), new SimpleOptionalitySelector(), new ManagedScopeDeriver(getScopeManager())), - new ManagedDependencyContextRefiner(getScopeManager())); + new ManagedDependencyContextRefiner(getScopeManager()), + new TypeDeriver()); } /** @@ -128,7 +130,7 @@ protected DependencyGraphTransformer getDependencyGraphTransformer() { */ protected ArtifactTypeRegistry getArtifactTypeRegistry() { DefaultArtifactTypeRegistry stereotypes = new DefaultArtifactTypeRegistry(); - new DefaultTypeProvider().types().forEach(stereotypes::add); + new DefaultTypeProvider().types().forEach(t -> stereotypes.add(t.toArtifactType())); return stereotypes; } diff --git a/compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/type/DefaultType.java b/compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/type/DefaultType.java index 016688ef4c3a..842b779d8b44 100644 --- a/compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/type/DefaultType.java +++ b/compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/type/DefaultType.java @@ -42,7 +42,7 @@ * @deprecated since 4.0.0, use {@code maven-api-impl} jar instead */ @Deprecated(since = "4.0.0") -public class DefaultType implements Type, ArtifactType { +public class DefaultType implements Type { private final String id; private final Language language; private final String extension; @@ -80,11 +80,6 @@ public String id() { return id; } - @Override - public String getId() { - return id(); - } - @Override public Language getLanguage() { return language; @@ -105,13 +100,44 @@ public boolean isIncludesDependencies() { return this.includesDependencies; } + public Map getProperties() { + return properties; + } + @Override public Set getPathTypes() { return this.pathTypes; } - @Override - public Map getProperties() { - return properties; + public ArtifactType toArtifactType() { + return new ArtifactTypeAdapter(this); + } + + private static class ArtifactTypeAdapter implements ArtifactType { + private final DefaultType type; + + private ArtifactTypeAdapter(DefaultType type) { + this.type = type; + } + + @Override + public String getId() { + return type.id(); + } + + @Override + public String getExtension() { + return type.getExtension(); + } + + @Override + public String getClassifier() { + return type.getClassifier() == null ? "" : type.getClassifier(); + } + + @Override + public Map getProperties() { + return type.getProperties(); + } } } diff --git a/compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/type/TypeDeriver.java b/compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/type/TypeDeriver.java new file mode 100644 index 000000000000..2120b4a58727 --- /dev/null +++ b/compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/type/TypeDeriver.java @@ -0,0 +1,147 @@ +/* + * 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.repository.internal.type; + +import java.util.ArrayDeque; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.maven.api.Type; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.ArtifactProperties; +import org.eclipse.aether.artifact.ArtifactType; +import org.eclipse.aether.artifact.ArtifactTypeRegistry; +import org.eclipse.aether.collection.DependencyGraphTransformationContext; +import org.eclipse.aether.collection.DependencyGraphTransformer; +import org.eclipse.aether.graph.DependencyNode; +import org.eclipse.aether.graph.DependencyVisitor; +import org.eclipse.aether.util.graph.visitor.DependencyGraphDumper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static java.util.Objects.requireNonNull; + +/** + * Type deriver, that handles special case of "processor" type: if a dependency node is of this type, all of its + * children need to be remapped to certain processor type as well, to end up on proper path type. + * + * @since 4.0.0 + * @deprecated since 4.0.0, this is internal detail of Maven. + */ +@Deprecated(since = "4.0.0") +public class TypeDeriver implements DependencyGraphTransformer { + private final Logger logger = LoggerFactory.getLogger(getClass()); + + @Override + public DependencyNode transformGraph(DependencyNode root, DependencyGraphTransformationContext context) { + if (logger.isDebugEnabled()) { + StringBuilder sb = new StringBuilder(); + root.accept(new DependencyGraphDumper( + l -> sb.append(l).append("\n"), + DependencyGraphDumper.defaultsWith( + List.of(DependencyGraphDumper.artifactProperties(List.of(ArtifactProperties.TYPE)))))); + logger.debug("TYPES: Before transform:\n {}", sb); + } + root.accept(new TypeDeriverVisitor(context.getSession().getArtifactTypeRegistry())); + if (logger.isDebugEnabled()) { + StringBuilder sb = new StringBuilder(); + root.accept(new DependencyGraphDumper( + l -> sb.append(l).append("\n"), + DependencyGraphDumper.defaultsWith( + List.of(DependencyGraphDumper.artifactProperties(List.of(ArtifactProperties.TYPE)))))); + logger.debug("TYPES: After transform:\n {}", sb); + } + return root; + } + + private static class TypeDeriverVisitor implements DependencyVisitor { + private final ArtifactTypeRegistry registry; + private final ArtifactType jar; + private final ArtifactType classpathJar; + private final ArtifactType modularJar; + private final ArtifactType processor; + private final ArtifactType classpathProcessor; + private final ArtifactType modularProcessor; + private final Set needsDerive; + private final ArrayDeque stack; + + private TypeDeriverVisitor(ArtifactTypeRegistry registry) { + this.registry = requireNonNull(registry); + this.jar = requireType(Type.JAR); + this.classpathJar = requireType(Type.CLASSPATH_JAR); + this.modularJar = requireType(Type.MODULAR_JAR); + this.processor = requireType(Type.PROCESSOR); + this.classpathProcessor = requireType(Type.CLASSPATH_PROCESSOR); + this.modularProcessor = requireType(Type.MODULAR_PROCESSOR); + this.needsDerive = Set.of(Type.PROCESSOR, Type.CLASSPATH_PROCESSOR, Type.MODULAR_PROCESSOR); + this.stack = new ArrayDeque<>(); + } + + private ArtifactType requireType(String id) { + return requireNonNull(registry.get(id), "Type " + id + " not found but is required"); + } + + @Override + public boolean visitEnter(DependencyNode node) { + ArtifactType currentType = jar; + if (node.getArtifact() != null) { + if (node.getArtifact().getProperties().containsKey(ArtifactProperties.TYPE)) { + currentType = registry.get(node.getArtifact() + .getProperty( + ArtifactProperties.TYPE, node.getArtifact().getExtension())); + if (currentType == null) { + currentType = jar; + } + } + if (!stack.isEmpty()) { + ArtifactType parentType = stack.peek(); + if (needsDerive.contains(parentType.getId())) { + Artifact artifact = node.getArtifact(); + Map props = new HashMap<>(artifact.getProperties()); + ArtifactType derived = derive(parentType, currentType); + props.putAll(derived.getProperties()); + node.setArtifact(artifact.setProperties(props)); + } + } + } + stack.push(currentType); + return true; + } + + @Override + public boolean visitLeave(DependencyNode node) { + stack.pop(); + return true; + } + + private ArtifactType derive(ArtifactType parentType, ArtifactType currentType) { + ArtifactType result = currentType; + if (jar.getId().equals(currentType.getId())) { + result = processor; + } else if (classpathJar.getId().equals(currentType.getId())) { + result = classpathProcessor; + } else if (modularJar.getId().equals(currentType.getId())) { + result = modularProcessor; + } + return result; + } + } +} diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java b/impl/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java index 541c8364ed8e..56e1566a01e5 100644 --- a/impl/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java +++ b/impl/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java @@ -40,6 +40,7 @@ import org.apache.maven.eventspy.internal.EventSpyDispatcher; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.impl.resolver.MavenSessionBuilderSupplier; +import org.apache.maven.impl.resolver.type.TypeRegistryAdapter; import org.apache.maven.internal.xml.XmlPlexusConfiguration; import org.apache.maven.model.ModelBase; import org.apache.maven.resolver.RepositorySystemSessionFactory; diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/DefaultArtifactDescriptorReader.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/DefaultArtifactDescriptorReader.java index 10c58e0fb8f7..4d0b65c594a5 100644 --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/DefaultArtifactDescriptorReader.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/DefaultArtifactDescriptorReader.java @@ -27,6 +27,7 @@ import java.util.Map; import java.util.Objects; +import org.apache.maven.api.Language; import org.apache.maven.api.RemoteRepository; import org.apache.maven.api.di.Inject; import org.apache.maven.api.di.Named; @@ -50,6 +51,7 @@ import org.apache.maven.impl.RequestTraceHelper; import org.apache.maven.impl.model.ModelProblemUtils; import org.apache.maven.impl.resolver.artifact.MavenArtifactProperties; +import org.apache.maven.impl.resolver.type.DefaultType; import org.eclipse.aether.RepositoryEvent; import org.eclipse.aether.RepositoryEvent.EventType; import org.eclipse.aether.RepositoryException; @@ -382,6 +384,10 @@ private void populateResult(InternalSession session, ArtifactDescriptorResult re private Dependency convert(org.apache.maven.api.model.Dependency dependency, ArtifactTypeRegistry stereotypes) { ArtifactType stereotype = stereotypes.get(dependency.getType()); + if (stereotype == null) { + stereotype = new DefaultType(dependency.getType(), Language.NONE, dependency.getType(), null, false) + .toArtifactType(); + } boolean system = dependency.getSystemPath() != null && !dependency.getSystemPath().isEmpty(); diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/MavenSessionBuilderSupplier.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/MavenSessionBuilderSupplier.java index 314595364431..f7b4c237dd7f 100644 --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/MavenSessionBuilderSupplier.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/MavenSessionBuilderSupplier.java @@ -26,6 +26,7 @@ import org.apache.maven.impl.resolver.scopes.Maven3ScopeManagerConfiguration; import org.apache.maven.impl.resolver.scopes.Maven4ScopeManagerConfiguration; import org.apache.maven.impl.resolver.type.DefaultTypeProvider; +import org.apache.maven.impl.resolver.type.TypeDeriver; import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.RepositorySystemSession.CloseableSession; import org.eclipse.aether.RepositorySystemSession.SessionBuilder; @@ -110,7 +111,8 @@ protected DependencyGraphTransformer getDependencyGraphTransformer() { new ConflictResolver( new ConfigurableVersionSelector(), new ManagedScopeSelector(getScopeManager()), new SimpleOptionalitySelector(), new ManagedScopeDeriver(getScopeManager())), - new ManagedDependencyContextRefiner(getScopeManager())); + new ManagedDependencyContextRefiner(getScopeManager()), + new TypeDeriver()); } /** @@ -124,7 +126,7 @@ protected DependencyGraphTransformer getDependencyGraphTransformer() { */ protected ArtifactTypeRegistry getArtifactTypeRegistry() { DefaultArtifactTypeRegistry stereotypes = new DefaultArtifactTypeRegistry(); - new DefaultTypeProvider().types().forEach(stereotypes::add); + new DefaultTypeProvider().types().forEach(t -> stereotypes.add(t.toArtifactType())); return stereotypes; } diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/type/DefaultType.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/type/DefaultType.java index 52ec4ba87fba..f9773f2a54e7 100644 --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/type/DefaultType.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/type/DefaultType.java @@ -36,11 +36,11 @@ import static java.util.Objects.requireNonNull; /** - * Default implementation of {@link Type} and Resolver {@link ArtifactType}. + * Default implementation of {@link Type} and adapter for Resolver {@link ArtifactType}. * * @since 4.0.0 */ -public class DefaultType implements Type, ArtifactType { +public class DefaultType implements Type { private final String id; private final Language language; private final String extension; @@ -78,11 +78,6 @@ public String id() { return id; } - @Override - public String getId() { - return id(); - } - @Override public Language getLanguage() { return language; @@ -103,14 +98,13 @@ public boolean isIncludesDependencies() { return this.includesDependencies; } - @Override - public Set getPathTypes() { - return this.pathTypes; + public Map getProperties() { + return properties; } @Override - public Map getProperties() { - return properties; + public Set getPathTypes() { + return this.pathTypes; } @Override @@ -124,4 +118,42 @@ public String toString() { + pathTypes + ", properties=" + properties + ']'; } + + /** + * Adapts this instance to Resolver {@link ArtifactType}. + *

+ * Note: one notable difference exists, the {@link #getClassifier()} method behavior. + * Once that harmonized, this adapting can go away. + */ + public ArtifactType toArtifactType() { + return new ArtifactTypeAdapter(this); + } + + private static class ArtifactTypeAdapter implements ArtifactType { + private final DefaultType type; + + private ArtifactTypeAdapter(DefaultType type) { + this.type = type; + } + + @Override + public String getId() { + return type.id(); + } + + @Override + public String getExtension() { + return type.getExtension(); + } + + @Override + public String getClassifier() { + return type.getClassifier() == null ? "" : type.getClassifier(); + } + + @Override + public Map getProperties() { + return type.getProperties(); + } + } } diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/type/DefaultTypeProvider.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/type/DefaultTypeProvider.java index 9140c0bb79ae..b0eead6840b1 100644 --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/type/DefaultTypeProvider.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/type/DefaultTypeProvider.java @@ -27,6 +27,9 @@ import org.apache.maven.api.di.Named; import org.apache.maven.api.spi.TypeProvider; +/** + * Maven 4 default {@link TypeProvider} implementation. + */ @Named public class DefaultTypeProvider implements TypeProvider { @SuppressWarnings({"rawtypes", "unchecked"}) diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/type/TypeDeriver.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/type/TypeDeriver.java new file mode 100644 index 000000000000..2a83ed83b110 --- /dev/null +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/type/TypeDeriver.java @@ -0,0 +1,153 @@ +/* + * 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.impl.resolver.type; + +import java.util.ArrayDeque; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.maven.api.Type; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.ArtifactProperties; +import org.eclipse.aether.artifact.ArtifactType; +import org.eclipse.aether.artifact.ArtifactTypeRegistry; +import org.eclipse.aether.collection.DependencyGraphTransformationContext; +import org.eclipse.aether.collection.DependencyGraphTransformer; +import org.eclipse.aether.graph.DependencyNode; +import org.eclipse.aether.graph.DependencyVisitor; +import org.eclipse.aether.util.graph.visitor.DependencyGraphDumper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static java.util.Objects.requireNonNull; + +/** + * Type deriver, that handles special cases of "processor" (annotation processor) node transitive dependencies: all + * children of "processor" type are "redirected" to corresponding processor subtypes: + *

    + *
  • {@code jar -> processor}
  • + *
  • {@code classpathJar -> classpathProcessor}
  • + *
  • {@code modularJar -> modularProcessor}
  • + *
+ * + * Maven 4 introduces new types to describe intent of dependencies, and the "processor" new type (and it's subtypes) + * will add processors and their dependencies to proper processor paths, as modern Java versions require. + * + * @since 4.0.0 + */ +public class TypeDeriver implements DependencyGraphTransformer { + private final Logger logger = LoggerFactory.getLogger(getClass()); + + @Override + public DependencyNode transformGraph(DependencyNode root, DependencyGraphTransformationContext context) { + if (logger.isDebugEnabled()) { + StringBuilder sb = new StringBuilder(); + root.accept(new DependencyGraphDumper( + l -> sb.append(l).append("\n"), + DependencyGraphDumper.defaultsWith( + List.of(DependencyGraphDumper.artifactProperties(List.of(ArtifactProperties.TYPE)))))); + logger.debug("TYPES: Before transform:\n {}", sb); + } + root.accept(new TypeDeriverVisitor(context.getSession().getArtifactTypeRegistry())); + if (logger.isDebugEnabled()) { + StringBuilder sb = new StringBuilder(); + root.accept(new DependencyGraphDumper( + l -> sb.append(l).append("\n"), + DependencyGraphDumper.defaultsWith( + List.of(DependencyGraphDumper.artifactProperties(List.of(ArtifactProperties.TYPE)))))); + logger.debug("TYPES: After transform:\n {}", sb); + } + return root; + } + + private static class TypeDeriverVisitor implements DependencyVisitor { + private final ArtifactTypeRegistry registry; + private final ArtifactType jar; + private final ArtifactType classpathJar; + private final ArtifactType modularJar; + private final ArtifactType processor; + private final ArtifactType classpathProcessor; + private final ArtifactType modularProcessor; + private final Set needsDerive; + private final ArrayDeque stack; + + private TypeDeriverVisitor(ArtifactTypeRegistry registry) { + this.registry = requireNonNull(registry); + this.jar = requireType(Type.JAR); + this.classpathJar = requireType(Type.CLASSPATH_JAR); + this.modularJar = requireType(Type.MODULAR_JAR); + this.processor = requireType(Type.PROCESSOR); + this.classpathProcessor = requireType(Type.CLASSPATH_PROCESSOR); + this.modularProcessor = requireType(Type.MODULAR_PROCESSOR); + this.needsDerive = Set.of(Type.PROCESSOR, Type.CLASSPATH_PROCESSOR, Type.MODULAR_PROCESSOR); + this.stack = new ArrayDeque<>(); + } + + private ArtifactType requireType(String id) { + return requireNonNull(registry.get(id), "Type " + id + " not found but is required"); + } + + @Override + public boolean visitEnter(DependencyNode node) { + ArtifactType currentType = jar; + if (node.getArtifact() != null) { + if (node.getArtifact().getProperties().containsKey(ArtifactProperties.TYPE)) { + currentType = registry.get(node.getArtifact() + .getProperty( + ArtifactProperties.TYPE, node.getArtifact().getExtension())); + if (currentType == null) { + currentType = jar; + } + } + if (!stack.isEmpty()) { + ArtifactType parentType = stack.peek(); + if (needsDerive.contains(parentType.getId())) { + Artifact artifact = node.getArtifact(); + Map props = new HashMap<>(artifact.getProperties()); + ArtifactType derived = derive(parentType, currentType); + props.putAll(derived.getProperties()); + node.setArtifact(artifact.setProperties(props)); + } + } + } + stack.push(currentType); + return true; + } + + @Override + public boolean visitLeave(DependencyNode node) { + stack.pop(); + return true; + } + + private ArtifactType derive(ArtifactType parentType, ArtifactType currentType) { + ArtifactType result = currentType; + if (jar.getId().equals(currentType.getId())) { + result = processor; + } else if (classpathJar.getId().equals(currentType.getId())) { + result = classpathProcessor; + } else if (modularJar.getId().equals(currentType.getId())) { + result = modularProcessor; + } + return result; + } + } +} diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/aether/TypeRegistryAdapter.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/type/TypeRegistryAdapter.java similarity index 70% rename from impl/maven-core/src/main/java/org/apache/maven/internal/aether/TypeRegistryAdapter.java rename to impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/type/TypeRegistryAdapter.java index b802e8a44c1f..31f2542dda9e 100644 --- a/impl/maven-core/src/main/java/org/apache/maven/internal/aether/TypeRegistryAdapter.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/type/TypeRegistryAdapter.java @@ -16,21 +16,23 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.maven.internal.aether; +package org.apache.maven.impl.resolver.type; import org.apache.maven.api.PathType; import org.apache.maven.api.Type; import org.apache.maven.api.services.TypeRegistry; -import org.apache.maven.impl.resolver.type.DefaultType; import org.eclipse.aether.artifact.ArtifactType; import org.eclipse.aether.artifact.ArtifactTypeRegistry; import static java.util.Objects.requireNonNull; -class TypeRegistryAdapter implements ArtifactTypeRegistry { +/** + * Adapter between Maven {@link TypeRegistry} and Resolver {@link ArtifactTypeRegistry}. + */ +public class TypeRegistryAdapter implements ArtifactTypeRegistry { private final TypeRegistry typeRegistry; - TypeRegistryAdapter(TypeRegistry typeRegistry) { + public TypeRegistryAdapter(TypeRegistry typeRegistry) { this.typeRegistry = requireNonNull(typeRegistry, "typeRegistry"); } @@ -41,11 +43,12 @@ public ArtifactType get(String typeId) { return artifactType; } return new DefaultType( - type.id(), - type.getLanguage(), - type.getExtension(), - type.getClassifier(), - type.isIncludesDependencies(), - type.getPathTypes().toArray(new PathType[0])); + type.id(), + type.getLanguage(), + type.getExtension(), + type.getClassifier(), + type.isIncludesDependencies(), + type.getPathTypes().toArray(new PathType[0])) + .toArtifactType(); } } diff --git a/impl/maven-impl/src/test/java/org/apache/maven/impl/resolver/type/TypeDeriverTest.java b/impl/maven-impl/src/test/java/org/apache/maven/impl/resolver/type/TypeDeriverTest.java new file mode 100644 index 000000000000..2426b4536cef --- /dev/null +++ b/impl/maven-impl/src/test/java/org/apache/maven/impl/resolver/type/TypeDeriverTest.java @@ -0,0 +1,156 @@ +/* + * 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.impl.resolver.type; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.apache.maven.api.Type; +import org.apache.maven.api.services.TypeRegistry; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.ArtifactProperties; +import org.eclipse.aether.artifact.ArtifactType; +import org.eclipse.aether.artifact.ArtifactTypeRegistry; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.graph.DefaultDependencyNode; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.graph.DependencyNode; +import org.eclipse.aether.internal.impl.collect.DefaultDependencyGraphTransformationContext; +import org.eclipse.aether.util.graph.visitor.DependencyGraphDumper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static java.util.Objects.requireNonNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class TypeDeriverTest { + private final ArtifactTypeRegistry typeRegistry = new TypeRegistryAdapter(new TypeRegistry() { + private final Map types = + new DefaultTypeProvider().types().stream().collect(Collectors.toMap(DefaultType::id, t -> t)); + + @Override + public Optional lookup(String id) { + return Optional.ofNullable(types.get(id)); + } + }); + private final TypeDeriver subject = new TypeDeriver(); + + @Test + void project() throws Exception { + RepositorySystemSession session = mock(RepositorySystemSession.class); + when(session.getArtifactTypeRegistry()).thenReturn(typeRegistry); + + ArtifactType jar = requireNonNull(typeRegistry.get(Type.JAR)); + ArtifactType modularJar = requireNonNull(typeRegistry.get(Type.MODULAR_JAR)); + ArtifactType processor = requireNonNull(typeRegistry.get(Type.PROCESSOR)); + + // root: "the project" + DefaultDependencyNode node = new DefaultDependencyNode(new DefaultArtifact("project:project:1.0", jar)); + + // direct: a plain JAR dependency + DefaultDependencyNode d1 = + new DefaultDependencyNode(new Dependency(new DefaultArtifact("deps:lib-a:1.0", jar), "compile")); + // direct: a plain JAR dependency + DefaultDependencyNode d2 = + new DefaultDependencyNode(new Dependency(new DefaultArtifact("deps:lib-b:1.0", jar), "compile")); + // direct: a processor dependency + DefaultDependencyNode d3 = new DefaultDependencyNode( + new Dependency(new DefaultArtifact("deps:processor:1.0", processor), "compile")); + + // transitive: processor depends on JAR + DefaultDependencyNode d31 = + new DefaultDependencyNode(new Dependency(new DefaultArtifact("tdeps:lib-a:1.0", jar), "compile")); + // transitive: processor depends on modularJar + DefaultDependencyNode d32 = new DefaultDependencyNode( + new Dependency(new DefaultArtifact("tdeps:lib-b:1.0", modularJar), "compile")); + d3.setChildren(List.of(d31, d32)); + + node.setChildren(List.of(d1, d2, d3)); + + node.accept(new DependencyGraphDumper( + System.out::println, + DependencyGraphDumper.defaultsWith( + List.of(DependencyGraphDumper.artifactProperties(List.of(ArtifactProperties.TYPE)))))); + + DependencyNode transformed = + subject.transformGraph(node, new DefaultDependencyGraphTransformationContext(session)); + + Assertions.assertNotNull(transformed); + transformed.accept(new DependencyGraphDumper( + System.out::println, + DependencyGraphDumper.defaultsWith( + List.of(DependencyGraphDumper.artifactProperties(List.of(ArtifactProperties.TYPE)))))); + + Assertions.assertEquals(Type.MODULAR_PROCESSOR, d32.getArtifact().getProperty(ArtifactProperties.TYPE, "")); + } + + @Test + void plugin() throws Exception { + RepositorySystemSession session = mock(RepositorySystemSession.class); + when(session.getArtifactTypeRegistry()).thenReturn(typeRegistry); + + ArtifactType mavenPlugin = requireNonNull(typeRegistry.get(Type.MAVEN_PLUGIN)); + ArtifactType jar = requireNonNull(typeRegistry.get(Type.JAR)); + ArtifactType classpathJar = requireNonNull(typeRegistry.get(Type.CLASSPATH_JAR)); + ArtifactType modularJar = requireNonNull(typeRegistry.get(Type.MODULAR_JAR)); + ArtifactType processor = requireNonNull(typeRegistry.get(Type.PROCESSOR)); + + // root: "the plugin" + DefaultDependencyNode node = new DefaultDependencyNode(new DefaultArtifact("plugin:plugin:1.0", mavenPlugin)); + + // direct: a plain JAR dependency + DefaultDependencyNode d1 = + new DefaultDependencyNode(new Dependency(new DefaultArtifact("deps:lib-a:1.0", jar), "compile")); + // direct: a plain JAR dependency + DefaultDependencyNode d2 = + new DefaultDependencyNode(new Dependency(new DefaultArtifact("deps:lib-b:1.0", jar), "compile")); + // direct: a processor dependency + DefaultDependencyNode d3 = new DefaultDependencyNode( + new Dependency(new DefaultArtifact("deps:processor:1.0", processor), "compile")); + + // transitive: processor depends on classpathJar + DefaultDependencyNode d31 = new DefaultDependencyNode( + new Dependency(new DefaultArtifact("tdeps:lib-a:1.0", classpathJar), "compile")); + // transitive: processor depends on modularJar + DefaultDependencyNode d32 = new DefaultDependencyNode( + new Dependency(new DefaultArtifact("tdeps:lib-b:1.0", modularJar), "compile")); + d3.setChildren(List.of(d31, d32)); + + node.setChildren(List.of(d1, d2, d3)); + + node.accept(new DependencyGraphDumper( + System.out::println, + DependencyGraphDumper.defaultsWith( + List.of(DependencyGraphDumper.artifactProperties(List.of(ArtifactProperties.TYPE)))))); + + DependencyNode transformed = + subject.transformGraph(node, new DefaultDependencyGraphTransformationContext(session)); + + Assertions.assertNotNull(transformed); + transformed.accept(new DependencyGraphDumper( + System.out::println, + DependencyGraphDumper.defaultsWith( + List.of(DependencyGraphDumper.artifactProperties(List.of(ArtifactProperties.TYPE)))))); + + Assertions.assertEquals(Type.MODULAR_PROCESSOR, d32.getArtifact().getProperty(ArtifactProperties.TYPE, "")); + } +}