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:25 UTC
[02/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/repository/AuthenticationContext.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/AuthenticationContext.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/AuthenticationContext.java
new file mode 100644
index 0000000..bd248a0
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/AuthenticationContext.java
@@ -0,0 +1,389 @@
+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.io.Closeable;
+import java.io.File;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.aether.RepositorySystemSession;
+
+/**
+ * A glorified map of key value pairs holding (cleartext) authentication data. Authentication contexts are used
+ * internally when network operations need to access secured repositories or proxies. Each authentication context
+ * manages the credentials required to access a single host. Unlike {@link Authentication} callbacks which exist for a
+ * potentially long time like the duration of a repository system session, an authentication context has a supposedly
+ * short lifetime and should be {@link #close() closed} as soon as the corresponding network operation has finished:
+ *
+ * <pre>
+ * AuthenticationContext context = AuthenticationContext.forRepository( session, repository );
+ * try {
+ * // get credentials
+ * char[] password = context.get( AuthenticationContext.PASSWORD, char[].class );
+ * // perform network operation using retrieved credentials
+ * ...
+ * } finally {
+ * // erase confidential authentication data from heap memory
+ * AuthenticationContext.close( context );
+ * }
+ * </pre>
+ *
+ * The same authentication data can often be presented using different data types, e.g. a password can be presented
+ * using a character array or (less securely) using a string. For ease of use, an authentication context treats the
+ * following groups of data types as equivalent and converts values automatically during retrieval:
+ * <ul>
+ * <li>{@code String}, {@code char[]}</li>
+ * <li>{@code String}, {@code File}</li>
+ * </ul>
+ * An authentication context is thread-safe.
+ */
+public final class AuthenticationContext
+ implements Closeable
+{
+
+ /**
+ * The key used to store the username. The corresponding authentication data should be of type {@link String}.
+ */
+ public static final String USERNAME = "username";
+
+ /**
+ * The key used to store the password. The corresponding authentication data should be of type {@code char[]} or
+ * {@link String}.
+ */
+ public static final String PASSWORD = "password";
+
+ /**
+ * The key used to store the NTLM domain. The corresponding authentication data should be of type {@link String}.
+ */
+ public static final String NTLM_DOMAIN = "ntlm.domain";
+
+ /**
+ * The key used to store the NTML workstation. The corresponding authentication data should be of type
+ * {@link String}.
+ */
+ public static final String NTLM_WORKSTATION = "ntlm.workstation";
+
+ /**
+ * The key used to store the pathname to a private key file. The corresponding authentication data should be of type
+ * {@link String} or {@link File}.
+ */
+ public static final String PRIVATE_KEY_PATH = "privateKey.path";
+
+ /**
+ * The key used to store the passphrase protecting the private key. The corresponding authentication data should be
+ * of type {@code char[]} or {@link String}.
+ */
+ public static final String PRIVATE_KEY_PASSPHRASE = "privateKey.passphrase";
+
+ /**
+ * The key used to store the acceptance policy for unknown host keys. The corresponding authentication data should
+ * be of type {@link Boolean}. When querying this authentication data, the extra data should provide
+ * {@link #HOST_KEY_REMOTE} and {@link #HOST_KEY_LOCAL}, e.g. to enable a well-founded decision of the user during
+ * an interactive prompt.
+ */
+ public static final String HOST_KEY_ACCEPTANCE = "hostKey.acceptance";
+
+ /**
+ * The key used to store the fingerprint of the public key advertised by remote host. Note that this key is used to
+ * query the extra data passed to {@link #get(String, Map, Class)} when getting {@link #HOST_KEY_ACCEPTANCE}, not
+ * the authentication data in a context.
+ */
+ public static final String HOST_KEY_REMOTE = "hostKey.remote";
+
+ /**
+ * The key used to store the fingerprint of the public key expected from remote host as recorded in a known hosts
+ * database. Note that this key is used to query the extra data passed to {@link #get(String, Map, Class)} when
+ * getting {@link #HOST_KEY_ACCEPTANCE}, not the authentication data in a context.
+ */
+ public static final String HOST_KEY_LOCAL = "hostKey.local";
+
+ /**
+ * The key used to store the SSL context. The corresponding authentication data should be of type
+ * {@link javax.net.ssl.SSLContext}.
+ */
+ public static final String SSL_CONTEXT = "ssl.context";
+
+ /**
+ * The key used to store the SSL hostname verifier. The corresponding authentication data should be of type
+ * {@link javax.net.ssl.HostnameVerifier}.
+ */
+ public static final String SSL_HOSTNAME_VERIFIER = "ssl.hostnameVerifier";
+
+ private final RepositorySystemSession session;
+
+ private final RemoteRepository repository;
+
+ private final Proxy proxy;
+
+ private final Authentication auth;
+
+ private final Map<String, Object> authData;
+
+ private boolean fillingAuthData;
+
+ /**
+ * Gets an authentication context for the specified repository.
+ *
+ * @param session The repository system session during which the repository is accessed, must not be {@code null}.
+ * @param repository The repository for which to create an authentication context, must not be {@code null}.
+ * @return An authentication context for the repository or {@code null} if no authentication is configured for it.
+ */
+ public static AuthenticationContext forRepository( RepositorySystemSession session, RemoteRepository repository )
+ {
+ return newInstance( session, repository, null, repository.getAuthentication() );
+ }
+
+ /**
+ * Gets an authentication context for the proxy of the specified repository.
+ *
+ * @param session The repository system session during which the repository is accessed, must not be {@code null}.
+ * @param repository The repository for whose proxy to create an authentication context, must not be {@code null}.
+ * @return An authentication context for the proxy or {@code null} if no proxy is set or no authentication is
+ * configured for it.
+ */
+ public static AuthenticationContext forProxy( RepositorySystemSession session, RemoteRepository repository )
+ {
+ Proxy proxy = repository.getProxy();
+ return newInstance( session, repository, proxy, ( proxy != null ) ? proxy.getAuthentication() : null );
+ }
+
+ private static AuthenticationContext newInstance( RepositorySystemSession session, RemoteRepository repository,
+ Proxy proxy, Authentication auth )
+ {
+ if ( auth == null )
+ {
+ return null;
+ }
+ return new AuthenticationContext( session, repository, proxy, auth );
+ }
+
+ private AuthenticationContext( RepositorySystemSession session, RemoteRepository repository, Proxy proxy,
+ Authentication auth )
+ {
+ if ( session == null )
+ {
+ throw new IllegalArgumentException( "repository system session missing" );
+ }
+ this.session = session;
+ this.repository = repository;
+ this.proxy = proxy;
+ this.auth = auth;
+ authData = new HashMap<String, Object>();
+ }
+
+ /**
+ * Gets the repository system session during which the authentication happens.
+ *
+ * @return The repository system session, never {@code null}.
+ */
+ public RepositorySystemSession getSession()
+ {
+ return session;
+ }
+
+ /**
+ * Gets the repository requiring authentication. If {@link #getProxy()} is not {@code null}, the data gathered by
+ * this authentication context does not apply to the repository's host but rather the proxy.
+ *
+ * @return The repository to be contacted, never {@code null}.
+ */
+ public RemoteRepository getRepository()
+ {
+ return repository;
+ }
+
+ /**
+ * Gets the proxy (if any) to be authenticated with.
+ *
+ * @return The proxy or {@code null} if authenticating directly with the repository's host.
+ */
+ public Proxy getProxy()
+ {
+ return proxy;
+ }
+
+ /**
+ * Gets the authentication data for the specified key.
+ *
+ * @param key The key whose authentication data should be retrieved, must not be {@code null}.
+ * @return The requested authentication data or {@code null} if none.
+ */
+ public String get( String key )
+ {
+ return get( key, null, String.class );
+ }
+
+ /**
+ * Gets the authentication data for the specified key.
+ *
+ * @param <T> The data type of the authentication data.
+ * @param key The key whose authentication data should be retrieved, must not be {@code null}.
+ * @param type The expected type of the authentication data, must not be {@code null}.
+ * @return The requested authentication data or {@code null} if none or if the data doesn't match the expected type.
+ */
+ public <T> T get( String key, Class<T> type )
+ {
+ return get( key, null, type );
+ }
+
+ /**
+ * Gets the authentication data for the specified key.
+ *
+ * @param <T> The data type of the authentication data.
+ * @param key The key whose authentication data should be retrieved, must not 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}.
+ * @param type The expected type of the authentication data, must not be {@code null}.
+ * @return The requested authentication data or {@code null} if none or if the data doesn't match the expected type.
+ */
+ public <T> T get( String key, Map<String, String> data, Class<T> type )
+ {
+ if ( key == null )
+ {
+ throw new IllegalArgumentException( "authentication data key missing" );
+ }
+ Object value;
+ synchronized ( authData )
+ {
+ value = authData.get( key );
+ if ( value == null && !authData.containsKey( key ) && !fillingAuthData )
+ {
+ if ( auth != null )
+ {
+ try
+ {
+ fillingAuthData = true;
+ auth.fill( this, key, data );
+ }
+ finally
+ {
+ fillingAuthData = false;
+ }
+ value = authData.get( key );
+ }
+ if ( value == null )
+ {
+ authData.put( key, value );
+ }
+ }
+ }
+
+ return convert( value, type );
+ }
+
+ private <T> T convert( Object value, Class<T> type )
+ {
+ if ( !type.isInstance( value ) )
+ {
+ if ( String.class.equals( type ) )
+ {
+ if ( value instanceof File )
+ {
+ value = ( (File) value ).getPath();
+ }
+ else if ( value instanceof char[] )
+ {
+ value = new String( (char[]) value );
+ }
+ }
+ else if ( File.class.equals( type ) )
+ {
+ if ( value instanceof String )
+ {
+ value = new File( (String) value );
+ }
+ }
+ else if ( char[].class.equals( type ) )
+ {
+ if ( value instanceof String )
+ {
+ value = ( (String) value ).toCharArray();
+ }
+ }
+ }
+
+ if ( type.isInstance( value ) )
+ {
+ return type.cast( value );
+ }
+
+ return null;
+ }
+
+ /**
+ * Puts the specified authentication data into this context. This method should only be called from implementors of
+ * {@link Authentication#fill(AuthenticationContext, String, Map)}. Passed in character arrays are not cloned and
+ * become owned by this context, i.e. get erased when the context gets closed.
+ *
+ * @param key The key to associate the authentication data with, must not be {@code null}.
+ * @param value The (cleartext) authentication data to store, may be {@code null}.
+ */
+ public void put( String key, Object value )
+ {
+ if ( key == null )
+ {
+ throw new IllegalArgumentException( "authentication data key missing" );
+ }
+ synchronized ( authData )
+ {
+ Object oldValue = authData.put( key, value );
+ if ( oldValue instanceof char[] )
+ {
+ Arrays.fill( (char[]) oldValue, '\0' );
+ }
+ }
+ }
+
+ /**
+ * Closes this authentication context and erases sensitive authentication data from heap memory. Closing an already
+ * closed context has no effect.
+ */
+ public void close()
+ {
+ synchronized ( authData )
+ {
+ for ( Object value : authData.values() )
+ {
+ if ( value instanceof char[] )
+ {
+ Arrays.fill( (char[]) value, '\0' );
+ }
+ }
+ authData.clear();
+ }
+ }
+
+ /**
+ * Closes the specified authentication context. This is a convenience method doing a {@code null} check before
+ * calling {@link #close()} on the given context.
+ *
+ * @param context The authentication context to close, may be {@code null}.
+ */
+ public static void close( AuthenticationContext context )
+ {
+ if ( context != null )
+ {
+ context.close();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/repository/AuthenticationDigest.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/AuthenticationDigest.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/AuthenticationDigest.java
new file mode 100644
index 0000000..03725b6
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/AuthenticationDigest.java
@@ -0,0 +1,219 @@
+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.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.eclipse.aether.RepositorySystemSession;
+
+/**
+ * A helper to calculate a fingerprint/digest for the authentication data of a repository/proxy. Such a fingerprint can
+ * be used to detect changes in the authentication data across JVM restarts without exposing sensitive information.
+ */
+public final class AuthenticationDigest
+{
+
+ private final MessageDigest digest;
+
+ private final RepositorySystemSession session;
+
+ private final RemoteRepository repository;
+
+ private final Proxy proxy;
+
+ /**
+ * Gets the fingerprint for the authentication of the specified repository.
+ *
+ * @param session The repository system session during which the fingerprint is requested, must not be {@code null}.
+ * @param repository The repository whose authentication is to be fingerprinted, must not be {@code null}.
+ * @return The fingerprint of the repository authentication or an empty string if no authentication is configured,
+ * never {@code null}.
+ */
+ public static String forRepository( RepositorySystemSession session, RemoteRepository repository )
+ {
+ String digest = "";
+ Authentication auth = repository.getAuthentication();
+ if ( auth != null )
+ {
+ AuthenticationDigest authDigest = new AuthenticationDigest( session, repository, null );
+ auth.digest( authDigest );
+ digest = authDigest.digest();
+ }
+ return digest;
+ }
+
+ /**
+ * Gets the fingerprint for the authentication of the specified repository's proxy.
+ *
+ * @param session The repository system session during which the fingerprint is requested, must not be {@code null}.
+ * @param repository The repository whose proxy authentication is to be fingerprinted, must not be {@code null}.
+ * @return The fingerprint of the proxy authentication or an empty string if no proxy is present or if no proxy
+ * authentication is configured, never {@code null}.
+ */
+ public static String forProxy( RepositorySystemSession session, RemoteRepository repository )
+ {
+ String digest = "";
+ Proxy proxy = repository.getProxy();
+ if ( proxy != null )
+ {
+ Authentication auth = proxy.getAuthentication();
+ if ( auth != null )
+ {
+ AuthenticationDigest authDigest = new AuthenticationDigest( session, repository, proxy );
+ auth.digest( authDigest );
+ digest = authDigest.digest();
+ }
+ }
+ return digest;
+ }
+
+ private AuthenticationDigest( RepositorySystemSession session, RemoteRepository repository, Proxy proxy )
+ {
+ this.session = session;
+ this.repository = repository;
+ this.proxy = proxy;
+ digest = newDigest();
+ }
+
+ private static MessageDigest newDigest()
+ {
+ try
+ {
+ return MessageDigest.getInstance( "SHA-1" );
+ }
+ catch ( NoSuchAlgorithmException e )
+ {
+ try
+ {
+ return MessageDigest.getInstance( "MD5" );
+ }
+ catch ( NoSuchAlgorithmException ne )
+ {
+ throw new IllegalStateException( ne );
+ }
+ }
+ }
+
+ /**
+ * Gets the repository system session during which the authentication fingerprint is calculated.
+ *
+ * @return The repository system session, never {@code null}.
+ */
+ public RepositorySystemSession getSession()
+ {
+ return session;
+ }
+
+ /**
+ * Gets the repository requiring authentication. If {@link #getProxy()} is not {@code null}, the data gathered by
+ * this authentication digest does not apply to the repository's host but rather the proxy.
+ *
+ * @return The repository to be contacted, never {@code null}.
+ */
+ public RemoteRepository getRepository()
+ {
+ return repository;
+ }
+
+ /**
+ * Gets the proxy (if any) to be authenticated with.
+ *
+ * @return The proxy or {@code null} if authenticating directly with the repository's host.
+ */
+ public Proxy getProxy()
+ {
+ return proxy;
+ }
+
+ /**
+ * Updates the digest with the specified strings.
+ *
+ * @param strings The strings to update the digest with, may be {@code null} or contain {@code null} elements.
+ */
+ public void update( String... strings )
+ {
+ if ( strings != null )
+ {
+ for ( String string : strings )
+ {
+ if ( string != null )
+ {
+ try
+ {
+ digest.update( string.getBytes( "UTF-8" ) );
+ }
+ catch ( UnsupportedEncodingException e )
+ {
+ throw new IllegalStateException( e );
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Updates the digest with the specified characters.
+ *
+ * @param chars The characters to update the digest with, may be {@code null}.
+ */
+ public void update( char... chars )
+ {
+ if ( chars != null )
+ {
+ for ( char c : chars )
+ {
+ digest.update( (byte) ( c >> 8 ) );
+ digest.update( (byte) ( c & 0xFF ) );
+ }
+ }
+ }
+
+ /**
+ * Updates the digest with the specified bytes.
+ *
+ * @param bytes The bytes to update the digest with, may be {@code null}.
+ */
+ public void update( byte... bytes )
+ {
+ if ( bytes != null )
+ {
+ digest.update( bytes );
+ }
+ }
+
+ private String digest()
+ {
+ byte[] bytes = digest.digest();
+ StringBuilder buffer = new StringBuilder( bytes.length * 2 );
+ for ( byte aByte : bytes )
+ {
+ int b = aByte & 0xFF;
+ if ( b < 0x10 )
+ {
+ buffer.append( '0' );
+ }
+ buffer.append( Integer.toHexString( b ) );
+ }
+ return buffer.toString();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/repository/AuthenticationSelector.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/AuthenticationSelector.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/AuthenticationSelector.java
new file mode 100644
index 0000000..0637d1c
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/AuthenticationSelector.java
@@ -0,0 +1,38 @@
+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.
+ */
+
+/**
+ * Selects authentication for a given remote repository.
+ *
+ * @see org.eclipse.aether.RepositorySystemSession#getAuthenticationSelector()
+ */
+public interface AuthenticationSelector
+{
+
+ /**
+ * Selects authentication for the specified remote repository.
+ *
+ * @param repository The repository for which to select authentication, must not be {@code null}.
+ * @return The selected authentication or {@code null} if none.
+ */
+ Authentication getAuthentication( RemoteRepository repository );
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalArtifactRegistration.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalArtifactRegistration.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalArtifactRegistration.java
new file mode 100644
index 0000000..1065779
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalArtifactRegistration.java
@@ -0,0 +1,149 @@
+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.Collection;
+import java.util.Collections;
+
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+
+/**
+ * A request to register an artifact within the local repository. Certain local repository implementations can refuse to
+ * serve physically present artifacts if those haven't been previously registered to them.
+ *
+ * @see LocalRepositoryManager#add(RepositorySystemSession, LocalArtifactRegistration)
+ */
+public final class LocalArtifactRegistration
+{
+
+ private Artifact artifact;
+
+ private RemoteRepository repository;
+
+ private Collection<String> contexts = Collections.emptyList();
+
+ /**
+ * Creates an uninitialized registration.
+ */
+ public LocalArtifactRegistration()
+ {
+ // enables default constructor
+ }
+
+ /**
+ * Creates a registration request for the specified (locally installed) artifact.
+ *
+ * @param artifact The artifact to register, may be {@code null}.
+ */
+ public LocalArtifactRegistration( Artifact artifact )
+ {
+ setArtifact( artifact );
+ }
+
+ /**
+ * Creates a registration request for the specified artifact.
+ *
+ * @param artifact The artifact to register, may be {@code null}.
+ * @param repository The remote repository from which the artifact was resolved or {@code null} if the artifact was
+ * locally installed.
+ * @param contexts The resolution contexts, may be {@code null}.
+ */
+ public LocalArtifactRegistration( Artifact artifact, RemoteRepository repository, Collection<String> contexts )
+ {
+ setArtifact( artifact );
+ setRepository( repository );
+ setContexts( contexts );
+ }
+
+ /**
+ * Gets the artifact to register.
+ *
+ * @return The artifact or {@code null} if not set.
+ */
+ public Artifact getArtifact()
+ {
+ return artifact;
+ }
+
+ /**
+ * Sets the artifact to register.
+ *
+ * @param artifact The artifact, may be {@code null}.
+ * @return This request for chaining, never {@code null}.
+ */
+ public LocalArtifactRegistration setArtifact( Artifact artifact )
+ {
+ this.artifact = artifact;
+ return this;
+ }
+
+ /**
+ * Gets the remote repository from which the artifact was resolved.
+ *
+ * @return The remote repository or {@code null} if the artifact was locally installed.
+ */
+ public RemoteRepository getRepository()
+ {
+ return repository;
+ }
+
+ /**
+ * Sets the remote repository from which the artifact was resolved.
+ *
+ * @param repository The remote repository or {@code null} if the artifact was locally installed.
+ * @return This request for chaining, never {@code null}.
+ */
+ public LocalArtifactRegistration setRepository( RemoteRepository repository )
+ {
+ this.repository = repository;
+ return this;
+ }
+
+ /**
+ * Gets the resolution contexts in which the artifact is available.
+ *
+ * @return The resolution contexts in which the artifact is available, never {@code null}.
+ */
+ public Collection<String> getContexts()
+ {
+ return contexts;
+ }
+
+ /**
+ * Sets the resolution contexts in which the artifact is available.
+ *
+ * @param contexts The resolution contexts, may be {@code null}.
+ * @return This request for chaining, never {@code null}.
+ */
+ public LocalArtifactRegistration setContexts( Collection<String> contexts )
+ {
+ if ( contexts != null )
+ {
+ this.contexts = contexts;
+ }
+ else
+ {
+ this.contexts = Collections.emptyList();
+ }
+ return this;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalArtifactRequest.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalArtifactRequest.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalArtifactRequest.java
new file mode 100644
index 0000000..8f6eabf
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalArtifactRequest.java
@@ -0,0 +1,145 @@
+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.Collections;
+import java.util.List;
+
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+
+/**
+ * A query to the local repository for the existence of an artifact.
+ *
+ * @see LocalRepositoryManager#find(RepositorySystemSession, LocalArtifactRequest)
+ */
+public final class LocalArtifactRequest
+{
+
+ private Artifact artifact;
+
+ private String context = "";
+
+ private List<RemoteRepository> repositories = Collections.emptyList();
+
+ /**
+ * Creates an uninitialized query.
+ */
+ public LocalArtifactRequest()
+ {
+ // enables default constructor
+ }
+
+ /**
+ * Creates a query with the specified properties.
+ *
+ * @param artifact The artifact to query for, may be {@code null}.
+ * @param repositories The remote repositories that should be considered as potential sources for the artifact, may
+ * be {@code null} or empty to only consider locally installed artifacts.
+ * @param context The resolution context for the artifact, may be {@code null}.
+ */
+ public LocalArtifactRequest( Artifact artifact, List<RemoteRepository> repositories, String context )
+ {
+ setArtifact( artifact );
+ setRepositories( repositories );
+ setContext( context );
+ }
+
+ /**
+ * Gets the artifact to query for.
+ *
+ * @return The artifact or {@code null} if not set.
+ */
+ public Artifact getArtifact()
+ {
+ return artifact;
+ }
+
+ /**
+ * Sets the artifact to query for.
+ *
+ * @param artifact The artifact, may be {@code null}.
+ * @return This query for chaining, never {@code null}.
+ */
+ public LocalArtifactRequest setArtifact( Artifact artifact )
+ {
+ this.artifact = artifact;
+ return this;
+ }
+
+ /**
+ * Gets the resolution context.
+ *
+ * @return The resolution context, never {@code null}.
+ */
+ public String getContext()
+ {
+ return context;
+ }
+
+ /**
+ * Sets the resolution context.
+ *
+ * @param context The resolution context, may be {@code null}.
+ * @return This query for chaining, never {@code null}.
+ */
+ public LocalArtifactRequest setContext( String context )
+ {
+ this.context = ( context != null ) ? context : "";
+ return this;
+ }
+
+ /**
+ * Gets the remote repositories to consider as sources of the artifact.
+ *
+ * @return The remote repositories, never {@code null}.
+ */
+ public List<RemoteRepository> getRepositories()
+ {
+ return repositories;
+ }
+
+ /**
+ * Sets the remote repositories to consider as sources of the artifact.
+ *
+ * @param repositories The remote repositories, may be {@code null} or empty to only consider locally installed
+ * artifacts.
+ * @return This query for chaining, never {@code null}.
+ */
+ public LocalArtifactRequest setRepositories( List<RemoteRepository> repositories )
+ {
+ if ( repositories != null )
+ {
+ this.repositories = repositories;
+ }
+ else
+ {
+ this.repositories = Collections.emptyList();
+ }
+ return this;
+ }
+
+ @Override
+ public String toString()
+ {
+ return getArtifact() + " @ " + getRepositories();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalArtifactResult.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalArtifactResult.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalArtifactResult.java
new file mode 100644
index 0000000..e611b27
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalArtifactResult.java
@@ -0,0 +1,147 @@
+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.io.File;
+
+import org.eclipse.aether.RepositorySystemSession;
+
+/**
+ * A result from the local repository about the existence of an artifact.
+ *
+ * @see LocalRepositoryManager#find(RepositorySystemSession, LocalArtifactRequest)
+ */
+public final class LocalArtifactResult
+{
+
+ private final LocalArtifactRequest request;
+
+ private File file;
+
+ private boolean available;
+
+ private RemoteRepository repository;
+
+ /**
+ * Creates a new result for the specified request.
+ *
+ * @param request The local artifact request, must not be {@code null}.
+ */
+ public LocalArtifactResult( LocalArtifactRequest request )
+ {
+ if ( request == null )
+ {
+ throw new IllegalArgumentException( "local artifact request has not been specified" );
+ }
+ this.request = request;
+ }
+
+ /**
+ * Gets the request corresponding to this result.
+ *
+ * @return The corresponding request, never {@code null}.
+ */
+ public LocalArtifactRequest getRequest()
+ {
+ return request;
+ }
+
+ /**
+ * Gets the file to the requested artifact. Note that this file must not be used unless {@link #isAvailable()}
+ * returns {@code true}. An artifact file can be found but considered unavailable if the artifact was cached from a
+ * remote repository that is not part of the list of remote repositories used for the query.
+ *
+ * @return The file to the requested artifact or {@code null} if the artifact does not exist locally.
+ */
+ public File getFile()
+ {
+ return file;
+ }
+
+ /**
+ * Sets the file to requested artifact.
+ *
+ * @param file The artifact file, may be {@code null}.
+ * @return This result for chaining, never {@code null}.
+ */
+ public LocalArtifactResult setFile( File file )
+ {
+ this.file = file;
+ return this;
+ }
+
+ /**
+ * Indicates whether the requested artifact is available for use. As a minimum, the file needs to be physically
+ * existent in the local repository to be available. Additionally, a local repository manager can consider the list
+ * of supplied remote repositories to determine whether the artifact is logically available and mark an artifact
+ * unavailable (despite its physical existence) if it is not known to be hosted by any of the provided repositories.
+ *
+ * @return {@code true} if the artifact is available, {@code false} otherwise.
+ * @see LocalArtifactRequest#getRepositories()
+ */
+ public boolean isAvailable()
+ {
+ return available;
+ }
+
+ /**
+ * Sets whether the artifact is available.
+ *
+ * @param available {@code true} if the artifact is available, {@code false} otherwise.
+ * @return This result for chaining, never {@code null}.
+ */
+ public LocalArtifactResult setAvailable( boolean available )
+ {
+ this.available = available;
+ return this;
+ }
+
+ /**
+ * Gets the (first) remote repository from which the artifact was cached (if any).
+ *
+ * @return The remote repository from which the artifact was originally retrieved or {@code null} if unknown or if
+ * the artifact has been locally installed.
+ * @see LocalArtifactRequest#getRepositories()
+ */
+ public RemoteRepository getRepository()
+ {
+ return repository;
+ }
+
+ /**
+ * Sets the (first) remote repository from which the artifact was cached.
+ *
+ * @param repository The remote repository from which the artifact was originally retrieved, may be {@code null} if
+ * unknown or if the artifact has been locally installed.
+ * @return This result for chaining, never {@code null}.
+ */
+ public LocalArtifactResult setRepository( RemoteRepository repository )
+ {
+ this.repository = repository;
+ return this;
+ }
+
+ @Override
+ public String toString()
+ {
+ return getFile() + " (" + ( isAvailable() ? "available" : "unavailable" ) + ")";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalMetadataRegistration.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalMetadataRegistration.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalMetadataRegistration.java
new file mode 100644
index 0000000..dd0d587
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalMetadataRegistration.java
@@ -0,0 +1,148 @@
+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.Collection;
+import java.util.Collections;
+
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.metadata.Metadata;
+
+/**
+ * A request to register metadata within the local repository.
+ *
+ * @see LocalRepositoryManager#add(RepositorySystemSession, LocalMetadataRegistration)
+ */
+public final class LocalMetadataRegistration
+{
+
+ private Metadata metadata;
+
+ private RemoteRepository repository;
+
+ private Collection<String> contexts = Collections.emptyList();
+
+ /**
+ * Creates an uninitialized registration.
+ */
+ public LocalMetadataRegistration()
+ {
+ // enables default constructor
+ }
+
+ /**
+ * Creates a registration request for the specified metadata accompanying a locally installed artifact.
+ *
+ * @param metadata The metadata to register, may be {@code null}.
+ */
+ public LocalMetadataRegistration( Metadata metadata )
+ {
+ setMetadata( metadata );
+ }
+
+ /**
+ * Creates a registration request for the specified metadata.
+ *
+ * @param metadata The metadata to register, may be {@code null}.
+ * @param repository The remote repository from which the metadata was resolved or {@code null} if the metadata
+ * accompanies a locally installed artifact.
+ * @param contexts The resolution contexts, may be {@code null}.
+ */
+ public LocalMetadataRegistration( Metadata metadata, RemoteRepository repository, Collection<String> contexts )
+ {
+ setMetadata( metadata );
+ setRepository( repository );
+ setContexts( contexts );
+ }
+
+ /**
+ * Gets the metadata to register.
+ *
+ * @return The metadata or {@code null} if not set.
+ */
+ public Metadata getMetadata()
+ {
+ return metadata;
+ }
+
+ /**
+ * Sets the metadata to register.
+ *
+ * @param metadata The metadata, may be {@code null}.
+ * @return This request for chaining, never {@code null}.
+ */
+ public LocalMetadataRegistration setMetadata( Metadata metadata )
+ {
+ this.metadata = metadata;
+ return this;
+ }
+
+ /**
+ * Gets the remote repository from which the metadata was resolved.
+ *
+ * @return The remote repository or {@code null} if the metadata was locally installed.
+ */
+ public RemoteRepository getRepository()
+ {
+ return repository;
+ }
+
+ /**
+ * Sets the remote repository from which the metadata was resolved.
+ *
+ * @param repository The remote repository or {@code null} if the metadata accompanies a locally installed artifact.
+ * @return This request for chaining, never {@code null}.
+ */
+ public LocalMetadataRegistration setRepository( RemoteRepository repository )
+ {
+ this.repository = repository;
+ return this;
+ }
+
+ /**
+ * Gets the resolution contexts in which the metadata is available.
+ *
+ * @return The resolution contexts in which the metadata is available, never {@code null}.
+ */
+ public Collection<String> getContexts()
+ {
+ return contexts;
+ }
+
+ /**
+ * Sets the resolution contexts in which the metadata is available.
+ *
+ * @param contexts The resolution contexts, may be {@code null}.
+ * @return This request for chaining, never {@code null}.
+ */
+ public LocalMetadataRegistration setContexts( Collection<String> contexts )
+ {
+ if ( contexts != null )
+ {
+ this.contexts = contexts;
+ }
+ else
+ {
+ this.contexts = Collections.emptyList();
+ }
+ return this;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalMetadataRequest.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalMetadataRequest.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalMetadataRequest.java
new file mode 100644
index 0000000..4c8f270
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalMetadataRequest.java
@@ -0,0 +1,133 @@
+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 org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.metadata.Metadata;
+
+/**
+ * A query to the local repository for the existence of metadata.
+ *
+ * @see LocalRepositoryManager#find(RepositorySystemSession, LocalMetadataRequest)
+ */
+public final class LocalMetadataRequest
+{
+
+ private Metadata metadata;
+
+ private String context = "";
+
+ private RemoteRepository repository = null;
+
+ /**
+ * Creates an uninitialized query.
+ */
+ public LocalMetadataRequest()
+ {
+ // enables default constructor
+ }
+
+ /**
+ * Creates a query with the specified properties.
+ *
+ * @param metadata The metadata to query for, may be {@code null}.
+ * @param repository The source remote repository for the metadata, may be {@code null} for local metadata.
+ * @param context The resolution context for the metadata, may be {@code null}.
+ */
+ public LocalMetadataRequest( Metadata metadata, RemoteRepository repository, String context )
+ {
+ setMetadata( metadata );
+ setRepository( repository );
+ setContext( context );
+ }
+
+ /**
+ * Gets the metadata to query for.
+ *
+ * @return The metadata or {@code null} if not set.
+ */
+ public Metadata getMetadata()
+ {
+ return metadata;
+ }
+
+ /**
+ * Sets the metadata to query for.
+ *
+ * @param metadata The metadata, may be {@code null}.
+ * @return This query for chaining, never {@code null}.
+ */
+ public LocalMetadataRequest setMetadata( Metadata metadata )
+ {
+ this.metadata = metadata;
+ return this;
+ }
+
+ /**
+ * Gets the resolution context.
+ *
+ * @return The resolution context, never {@code null}.
+ */
+ public String getContext()
+ {
+ return context;
+ }
+
+ /**
+ * Sets the resolution context.
+ *
+ * @param context The resolution context, may be {@code null}.
+ * @return This query for chaining, never {@code null}.
+ */
+ public LocalMetadataRequest setContext( String context )
+ {
+ this.context = ( context != null ) ? context : "";
+ return this;
+ }
+
+ /**
+ * Gets the remote repository to use as source of the metadata.
+ *
+ * @return The remote repositories, may be {@code null} for local metadata.
+ */
+ public RemoteRepository getRepository()
+ {
+ return repository;
+ }
+
+ /**
+ * Sets the remote repository to use as sources of the metadata.
+ *
+ * @param repository The remote repository, may be {@code null}.
+ * @return This query for chaining, may be {@code null} for local metadata.
+ */
+ public LocalMetadataRequest setRepository( RemoteRepository repository )
+ {
+ this.repository = repository;
+ return this;
+ }
+
+ @Override
+ public String toString()
+ {
+ return getMetadata() + " @ " + getRepository();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalMetadataResult.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalMetadataResult.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalMetadataResult.java
new file mode 100644
index 0000000..29bd045
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalMetadataResult.java
@@ -0,0 +1,114 @@
+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.io.File;
+
+import org.eclipse.aether.RepositorySystemSession;
+
+/**
+ * A result from the local repository about the existence of metadata.
+ *
+ * @see LocalRepositoryManager#find(RepositorySystemSession, LocalMetadataRequest)
+ */
+public final class LocalMetadataResult
+{
+
+ private final LocalMetadataRequest request;
+
+ private File file;
+
+ private boolean stale;
+
+ /**
+ * Creates a new result for the specified request.
+ *
+ * @param request The local metadata request, must not be {@code null}.
+ */
+ public LocalMetadataResult( LocalMetadataRequest request )
+ {
+ if ( request == null )
+ {
+ throw new IllegalArgumentException( "local metadata request has not been specified" );
+ }
+ this.request = request;
+ }
+
+ /**
+ * Gets the request corresponding to this result.
+ *
+ * @return The corresponding request, never {@code null}.
+ */
+ public LocalMetadataRequest getRequest()
+ {
+ return request;
+ }
+
+ /**
+ * Gets the file to the requested metadata if the metadata is available in the local repository.
+ *
+ * @return The file to the requested metadata or {@code null}.
+ */
+ public File getFile()
+ {
+ return file;
+ }
+
+ /**
+ * Sets the file to requested metadata.
+ *
+ * @param file The metadata file, may be {@code null}.
+ * @return This result for chaining, never {@code null}.
+ */
+ public LocalMetadataResult setFile( File file )
+ {
+ this.file = file;
+ return this;
+ }
+
+ /**
+ * This value indicates whether the metadata is stale and should be updated.
+ *
+ * @return {@code true} if the metadata is stale and should be updated, {@code false} otherwise.
+ */
+ public boolean isStale()
+ {
+ return stale;
+ }
+
+ /**
+ * Sets whether the metadata is stale.
+ *
+ * @param stale {@code true} if the metadata is stale and should be updated, {@code false} otherwise.
+ * @return This result for chaining, never {@code null}.
+ */
+ public LocalMetadataResult setStale( boolean stale )
+ {
+ this.stale = stale;
+ return this;
+ }
+
+ @Override
+ public String toString()
+ {
+ return request.toString() + "(" + getFile() + ")";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalRepository.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalRepository.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalRepository.java
new file mode 100644
index 0000000..32dce73
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalRepository.java
@@ -0,0 +1,132 @@
+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.io.File;
+
+/**
+ * A repository on the local file system used to cache contents of remote repositories and to store locally installed
+ * artifacts. Note that this class merely describes such a repository, actual access to the contained artifacts is
+ * handled by a {@link LocalRepositoryManager} which is usually determined from the {@link #getContentType() type} of
+ * the repository.
+ */
+public final class LocalRepository
+ implements ArtifactRepository
+{
+
+ private final File basedir;
+
+ private final String type;
+
+ /**
+ * Creates a new local repository with the specified base directory and unknown type.
+ *
+ * @param basedir The base directory of the repository, may be {@code null}.
+ */
+ public LocalRepository( String basedir )
+ {
+ this( ( basedir != null ) ? new File( basedir ) : null, "" );
+ }
+
+ /**
+ * Creates a new local repository with the specified base directory and unknown type.
+ *
+ * @param basedir The base directory of the repository, may be {@code null}.
+ */
+ public LocalRepository( File basedir )
+ {
+ this( basedir, "" );
+ }
+
+ /**
+ * Creates a new local repository with the specified properties.
+ *
+ * @param basedir The base directory of the repository, may be {@code null}.
+ * @param type The type of the repository, may be {@code null}.
+ */
+ public LocalRepository( File basedir, String type )
+ {
+ this.basedir = basedir;
+ this.type = ( type != null ) ? type : "";
+ }
+
+ public String getContentType()
+ {
+ return type;
+ }
+
+ public String getId()
+ {
+ return "local";
+ }
+
+ /**
+ * Gets the base directory of the repository.
+ *
+ * @return The base directory or {@code null} if none.
+ */
+ public File getBasedir()
+ {
+ return basedir;
+ }
+
+ @Override
+ public String toString()
+ {
+ return getBasedir() + " (" + getContentType() + ")";
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ {
+ return true;
+ }
+ if ( obj == null || !getClass().equals( obj.getClass() ) )
+ {
+ return false;
+ }
+
+ LocalRepository that = (LocalRepository) obj;
+
+ return eq( basedir, that.basedir ) && eq( type, that.type );
+ }
+
+ private static <T> boolean eq( T s1, T s2 )
+ {
+ return s1 != null ? s1.equals( s2 ) : s2 == null;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int hash = 17;
+ hash = hash * 31 + hash( basedir );
+ hash = hash * 31 + hash( type );
+ 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/repository/LocalRepositoryManager.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalRepositoryManager.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalRepositoryManager.java
new file mode 100644
index 0000000..649707c
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/LocalRepositoryManager.java
@@ -0,0 +1,127 @@
+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 org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.metadata.Metadata;
+
+/**
+ * Manages access to a local repository.
+ *
+ * @see RepositorySystemSession#getLocalRepositoryManager()
+ * @see org.eclipse.aether.RepositorySystem#newLocalRepositoryManager(RepositorySystemSession, LocalRepository)
+ */
+public interface LocalRepositoryManager
+{
+
+ /**
+ * Gets the description of the local repository being managed.
+ *
+ * @return The description of the local repository, never {@code null}.
+ */
+ LocalRepository getRepository();
+
+ /**
+ * Gets the relative path for a locally installed artifact. Note that the artifact need not actually exist yet at
+ * the returned location, the path merely indicates where the artifact would eventually be stored. The path uses the
+ * forward slash as directory separator regardless of the underlying file system.
+ *
+ * @param artifact The artifact for which to determine the path, must not be {@code null}.
+ * @return The path, relative to the local repository's base directory.
+ */
+ String getPathForLocalArtifact( Artifact artifact );
+
+ /**
+ * Gets the relative path for an artifact cached from a remote repository. Note that the artifact need not actually
+ * exist yet at the returned location, the path merely indicates where the artifact would eventually be stored. The
+ * path uses the forward slash as directory separator regardless of the underlying file system.
+ *
+ * @param artifact The artifact for which to determine the path, must not be {@code null}.
+ * @param repository The source repository of the artifact, must not be {@code null}.
+ * @param context The resolution context in which the artifact is being requested, may be {@code null}.
+ * @return The path, relative to the local repository's base directory.
+ */
+ String getPathForRemoteArtifact( Artifact artifact, RemoteRepository repository, String context );
+
+ /**
+ * Gets the relative path for locally installed metadata. Note that the metadata need not actually exist yet at the
+ * returned location, the path merely indicates where the metadata would eventually be stored. The path uses the
+ * forward slash as directory separator regardless of the underlying file system.
+ *
+ * @param metadata The metadata for which to determine the path, must not be {@code null}.
+ * @return The path, relative to the local repository's base directory.
+ */
+ String getPathForLocalMetadata( Metadata metadata );
+
+ /**
+ * Gets the relative path for metadata cached from a remote repository. Note that the metadata need not actually
+ * exist yet at the returned location, the path merely indicates where the metadata would eventually be stored. The
+ * path uses the forward slash as directory separator regardless of the underlying file system.
+ *
+ * @param metadata The metadata for which to determine the path, must not be {@code null}.
+ * @param repository The source repository of the metadata, must not be {@code null}.
+ * @param context The resolution context in which the metadata is being requested, may be {@code null}.
+ * @return The path, relative to the local repository's base directory.
+ */
+ String getPathForRemoteMetadata( Metadata metadata, RemoteRepository repository, String context );
+
+ /**
+ * Queries for the existence of an artifact in the local repository. The request could be satisfied by a locally
+ * installed artifact or a previously downloaded artifact.
+ *
+ * @param session The repository system session during which the request is made, must not be {@code null}.
+ * @param request The artifact request, must not be {@code null}.
+ * @return The result of the request, never {@code null}.
+ */
+ LocalArtifactResult find( RepositorySystemSession session, LocalArtifactRequest request );
+
+ /**
+ * Registers an installed or resolved artifact with the local repository. Note that artifact registration is merely
+ * concerned about updating the local repository's internal state, not about actually installing the artifact or its
+ * accompanying metadata.
+ *
+ * @param session The repository system session during which the registration is made, must not be {@code null}.
+ * @param request The registration request, must not be {@code null}.
+ */
+ void add( RepositorySystemSession session, LocalArtifactRegistration request );
+
+ /**
+ * Queries for the existence of metadata in the local repository. The request could be satisfied by locally
+ * installed or previously downloaded metadata.
+ *
+ * @param session The repository system session during which the request is made, must not be {@code null}.
+ * @param request The metadata request, must not be {@code null}.
+ * @return The result of the request, never {@code null}.
+ */
+ LocalMetadataResult find( RepositorySystemSession session, LocalMetadataRequest request );
+
+ /**
+ * Registers installed or resolved metadata with the local repository. Note that metadata registration is merely
+ * concerned about updating the local repository's internal state, not about actually installing the metadata.
+ * However, this method MUST be called after the actual install to give the repository manager the opportunity to
+ * inspect the added metadata.
+ *
+ * @param session The repository system session during which the registration is made, must not be {@code null}.
+ * @param request The registration request, must not be {@code null}.
+ */
+ void add( RepositorySystemSession session, LocalMetadataRegistration request );
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/repository/MirrorSelector.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/MirrorSelector.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/MirrorSelector.java
new file mode 100644
index 0000000..d50262c
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/MirrorSelector.java
@@ -0,0 +1,39 @@
+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.
+ */
+
+/**
+ * Selects a mirror for a given remote repository.
+ *
+ * @see org.eclipse.aether.RepositorySystemSession#getMirrorSelector()
+ */
+public interface MirrorSelector
+{
+
+ /**
+ * Selects a mirror for the specified repository.
+ *
+ * @param repository The repository to select a mirror for, must not be {@code null}.
+ * @return The selected mirror or {@code null} if none.
+ * @see RemoteRepository#getMirroredRepositories()
+ */
+ RemoteRepository getMirror( RemoteRepository repository );
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/repository/NoLocalRepositoryManagerException.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/NoLocalRepositoryManagerException.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/NoLocalRepositoryManagerException.java
new file mode 100644
index 0000000..c804821
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/NoLocalRepositoryManagerException.java
@@ -0,0 +1,102 @@
+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 org.eclipse.aether.RepositoryException;
+
+/**
+ * Thrown in case of an unsupported local repository type.
+ */
+public class NoLocalRepositoryManagerException
+ extends RepositoryException
+{
+
+ private final transient LocalRepository repository;
+
+ /**
+ * Creates a new exception with the specified repository.
+ *
+ * @param repository The local repository for which no support is available, may be {@code null}.
+ */
+ public NoLocalRepositoryManagerException( LocalRepository repository )
+ {
+ this( repository, toMessage( repository ) );
+ }
+
+ /**
+ * Creates a new exception with the specified repository and detail message.
+ *
+ * @param repository The local repository for which no support is available, may be {@code null}.
+ * @param message The detail message, may be {@code null}.
+ */
+ public NoLocalRepositoryManagerException( LocalRepository repository, String message )
+ {
+ super( message );
+ this.repository = repository;
+ }
+
+ /**
+ * Creates a new exception with the specified repository and cause.
+ *
+ * @param repository The local repository for which no support is available, may be {@code null}.
+ * @param cause The exception that caused this one, may be {@code null}.
+ */
+ public NoLocalRepositoryManagerException( LocalRepository repository, Throwable cause )
+ {
+ this( repository, toMessage( repository ), cause );
+ }
+
+ /**
+ * Creates a new exception with the specified repository, detail message and cause.
+ *
+ * @param repository The local repository for which no support is available, may be {@code null}.
+ * @param message The detail message, may be {@code null}.
+ * @param cause The exception that caused this one, may be {@code null}.
+ */
+ public NoLocalRepositoryManagerException( LocalRepository repository, String message, Throwable cause )
+ {
+ super( message, cause );
+ this.repository = repository;
+ }
+
+ private static String toMessage( LocalRepository repository )
+ {
+ if ( repository != null )
+ {
+ return "No manager available for local repository (" + repository.getBasedir().getAbsolutePath()
+ + ") of type " + repository.getContentType();
+ }
+ else
+ {
+ return "No manager available for local repository";
+ }
+ }
+
+ /**
+ * Gets the local repository whose content type is not supported.
+ *
+ * @return The unsupported local repository or {@code null} if unknown.
+ */
+ public LocalRepository getRepository()
+ {
+ return repository;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/maven-resolver-api/src/main/java/org/eclipse/aether/repository/Proxy.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/Proxy.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/Proxy.java
new file mode 100644
index 0000000..8e8cba1
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/Proxy.java
@@ -0,0 +1,158 @@
+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 proxy to use for connections to a repository.
+ */
+public final class Proxy
+{
+
+ /**
+ * Type denoting a proxy for HTTP transfers.
+ */
+ public static final String TYPE_HTTP = "http";
+
+ /**
+ * Type denoting a proxy for HTTPS transfers.
+ */
+ public static final String TYPE_HTTPS = "https";
+
+ private final String type;
+
+ private final String host;
+
+ private final int port;
+
+ private final Authentication auth;
+
+ /**
+ * Creates a new proxy with the specified properties and no authentication.
+ *
+ * @param type The type of the proxy, e.g. "http", may be {@code null}.
+ * @param host The host of the proxy, may be {@code null}.
+ * @param port The port of the proxy.
+ */
+ public Proxy( String type, String host, int port )
+ {
+ this( type, host, port, null );
+ }
+
+ /**
+ * Creates a new proxy with the specified properties.
+ *
+ * @param type The type of the proxy, e.g. "http", may be {@code null}.
+ * @param host The host of the proxy, may be {@code null}.
+ * @param port The port of the proxy.
+ * @param auth The authentication to use for the proxy connection, may be {@code null}.
+ */
+ public Proxy( String type, String host, int port, Authentication auth )
+ {
+ this.type = ( type != null ) ? type : "";
+ this.host = ( host != null ) ? host : "";
+ this.port = port;
+ this.auth = auth;
+ }
+
+ /**
+ * Gets the type of this proxy.
+ *
+ * @return The type of this proxy, never {@code null}.
+ */
+ public String getType()
+ {
+ return type;
+ }
+
+ /**
+ * Gets the host for this proxy.
+ *
+ * @return The host for this proxy, never {@code null}.
+ */
+ public String getHost()
+ {
+ return host;
+ }
+
+ /**
+ * Gets the port number for this proxy.
+ *
+ * @return The port number for this proxy.
+ */
+ public int getPort()
+ {
+ return port;
+ }
+
+ /**
+ * Gets the authentication to use for the proxy connection.
+ *
+ * @return The authentication to use or {@code null} if none.
+ */
+ public Authentication getAuthentication()
+ {
+ return auth;
+ }
+
+ @Override
+ public String toString()
+ {
+ return getHost() + ':' + getPort();
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ {
+ return true;
+ }
+ if ( obj == null || !getClass().equals( obj.getClass() ) )
+ {
+ return false;
+ }
+
+ Proxy that = (Proxy) obj;
+
+ return eq( type, that.type ) && eq( host, that.host ) && port == that.port && eq( auth, that.auth );
+ }
+
+ private static <T> boolean eq( T s1, T s2 )
+ {
+ return s1 != null ? s1.equals( s2 ) : s2 == null;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int hash = 17;
+ hash = hash * 31 + hash( host );
+ hash = hash * 31 + hash( type );
+ hash = hash * 31 + port;
+ hash = hash * 31 + hash( auth );
+ 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/repository/ProxySelector.java
----------------------------------------------------------------------
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/ProxySelector.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/ProxySelector.java
new file mode 100644
index 0000000..29b9e4e
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/ProxySelector.java
@@ -0,0 +1,38 @@
+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.
+ */
+
+/**
+ * Selects a proxy for a given remote repository.
+ *
+ * @see org.eclipse.aether.RepositorySystemSession#getProxySelector()
+ */
+public interface ProxySelector
+{
+
+ /**
+ * Selects a proxy for the specified remote repository.
+ *
+ * @param repository The repository for which to select a proxy, must not be {@code null}.
+ * @return The selected proxy or {@code null} if none.
+ */
+ Proxy getProxy( RemoteRepository repository );
+
+}