This is an automated email from the ASF dual-hosted git repository.
cstamas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-resolver.git
The following commit(s) were added to refs/heads/master by this push:
new 0320c866 [MRESOLVER-289][MRESOLVER-526] Reuse relevant bits from
Eclipse Aether wiki contents (#496)
0320c866 is described below
commit 0320c866bdcfcb6f4ca60286f6d1e3f04411721f
Author: Tamas Cservenak <[email protected]>
AuthorDate: Thu May 23 13:21:30 2024 +0200
[MRESOLVER-289][MRESOLVER-526] Reuse relevant bits from Eclipse Aether wiki
contents (#496)
With applied updates for Resolver 2.0.
Reworked side menu:
* Overview (as before)
* Guides (added)
* Reference (added)
* See also (as before)
Content from EOLd Eclipse wiki https://wiki.eclipse.org/Aether The dump is
attached to MRESOLVER-526 but is filtered (outdated pages omitted) as explained
on issue.
---
https://issues.apache.org/jira/browse/MRESOLVER-526
https://issues.apache.org/jira/browse/MRESOLVER-289
---
src/site/markdown/about-checksums.md | 2 +-
.../creating-a-repository-system-session.md | 61 ++++++++++++
src/site/markdown/dependency-graph.md | 82 ++++++++++++++++
src/site/markdown/resolving-dependencies.md | 62 ++++++++++++
.../markdown/transitive-dependency-resolution.md | 88 +++++++++++++++++
.../markdown/using-resolver-in-maven-plugins.md | 106 +++++++++++++++++++++
src/site/markdown/what-is-resolver.md | 64 +++++++++++++
src/site/site.xml | 26 +++--
8 files changed, 481 insertions(+), 10 deletions(-)
diff --git a/src/site/markdown/about-checksums.md
b/src/site/markdown/about-checksums.md
index 58c60e2d..aec7808c 100644
--- a/src/site/markdown/about-checksums.md
+++ b/src/site/markdown/about-checksums.md
@@ -1,4 +1,4 @@
-# About Checksums
+# Checksums
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
diff --git a/src/site/markdown/creating-a-repository-system-session.md
b/src/site/markdown/creating-a-repository-system-session.md
new file mode 100644
index 00000000..8bf604c8
--- /dev/null
+++ b/src/site/markdown/creating-a-repository-system-session.md
@@ -0,0 +1,61 @@
+# Creating a RepositorySystemSession
+<!--
+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.
+-->
+
+Resolver (former Aether) and its components are designed to be stateless and
as such all
+configuration/state has to be passed into the methods. When one makes
+multiple requests to resolve dependencies, a fair amount of settings
+usually remains the same across these method calls, like the proxy
+settings or the path to the local repository. Those settings that tend
+to be the same for an entire usage session of the repository system are
+represented by an instance of
+`org.eclipse.aether.RepositorySystemSession`. Using classes from
+`maven-resolver-supplier`, creating such a session that mimics Maven's
+setup can be done like this:
+
+```java
+import org.eclipse.aether.supplier.RepositorySystemSupplier;
+
+...
+ private static RepositorySystemSession newSession( RepositorySystem system
)
+ {
+ RepositorySystemSession.SessionBuilder sessionBuilder =
SessionBuilderSupplier.get();
+
+ LocalRepository localRepo = new LocalRepository( "target/local-repo" );
+ sessionBuilder.setLocalRepositoryManager(
system.newLocalRepositoryManager( session, localRepo ) );
+
+ return session.build();
+ }
+```
+
+As you see, the only setting that must be specified is the local
+repository, other settings are initialized with default values. Please
+have a look at the API docs for `RepositorySystemSession.SessionBuilder` to
+learn about all the other things you can configure for a session.
+
+In case of Maven plugin, or when code runs embedded in Maven, the session
+is already created for you, but you can still "derive" using copy constructor
+of `DefaultRepositorySystemSession` if some session alteration is needed.
+
+If you seek a closer cooperation with [Apache
+Maven](http://maven.apache.org/) and want to read configuration from the
+user's `settings.xml`, you should have a look at the library
+[MIMA](https://github.com/maveniverse/mima) which provides the necessary
+bits. Please direct any questions regarding usage of that library to the
+Maven mailing list.
diff --git a/src/site/markdown/dependency-graph.md
b/src/site/markdown/dependency-graph.md
new file mode 100644
index 00000000..c97c4789
--- /dev/null
+++ b/src/site/markdown/dependency-graph.md
@@ -0,0 +1,82 @@
+# Dependency Graph
+<!--
+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.
+-->
+
+When resolving transitive dependencies, Resolver (former Aether) constructs a
*dependency
+graph* consisting of `DependencyNode` instances where each node
+represents a dependency and its direct dependencies are represented as
+child nodes. During early stages of the resolution process, there are
+usually duplicate dependencies or even cycles in the graph as sketched
+below:
+
+```
+ root
+ / \
+ / \
+a:1 b:1 <--+
+ \ / \ |
+ \ / \ |
+ c:1 a:2 |
+ | |
+ +---------+
+```
+
+Once this dependency graph has undergone conflict resolution, i.e.
+duplicate dependencies have been removed, one actually has a *dependency
+tree*. Taking the previous example, the tree might look like this:
+
+```
+ root
+ / \
+ / \
+a:1 b:1
+ |
+ |
+c:1
+```
+
+The dependency tree is a handy data structure to get the complete set of
+artifacts one would need to form a classpath etc. as a simple recursive
+traversal is sufficient to gather the relevant dependencies.
+
+## Troubleshooting a Dependency Graph
+
+The dependency tree provides a compact and basic means to end users to
+understand why/how a given artifact ended up among the dependencies. But
+as the examples above illustrate, the dependency tree misses some
+information compared to the dependency graph. For instance, the tree
+does not indicate that `b:1` also depends on `c:1`. To help
+troubleshooting complex dependency graphs, some configuration properties
+exist to keep useful data in the dependency graph returned by
+`RepositorySystem.collectDependencies()`.
+
+For instance, the configuration property
+`ConflictResolver.CONFIG_PROP_VERBOSE` can be enabled to produce a graph
+similar to m2e's dependency hierarchy view where conflicting nodes are
+retained. This gives end users a better understanding of all the paths
+that pull in a given dependency.
+
+The configuration property `DependencyManagerUtils.CONFIG_PROP_VERBOSE`
+can be enabled to record the attributes of a dependency before they were
+updated due to dependency management. This helps end users to understand
+why one version of a dependency and not the other is found in the graph
+or why a dependency ended up in a given scope.
+
+Please see the API docs for said configuration properties for details
+regarding their effects and ways to access the additional data.
diff --git a/src/site/markdown/resolving-dependencies.md
b/src/site/markdown/resolving-dependencies.md
new file mode 100644
index 00000000..b53ad646
--- /dev/null
+++ b/src/site/markdown/resolving-dependencies.md
@@ -0,0 +1,62 @@
+# Resolving Dependencies
+<!--
+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.
+-->
+
+Extending the code snippets from [Creating a
RepositorySystemSession](creating-a-repository-system-session.html), the
snippet below demonstrates
+how to actually resolve the transitive dependencies of say
+`org.apache.maven:maven-core:3.9.6` and to dump the result as a class
+path to the console:
+
+```java
+ public static void main( String[] args )
+ throws Exception
+ {
+ RepositorySystem repoSystem = newRepositorySystem();
+
+ RepositorySystemSession session = newSession( repoSystem );
+
+ Dependency dependency =
+ new Dependency( new DefaultArtifact(
"org.apache.maven:maven-core:3.9.6" ), "compile" );
+ RemoteRepository central = new RemoteRepository.Builder( "central",
"default", "https://repo.maven.apache.org/maven2/" ).build();
+
+ CollectRequest collectRequest = new CollectRequest();
+ collectRequest.setRoot( dependency );
+ collectRequest.addRepository( central );
+ DependencyNode node = repoSystem.collectDependencies( session,
collectRequest ).getRoot();
+
+ DependencyRequest dependencyRequest = new DependencyRequest();
+ dependencyRequest.setRoot( node );
+
+ repoSystem.resolveDependencies( session, dependencyRequest );
+
+ PreorderNodeListGenerator nlg = new PreorderNodeListGenerator();
+ node.accept( nlg );
+ System.out.println( nlg.getClassPath() );
+ }
+```
+
+So once you have initialized the repository system and created a
+session, the general pattern is to create some request object, call its
+setters to configure the request, do the operation and evaluate the
+result object.
+
+Since "all theory is grey", we maintain some runnable
+[examples and
demos](https://github.com/apache/maven-resolver/tree/master/maven-resolver-demos)
among
+our sources. These examples provide a more extensive demonstration of
+Resolver and its use, so what are you waiting for?
\ No newline at end of file
diff --git a/src/site/markdown/transitive-dependency-resolution.md
b/src/site/markdown/transitive-dependency-resolution.md
new file mode 100644
index 00000000..d68db8bb
--- /dev/null
+++ b/src/site/markdown/transitive-dependency-resolution.md
@@ -0,0 +1,88 @@
+# Transitive Dependency Resolution
+<!--
+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.
+-->
+
+An important task of Resolver (former Aether) is to resolve transitive
dependencies. This
+task can be split into two sub-tasks:
+
+1. Determine the coordinates of the artifacts that make up the
+ transitive dependencies.
+2. Resolve the files for the artifacts that have been identified in
+ step 1.
+
+Artifacts and their dependencies among each other form a *[dependency
graph](dependency-graph.html)*. So in other
+words, step 1 means to calculate this dependency graph and step 2 is a
+simple graph traversal that fetches the file for each artifact in the
+dependency graph. In Resolver, this dependency graph can be easily
+inspected and extension points are provided to allow for more control
+over the construction of the dependency graph. To understand those
+extension points, we will have a closer look at the way the dependency
+graph is constructed.
+
+Starting from a given root dependency like
+`org.eclipse.aether:aether-impl:0.9.0`, the repository system first
+reads the corresponding *artifact descriptor* (i.e. the POM when dealing
+with Maven repositories). The artifact descriptor tells about direct
+dependencies, dependency management and additional remote repositories
+to consider during the resolution. For each direct dependency, a
+*dependency selector* is given a chance to exclude the dependency from
+the graph. If the dependency is included, a *dependency manager* applies
+dependency management (if any). Next, the declared dependency version is
+expanded to a list of matching versions from the repositories. For a
+simple version like "1.0", the resulting list contains only that
+version. For a version range like "\[1.0,2.0)", the version list
+generally contains multiple versions and is subject to filtering by a
+*version filter*. For each matching version of the dependency, a child
+node is added to the dependency graph. Recursion of the process for each
+child dependency is controlled by a *dependency traverser*.
+
+The above process creates a dependency graph that often contains
+duplicate or conflicting dependencies or even cycles and as such is
+called a *dirty graph*. A chain of *dependency graph transformers* is
+then used to trim this graph down and to form a *resolved graph*.
+
+So more technically, the dependency graph that the repository system
+returns to its caller is affected by instances of
+`org.eclipse.aether.collection.DependencySelector`,
+`org.eclipse.aether.collection.DependencyManager`,
+`org.eclipse.aether.collection.VersionFilter`,
+`org.eclipse.aether.collection.DependencyTraverser` and
+`org.eclipse.aether.collection.DependencyGraphTransformer`. Users of the
+repository system can directly control those extension points when
+creating the repository system session by providing implementations that
+fit their needs.
+
+For example, a dependency selector can process exclusions on child
+dependencies, exclude optional dependencies or dependencies with certain
+unwanted scopes. A dependency traverser can be used to decide whether
+the dependencies of a (fat) WAR should be included in the dependency
+graph or not. The version filter can exclude specific versions of an
+artifact which are unacceptable in the current context, e.g. ban
+snapshots. Dependency graph transformers can identify and mark
+conflicting nodes in the dirty tree and resolve conflicting versions or
+scopes by pruning unwanted parts from the graph.
+
+Several classes from `maven-resolver-provider` helps to construct a
+session that mimics the resolution rules used by Maven. In
+case you want to customize the graph construction, feel free to have a
+look at the source of that class to learn about the implementation
+classes being used there to achieve Maven style behavior, you might want
+to reuse some of those for your own repository system session as well.
+Maven plugins can easily get access to the current repository system
+session via the usual parameter injection, see for the actual code bits.
diff --git a/src/site/markdown/using-resolver-in-maven-plugins.md
b/src/site/markdown/using-resolver-in-maven-plugins.md
new file mode 100644
index 00000000..67d738fe
--- /dev/null
+++ b/src/site/markdown/using-resolver-in-maven-plugins.md
@@ -0,0 +1,106 @@
+# Using Resolver in Maven Plugins
+<!--
+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.
+-->
+
+[Apache Maven](http://maven.apache.org/) 3.x uses Resolver (former Aether) for
repository
+tasks and Maven plugins that target Maven 3.x can do so as well. To
+start, you likely want to add the following dependencies to your plugin
+POM:
+
+```xml
+<project>
+ ...
+ <prerequisites>
+ <!-- Maven 3.1.0 is the earliest version using Eclipse Aether, Maven 3.0.x
uses the incompatible predecessor Sonatype Aether -->
+ <maven>3.1</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <!-- required in all cases -->
+ <groupId>org.apache.maven.resolver</groupId>
+ <artifactId>maven-resolver-api</artifactId>
+ <version>1.9.20</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <!-- optional helpers, might be superfluous depending on your use case
-->
+ <groupId>org.apache.maven.resolver</groupId>
+ <artifactId>maven-resolver-util</artifactId>
+ <version>1.9.20</version>
+ <!-- Scope: use compile to make plugin work in Maven 3.8 and earlier -->
+ <scope>compile</scope>
+ </dependency>
+ ...
+ </dependencies>
+ ...
+</project>
+```
+
+*Note:* At runtime, the actual version of `maven-resolver-api` being used is
+enforced by the Maven core, just like other Maven APIs. So be sure to
+compile/test your plugin against the version of `maven-resolver-api` that is
+used by the minimum version of Maven that your plugin wants to support.
+
+Next, in your mojo source, you would need to grab the repository related
+components and parameters:
+
+```java
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.repository.RemoteRepository;
+...
+
+public class MyMojo extends AbstractMojo
+{
+
+ /**
+ * The entry point to Aether, i.e. the component doing all the work.
+ */
+ @Component
+ private RepositorySystem repoSystem;
+
+ /**
+ * The current repository/network configuration of Maven.
+ */
+ @Parameter(defaultValue="${repositorySystemSession}", readOnly = true)
+ private RepositorySystemSession repoSession;
+
+ /**
+ * The project's remote repositories to use for the resolution of project
dependencies.
+ */
+ @Parameter(defaultValue = "${project.remoteProjectRepositories}", readOnly
= true)
+ private List<RemoteRepository> projectRepos;
+
+ /**
+ * The project's remote repositories to use for the resolution of plugins
and their dependencies.
+ */
+ @Parameter(defaultValue = "${project.remotePluginRepositories}", readOnly
= true)
+ private List<RemoteRepository> pluginRepos;
+
+ // Your other mojo parameters and code here
+ ...
+}
+```
+
+Usually, you need only `projectRepos` or `pluginRepos` depending on the
+nature of artifacts your plugin is dealing with, so the other plugin
+parameter would be superfluous in that case. But in general, the bits
+shown above should give you all handles that you need to work with
+Aether from within a Maven plugin.
diff --git a/src/site/markdown/what-is-resolver.md
b/src/site/markdown/what-is-resolver.md
new file mode 100644
index 00000000..9640ad14
--- /dev/null
+++ b/src/site/markdown/what-is-resolver.md
@@ -0,0 +1,64 @@
+# What Is Resolver?
+<!--
+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.
+-->
+
+Did you ever want to integrate Maven's dependency resolution mechanism
+into your application and ended up trying to embed Plexus and an entire
+Maven distribution? Did you ever want to use Maven's dependency
+resolution mechanism in a multithreaded fashion and got burned by the
+stateful singletons in there? Did you ever want to have a little more
+control over how Maven calculates the resolved dependency graph, say use
+another strategy for conflict resolution or inspect some intermediate
+dependency graph?
+
+Well, Resolver (former Aether) is the answer. It's an *embeddable Java library
to
+work with artifact repositories*, enabling you to fetch artifacts from
+remote repositories for local consumption and to publish local artifacts
+to remote repositories for sharing with others.
+
+There are many ways to transfer artifacts, to describe their
+relationships and to use them. Resolver was designed with an open mind
+towards customization of these aspects, allowing you to augment or even
+replace stock functionality to fit your needs. In fact, the Resolver Core
+itself doesn't know how to deal with Maven repositories for instance.
+It's tool agnostic and provides some general artifact
+resolution/deployment framework and leaves details like the repository
+format to extensions.
+
+At this point, the `maven-resolver-provider` from the [Apache
+Maven](http://maven.apache.org/) project is probably the most
+interesting extension as it brings support for, well Maven repositories.
+So if you're looking for a way to consume artifacts from the [Central
+Repository](http://search.maven.org/), Resolver in combination with the
+Maven Resolver Provider is your best bet. Usage of Resolver in this way does
+not only ease your work when dealing with artifacts but also ensures
+interoperability with other tools that work with Maven repositories.
+
+## Embedding Resolver
+
+As noted above, Resolver alone is not "complete", in a way, it does not
+know how to deal even with Maven repositories (and models). To "minimally
+complete" Resolver, one needs `maven-resolver-provider` module, that
+makes Resolver "minimally complete" (contains required component
implementations
+and introduces required models for Maven repositories). But this is still
+just "basic resolver functionality". Next functionality
+level is add "Maven environment awareness" (like honoring settings.xml and
alike). This
+can be achieved by using libraries like
[MIMA](https://github.com/maveniverse/mima)
+is. And finally, Maven (that incorporates Resolver) offers full experience
(while
+embedding Maven is really not trivial).
diff --git a/src/site/site.xml b/src/site/site.xml
index 46df9174..dce27f2e 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -20,30 +20,38 @@ under the License.
-->
<project xmlns="http://maven.apache.org/DECORATION/1.8.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/DECORATION/1.8.0
http://maven.apache.org/xsd/decoration-1.8.0.xsd"
+ xsi:schemaLocation="http://maven.apache.org/DECORATION/1.8.0
https://maven.apache.org/xsd/decoration-1.8.0.xsd"
name="Artifact Resolver">
<edit>${project.scm.url}</edit>
<body>
<menu name="Overview">
<item name="Introduction" href="index.html"/>
- <item name="API Compatibility" href="api-compatibility.html"/>
- <item name="Configuration" href="configuration.html"/>
- <item name="About Checksums" href="about-checksums.html"/>
+ <item name="What Is Resolver?" href="what-is-resolver.html"/>
+ <item name="Checksums" href="about-checksums.html"/>
<item name="Expected Checksums" href="expected-checksums.html"/>
- <item name="About Local Repository" href="local-repository.html"/>
+ <item name="Local Repository" href="local-repository.html"/>
<item name="Remote Repository Filtering"
href="remote-repository-filtering.html"/>
<item name="Third-party Integrations"
href="third-party-integrations.html"/>
- <item name="Common Misconceptions" href="common-misconceptions.html"/>
+ <item name="Download" href="download.html"/>
+ </menu>
+ <menu name="Guides">
+ <item name="API Compatibility" href="api-compatibility.html"/>
<item name="Upgrading Resolver" href="upgrading-resolver.html"/>
+ <item name="Using Resolver in Maven Plugins"
href="using-resolver-in-maven-plugins.html"/>
+ <item name="Transitive Dependency Resolution"
href="transitive-dependency-resolution.html"/>
+ <item name="Dependency Graph" href="dependency-graph.html"/>
+ <item name="Creating a RepositorySystemSession"
href="creating-a-repository-system-session.html"/>
+ <item name="Resolving Dependencies" href="resolving-dependencies.html"/>
+ <item name="Common Misconceptions" href="common-misconceptions.html"/>
+ </menu>
+ <menu name="Reference">
+ <item name="Configuration" href="configuration.html"/>
<item name="JavaDocs" href="apidocs/index.html"/>
<item name="Source Xref" href="xref/index.html"/>
- <!--item name="FAQ" href="faq.html"/-->
<item name="License" href="https://www.apache.org/licenses/"/>
- <item name="Download" href="download.html"/>
</menu>
<menu name="See Also">
<item name="Maven Artifact Resolver Ant Tasks"
href="https://maven.apache.org/resolver-ant-tasks/"/>
- <item name="Aether wiki" href="https://wiki.eclipse.org/Aether"/>
</menu>
<menu ref="modules"/>