--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2012 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.aether.repository;
+
+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();
+ }
+
+}