[MNG-8015] Control the type of path where each dependency can be placed#1378
[MNG-8015] Control the type of path where each dependency can be placed#1378desruisseaux wants to merge 32 commits intoapache:masterfrom
Conversation
- Refactor some `MavenProject` methods for reducing code duplication. Their behavior should be as before. - Add `@Override` annotations.
Refactor `DependencyProperties` as a type-safe map of objects instead of a map of strings. This is in anticipation for the introduction of a `PathType` property in future commits. The type of property values is specified by `DependencyProperties.Key.valueType()`.
- Add a `PathType` enumeration (actually a class for making the enumeration extensible). - Add a `DependencyResolverResult.getDispatchedPath()` method, unimplemented for now. - Move `DefaultDependencyResolverResult` as a top-level class for further developments. - Some changes in `DefaultDependencyResolver` in anticipation for further developments.
- Add a `DependencyProperties.PATH_TYPES` property. - Deprecate `DependencyProperties.FLAG_CLASS_PATH_CONSTITUENT` and `isAddedToClasspath()` methods. - Add documentation for explaining better the context-sensitive interpretation of path constituents.
- Added implementation of `DependencyResolverResult.getDispatchedPaths()`. - The code in `DefaultDependencyResolver` has been refactored, but the new code should be equivalent to the previous code for the collections that existed before this commit. The significant changes are the new code for computing the new `dispatchedPaths` map.
Add types: - Type.MODULAR_JAR: unconditionally on the module-path. - Type.CLASSPATH_JAR: unconditionally on the class-path. - And more.
|
CI build has been successful on Java 17 and 21, but failed on Java 11 because of the use of the |
|
If am not mistaken, this feature is available since Java 16? Given master is still Java 8 (build time requirement is same I think)... I'd stick with it. So please use Java 8 conformant javadoc... |
maven-artifact/src/main/java/org/apache/maven/artifact/handler/ArtifactHandler.java
Show resolved
Hide resolved
api/maven-api-core/src/main/java/org/apache/maven/api/DependencyProperties.java
Outdated
Show resolved
Hide resolved
api/maven-api-core/src/main/java/org/apache/maven/api/DependencyProperties.java
Outdated
Show resolved
Hide resolved
api/maven-api-core/src/main/java/org/apache/maven/api/DependencyProperties.java
Outdated
Show resolved
Hide resolved
api/maven-api-core/src/main/java/org/apache/maven/api/DependencyProperties.java
Outdated
Show resolved
Hide resolved
api/maven-api-core/src/main/java/org/apache/maven/api/DependencyProperties.java
Outdated
Show resolved
Hide resolved
| * @see String#intern() | ||
| */ | ||
| @SuppressWarnings("unchecked") | ||
| public Key<V> intern() { |
There was a problem hiding this comment.
I don't think the whole intern thing is needed at all.
I would suppose all references to Keys will be done using DependencyProperties.XXX, so I don't see a good use case for users to create duplicate instances.
There was a problem hiding this comment.
The intern() mechanism is for the org.apache.maven.internal.impl.DefaultDependency constructor. That constructor takes in argument an instance of org.eclipse.aether.graph.Dependency and copies its properties. But the Eclipse's properties are <String, String> entries, so the String keys need to be converted to DependencyProperties.Key instances. This is the purpose of DependencyProperties.Key.forName(…), which provides String → Key conversions. The intern() stuff is a side-effect of the need to support that conversion. It could be removed if DefaultDependency wasn't merely a wrapper for org.eclipse.aether.graph.Dependency.
There was a problem hiding this comment.
Do we need extensibility here ? Or could we use an enum ? @cstamas ?
There was a problem hiding this comment.
Even if we restrict the scope to standard Java tools, the extensibility is still needed for supporting the --patch-module option, which can be seen as class-paths specific to each module. So a new enumeration value needs to be created (but not internalized) for each module to patch. An alternative design would be to make JavaPathType an Enum and support the --path-module option in a separated implementation of PathType. Whether it would make the API simpler or not is unclear to me.
There was a problem hiding this comment.
We need extensibility, as tomorrow somebody could come up with custom package that would need some special handling... story is same as in Mave3 and ArtifactHandlers... they have to be extensible, that is the whole point.
There was a problem hiding this comment.
Would it make sense to remove the intern() method and redefine forName as:
@Nullable
public static <T> Key<T> forName(@Nonnull String name, @Nullable Class<T> defaultType, boolean intern) {
Key<?> key;
synchronized (INTERNS) {
key = INTERNS.get(name);
if (defaultType != null) {
if (key == null) {
key = new Key<>(name, defaultType);
if (intern) {
INTERNS.put(name, key);
}
} else if (key.valueType() != defaultType && intern) {
throw new IllegalStateException("Key " + name + " already exists for a different class of values.");
}
}
}
return (Key) key;
}
The constructor could be made private, so that the only entry point is the above method.
There was a problem hiding this comment.
Yes, we can do that.
There was a problem hiding this comment.
Actually the above code does not fit exactly the DefaultDependencies needs, because it forces the key to be of the type specified by defaultType. This is the correct thing to do for above method because its return value is Key<T>. However, DefaultDependencies needs to first check for a key with whatever type an existing key may have. So we cannot escape the need to have two methods, one with return value Key<?> and another one with return value Key<V>.
I will replace the existing forName method with a simpler one like below, checking only for existing key:
Optional<Key<?>> forName(String);
As a replacement of intern(), I considered adding the following method:
<V> Key<V> createAndCache(String name, Class<V> valueType);
However it would not work if some plugin wants to define its own subclass of Key, while intern() allows this flexibility. I'm not sure if it is a flexibility worth to have however.
api/maven-api-core/src/main/java/org/apache/maven/api/JavaPathType.java
Outdated
Show resolved
Hide resolved
api/maven-api-core/src/main/java/org/apache/maven/api/PathType.java
Outdated
Show resolved
Hide resolved
api/maven-api-core/src/main/java/org/apache/maven/api/DependencyProperties.java
Outdated
Show resolved
Hide resolved
api/maven-api-core/src/main/java/org/apache/maven/api/DependencyProperties.java
Outdated
Show resolved
Hide resolved
api/maven-api-core/src/main/java/org/apache/maven/api/Type.java
Outdated
Show resolved
Hide resolved
api/maven-api-core/src/main/java/org/apache/maven/api/DependencyProperties.java
Outdated
Show resolved
Hide resolved
…ges in method signatures,
removal of {@return} Javadoc tags for compatibility with older compilers.
….isAddedToClassPath()` method.
…ting that interface, and the case of the `--patch-module` option an inner class named `Modular` also implementing the `PathType` interface. The latter class generalizes `--path-module` support to other kinds of module-dependent option if some appear in the future.
|
Applied most of above comments (still thinking for a solution about the two remaining ones). The build continues to fail on Java 11, again because of Javadoc, but this new error is more annoying. The error message is "Header used out of sequence: So it is impossible (as far as I know) to have a code compilable on both Java 11 and Java 17 when HTML headers are used in Javadoc and Javadoc checks are enabled. If compilation or Javadoc generation passes on one, it fails on the other. Workaround can be one of the following:
Which approach should we take? The last one would be the one allowing most gradual transition to newest Java versions (by allowing the use of most recent conventions right now) while preserving compatibility. |
…pendencyProperties.PATH_TYPES`.
…ompilation issues on Java 11. This commit may be reverted in the future if Java 17 become a minimal requirement for compilation.
- Refactor some `MavenProject` methods for reducing code duplication. Their behavior should be as before. - Add `@Override` annotations.
# Conflicts: # api/maven-api-core/src/main/java/org/apache/maven/api/JavaPathType.java # api/maven-api-core/src/main/java/org/apache/maven/api/Packaging.java # api/maven-api-core/src/main/java/org/apache/maven/api/PathType.java # api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java # maven-core/src/main/java/org/apache/maven/artifact/handler/manager/DefaultArtifactHandlerManager.java # maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java # maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyProperties.java # maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java # maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolverResult.java # maven-core/src/main/java/org/apache/maven/internal/impl/DefaultType.java # maven-core/src/main/java/org/apache/maven/internal/impl/DefaultTypeRegistry.java # maven-core/src/main/java/org/apache/maven/internal/impl/PathModularizationCache.java # maven-core/src/main/java/org/apache/maven/internal/impl/types/ClasspathJarTypeProvider.java # maven-core/src/main/java/org/apache/maven/internal/impl/types/EjbClientTypeProvider.java # maven-core/src/main/java/org/apache/maven/internal/impl/types/EjbTypeProvider.java # maven-core/src/main/java/org/apache/maven/internal/impl/types/JarTypeProvider.java # maven-core/src/main/java/org/apache/maven/internal/impl/types/JavadocTypeProvider.java # maven-core/src/main/java/org/apache/maven/internal/impl/types/MavenPluginTypeProvider.java # maven-core/src/main/java/org/apache/maven/internal/impl/types/ModularJarTypeProvider.java # maven-core/src/main/java/org/apache/maven/internal/impl/types/TestJarTypeProvider.java
|
@desruisseaux I've pushed a small rework of this PR on top of #1391 on my fork. The main change is that I removed the |
|
Thanks, it look good to me. I will try to add a few JUnit tests today or tomorrow. |
Note: contains some "todo" about aspects that may need clarification.
…ce method and expand an existing test case.
However, those question still need to be answered.
|
Added Javadoc on shortcut methods in Added a convenience method: @Nonnull
Map<PathType, List<Path>> resolveDependencies(
@Nonnull DependencyCoordinate dependencyCoordinate,
@Nonnull PathScope scope,
@Nonnull Collection<PathType> desiredTypes);Expanded an existing test case: after fetching the dependency paths, fetch again the same dependency paths but this time dispatched by type.
Note: A test if failing in the "Maven Core ITs suite" module: I don't know what is happening here. A search for |
|
@desruisseaux fwiw, I've merge master branch into this branch at https://github.com/apache/maven/tree/explicit-module-path |
|
Thanks. Closing this pull request in favour of #1401 then. |
|
Resolve #9864 |
Introduces new API described in JIRA issue MNG-8015:
PathTypeenumeration-like class.JavaPathTypesubtype with values such asMODULES,CLASSES,DOCLET,TAGLETS, etc.PATH_TYPESdependency property key (as a side-effect, theDependencyPropertiesAPI is modified for making it type-safe).DependencyResolverRequestAPI for allowing plugins to specify thePathTypethat the plugin wants.DependencyResolverResult.getDispatchedPath()method for getting the result: the paths to dependencies for each path type.Open issues
Commit 9c5e9ff (which add implementation) introduces a dependency to Java 9 or later (the
ModuleDescriptorclass). If Maven 4 decides to stay executable on Java 8, this part will need to be refactored in a multi-version JAR file. If Maven 4 decides to require Java 9 or later, thesourceandtargetoptions in thepom.xmlfile should be replaced by areleaseoption.The implementation has no JUnit tests yet, so it may contain bug. We may want to write JUnit tests before to integrate this pull request. Waiting to see if a discussion causes a modification of this proposal before to write tests.