Skip to content

Commit 46cf946

Browse files
authored
Type derive (simpler) (#11380)
Instead to "smear" this feature across Maven and Resolver classes, for start let's keep it "confined" with single class: the TypeDeriver. Later we can see where to go further with it. This PR also includes bugfix, where Maven `DefaultType` implements `ArtifactType`, while in reality it does not (violates contract by returning `null` when no classifier present).
1 parent 166178e commit 46cf946

File tree

12 files changed

+568
-36
lines changed

12 files changed

+568
-36
lines changed

compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/ArtifactDescriptorReaderDelegate.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ public void populateResult(RepositorySystemSession session, ArtifactDescriptorRe
9696
private Dependency convert(org.apache.maven.model.Dependency dependency, ArtifactTypeRegistry stereotypes) {
9797
ArtifactType stereotype = stereotypes.get(dependency.getType());
9898
if (stereotype == null) {
99-
stereotype = new DefaultType(dependency.getType(), Language.NONE, dependency.getType(), null, false);
99+
stereotype = new DefaultType(dependency.getType(), Language.NONE, dependency.getType(), null, false)
100+
.toArtifactType();
100101
}
101102

102103
boolean system = dependency.getSystemPath() != null

compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenSessionBuilderSupplier.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.apache.maven.repository.internal.artifact.FatArtifactTraverser;
2626
import org.apache.maven.repository.internal.scopes.Maven4ScopeManagerConfiguration;
2727
import org.apache.maven.repository.internal.type.DefaultTypeProvider;
28+
import org.apache.maven.repository.internal.type.TypeDeriver;
2829
import org.eclipse.aether.RepositorySystem;
2930
import org.eclipse.aether.RepositorySystemSession.CloseableSession;
3031
import org.eclipse.aether.RepositorySystemSession.SessionBuilder;
@@ -114,7 +115,8 @@ protected DependencyGraphTransformer getDependencyGraphTransformer() {
114115
new ConflictResolver(
115116
new ConfigurableVersionSelector(), new ManagedScopeSelector(getScopeManager()),
116117
new SimpleOptionalitySelector(), new ManagedScopeDeriver(getScopeManager())),
117-
new ManagedDependencyContextRefiner(getScopeManager()));
118+
new ManagedDependencyContextRefiner(getScopeManager()),
119+
new TypeDeriver());
118120
}
119121

120122
/**
@@ -128,7 +130,7 @@ protected DependencyGraphTransformer getDependencyGraphTransformer() {
128130
*/
129131
protected ArtifactTypeRegistry getArtifactTypeRegistry() {
130132
DefaultArtifactTypeRegistry stereotypes = new DefaultArtifactTypeRegistry();
131-
new DefaultTypeProvider().types().forEach(stereotypes::add);
133+
new DefaultTypeProvider().types().forEach(t -> stereotypes.add(t.toArtifactType()));
132134
return stereotypes;
133135
}
134136

compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/type/DefaultType.java

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
* @deprecated since 4.0.0, use {@code maven-api-impl} jar instead
4343
*/
4444
@Deprecated(since = "4.0.0")
45-
public class DefaultType implements Type, ArtifactType {
45+
public class DefaultType implements Type {
4646
private final String id;
4747
private final Language language;
4848
private final String extension;
@@ -80,11 +80,6 @@ public String id() {
8080
return id;
8181
}
8282

83-
@Override
84-
public String getId() {
85-
return id();
86-
}
87-
8883
@Override
8984
public Language getLanguage() {
9085
return language;
@@ -105,13 +100,44 @@ public boolean isIncludesDependencies() {
105100
return this.includesDependencies;
106101
}
107102

103+
public Map<String, String> getProperties() {
104+
return properties;
105+
}
106+
108107
@Override
109108
public Set<PathType> getPathTypes() {
110109
return this.pathTypes;
111110
}
112111

113-
@Override
114-
public Map<String, String> getProperties() {
115-
return properties;
112+
public ArtifactType toArtifactType() {
113+
return new ArtifactTypeAdapter(this);
114+
}
115+
116+
private static class ArtifactTypeAdapter implements ArtifactType {
117+
private final DefaultType type;
118+
119+
private ArtifactTypeAdapter(DefaultType type) {
120+
this.type = type;
121+
}
122+
123+
@Override
124+
public String getId() {
125+
return type.id();
126+
}
127+
128+
@Override
129+
public String getExtension() {
130+
return type.getExtension();
131+
}
132+
133+
@Override
134+
public String getClassifier() {
135+
return type.getClassifier() == null ? "" : type.getClassifier();
136+
}
137+
138+
@Override
139+
public Map<String, String> getProperties() {
140+
return type.getProperties();
141+
}
116142
}
117143
}
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.maven.repository.internal.type;
20+
21+
import java.util.ArrayDeque;
22+
import java.util.HashMap;
23+
import java.util.List;
24+
import java.util.Map;
25+
import java.util.Set;
26+
27+
import org.apache.maven.api.Type;
28+
import org.eclipse.aether.artifact.Artifact;
29+
import org.eclipse.aether.artifact.ArtifactProperties;
30+
import org.eclipse.aether.artifact.ArtifactType;
31+
import org.eclipse.aether.artifact.ArtifactTypeRegistry;
32+
import org.eclipse.aether.collection.DependencyGraphTransformationContext;
33+
import org.eclipse.aether.collection.DependencyGraphTransformer;
34+
import org.eclipse.aether.graph.DependencyNode;
35+
import org.eclipse.aether.graph.DependencyVisitor;
36+
import org.eclipse.aether.util.graph.visitor.DependencyGraphDumper;
37+
import org.slf4j.Logger;
38+
import org.slf4j.LoggerFactory;
39+
40+
import static java.util.Objects.requireNonNull;
41+
42+
/**
43+
* Type deriver, that handles special case of "processor" type: if a dependency node is of this type, all of its
44+
* children need to be remapped to certain processor type as well, to end up on proper path type.
45+
*
46+
* @since 4.0.0
47+
* @deprecated since 4.0.0, this is internal detail of Maven.
48+
*/
49+
@Deprecated(since = "4.0.0")
50+
public class TypeDeriver implements DependencyGraphTransformer {
51+
private final Logger logger = LoggerFactory.getLogger(getClass());
52+
53+
@Override
54+
public DependencyNode transformGraph(DependencyNode root, DependencyGraphTransformationContext context) {
55+
if (logger.isDebugEnabled()) {
56+
StringBuilder sb = new StringBuilder();
57+
root.accept(new DependencyGraphDumper(
58+
l -> sb.append(l).append("\n"),
59+
DependencyGraphDumper.defaultsWith(
60+
List.of(DependencyGraphDumper.artifactProperties(List.of(ArtifactProperties.TYPE))))));
61+
logger.debug("TYPES: Before transform:\n {}", sb);
62+
}
63+
root.accept(new TypeDeriverVisitor(context.getSession().getArtifactTypeRegistry()));
64+
if (logger.isDebugEnabled()) {
65+
StringBuilder sb = new StringBuilder();
66+
root.accept(new DependencyGraphDumper(
67+
l -> sb.append(l).append("\n"),
68+
DependencyGraphDumper.defaultsWith(
69+
List.of(DependencyGraphDumper.artifactProperties(List.of(ArtifactProperties.TYPE))))));
70+
logger.debug("TYPES: After transform:\n {}", sb);
71+
}
72+
return root;
73+
}
74+
75+
private static class TypeDeriverVisitor implements DependencyVisitor {
76+
private final ArtifactTypeRegistry registry;
77+
private final ArtifactType jar;
78+
private final ArtifactType classpathJar;
79+
private final ArtifactType modularJar;
80+
private final ArtifactType processor;
81+
private final ArtifactType classpathProcessor;
82+
private final ArtifactType modularProcessor;
83+
private final Set<String> needsDerive;
84+
private final ArrayDeque<ArtifactType> stack;
85+
86+
private TypeDeriverVisitor(ArtifactTypeRegistry registry) {
87+
this.registry = requireNonNull(registry);
88+
this.jar = requireType(Type.JAR);
89+
this.classpathJar = requireType(Type.CLASSPATH_JAR);
90+
this.modularJar = requireType(Type.MODULAR_JAR);
91+
this.processor = requireType(Type.PROCESSOR);
92+
this.classpathProcessor = requireType(Type.CLASSPATH_PROCESSOR);
93+
this.modularProcessor = requireType(Type.MODULAR_PROCESSOR);
94+
this.needsDerive = Set.of(Type.PROCESSOR, Type.CLASSPATH_PROCESSOR, Type.MODULAR_PROCESSOR);
95+
this.stack = new ArrayDeque<>();
96+
}
97+
98+
private ArtifactType requireType(String id) {
99+
return requireNonNull(registry.get(id), "Type " + id + " not found but is required");
100+
}
101+
102+
@Override
103+
public boolean visitEnter(DependencyNode node) {
104+
ArtifactType currentType = jar;
105+
if (node.getArtifact() != null) {
106+
if (node.getArtifact().getProperties().containsKey(ArtifactProperties.TYPE)) {
107+
currentType = registry.get(node.getArtifact()
108+
.getProperty(
109+
ArtifactProperties.TYPE, node.getArtifact().getExtension()));
110+
if (currentType == null) {
111+
currentType = jar;
112+
}
113+
}
114+
if (!stack.isEmpty()) {
115+
ArtifactType parentType = stack.peek();
116+
if (needsDerive.contains(parentType.getId())) {
117+
Artifact artifact = node.getArtifact();
118+
Map<String, String> props = new HashMap<>(artifact.getProperties());
119+
ArtifactType derived = derive(parentType, currentType);
120+
props.putAll(derived.getProperties());
121+
node.setArtifact(artifact.setProperties(props));
122+
}
123+
}
124+
}
125+
stack.push(currentType);
126+
return true;
127+
}
128+
129+
@Override
130+
public boolean visitLeave(DependencyNode node) {
131+
stack.pop();
132+
return true;
133+
}
134+
135+
private ArtifactType derive(ArtifactType parentType, ArtifactType currentType) {
136+
ArtifactType result = currentType;
137+
if (jar.getId().equals(currentType.getId())) {
138+
result = processor;
139+
} else if (classpathJar.getId().equals(currentType.getId())) {
140+
result = classpathProcessor;
141+
} else if (modularJar.getId().equals(currentType.getId())) {
142+
result = modularProcessor;
143+
}
144+
return result;
145+
}
146+
}
147+
}

impl/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.apache.maven.eventspy.internal.EventSpyDispatcher;
4141
import org.apache.maven.execution.MavenExecutionRequest;
4242
import org.apache.maven.impl.resolver.MavenSessionBuilderSupplier;
43+
import org.apache.maven.impl.resolver.type.TypeRegistryAdapter;
4344
import org.apache.maven.internal.xml.XmlPlexusConfiguration;
4445
import org.apache.maven.model.ModelBase;
4546
import org.apache.maven.resolver.RepositorySystemSessionFactory;

impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/DefaultArtifactDescriptorReader.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.Map;
2828
import java.util.Objects;
2929

30+
import org.apache.maven.api.Language;
3031
import org.apache.maven.api.RemoteRepository;
3132
import org.apache.maven.api.di.Inject;
3233
import org.apache.maven.api.di.Named;
@@ -50,6 +51,7 @@
5051
import org.apache.maven.impl.RequestTraceHelper;
5152
import org.apache.maven.impl.model.ModelProblemUtils;
5253
import org.apache.maven.impl.resolver.artifact.MavenArtifactProperties;
54+
import org.apache.maven.impl.resolver.type.DefaultType;
5355
import org.eclipse.aether.RepositoryEvent;
5456
import org.eclipse.aether.RepositoryEvent.EventType;
5557
import org.eclipse.aether.RepositoryException;
@@ -382,6 +384,10 @@ private void populateResult(InternalSession session, ArtifactDescriptorResult re
382384

383385
private Dependency convert(org.apache.maven.api.model.Dependency dependency, ArtifactTypeRegistry stereotypes) {
384386
ArtifactType stereotype = stereotypes.get(dependency.getType());
387+
if (stereotype == null) {
388+
stereotype = new DefaultType(dependency.getType(), Language.NONE, dependency.getType(), null, false)
389+
.toArtifactType();
390+
}
385391

386392
boolean system = dependency.getSystemPath() != null
387393
&& !dependency.getSystemPath().isEmpty();

impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/MavenSessionBuilderSupplier.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.apache.maven.impl.resolver.scopes.Maven3ScopeManagerConfiguration;
2727
import org.apache.maven.impl.resolver.scopes.Maven4ScopeManagerConfiguration;
2828
import org.apache.maven.impl.resolver.type.DefaultTypeProvider;
29+
import org.apache.maven.impl.resolver.type.TypeDeriver;
2930
import org.eclipse.aether.RepositorySystem;
3031
import org.eclipse.aether.RepositorySystemSession.CloseableSession;
3132
import org.eclipse.aether.RepositorySystemSession.SessionBuilder;
@@ -110,7 +111,8 @@ protected DependencyGraphTransformer getDependencyGraphTransformer() {
110111
new ConflictResolver(
111112
new ConfigurableVersionSelector(), new ManagedScopeSelector(getScopeManager()),
112113
new SimpleOptionalitySelector(), new ManagedScopeDeriver(getScopeManager())),
113-
new ManagedDependencyContextRefiner(getScopeManager()));
114+
new ManagedDependencyContextRefiner(getScopeManager()),
115+
new TypeDeriver());
114116
}
115117

116118
/**
@@ -124,7 +126,7 @@ protected DependencyGraphTransformer getDependencyGraphTransformer() {
124126
*/
125127
protected ArtifactTypeRegistry getArtifactTypeRegistry() {
126128
DefaultArtifactTypeRegistry stereotypes = new DefaultArtifactTypeRegistry();
127-
new DefaultTypeProvider().types().forEach(stereotypes::add);
129+
new DefaultTypeProvider().types().forEach(t -> stereotypes.add(t.toArtifactType()));
128130
return stereotypes;
129131
}
130132

0 commit comments

Comments
 (0)