You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by hb...@apache.org on 2016/09/03 20:23:26 UTC
[03/51] [partial] maven-aether git commit: [MNG-6007] rename Aether
to Maven Artifact Resolver
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/graph/Dependency.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/Dependency.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/Dependency.java
new file mode 100644
index 0000000..b9e7cb4
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/Dependency.java
@@ -0,0 +1,330 @@
+package org.eclipse.aether.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.
+ */
+
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.eclipse.aether.artifact.Artifact;
+
+/**
+ * A dependency to some artifact. <em>Note:</em> Instances of this class are immutable and the exposed mutators return
+ * new objects rather than changing the current instance.
+ */
+public final class Dependency
+{
+
+ private final Artifact artifact;
+
+ private final String scope;
+
+ private final Boolean optional;
+
+ private final Set<Exclusion> exclusions;
+
+ /**
+ * Creates a mandatory dependency on the specified artifact with the given scope.
+ *
+ * @param artifact The artifact being depended on, must not be {@code null}.
+ * @param scope The scope of the dependency, may be {@code null}.
+ */
+ public Dependency( Artifact artifact, String scope )
+ {
+ this( artifact, scope, false );
+ }
+
+ /**
+ * Creates a dependency on the specified artifact with the given scope.
+ *
+ * @param artifact The artifact being depended on, must not be {@code null}.
+ * @param scope The scope of the dependency, may be {@code null}.
+ * @param optional A flag whether the dependency is optional or mandatory, may be {@code null}.
+ */
+ public Dependency( Artifact artifact, String scope, Boolean optional )
+ {
+ this( artifact, scope, optional, null );
+ }
+
+ /**
+ * Creates a dependency on the specified artifact with the given scope and exclusions.
+ *
+ * @param artifact The artifact being depended on, must not be {@code null}.
+ * @param scope The scope of the dependency, may be {@code null}.
+ * @param optional A flag whether the dependency is optional or mandatory, may be {@code null}.
+ * @param exclusions The exclusions that apply to transitive dependencies, may be {@code null} if none.
+ */
+ public Dependency( Artifact artifact, String scope, Boolean optional, Collection<Exclusion> exclusions )
+ {
+ this( artifact, scope, Exclusions.copy( exclusions ), optional );
+ }
+
+ private Dependency( Artifact artifact, String scope, Set<Exclusion> exclusions, Boolean optional )
+ {
+ // NOTE: This constructor assumes immutability of the provided exclusion collection, for internal use only
+ if ( artifact == null )
+ {
+ throw new IllegalArgumentException( "no artifact specified for dependency" );
+ }
+ this.artifact = artifact;
+ this.scope = ( scope != null ) ? scope : "";
+ this.optional = optional;
+ this.exclusions = exclusions;
+ }
+
+ /**
+ * Gets the artifact being depended on.
+ *
+ * @return The artifact, never {@code null}.
+ */
+ public Artifact getArtifact()
+ {
+ return artifact;
+ }
+
+ /**
+ * Sets the artifact being depended on.
+ *
+ * @param artifact The artifact, must not be {@code null}.
+ * @return The new dependency, never {@code null}.
+ */
+ public Dependency setArtifact( Artifact artifact )
+ {
+ if ( this.artifact.equals( artifact ) )
+ {
+ return this;
+ }
+ return new Dependency( artifact, scope, exclusions, optional );
+ }
+
+ /**
+ * Gets the scope of the dependency. The scope defines in which context this dependency is relevant.
+ *
+ * @return The scope or an empty string if not set, never {@code null}.
+ */
+ public String getScope()
+ {
+ return scope;
+ }
+
+ /**
+ * Sets the scope of the dependency, e.g. "compile".
+ *
+ * @param scope The scope of the dependency, may be {@code null}.
+ * @return The new dependency, never {@code null}.
+ */
+ public Dependency setScope( String scope )
+ {
+ if ( this.scope.equals( scope ) || ( scope == null && this.scope.length() <= 0 ) )
+ {
+ return this;
+ }
+ return new Dependency( artifact, scope, exclusions, optional );
+ }
+
+ /**
+ * Indicates whether this dependency is optional or not. Optional dependencies can be ignored in some contexts.
+ *
+ * @return {@code true} if the dependency is (definitively) optional, {@code false} otherwise.
+ */
+ public boolean isOptional()
+ {
+ return Boolean.TRUE.equals( optional );
+ }
+
+ /**
+ * Gets the optional flag for the dependency. Note: Most clients will usually call {@link #isOptional()} to
+ * determine the optional flag, this method is for advanced use cases where three-valued logic is required.
+ *
+ * @return The optional flag or {@code null} if unspecified.
+ */
+ public Boolean getOptional()
+ {
+ return optional;
+ }
+
+ /**
+ * Sets the optional flag for the dependency.
+ *
+ * @param optional {@code true} if the dependency is optional, {@code false} if the dependency is mandatory, may be
+ * {@code null} if unspecified.
+ * @return The new dependency, never {@code null}.
+ */
+ public Dependency setOptional( Boolean optional )
+ {
+ if ( eq( this.optional, optional ) )
+ {
+ return this;
+ }
+ return new Dependency( artifact, scope, exclusions, optional );
+ }
+
+ /**
+ * Gets the exclusions for this dependency. Exclusions can be used to remove transitive dependencies during
+ * resolution.
+ *
+ * @return The (read-only) exclusions, never {@code null}.
+ */
+ public Collection<Exclusion> getExclusions()
+ {
+ return exclusions;
+ }
+
+ /**
+ * Sets the exclusions for the dependency.
+ *
+ * @param exclusions The exclusions, may be {@code null}.
+ * @return The new dependency, never {@code null}.
+ */
+ public Dependency setExclusions( Collection<Exclusion> exclusions )
+ {
+ if ( hasEquivalentExclusions( exclusions ) )
+ {
+ return this;
+ }
+ return new Dependency( artifact, scope, optional, exclusions );
+ }
+
+ private boolean hasEquivalentExclusions( Collection<Exclusion> exclusions )
+ {
+ if ( exclusions == null || exclusions.isEmpty() )
+ {
+ return this.exclusions.isEmpty();
+ }
+ if ( exclusions instanceof Set )
+ {
+ return this.exclusions.equals( exclusions );
+ }
+ return exclusions.size() >= this.exclusions.size() && this.exclusions.containsAll( exclusions )
+ && exclusions.containsAll( this.exclusions );
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.valueOf( getArtifact() ) + " (" + getScope() + ( isOptional() ? "?" : "" ) + ")";
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( obj == this )
+ {
+ return true;
+ }
+ else if ( obj == null || !getClass().equals( obj.getClass() ) )
+ {
+ return false;
+ }
+
+ Dependency that = (Dependency) obj;
+
+ return artifact.equals( that.artifact ) && scope.equals( that.scope ) && eq( optional, that.optional )
+ && exclusions.equals( that.exclusions );
+ }
+
+ private static <T> boolean eq( T o1, T o2 )
+ {
+ return ( o1 != null ) ? o1.equals( o2 ) : o2 == null;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int hash = 17;
+ hash = hash * 31 + artifact.hashCode();
+ hash = hash * 31 + scope.hashCode();
+ hash = hash * 31 + ( optional != null ? optional.hashCode() : 0 );
+ hash = hash * 31 + exclusions.size();
+ return hash;
+ }
+
+ private static class Exclusions
+ extends AbstractSet<Exclusion>
+ {
+
+ private final Exclusion[] exclusions;
+
+ public static Set<Exclusion> copy( Collection<Exclusion> exclusions )
+ {
+ if ( exclusions == null || exclusions.isEmpty() )
+ {
+ return Collections.emptySet();
+ }
+ return new Exclusions( exclusions );
+ }
+
+ private Exclusions( Collection<Exclusion> exclusions )
+ {
+ if ( exclusions.size() > 1 && !( exclusions instanceof Set ) )
+ {
+ exclusions = new LinkedHashSet<Exclusion>( exclusions );
+ }
+ this.exclusions = exclusions.toArray( new Exclusion[exclusions.size()] );
+ }
+
+ @Override
+ public Iterator<Exclusion> iterator()
+ {
+ return new Iterator<Exclusion>()
+ {
+
+ private int cursor = 0;
+
+ public boolean hasNext()
+ {
+ return cursor < exclusions.length;
+ }
+
+ public Exclusion next()
+ {
+ try
+ {
+ Exclusion exclusion = exclusions[cursor];
+ cursor++;
+ return exclusion;
+ }
+ catch ( IndexOutOfBoundsException e )
+ {
+ throw new NoSuchElementException();
+ }
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ };
+ }
+
+ @Override
+ public int size()
+ {
+ return exclusions.length;
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyCycle.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyCycle.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyCycle.java
new file mode 100644
index 0000000..1076ab8
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyCycle.java
@@ -0,0 +1,53 @@
+package org.eclipse.aether.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.
+ */
+
+import java.util.List;
+
+/**
+ * A cycle within a dependency graph, that is a sequence of dependencies d_1, d_2, ..., d_n where d_1 and d_n have the
+ * same versionless coordinates. In more practical terms, a cycle occurs when a project directly or indirectly depends
+ * on its own output artifact.
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface DependencyCycle
+{
+
+ /**
+ * Gets the dependencies that lead to the first dependency on the cycle, starting from the root of the dependency
+ * graph.
+ *
+ * @return The (read-only) sequence of dependencies that precedes the cycle in the graph, potentially empty but
+ * never {@code null}.
+ */
+ List<Dependency> getPrecedingDependencies();
+
+ /**
+ * Gets the dependencies that actually form the cycle. For example, a -> b -> c -> a, i.e. the last
+ * dependency in this sequence duplicates the first element and closes the cycle. Hence the length of the cycle is
+ * the size of the returned sequence minus 1.
+ *
+ * @return The (read-only) sequence of dependencies that forms the cycle, never {@code null}.
+ */
+ List<Dependency> getCyclicDependencies();
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyFilter.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyFilter.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyFilter.java
new file mode 100644
index 0000000..41776ff
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyFilter.java
@@ -0,0 +1,42 @@
+package org.eclipse.aether.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.
+ */
+
+import java.util.List;
+
+/**
+ * A filter to include/exclude dependency nodes during other operations.
+ */
+public interface DependencyFilter
+{
+
+ /**
+ * Indicates whether the specified dependency node shall be included or excluded.
+ *
+ * @param node The dependency node to filter, must not be {@code null}.
+ * @param parents The (read-only) chain of parent nodes that leads to the node to be filtered, must not be
+ * {@code null}. Iterating this (possibly empty) list walks up the dependency graph towards the root
+ * node, i.e. the immediate parent node (if any) is the first node in the list. The size of the list also
+ * denotes the zero-based depth of the filtered node.
+ * @return {@code true} to include the dependency node, {@code false} to exclude it.
+ */
+ boolean accept( DependencyNode node, List<DependencyNode> parents );
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java
new file mode 100644
index 0000000..da30124
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java
@@ -0,0 +1,250 @@
+package org.eclipse.aether.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.
+ */
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.version.Version;
+import org.eclipse.aether.version.VersionConstraint;
+
+/**
+ * A node within a dependency graph. To conserve memory, dependency graphs may reuse a given node instance multiple
+ * times to represent reoccurring dependencies. As such clients traversing a dependency graph should be prepared to
+ * discover multiple paths leading to the same node instance unless the input graph is known to be a duplicate-free
+ * tree. <em>Note:</em> Unless otherwise noted, implementation classes are not thread-safe and dependency nodes should
+ * not be mutated by concurrent threads.
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface DependencyNode
+{
+
+ /**
+ * A bit flag indicating the dependency version was subject to dependency management
+ *
+ * @see #getManagedBits()
+ */
+ int MANAGED_VERSION = 0x01;
+
+ /**
+ * A bit flag indicating the dependency scope was subject to dependency management
+ *
+ * @see #getManagedBits()
+ */
+ int MANAGED_SCOPE = 0x02;
+
+ /**
+ * A bit flag indicating the optional flag was subject to dependency management
+ *
+ * @see #getManagedBits()
+ */
+ int MANAGED_OPTIONAL = 0x04;
+
+ /**
+ * A bit flag indicating the artifact properties were subject to dependency management
+ *
+ * @see #getManagedBits()
+ */
+ int MANAGED_PROPERTIES = 0x08;
+
+ /**
+ * A bit flag indicating the exclusions were subject to dependency management
+ *
+ * @see #getManagedBits()
+ */
+ int MANAGED_EXCLUSIONS = 0x10;
+
+ /**
+ * Gets the depth of the node.
+ *
+ * @return The depth of the node.
+ *
+ * @since 1.2
+ */
+ long getDepth();
+
+ /**
+ * Gets the parent node of this node.
+ *
+ * @return The parent node of this node or {@code null}, if this node is the root of the graph.
+ *
+ * @since 1.2
+ */
+ DependencyNode getParent();
+
+ /**
+ * Gets the child nodes of this node. To conserve memory, dependency nodes with equal dependencies may share the
+ * same child list instance. Hence clients mutating the child list need to be aware that these changes might affect
+ * more than this node. Where this is not desired, the child list should be copied before mutation if the client
+ * cannot be sure whether it might be shared with other nodes in the graph.
+ *
+ * @return The child nodes of this node, never {@code null}.
+ */
+ List<DependencyNode> getChildren();
+
+ /**
+ * Sets the child nodes of this node.
+ *
+ * @param children The child nodes, may be {@code null}
+ */
+ void setChildren( List<DependencyNode> children );
+
+ /**
+ * Gets the dependency associated with this node. <em>Note:</em> For dependency graphs that have been constructed
+ * without a root dependency, this method will yield {@code null} when invoked on the graph's root node. The root
+ * node of such graphs may however still have a label as returned by {@link #getArtifact()}.
+ *
+ * @return The dependency or {@code null} if none.
+ */
+ Dependency getDependency();
+
+ /**
+ * Gets the artifact associated with this node. If this node is associated with a dependency, this is equivalent to
+ * {@code getDependency().getArtifact()}. Otherwise the artifact merely provides a label for this node in which case
+ * the artifact must not be subjected to dependency collection/resolution.
+ *
+ * @return The associated artifact or {@code null} if none.
+ */
+ Artifact getArtifact();
+
+ /**
+ * Updates the artifact of the dependency after resolution. The new artifact must have the same coordinates as the
+ * original artifact. This method may only be invoked if this node actually has a dependency, i.e. if
+ * {@link #getDependency()} is not null.
+ *
+ * @param artifact The artifact satisfying the dependency, must not be {@code null}.
+ */
+ void setArtifact( Artifact artifact );
+
+ /**
+ * Gets the sequence of relocations that was followed to resolve the artifact referenced by the dependency.
+ *
+ * @return The (read-only) sequence of relocations, never {@code null}.
+ */
+ List<? extends Artifact> getRelocations();
+
+ /**
+ * Gets the known aliases for this dependency's artifact. An alias can be used to mark a patched rebuild of some
+ * other artifact as such, thereby allowing conflict resolution to consider the patched and the original artifact as
+ * a conflict.
+ *
+ * @return The (read-only) set of known aliases, never {@code null}.
+ */
+ Collection<? extends Artifact> getAliases();
+
+ /**
+ * Gets the version constraint that was parsed from the dependency's version declaration.
+ *
+ * @return The version constraint for this node or {@code null}.
+ */
+ VersionConstraint getVersionConstraint();
+
+ /**
+ * Gets the version that was selected for the dependency's target artifact.
+ *
+ * @return The parsed version or {@code null}.
+ */
+ Version getVersion();
+
+ /**
+ * Sets the scope of the dependency. This method may only be invoked if this node actually has a dependency, i.e. if
+ * {@link #getDependency()} is not null.
+ *
+ * @param scope The scope, may be {@code null}.
+ */
+ void setScope( String scope );
+
+ /**
+ * Sets the optional flag of the dependency. This method may only be invoked if this node actually has a dependency,
+ * i.e. if {@link #getDependency()} is not null.
+ *
+ * @param optional The optional flag, may be {@code null}.
+ */
+ void setOptional( Boolean optional );
+
+ /**
+ * Gets a bit field indicating which attributes of this node were subject to dependency management.
+ *
+ * @return A bit field containing any of the bits {@link #MANAGED_VERSION}, {@link #MANAGED_SCOPE},
+ * {@link #MANAGED_OPTIONAL}, {@link #MANAGED_PROPERTIES} and {@link #MANAGED_EXCLUSIONS} if the
+ * corresponding attribute was set via dependency management.
+ */
+ int getManagedBits();
+
+ /**
+ * Gets the remote repositories from which this node's artifact shall be resolved.
+ *
+ * @return The (read-only) list of remote repositories to use for artifact resolution, never {@code null}.
+ */
+ List<RemoteRepository> getRepositories();
+
+ /**
+ * Gets the request context in which this dependency node was created.
+ *
+ * @return The request context, never {@code null}.
+ */
+ String getRequestContext();
+
+ /**
+ * Sets the request context in which this dependency node was created.
+ *
+ * @param context The context, may be {@code null}.
+ */
+ void setRequestContext( String context );
+
+ /**
+ * Gets the custom data associated with this dependency node. Clients of the repository system can use this data to
+ * annotate dependency nodes with domain-specific information. Note that the returned map is read-only and
+ * {@link #setData(Object, Object)} needs to be used to update the custom data.
+ *
+ * @return The (read-only) key-value mappings, never {@code null}.
+ */
+ Map<?, ?> getData();
+
+ /**
+ * Sets the custom data associated with this dependency node.
+ *
+ * @param data The new custom data, may be {@code null}.
+ */
+ void setData( Map<Object, Object> data );
+
+ /**
+ * Associates the specified dependency node data with the given key. <em>Note:</em> This method must not be called
+ * while {@link #getData()} is being iterated.
+ *
+ * @param key The key under which to store the data, must not be {@code null}.
+ * @param value The data to associate with the key, may be {@code null} to remove the mapping.
+ */
+ void setData( Object key, Object value );
+
+ /**
+ * Traverses this node and potentially its children using the specified visitor.
+ *
+ * @param visitor The visitor to call back, must not be {@code null}.
+ * @return {@code true} to visit siblings nodes of this node as well, {@code false} to skip siblings.
+ */
+ boolean accept( DependencyVisitor visitor );
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyVisitor.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyVisitor.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyVisitor.java
new file mode 100644
index 0000000..2a85f2d
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyVisitor.java
@@ -0,0 +1,47 @@
+package org.eclipse.aether.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.
+ */
+
+/**
+ * A visitor for nodes of the dependency graph.
+ *
+ * @see DependencyNode#accept(DependencyVisitor)
+ */
+public interface DependencyVisitor
+{
+
+ /**
+ * Notifies the visitor of a node visit before its children have been processed.
+ *
+ * @param node The dependency node being visited, must not be {@code null}.
+ * @return {@code true} to visit child nodes of the specified node as well, {@code false} to skip children.
+ */
+ boolean visitEnter( DependencyNode node );
+
+ /**
+ * Notifies the visitor of a node visit after its children have been processed. Note that this method is always
+ * invoked regardless whether any children have actually been visited.
+ *
+ * @param node The dependency node being visited, must not be {@code null}.
+ * @return {@code true} to visit siblings nodes of the specified node as well, {@code false} to skip siblings.
+ */
+ boolean visitLeave( DependencyNode node );
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/graph/Exclusion.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/Exclusion.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/Exclusion.java
new file mode 100644
index 0000000..497cf43
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/Exclusion.java
@@ -0,0 +1,131 @@
+package org.eclipse.aether.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.
+ */
+
+/**
+ * An exclusion of one or more transitive dependencies. <em>Note:</em> Instances of this class are immutable and the
+ * exposed mutators return new objects rather than changing the current instance.
+ *
+ * @see Dependency#getExclusions()
+ */
+public final class Exclusion
+{
+
+ private final String groupId;
+
+ private final String artifactId;
+
+ private final String classifier;
+
+ private final String extension;
+
+ /**
+ * Creates an exclusion for artifacts with the specified coordinates.
+ *
+ * @param groupId The group identifier, may be {@code null}.
+ * @param artifactId The artifact identifier, may be {@code null}.
+ * @param classifier The classifier, may be {@code null}.
+ * @param extension The file extension, may be {@code null}.
+ */
+ public Exclusion( String groupId, String artifactId, String classifier, String extension )
+ {
+ this.groupId = ( groupId != null ) ? groupId : "";
+ this.artifactId = ( artifactId != null ) ? artifactId : "";
+ this.classifier = ( classifier != null ) ? classifier : "";
+ this.extension = ( extension != null ) ? extension : "";
+ }
+
+ /**
+ * Gets the group identifier for artifacts to exclude.
+ *
+ * @return The group identifier, never {@code null}.
+ */
+ public String getGroupId()
+ {
+ return groupId;
+ }
+
+ /**
+ * Gets the artifact identifier for artifacts to exclude.
+ *
+ * @return The artifact identifier, never {@code null}.
+ */
+ public String getArtifactId()
+ {
+ return artifactId;
+ }
+
+ /**
+ * Gets the classifier for artifacts to exclude.
+ *
+ * @return The classifier, never {@code null}.
+ */
+ public String getClassifier()
+ {
+ return classifier;
+ }
+
+ /**
+ * Gets the file extension for artifacts to exclude.
+ *
+ * @return The file extension of artifacts to exclude, never {@code null}.
+ */
+ public String getExtension()
+ {
+ return extension;
+ }
+
+ @Override
+ public String toString()
+ {
+ return getGroupId() + ':' + getArtifactId() + ':' + getExtension()
+ + ( getClassifier().length() > 0 ? ':' + getClassifier() : "" );
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( obj == this )
+ {
+ return true;
+ }
+ else if ( obj == null || !getClass().equals( obj.getClass() ) )
+ {
+ return false;
+ }
+
+ Exclusion that = (Exclusion) obj;
+
+ return artifactId.equals( that.artifactId ) && groupId.equals( that.groupId )
+ && extension.equals( that.extension ) && classifier.equals( that.classifier );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int hash = 17;
+ hash = hash * 31 + artifactId.hashCode();
+ hash = hash * 31 + groupId.hashCode();
+ hash = hash * 31 + classifier.hashCode();
+ hash = hash * 31 + extension.hashCode();
+ return hash;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/graph/package-info.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/package-info.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/package-info.java
new file mode 100644
index 0000000..c3ba9db
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/package-info.java
@@ -0,0 +1,24 @@
+// CHECKSTYLE_OFF: RegexpHeader
+/*
+ * 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.
+ */
+/**
+ * The representation of a dependency graph by means of connected dependency nodes.
+ */
+package org.eclipse.aether.graph;
+
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/installation/InstallRequest.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/installation/InstallRequest.java b/maven-resolver-api/src/main/java/org/eclipse/aether/installation/InstallRequest.java
new file mode 100644
index 0000000..f9b3163
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/installation/InstallRequest.java
@@ -0,0 +1,177 @@
+package org.eclipse.aether.installation;
+
+/*
+ * 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.
+ */
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.RequestTrace;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.metadata.Metadata;
+
+/**
+ * A request to install artifacts and their accompanying metadata into the local repository.
+ *
+ * @see RepositorySystem#install(RepositorySystemSession, InstallRequest)
+ */
+public final class InstallRequest
+{
+
+ private Collection<Artifact> artifacts = Collections.emptyList();
+
+ private Collection<Metadata> metadata = Collections.emptyList();
+
+ private RequestTrace trace;
+
+ /**
+ * Creates an uninitialized request.
+ */
+ public InstallRequest()
+ {
+ }
+
+ /**
+ * Gets the artifact to install.
+ *
+ * @return The artifacts to install, never {@code null}.
+ */
+ public Collection<Artifact> getArtifacts()
+ {
+ return artifacts;
+ }
+
+ /**
+ * Sets the artifacts to install.
+ *
+ * @param artifacts The artifacts to install, may be {@code null}.
+ * @return This request for chaining, never {@code null}.
+ */
+ public InstallRequest setArtifacts( Collection<Artifact> artifacts )
+ {
+ if ( artifacts == null )
+ {
+ this.artifacts = Collections.emptyList();
+ }
+ else
+ {
+ this.artifacts = artifacts;
+ }
+ return this;
+ }
+
+ /**
+ * Adds the specified artifacts for installation.
+ *
+ * @param artifact The artifact to add, may be {@code null}.
+ * @return This request for chaining, never {@code null}.
+ */
+ public InstallRequest addArtifact( Artifact artifact )
+ {
+ if ( artifact != null )
+ {
+ if ( artifacts.isEmpty() )
+ {
+ artifacts = new ArrayList<Artifact>();
+ }
+ artifacts.add( artifact );
+ }
+ return this;
+ }
+
+ /**
+ * Gets the metadata to install.
+ *
+ * @return The metadata to install, never {@code null}.
+ */
+ public Collection<Metadata> getMetadata()
+ {
+ return metadata;
+ }
+
+ /**
+ * Sets the metadata to install.
+ *
+ * @param metadata The metadata to install.
+ * @return This request for chaining, never {@code null}.
+ */
+ public InstallRequest setMetadata( Collection<Metadata> metadata )
+ {
+ if ( metadata == null )
+ {
+ this.metadata = Collections.emptyList();
+ }
+ else
+ {
+ this.metadata = metadata;
+ }
+ return this;
+ }
+
+ /**
+ * Adds the specified metadata for installation.
+ *
+ * @param metadata The metadata to add, may be {@code null}.
+ * @return This request for chaining, never {@code null}.
+ */
+ public InstallRequest addMetadata( Metadata metadata )
+ {
+ if ( metadata != null )
+ {
+ if ( this.metadata.isEmpty() )
+ {
+ this.metadata = new ArrayList<Metadata>();
+ }
+ this.metadata.add( metadata );
+ }
+ return this;
+ }
+
+ /**
+ * Gets the trace information that describes the higher level request/operation in which this request is issued.
+ *
+ * @return The trace information about the higher level operation or {@code null} if none.
+ */
+ public RequestTrace getTrace()
+ {
+ return trace;
+ }
+
+ /**
+ * Sets the trace information that describes the higher level request/operation in which this request is issued.
+ *
+ * @param trace The trace information about the higher level operation, may be {@code null}.
+ * @return This request for chaining, never {@code null}.
+ */
+ public InstallRequest setTrace( RequestTrace trace )
+ {
+ this.trace = trace;
+ return this;
+ }
+
+ @Override
+ public String toString()
+ {
+ return getArtifacts() + ", " + getMetadata();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/installation/InstallResult.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/installation/InstallResult.java b/maven-resolver-api/src/main/java/org/eclipse/aether/installation/InstallResult.java
new file mode 100644
index 0000000..6624585
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/installation/InstallResult.java
@@ -0,0 +1,174 @@
+package org.eclipse.aether.installation;
+
+/*
+ * 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.
+ */
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.metadata.Metadata;
+
+/**
+ * The result of installing artifacts and their accompanying metadata into the a remote repository.
+ *
+ * @see RepositorySystem#install(RepositorySystemSession, InstallRequest)
+ */
+public final class InstallResult
+{
+
+ private final InstallRequest request;
+
+ private Collection<Artifact> artifacts;
+
+ private Collection<Metadata> metadata;
+
+ /**
+ * Creates a new result for the specified request.
+ *
+ * @param request The installation request, must not be {@code null}.
+ */
+ public InstallResult( InstallRequest request )
+ {
+ if ( request == null )
+ {
+ throw new IllegalArgumentException( "install request has not been specified" );
+ }
+ this.request = request;
+ artifacts = Collections.emptyList();
+ metadata = Collections.emptyList();
+ }
+
+ /**
+ * Gets the install request that was made.
+ *
+ * @return The install request, never {@code null}.
+ */
+ public InstallRequest getRequest()
+ {
+ return request;
+ }
+
+ /**
+ * Gets the artifacts that got installed.
+ *
+ * @return The installed artifacts, never {@code null}.
+ */
+ public Collection<Artifact> getArtifacts()
+ {
+ return artifacts;
+ }
+
+ /**
+ * Sets the artifacts that got installed.
+ *
+ * @param artifacts The installed artifacts, may be {@code null}.
+ * @return This result for chaining, never {@code null}.
+ */
+ public InstallResult setArtifacts( Collection<Artifact> artifacts )
+ {
+ if ( artifacts == null )
+ {
+ this.artifacts = Collections.emptyList();
+ }
+ else
+ {
+ this.artifacts = artifacts;
+ }
+ return this;
+ }
+
+ /**
+ * Adds the specified artifacts to the result.
+ *
+ * @param artifact The installed artifact to add, may be {@code null}.
+ * @return This result for chaining, never {@code null}.
+ */
+ public InstallResult addArtifact( Artifact artifact )
+ {
+ if ( artifact != null )
+ {
+ if ( artifacts.isEmpty() )
+ {
+ artifacts = new ArrayList<Artifact>();
+ }
+ artifacts.add( artifact );
+ }
+ return this;
+ }
+
+ /**
+ * Gets the metadata that got installed. Note that due to automatically generated metadata, there might have been
+ * more metadata installed than originally specified in the install request.
+ *
+ * @return The installed metadata, never {@code null}.
+ */
+ public Collection<Metadata> getMetadata()
+ {
+ return metadata;
+ }
+
+ /**
+ * Sets the metadata that got installed.
+ *
+ * @param metadata The installed metadata, may be {@code null}.
+ * @return This result for chaining, never {@code null}.
+ */
+ public InstallResult setMetadata( Collection<Metadata> metadata )
+ {
+ if ( metadata == null )
+ {
+ this.metadata = Collections.emptyList();
+ }
+ else
+ {
+ this.metadata = metadata;
+ }
+ return this;
+ }
+
+ /**
+ * Adds the specified metadata to this result.
+ *
+ * @param metadata The installed metadata to add, may be {@code null}.
+ * @return This result for chaining, never {@code null}.
+ */
+ public InstallResult addMetadata( Metadata metadata )
+ {
+ if ( metadata != null )
+ {
+ if ( this.metadata.isEmpty() )
+ {
+ this.metadata = new ArrayList<Metadata>();
+ }
+ this.metadata.add( metadata );
+ }
+ return this;
+ }
+
+ @Override
+ public String toString()
+ {
+ return getArtifacts() + ", " + getMetadata();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/installation/InstallationException.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/installation/InstallationException.java b/maven-resolver-api/src/main/java/org/eclipse/aether/installation/InstallationException.java
new file mode 100644
index 0000000..9a556bb
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/installation/InstallationException.java
@@ -0,0 +1,52 @@
+package org.eclipse.aether.installation;
+
+/*
+ * 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.
+ */
+
+import org.eclipse.aether.RepositoryException;
+
+/**
+ * Thrown in case of an installation error like an IO error.
+ */
+public class InstallationException
+ extends RepositoryException
+{
+
+ /**
+ * Creates a new exception with the specified detail message.
+ *
+ * @param message The detail message, may be {@code null}.
+ */
+ public InstallationException( String message )
+ {
+ super( message );
+ }
+
+ /**
+ * Creates a new exception with the specified detail message and cause.
+ *
+ * @param message The detail message, may be {@code null}.
+ * @param cause The exception that caused this one, may be {@code null}.
+ */
+ public InstallationException( String message, Throwable cause )
+ {
+ super( message, cause );
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/installation/package-info.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/installation/package-info.java b/maven-resolver-api/src/main/java/org/eclipse/aether/installation/package-info.java
new file mode 100644
index 0000000..d4ac077
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/installation/package-info.java
@@ -0,0 +1,24 @@
+// CHECKSTYLE_OFF: RegexpHeader
+/*
+ * 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.
+ */
+/**
+ * The types supporting the publishing of artifacts to a local repository.
+ */
+package org.eclipse.aether.installation;
+
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/AbstractMetadata.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/AbstractMetadata.java b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/AbstractMetadata.java
new file mode 100644
index 0000000..49dab35
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/AbstractMetadata.java
@@ -0,0 +1,160 @@
+package org.eclipse.aether.metadata;
+
+/*
+ * 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.
+ */
+
+import java.io.File;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A skeleton class for metadata.
+ */
+public abstract class AbstractMetadata
+ implements Metadata
+{
+
+ private Metadata newInstance( Map<String, String> properties, File file )
+ {
+ return new DefaultMetadata( getGroupId(), getArtifactId(), getVersion(), getType(), getNature(), file,
+ properties );
+ }
+
+ public Metadata setFile( File file )
+ {
+ File current = getFile();
+ if ( ( current == null ) ? file == null : current.equals( file ) )
+ {
+ return this;
+ }
+ return newInstance( getProperties(), file );
+ }
+
+ public Metadata setProperties( Map<String, String> properties )
+ {
+ Map<String, String> current = getProperties();
+ if ( current.equals( properties ) || ( properties == null && current.isEmpty() ) )
+ {
+ return this;
+ }
+ return newInstance( copyProperties( properties ), getFile() );
+ }
+
+ public String getProperty( String key, String defaultValue )
+ {
+ String value = getProperties().get( key );
+ return ( value != null ) ? value : defaultValue;
+ }
+
+ /**
+ * Copies the specified metadata properties. This utility method should be used when creating new metadata instances
+ * with caller-supplied properties.
+ *
+ * @param properties The properties to copy, may be {@code null}.
+ * @return The copied and read-only properties, never {@code null}.
+ */
+ protected static Map<String, String> copyProperties( Map<String, String> properties )
+ {
+ if ( properties != null && !properties.isEmpty() )
+ {
+ return Collections.unmodifiableMap( new HashMap<String, String>( properties ) );
+ }
+ else
+ {
+ return Collections.emptyMap();
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder buffer = new StringBuilder( 128 );
+ if ( getGroupId().length() > 0 )
+ {
+ buffer.append( getGroupId() );
+ }
+ if ( getArtifactId().length() > 0 )
+ {
+ buffer.append( ':' ).append( getArtifactId() );
+ }
+ if ( getVersion().length() > 0 )
+ {
+ buffer.append( ':' ).append( getVersion() );
+ }
+ buffer.append( '/' ).append( getType() );
+ return buffer.toString();
+ }
+
+ /**
+ * Compares this metadata with the specified object.
+ *
+ * @param obj The object to compare this metadata against, may be {@code null}.
+ * @return {@code true} if and only if the specified object is another {@link Metadata} with equal coordinates,
+ * type, nature, properties and file, {@code false} otherwise.
+ */
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( obj == this )
+ {
+ return true;
+ }
+ else if ( !( obj instanceof Metadata ) )
+ {
+ return false;
+ }
+
+ Metadata that = (Metadata) obj;
+
+ return getArtifactId().equals( that.getArtifactId() ) && getGroupId().equals( that.getGroupId() )
+ && getVersion().equals( that.getVersion() ) && getType().equals( that.getType() )
+ && getNature().equals( that.getNature() ) && eq( getFile(), that.getFile() )
+ && eq( getProperties(), that.getProperties() );
+ }
+
+ private static <T> boolean eq( T s1, T s2 )
+ {
+ return s1 != null ? s1.equals( s2 ) : s2 == null;
+ }
+
+ /**
+ * Returns a hash code for this metadata.
+ *
+ * @return A hash code for the metadata.
+ */
+ @Override
+ public int hashCode()
+ {
+ int hash = 17;
+ hash = hash * 31 + getGroupId().hashCode();
+ hash = hash * 31 + getArtifactId().hashCode();
+ hash = hash * 31 + getType().hashCode();
+ hash = hash * 31 + getNature().hashCode();
+ hash = hash * 31 + getVersion().hashCode();
+ hash = hash * 31 + hash( getFile() );
+ return hash;
+ }
+
+ private static int hash( Object obj )
+ {
+ return ( obj != null ) ? obj.hashCode() : 0;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/DefaultMetadata.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/DefaultMetadata.java b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/DefaultMetadata.java
new file mode 100644
index 0000000..1efbb72
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/DefaultMetadata.java
@@ -0,0 +1,192 @@
+package org.eclipse.aether.metadata;
+
+/*
+ * 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.
+ */
+
+import java.io.File;
+import java.util.Map;
+
+/**
+ * A basic metadata instance. <em>Note:</em> Instances of this class are immutable and the exposed mutators return new
+ * objects rather than changing the current instance.
+ */
+public final class DefaultMetadata
+ extends AbstractMetadata
+{
+
+ private final String groupId;
+
+ private final String artifactId;
+
+ private final String version;
+
+ private final String type;
+
+ private final Nature nature;
+
+ private final File file;
+
+ private final Map<String, String> properties;
+
+ /**
+ * Creates a new metadata for the repository root with the specific type and nature.
+ *
+ * @param type The type of the metadata, e.g. "maven-metadata.xml", may be {@code null}.
+ * @param nature The nature of the metadata, must not be {@code null}.
+ */
+ public DefaultMetadata( String type, Nature nature )
+ {
+ this( "", "", "", type, nature, null, (File) null );
+ }
+
+ /**
+ * Creates a new metadata for the groupId level with the specific type and nature.
+ *
+ * @param groupId The group identifier to which this metadata applies, may be {@code null}.
+ * @param type The type of the metadata, e.g. "maven-metadata.xml", may be {@code null}.
+ * @param nature The nature of the metadata, must not be {@code null}.
+ */
+ public DefaultMetadata( String groupId, String type, Nature nature )
+ {
+ this( groupId, "", "", type, nature, null, (File) null );
+ }
+
+ /**
+ * Creates a new metadata for the groupId:artifactId level with the specific type and nature.
+ *
+ * @param groupId The group identifier to which this metadata applies, may be {@code null}.
+ * @param artifactId The artifact identifier to which this metadata applies, may be {@code null}.
+ * @param type The type of the metadata, e.g. "maven-metadata.xml", may be {@code null}.
+ * @param nature The nature of the metadata, must not be {@code null}.
+ */
+ public DefaultMetadata( String groupId, String artifactId, String type, Nature nature )
+ {
+ this( groupId, artifactId, "", type, nature, null, (File) null );
+ }
+
+ /**
+ * Creates a new metadata for the groupId:artifactId:version level with the specific type and nature.
+ *
+ * @param groupId The group identifier to which this metadata applies, may be {@code null}.
+ * @param artifactId The artifact identifier to which this metadata applies, may be {@code null}.
+ * @param version The version to which this metadata applies, may be {@code null}.
+ * @param type The type of the metadata, e.g. "maven-metadata.xml", may be {@code null}.
+ * @param nature The nature of the metadata, must not be {@code null}.
+ */
+ public DefaultMetadata( String groupId, String artifactId, String version, String type, Nature nature )
+ {
+ this( groupId, artifactId, version, type, nature, null, (File) null );
+ }
+
+ /**
+ * Creates a new metadata for the groupId:artifactId:version level with the specific type and nature.
+ *
+ * @param groupId The group identifier to which this metadata applies, may be {@code null}.
+ * @param artifactId The artifact identifier to which this metadata applies, may be {@code null}.
+ * @param version The version to which this metadata applies, may be {@code null}.
+ * @param type The type of the metadata, e.g. "maven-metadata.xml", may be {@code null}.
+ * @param nature The nature of the metadata, must not be {@code null}.
+ * @param file The resolved file of the metadata, may be {@code null}.
+ */
+ public DefaultMetadata( String groupId, String artifactId, String version, String type, Nature nature, File file )
+ {
+ this( groupId, artifactId, version, type, nature, null, file );
+ }
+
+ /**
+ * Creates a new metadata for the groupId:artifactId:version level with the specific type and nature.
+ *
+ * @param groupId The group identifier to which this metadata applies, may be {@code null}.
+ * @param artifactId The artifact identifier to which this metadata applies, may be {@code null}.
+ * @param version The version to which this metadata applies, may be {@code null}.
+ * @param type The type of the metadata, e.g. "maven-metadata.xml", may be {@code null}.
+ * @param nature The nature of the metadata, must not be {@code null}.
+ * @param properties The properties of the metadata, may be {@code null} if none.
+ * @param file The resolved file of the metadata, may be {@code null}.
+ */
+ public DefaultMetadata( String groupId, String artifactId, String version, String type, Nature nature,
+ Map<String, String> properties, File file )
+ {
+ this.groupId = emptify( groupId );
+ this.artifactId = emptify( artifactId );
+ this.version = emptify( version );
+ this.type = emptify( type );
+ if ( nature == null )
+ {
+ throw new IllegalArgumentException( "metadata nature was not specified" );
+ }
+ this.nature = nature;
+ this.file = file;
+ this.properties = copyProperties( properties );
+ }
+
+ DefaultMetadata( String groupId, String artifactId, String version, String type, Nature nature, File file,
+ Map<String, String> properties )
+ {
+ // NOTE: This constructor assumes immutability of the provided properties, for internal use only
+ this.groupId = emptify( groupId );
+ this.artifactId = emptify( artifactId );
+ this.version = emptify( version );
+ this.type = emptify( type );
+ this.nature = nature;
+ this.file = file;
+ this.properties = properties;
+ }
+
+ private static String emptify( String str )
+ {
+ return ( str == null ) ? "" : str;
+ }
+
+ public String getGroupId()
+ {
+ return groupId;
+ }
+
+ public String getArtifactId()
+ {
+ return artifactId;
+ }
+
+ public String getVersion()
+ {
+ return version;
+ }
+
+ public String getType()
+ {
+ return type;
+ }
+
+ public Nature getNature()
+ {
+ return nature;
+ }
+
+ public File getFile()
+ {
+ return file;
+ }
+
+ public Map<String, String> getProperties()
+ {
+ return properties;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/MergeableMetadata.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/MergeableMetadata.java b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/MergeableMetadata.java
new file mode 100644
index 0000000..deaff70
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/MergeableMetadata.java
@@ -0,0 +1,51 @@
+package org.eclipse.aether.metadata;
+
+/*
+ * 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.
+ */
+
+import java.io.File;
+
+import org.eclipse.aether.RepositoryException;
+
+/**
+ * A piece of metadata that needs to be merged with any current metadata before installation/deployment.
+ */
+public interface MergeableMetadata
+ extends Metadata
+{
+
+ /**
+ * Merges this metadata into the current metadata (if any). Note that this method will be invoked regardless whether
+ * metadata currently exists or not.
+ *
+ * @param current The path to the current metadata file, may not exist but must not be {@code null}.
+ * @param result The path to the result file where the merged metadata should be stored, must not be {@code null}.
+ * @throws RepositoryException If the metadata could not be merged.
+ */
+ void merge( File current, File result )
+ throws RepositoryException;
+
+ /**
+ * Indicates whether this metadata has been merged.
+ *
+ * @return {@code true} if the metadata has been merged, {@code false} otherwise.
+ */
+ boolean isMerged();
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/Metadata.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/Metadata.java b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/Metadata.java
new file mode 100644
index 0000000..84e9212
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/Metadata.java
@@ -0,0 +1,138 @@
+package org.eclipse.aether.metadata;
+
+/*
+ * 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.
+ */
+
+import java.io.File;
+import java.util.Map;
+
+/**
+ * A piece of repository metadata, e.g. an index of available versions. In contrast to an artifact, which usually exists
+ * in only one repository, metadata usually exists in multiple repositories and each repository contains a different
+ * copy of the metadata. <em>Note:</em> Metadata instances are supposed to be immutable, e.g. any exposed mutator method
+ * returns a new metadata instance and leaves the original instance unchanged. Implementors are strongly advised to obey
+ * this contract. <em>Note:</em> Implementors are strongly advised to inherit from {@link AbstractMetadata} instead of
+ * directly implementing this interface.
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface Metadata
+{
+
+ /**
+ * The nature of the metadata.
+ */
+ enum Nature
+ {
+ /**
+ * The metadata refers to release artifacts only.
+ */
+ RELEASE,
+
+ /**
+ * The metadata refers to snapshot artifacts only.
+ */
+ SNAPSHOT,
+
+ /**
+ * The metadata refers to either release or snapshot artifacts.
+ */
+ RELEASE_OR_SNAPSHOT
+ }
+
+ /**
+ * Gets the group identifier of this metadata.
+ *
+ * @return The group identifier or an empty string if the metadata applies to the entire repository, never
+ * {@code null}.
+ */
+ String getGroupId();
+
+ /**
+ * Gets the artifact identifier of this metadata.
+ *
+ * @return The artifact identifier or an empty string if the metadata applies to the groupId level only, never
+ * {@code null}.
+ */
+ String getArtifactId();
+
+ /**
+ * Gets the version of this metadata.
+ *
+ * @return The version or an empty string if the metadata applies to the groupId:artifactId level only, never
+ * {@code null}.
+ */
+ String getVersion();
+
+ /**
+ * Gets the type of the metadata, e.g. "maven-metadata.xml".
+ *
+ * @return The type of the metadata, never {@code null}.
+ */
+ String getType();
+
+ /**
+ * Gets the nature of this metadata. The nature indicates to what artifact versions the metadata refers.
+ *
+ * @return The nature, never {@code null}.
+ */
+ Nature getNature();
+
+ /**
+ * Gets the file of this metadata. Note that only resolved metadata has a file associated with it.
+ *
+ * @return The file or {@code null} if none.
+ */
+ File getFile();
+
+ /**
+ * Sets the file of the metadata.
+ *
+ * @param file The file of the metadata, may be {@code null}
+ * @return The new metadata, never {@code null}.
+ */
+ Metadata setFile( File file );
+
+ /**
+ * Gets the specified property.
+ *
+ * @param key The name of the property, must not be {@code null}.
+ * @param defaultValue The default value to return in case the property is not set, may be {@code null}.
+ * @return The requested property value or {@code null} if the property is not set and no default value was
+ * provided.
+ */
+ String getProperty( String key, String defaultValue );
+
+ /**
+ * Gets the properties of this metadata.
+ *
+ * @return The (read-only) properties, never {@code null}.
+ */
+ Map<String, String> getProperties();
+
+ /**
+ * Sets the properties for the metadata.
+ *
+ * @param properties The properties for the metadata, may be {@code null}.
+ * @return The new metadata, never {@code null}.
+ */
+ Metadata setProperties( Map<String, String> properties );
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/package-info.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/package-info.java b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/package-info.java
new file mode 100644
index 0000000..e41f98e
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/package-info.java
@@ -0,0 +1,24 @@
+// CHECKSTYLE_OFF: RegexpHeader
+/*
+ * 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.
+ */
+/**
+ * The definition of metadata, that is an auxiliary entity managed by the repository system to locate artifacts.
+ */
+package org.eclipse.aether.metadata;
+
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/package-info.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/package-info.java b/maven-resolver-api/src/main/java/org/eclipse/aether/package-info.java
new file mode 100644
index 0000000..8d11fa8
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/package-info.java
@@ -0,0 +1,24 @@
+// CHECKSTYLE_OFF: RegexpHeader
+/*
+ * 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.
+ */
+/**
+ * The primary API of the {@link org.eclipse.aether.RepositorySystem} and its functionality.
+ */
+package org.eclipse.aether;
+
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/repository/ArtifactRepository.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/ArtifactRepository.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/ArtifactRepository.java
new file mode 100644
index 0000000..c62bf87
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/ArtifactRepository.java
@@ -0,0 +1,45 @@
+package org.eclipse.aether.repository;
+
+/*
+ * 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.
+ */
+
+/**
+ * A repository hosting artifacts.
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface ArtifactRepository
+{
+
+ /**
+ * Gets the type of the repository, for example "default".
+ *
+ * @return The (case-sensitive) type of the repository, never {@code null}.
+ */
+ String getContentType();
+
+ /**
+ * Gets the identifier of this repository.
+ *
+ * @return The (case-sensitive) identifier, never {@code null}.
+ */
+ String getId();
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/repository/Authentication.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/Authentication.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/Authentication.java
new file mode 100644
index 0000000..d85c2a2
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/Authentication.java
@@ -0,0 +1,55 @@
+package org.eclipse.aether.repository;
+
+/*
+ * 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.
+ */
+
+import java.util.Map;
+
+/**
+ * The authentication to use for accessing a protected resource. This acts basically as an extensible callback mechanism
+ * from which network operations can request authentication data like username and password when needed.
+ */
+public interface Authentication
+{
+
+ /**
+ * Fills the given authentication context with the data from this authentication callback. To do so, implementors
+ * have to call {@link AuthenticationContext#put(String, Object)}. <br>
+ * <br>
+ * The {@code key} parameter supplied to this method acts merely as a hint for interactive callbacks that want to
+ * prompt the user for only that authentication data which is required. Implementations are free to ignore this
+ * parameter and put all the data they have into the authentication context at once.
+ *
+ * @param context The authentication context to populate, must not be {@code null}.
+ * @param key The key denoting a specific piece of authentication data that is being requested for a network
+ * operation, may be {@code null}.
+ * @param data Any (read-only) extra data in form of key value pairs that might be useful when getting the
+ * authentication data, may be {@code null}.
+ */
+ void fill( AuthenticationContext context, String key, Map<String, String> data );
+
+ /**
+ * Updates the given digest with data from this authentication callback. To do so, implementors have to call the
+ * {@code update()} methods in {@link AuthenticationDigest}.
+ *
+ * @param digest The digest to update, must not be {@code null}.
+ */
+ void digest( AuthenticationDigest digest );
+
+}