http://git-wip-us.apache.org/repos/asf/maven-resolver/blob/3a1b8ae0/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/DefaultMetadata.java ---------------------------------------------------------------------- diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/DefaultMetadata.java b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/DefaultMetadata.java new file mode 100644 index 0000000..1efbb72 --- /dev/null +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/DefaultMetadata.java @@ -0,0 +1,192 @@ +package org.eclipse.aether.metadata; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.util.Map; + +/** + * A basic metadata instance. <em>Note:</em> Instances of this class are immutable and the exposed mutators return new + * objects rather than changing the current instance. + */ +public final class DefaultMetadata + extends AbstractMetadata +{ + + private final String groupId; + + private final String artifactId; + + private final String version; + + private final String type; + + private final Nature nature; + + private final File file; + + private final Map<String, String> properties; + + /** + * Creates a new metadata for the repository root with the specific type and nature. + * + * @param type The type of the metadata, e.g. "maven-metadata.xml", may be {@code null}. + * @param nature The nature of the metadata, must not be {@code null}. + */ + public DefaultMetadata( String type, Nature nature ) + { + this( "", "", "", type, nature, null, (File) null ); + } + + /** + * Creates a new metadata for the groupId level with the specific type and nature. + * + * @param groupId The group identifier to which this metadata applies, may be {@code null}. + * @param type The type of the metadata, e.g. "maven-metadata.xml", may be {@code null}. + * @param nature The nature of the metadata, must not be {@code null}. + */ + public DefaultMetadata( String groupId, String type, Nature nature ) + { + this( groupId, "", "", type, nature, null, (File) null ); + } + + /** + * Creates a new metadata for the groupId:artifactId level with the specific type and nature. + * + * @param groupId The group identifier to which this metadata applies, may be {@code null}. + * @param artifactId The artifact identifier to which this metadata applies, may be {@code null}. + * @param type The type of the metadata, e.g. "maven-metadata.xml", may be {@code null}. + * @param nature The nature of the metadata, must not be {@code null}. + */ + public DefaultMetadata( String groupId, String artifactId, String type, Nature nature ) + { + this( groupId, artifactId, "", type, nature, null, (File) null ); + } + + /** + * Creates a new metadata for the groupId:artifactId:version level with the specific type and nature. + * + * @param groupId The group identifier to which this metadata applies, may be {@code null}. + * @param artifactId The artifact identifier to which this metadata applies, may be {@code null}. + * @param version The version to which this metadata applies, may be {@code null}. + * @param type The type of the metadata, e.g. "maven-metadata.xml", may be {@code null}. + * @param nature The nature of the metadata, must not be {@code null}. + */ + public DefaultMetadata( String groupId, String artifactId, String version, String type, Nature nature ) + { + this( groupId, artifactId, version, type, nature, null, (File) null ); + } + + /** + * Creates a new metadata for the groupId:artifactId:version level with the specific type and nature. + * + * @param groupId The group identifier to which this metadata applies, may be {@code null}. + * @param artifactId The artifact identifier to which this metadata applies, may be {@code null}. + * @param version The version to which this metadata applies, may be {@code null}. + * @param type The type of the metadata, e.g. "maven-metadata.xml", may be {@code null}. + * @param nature The nature of the metadata, must not be {@code null}. + * @param file The resolved file of the metadata, may be {@code null}. + */ + public DefaultMetadata( String groupId, String artifactId, String version, String type, Nature nature, File file ) + { + this( groupId, artifactId, version, type, nature, null, file ); + } + + /** + * Creates a new metadata for the groupId:artifactId:version level with the specific type and nature. + * + * @param groupId The group identifier to which this metadata applies, may be {@code null}. + * @param artifactId The artifact identifier to which this metadata applies, may be {@code null}. + * @param version The version to which this metadata applies, may be {@code null}. + * @param type The type of the metadata, e.g. "maven-metadata.xml", may be {@code null}. + * @param nature The nature of the metadata, must not be {@code null}. + * @param properties The properties of the metadata, may be {@code null} if none. + * @param file The resolved file of the metadata, may be {@code null}. + */ + public DefaultMetadata( String groupId, String artifactId, String version, String type, Nature nature, + Map<String, String> properties, File file ) + { + this.groupId = emptify( groupId ); + this.artifactId = emptify( artifactId ); + this.version = emptify( version ); + this.type = emptify( type ); + if ( nature == null ) + { + throw new IllegalArgumentException( "metadata nature was not specified" ); + } + this.nature = nature; + this.file = file; + this.properties = copyProperties( properties ); + } + + DefaultMetadata( String groupId, String artifactId, String version, String type, Nature nature, File file, + Map<String, String> properties ) + { + // NOTE: This constructor assumes immutability of the provided properties, for internal use only + this.groupId = emptify( groupId ); + this.artifactId = emptify( artifactId ); + this.version = emptify( version ); + this.type = emptify( type ); + this.nature = nature; + this.file = file; + this.properties = properties; + } + + private static String emptify( String str ) + { + return ( str == null ) ? "" : str; + } + + public String getGroupId() + { + return groupId; + } + + public String getArtifactId() + { + return artifactId; + } + + public String getVersion() + { + return version; + } + + public String getType() + { + return type; + } + + public Nature getNature() + { + return nature; + } + + public File getFile() + { + return file; + } + + public Map<String, String> getProperties() + { + return properties; + } + +}
http://git-wip-us.apache.org/repos/asf/maven-resolver/blob/3a1b8ae0/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/MergeableMetadata.java ---------------------------------------------------------------------- diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/MergeableMetadata.java b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/MergeableMetadata.java new file mode 100644 index 0000000..deaff70 --- /dev/null +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/MergeableMetadata.java @@ -0,0 +1,51 @@ +package org.eclipse.aether.metadata; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; + +import org.eclipse.aether.RepositoryException; + +/** + * A piece of metadata that needs to be merged with any current metadata before installation/deployment. + */ +public interface MergeableMetadata + extends Metadata +{ + + /** + * Merges this metadata into the current metadata (if any). Note that this method will be invoked regardless whether + * metadata currently exists or not. + * + * @param current The path to the current metadata file, may not exist but must not be {@code null}. + * @param result The path to the result file where the merged metadata should be stored, must not be {@code null}. + * @throws RepositoryException If the metadata could not be merged. + */ + void merge( File current, File result ) + throws RepositoryException; + + /** + * Indicates whether this metadata has been merged. + * + * @return {@code true} if the metadata has been merged, {@code false} otherwise. + */ + boolean isMerged(); + +} http://git-wip-us.apache.org/repos/asf/maven-resolver/blob/3a1b8ae0/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/Metadata.java ---------------------------------------------------------------------- diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/Metadata.java b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/Metadata.java new file mode 100644 index 0000000..84e9212 --- /dev/null +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/Metadata.java @@ -0,0 +1,138 @@ +package org.eclipse.aether.metadata; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.util.Map; + +/** + * A piece of repository metadata, e.g. an index of available versions. In contrast to an artifact, which usually exists + * in only one repository, metadata usually exists in multiple repositories and each repository contains a different + * copy of the metadata. <em>Note:</em> Metadata instances are supposed to be immutable, e.g. any exposed mutator method + * returns a new metadata instance and leaves the original instance unchanged. Implementors are strongly advised to obey + * this contract. <em>Note:</em> Implementors are strongly advised to inherit from {@link AbstractMetadata} instead of + * directly implementing this interface. + * + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + */ +public interface Metadata +{ + + /** + * The nature of the metadata. + */ + enum Nature + { + /** + * The metadata refers to release artifacts only. + */ + RELEASE, + + /** + * The metadata refers to snapshot artifacts only. + */ + SNAPSHOT, + + /** + * The metadata refers to either release or snapshot artifacts. + */ + RELEASE_OR_SNAPSHOT + } + + /** + * Gets the group identifier of this metadata. + * + * @return The group identifier or an empty string if the metadata applies to the entire repository, never + * {@code null}. + */ + String getGroupId(); + + /** + * Gets the artifact identifier of this metadata. + * + * @return The artifact identifier or an empty string if the metadata applies to the groupId level only, never + * {@code null}. + */ + String getArtifactId(); + + /** + * Gets the version of this metadata. + * + * @return The version or an empty string if the metadata applies to the groupId:artifactId level only, never + * {@code null}. + */ + String getVersion(); + + /** + * Gets the type of the metadata, e.g. "maven-metadata.xml". + * + * @return The type of the metadata, never {@code null}. + */ + String getType(); + + /** + * Gets the nature of this metadata. The nature indicates to what artifact versions the metadata refers. + * + * @return The nature, never {@code null}. + */ + Nature getNature(); + + /** + * Gets the file of this metadata. Note that only resolved metadata has a file associated with it. + * + * @return The file or {@code null} if none. + */ + File getFile(); + + /** + * Sets the file of the metadata. + * + * @param file The file of the metadata, may be {@code null} + * @return The new metadata, never {@code null}. + */ + Metadata setFile( File file ); + + /** + * Gets the specified property. + * + * @param key The name of the property, must not be {@code null}. + * @param defaultValue The default value to return in case the property is not set, may be {@code null}. + * @return The requested property value or {@code null} if the property is not set and no default value was + * provided. + */ + String getProperty( String key, String defaultValue ); + + /** + * Gets the properties of this metadata. + * + * @return The (read-only) properties, never {@code null}. + */ + Map<String, String> getProperties(); + + /** + * Sets the properties for the metadata. + * + * @param properties The properties for the metadata, may be {@code null}. + * @return The new metadata, never {@code null}. + */ + Metadata setProperties( Map<String, String> properties ); + +} http://git-wip-us.apache.org/repos/asf/maven-resolver/blob/3a1b8ae0/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/package-info.java ---------------------------------------------------------------------- diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/package-info.java b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/package-info.java new file mode 100644 index 0000000..e41f98e --- /dev/null +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/metadata/package-info.java @@ -0,0 +1,24 @@ +// CHECKSTYLE_OFF: RegexpHeader +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * The definition of metadata, that is an auxiliary entity managed by the repository system to locate artifacts. + */ +package org.eclipse.aether.metadata; + http://git-wip-us.apache.org/repos/asf/maven-resolver/blob/3a1b8ae0/maven-resolver-api/src/main/java/org/eclipse/aether/package-info.java ---------------------------------------------------------------------- diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/package-info.java b/maven-resolver-api/src/main/java/org/eclipse/aether/package-info.java new file mode 100644 index 0000000..8d11fa8 --- /dev/null +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/package-info.java @@ -0,0 +1,24 @@ +// CHECKSTYLE_OFF: RegexpHeader +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * The primary API of the {@link org.eclipse.aether.RepositorySystem} and its functionality. + */ +package org.eclipse.aether; + http://git-wip-us.apache.org/repos/asf/maven-resolver/blob/3a1b8ae0/maven-resolver-api/src/main/java/org/eclipse/aether/repository/ArtifactRepository.java ---------------------------------------------------------------------- diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/ArtifactRepository.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/ArtifactRepository.java new file mode 100644 index 0000000..c62bf87 --- /dev/null +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/ArtifactRepository.java @@ -0,0 +1,45 @@ +package org.eclipse.aether.repository; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * A repository hosting artifacts. + * + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + */ +public interface ArtifactRepository +{ + + /** + * Gets the type of the repository, for example "default". + * + * @return The (case-sensitive) type of the repository, never {@code null}. + */ + String getContentType(); + + /** + * Gets the identifier of this repository. + * + * @return The (case-sensitive) identifier, never {@code null}. + */ + String getId(); + +} http://git-wip-us.apache.org/repos/asf/maven-resolver/blob/3a1b8ae0/maven-resolver-api/src/main/java/org/eclipse/aether/repository/Authentication.java ---------------------------------------------------------------------- diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/Authentication.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/Authentication.java new file mode 100644 index 0000000..d85c2a2 --- /dev/null +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/Authentication.java @@ -0,0 +1,55 @@ +package org.eclipse.aether.repository; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.Map; + +/** + * The authentication to use for accessing a protected resource. This acts basically as an extensible callback mechanism + * from which network operations can request authentication data like username and password when needed. + */ +public interface Authentication +{ + + /** + * Fills the given authentication context with the data from this authentication callback. To do so, implementors + * have to call {@link AuthenticationContext#put(String, Object)}. <br> + * <br> + * The {@code key} parameter supplied to this method acts merely as a hint for interactive callbacks that want to + * prompt the user for only that authentication data which is required. Implementations are free to ignore this + * parameter and put all the data they have into the authentication context at once. + * + * @param context The authentication context to populate, must not be {@code null}. + * @param key The key denoting a specific piece of authentication data that is being requested for a network + * operation, may be {@code null}. + * @param data Any (read-only) extra data in form of key value pairs that might be useful when getting the + * authentication data, may be {@code null}. + */ + void fill( AuthenticationContext context, String key, Map<String, String> data ); + + /** + * Updates the given digest with data from this authentication callback. To do so, implementors have to call the + * {@code update()} methods in {@link AuthenticationDigest}. + * + * @param digest The digest to update, must not be {@code null}. + */ + void digest( AuthenticationDigest digest ); + +} http://git-wip-us.apache.org/repos/asf/maven-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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-resolver/blob/3a1b8ae0/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; + } + +}