http://git-wip-us.apache.org/repos/asf/maven-resolver/blob/3a1b8ae0/maven-resolver-api/src/main/java/org/eclipse/aether/collection/package-info.java ---------------------------------------------------------------------- diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/collection/package-info.java b/maven-resolver-api/src/main/java/org/eclipse/aether/collection/package-info.java new file mode 100644 index 0000000..414629f --- /dev/null +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/collection/package-info.java @@ -0,0 +1,25 @@ +// 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 and extension points for collecting the transitive dependencies of an artifact and building a dependency + * graph. + */ +package org.eclipse.aether.collection; +
http://git-wip-us.apache.org/repos/asf/maven-resolver/blob/3a1b8ae0/maven-resolver-api/src/main/java/org/eclipse/aether/deployment/DeployRequest.java ---------------------------------------------------------------------- diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/deployment/DeployRequest.java b/maven-resolver-api/src/main/java/org/eclipse/aether/deployment/DeployRequest.java new file mode 100644 index 0000000..637f47d --- /dev/null +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/deployment/DeployRequest.java @@ -0,0 +1,202 @@ +package org.eclipse.aether.deployment; + +/* + * 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; +import org.eclipse.aether.repository.RemoteRepository; + +/** + * A request to deploy artifacts and their accompanying metadata into the a remote repository. + * + * @see RepositorySystem#deploy(RepositorySystemSession, DeployRequest) + */ +public final class DeployRequest +{ + + private Collection<Artifact> artifacts = Collections.emptyList(); + + private Collection<Metadata> metadata = Collections.emptyList(); + + private RemoteRepository repository; + + private RequestTrace trace; + + /** + * Creates an uninitialized request. + */ + public DeployRequest() + { + } + + /** + * Gets the artifact to deploy. + * + * @return The artifacts to deploy, never {@code null}. + */ + public Collection<Artifact> getArtifacts() + { + return artifacts; + } + + /** + * Sets the artifacts to deploy. + * + * @param artifacts The artifacts to deploy, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + public DeployRequest setArtifacts( Collection<Artifact> artifacts ) + { + if ( artifacts == null ) + { + this.artifacts = Collections.emptyList(); + } + else + { + this.artifacts = artifacts; + } + return this; + } + + /** + * Adds the specified artifacts for deployment. + * + * @param artifact The artifact to add, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + public DeployRequest addArtifact( Artifact artifact ) + { + if ( artifact != null ) + { + if ( artifacts.isEmpty() ) + { + artifacts = new ArrayList<Artifact>(); + } + artifacts.add( artifact ); + } + return this; + } + + /** + * Gets the metadata to deploy. + * + * @return The metadata to deploy, never {@code null}. + */ + public Collection<Metadata> getMetadata() + { + return metadata; + } + + /** + * Sets the metadata to deploy. + * + * @param metadata The metadata to deploy, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + public DeployRequest setMetadata( Collection<Metadata> metadata ) + { + if ( metadata == null ) + { + this.metadata = Collections.emptyList(); + } + else + { + this.metadata = metadata; + } + return this; + } + + /** + * Adds the specified metadata for deployment. + * + * @param metadata The metadata to add, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + public DeployRequest addMetadata( Metadata metadata ) + { + if ( metadata != null ) + { + if ( this.metadata.isEmpty() ) + { + this.metadata = new ArrayList<Metadata>(); + } + this.metadata.add( metadata ); + } + return this; + } + + /** + * Gets the repository to deploy to. + * + * @return The repository to deploy to or {@code null} if not set. + */ + public RemoteRepository getRepository() + { + return repository; + } + + /** + * Sets the repository to deploy to. + * + * @param repository The repository to deploy to, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + public DeployRequest setRepository( RemoteRepository repository ) + { + this.repository = repository; + 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 DeployRequest setTrace( RequestTrace trace ) + { + this.trace = trace; + return this; + } + + @Override + public String toString() + { + return getArtifacts() + ", " + getMetadata() + " > " + getRepository(); + } + +} http://git-wip-us.apache.org/repos/asf/maven-resolver/blob/3a1b8ae0/maven-resolver-api/src/main/java/org/eclipse/aether/deployment/DeployResult.java ---------------------------------------------------------------------- diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/deployment/DeployResult.java b/maven-resolver-api/src/main/java/org/eclipse/aether/deployment/DeployResult.java new file mode 100644 index 0000000..f75705e --- /dev/null +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/deployment/DeployResult.java @@ -0,0 +1,174 @@ +package org.eclipse.aether.deployment; + +/* + * 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 deploying artifacts and their accompanying metadata into the a remote repository. + * + * @see RepositorySystem#deploy(RepositorySystemSession, DeployRequest) + */ +public final class DeployResult +{ + + private final DeployRequest request; + + private Collection<Artifact> artifacts; + + private Collection<Metadata> metadata; + + /** + * Creates a new result for the specified request. + * + * @param request The deployment request, must not be {@code null}. + */ + public DeployResult( DeployRequest request ) + { + if ( request == null ) + { + throw new IllegalArgumentException( "deploy request has not been specified" ); + } + this.request = request; + artifacts = Collections.emptyList(); + metadata = Collections.emptyList(); + } + + /** + * Gets the deploy request that was made. + * + * @return The deploy request, never {@code null}. + */ + public DeployRequest getRequest() + { + return request; + } + + /** + * Gets the artifacts that got deployed. + * + * @return The deployed artifacts, never {@code null}. + */ + public Collection<Artifact> getArtifacts() + { + return artifacts; + } + + /** + * Sets the artifacts that got deployed. + * + * @param artifacts The deployed artifacts, may be {@code null}. + * @return This result for chaining, never {@code null}. + */ + public DeployResult 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 deployed artifact to add, may be {@code null}. + * @return This result for chaining, never {@code null}. + */ + public DeployResult addArtifact( Artifact artifact ) + { + if ( artifact != null ) + { + if ( artifacts.isEmpty() ) + { + artifacts = new ArrayList<Artifact>(); + } + artifacts.add( artifact ); + } + return this; + } + + /** + * Gets the metadata that got deployed. Note that due to automatically generated metadata, there might have been + * more metadata deployed than originally specified in the deploy request. + * + * @return The deployed metadata, never {@code null}. + */ + public Collection<Metadata> getMetadata() + { + return metadata; + } + + /** + * Sets the metadata that got deployed. + * + * @param metadata The deployed metadata, may be {@code null}. + * @return This result for chaining, never {@code null}. + */ + public DeployResult 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 deployed metadata to add, may be {@code null}. + * @return This result for chaining, never {@code null}. + */ + public DeployResult 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-resolver/blob/3a1b8ae0/maven-resolver-api/src/main/java/org/eclipse/aether/deployment/DeploymentException.java ---------------------------------------------------------------------- diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/deployment/DeploymentException.java b/maven-resolver-api/src/main/java/org/eclipse/aether/deployment/DeploymentException.java new file mode 100644 index 0000000..53252ba --- /dev/null +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/deployment/DeploymentException.java @@ -0,0 +1,52 @@ +package org.eclipse.aether.deployment; + +/* + * 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 a deployment error like authentication failure. + */ +public class DeploymentException + extends RepositoryException +{ + + /** + * Creates a new exception with the specified detail message. + * + * @param message The detail message, may be {@code null}. + */ + public DeploymentException( 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 DeploymentException( String message, Throwable cause ) + { + super( message, cause ); + } + +} http://git-wip-us.apache.org/repos/asf/maven-resolver/blob/3a1b8ae0/maven-resolver-api/src/main/java/org/eclipse/aether/deployment/package-info.java ---------------------------------------------------------------------- diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/deployment/package-info.java b/maven-resolver-api/src/main/java/org/eclipse/aether/deployment/package-info.java new file mode 100644 index 0000000..dc50c21 --- /dev/null +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/deployment/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 remote repository. + */ +package org.eclipse.aether.deployment; + http://git-wip-us.apache.org/repos/asf/maven-resolver/blob/3a1b8ae0/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java ---------------------------------------------------------------------- diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java new file mode 100644 index 0000000..66a60c6 --- /dev/null +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java @@ -0,0 +1,368 @@ +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.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +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. + */ +public final class DefaultDependencyNode + implements DependencyNode +{ + + private List<DependencyNode> children; + + private Dependency dependency; + + private Artifact artifact; + + private List<? extends Artifact> relocations; + + private Collection<? extends Artifact> aliases; + + private VersionConstraint versionConstraint; + + private Version version; + + private byte managedBits; + + private List<RemoteRepository> repositories; + + private String context; + + private Map<Object, Object> data; + + /** + * Creates a new node with the specified dependency. + * + * @param dependency The dependency associated with this node, may be {@code null} for a root node. + */ + public DefaultDependencyNode( Dependency dependency ) + { + this.dependency = dependency; + artifact = ( dependency != null ) ? dependency.getArtifact() : null; + children = new ArrayList<DependencyNode>( 0 ); + aliases = relocations = Collections.emptyList(); + repositories = Collections.emptyList(); + context = ""; + data = Collections.emptyMap(); + } + + /** + * Creates a new root node with the specified artifact as its label. Note that the new node has no dependency, i.e. + * {@link #getDependency()} will return {@code null}. Put differently, the specified artifact will not be subject to + * dependency collection/resolution. + * + * @param artifact The artifact to use as label for this node, may be {@code null}. + */ + public DefaultDependencyNode( Artifact artifact ) + { + this.artifact = artifact; + children = new ArrayList<DependencyNode>( 0 ); + aliases = relocations = Collections.emptyList(); + repositories = Collections.emptyList(); + context = ""; + data = Collections.emptyMap(); + } + + /** + * Creates a mostly shallow clone of the specified node. The new node has its own copy of any custom data and + * initially no children. + * + * @param node The node to copy, must not be {@code null}. + */ + public DefaultDependencyNode( DependencyNode node ) + { + dependency = node.getDependency(); + artifact = node.getArtifact(); + children = new ArrayList<DependencyNode>( 0 ); + setAliases( node.getAliases() ); + setRequestContext( node.getRequestContext() ); + setManagedBits( node.getManagedBits() ); + setRelocations( node.getRelocations() ); + setRepositories( node.getRepositories() ); + setVersion( node.getVersion() ); + setVersionConstraint( node.getVersionConstraint() ); + Map<?, ?> data = node.getData(); + setData( data.isEmpty() ? null : new HashMap<Object, Object>( data ) ); + } + + public List<DependencyNode> getChildren() + { + return children; + } + + public void setChildren( List<DependencyNode> children ) + { + if ( children == null ) + { + this.children = new ArrayList<DependencyNode>( 0 ); + } + else + { + this.children = children; + } + } + + public Dependency getDependency() + { + return dependency; + } + + public Artifact getArtifact() + { + return artifact; + } + + public void setArtifact( Artifact artifact ) + { + if ( dependency == null ) + { + throw new UnsupportedOperationException( "node does not have a dependency" ); + } + dependency = dependency.setArtifact( artifact ); + this.artifact = dependency.getArtifact(); + } + + public List<? extends Artifact> getRelocations() + { + return relocations; + } + + /** + * Sets the sequence of relocations that was followed to resolve this dependency's artifact. + * + * @param relocations The sequence of relocations, may be {@code null}. + */ + public void setRelocations( List<? extends Artifact> relocations ) + { + if ( relocations == null || relocations.isEmpty() ) + { + this.relocations = Collections.emptyList(); + } + else + { + this.relocations = relocations; + } + } + + public Collection<? extends Artifact> getAliases() + { + return aliases; + } + + /** + * Sets the known aliases for this dependency's artifact. + * + * @param aliases The known aliases, may be {@code null}. + */ + public void setAliases( Collection<? extends Artifact> aliases ) + { + if ( aliases == null || aliases.isEmpty() ) + { + this.aliases = Collections.emptyList(); + } + else + { + this.aliases = aliases; + } + } + + public VersionConstraint getVersionConstraint() + { + return versionConstraint; + } + + /** + * Sets the version constraint that was parsed from the dependency's version declaration. + * + * @param versionConstraint The version constraint for this node, may be {@code null}. + */ + public void setVersionConstraint( VersionConstraint versionConstraint ) + { + this.versionConstraint = versionConstraint; + } + + public Version getVersion() + { + return version; + } + + /** + * Sets the version that was selected for the dependency's target artifact. + * + * @param version The parsed version, may be {@code null}. + */ + public void setVersion( Version version ) + { + this.version = version; + } + + public void setScope( String scope ) + { + if ( dependency == null ) + { + throw new UnsupportedOperationException( "node does not have a dependency" ); + } + dependency = dependency.setScope( scope ); + } + + public void setOptional( Boolean optional ) + { + if ( dependency == null ) + { + throw new UnsupportedOperationException( "node does not have a dependency" ); + } + dependency = dependency.setOptional( optional ); + } + + public int getManagedBits() + { + return managedBits; + } + + /** + * Sets a bit field indicating which attributes of this node were subject to dependency management. + * + * @param managedBits The bit field indicating the managed attributes or {@code 0} if dependency management wasn't + * applied. + */ + public void setManagedBits( int managedBits ) + { + this.managedBits = (byte) ( managedBits & 0x1F ); + } + + public List<RemoteRepository> getRepositories() + { + return repositories; + } + + /** + * Sets the remote repositories from which this node's artifact shall be resolved. + * + * @param repositories The remote repositories to use for artifact resolution, may be {@code null}. + */ + public void setRepositories( List<RemoteRepository> repositories ) + { + if ( repositories == null || repositories.isEmpty() ) + { + this.repositories = Collections.emptyList(); + } + else + { + this.repositories = repositories; + } + } + + public String getRequestContext() + { + return context; + } + + public void setRequestContext( String context ) + { + this.context = ( context != null ) ? context : ""; + } + + public Map<Object, Object> getData() + { + return data; + } + + public void setData( Map<Object, Object> data ) + { + if ( data == null ) + { + this.data = Collections.emptyMap(); + } + else + { + this.data = data; + } + } + + public void setData( Object key, Object value ) + { + if ( key == null ) + { + throw new IllegalArgumentException( "key must not be null" ); + } + + if ( value == null ) + { + if ( !data.isEmpty() ) + { + data.remove( key ); + + if ( data.isEmpty() ) + { + data = Collections.emptyMap(); + } + } + } + else + { + if ( data.isEmpty() ) + { + data = new HashMap<Object, Object>( 1, 2 ); // nodes can be numerous so let's be space conservative + } + data.put( key, value ); + } + } + + public boolean accept( DependencyVisitor visitor ) + { + if ( visitor.visitEnter( this ) ) + { + for ( DependencyNode child : children ) + { + if ( !child.accept( visitor ) ) + { + break; + } + } + } + + return visitor.visitLeave( this ); + } + + @Override + public String toString() + { + Dependency dep = getDependency(); + if ( dep == null ) + { + return String.valueOf( getArtifact() ); + } + return dep.toString(); + } + +} http://git-wip-us.apache.org/repos/asf/maven-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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..2551043 --- /dev/null +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java @@ -0,0 +1,232 @@ +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 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-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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; + } + +}