public static final String CREDENTIALS_ENVIRONMENT_VARIABLE = CREDENTIALS_SYSTEM_PROPERTY.replaceAll("\\.", "_").toUpperCase(); public static final String CREDENTIALS_SYSTEM_PROPERTY = "artifactory.rest.credentials"; public static final String ENDPOINT_ENVIRONMENT_VARIABLE = ENDPOINT_SYSTEM_PROPERTY.replaceAll("\\.", "_").toUpperCase(); public static final String ENDPOINT_SYSTEM_PROPERTY = "artifactory.rest.endpoint"; public static final String TOKEN_ENVIRONMENT_VARIABLE = TOKEN_SYSTEM_PROPERTY.replaceAll("\\.", "_").toUpperCase(); public static final String TOKEN_SYSTEM_PROPERTY = "artifactory.rest.token"; public class ArtifactoryAuthentication extends Credentials {

    private final AuthenticationType authType;

    /**
     * Create instance of ArtifactoryAuthentication
     * 
     * @param authValue value to use for authentication type HTTP header.
     * @param authType authentication type (e.g. Basic, Bearer, Anonymous).
     */
    private ArtifactoryAuthentication(final String authValue, final AuthenticationType authType) {
        super(null, authType == AuthenticationType.Basic && authValue.contains(":")
                ? base64().encode(authValue.getBytes())
                : authValue);
        this.authType = authType;    
    }

    @Nullable
    public String authValue() {
        return this.credential;
    }

    public AuthenticationType authType() {
        return authType;
    }

    public static Builder builder() {
        return new Builder();
    }

    public static class Builder {

        private String authValue;
        private AuthenticationType authType;

        /**
         * Set 'Basic' credentials.
         * 
         * @param basicCredentials value to use for 'Basic' credentials.
         * @return this Builder.
         */
        public Builder credentials(final String basicCredentials) {
            this.authValue = Objects.requireNonNull(basicCredentials);
            this.authType = AuthenticationType.Basic;
            return this;
        }

        /**
         * Set 'Bearer' credentials.
         * 
         * @param tokenCredentials value to use for 'Bearer' credentials.
         * @return this Builder.
         */
        public Builder token(final String tokenCredentials) {
            this.authValue = Objects.requireNonNull(tokenCredentials);
            this.authType = AuthenticationType.Bearer;
            return this;
        }

        /**
         * Build and instance of ArtifactoryCredentials.
         * 
         * @return instance of ArtifactoryCredentials.
         */
        public ArtifactoryAuthentication build() {
            return new ArtifactoryAuthentication(authValue, authType != null
                    ? authType
                    : AuthenticationType.Anonymous);
        }
    }
} public final class ArtifactoryClient implements Closeable {

    private final String endPoint;
    private final ArtifactoryAuthentication credentials;
    private final ArtifactoryApi artifactoryApi;
    private final Properties overrides;

    /**
     * Create a ArtifactoryClient inferring endpoint and authentication from
     * environment and system properties.
     */
    public ArtifactoryClient() {
        this(null, null, null);
    }

    /**
     * Create an ArtifactoryClient. If any of the passed in variables are null we
     * will query System Properties and Environment Variables, in order, to
     * search for values that may be set in a devops/CI fashion. The only
     * difference is the `overrides` which gets merged, but takes precedence,
     * with those System Properties and Environment Variables found.
     *
     * @param endPoint URL of Artifactory instance.
     * @param authentication authentication used to connect to Artifactory instance.
     * @param overrides jclouds Properties to override defaults when creating a new ArtifactoryApi.
     */
    public ArtifactoryClient(@Nullable final String endPoint,
            @Nullable final ArtifactoryAuthentication authentication,
            @Nullable final Properties overrides) {
        this.endPoint = endPoint != null
                ? endPoint
                : ArtifactoryUtils.inferEndpoint();
        this.credentials = authentication != null
                ? authentication
                : ArtifactoryUtils.inferAuthentication();
        this.overrides = mergeOverrides(overrides);
        this.artifactoryApi = createApi(this.endPoint, this.credentials, this.overrides);
    }

    private ArtifactoryApi createApi(final String endPoint, final ArtifactoryAuthentication authentication, final Properties overrides) {
        return ContextBuilder
                .newBuilder(new ArtifactoryApiMetadata.Builder().build())
                .endpoint(endPoint)
                .modules(Lists.newArrayList(new ArtifactoryAuthenticationModule(authentication)))
                .overrides(overrides)
                .buildApi(ArtifactoryApi.class);
    }

    /**
     * Query System Properties and Environment Variables for overrides and merge
     * the potentially passed in overrides with those.
     *
     * @param possibleOverrides Optional passed in overrides.
     * @return Properties object.
     */
    private Properties mergeOverrides(final Properties possibleOverrides) {
        final Properties inferOverrides = ArtifactoryUtils.inferOverrides();
        if (possibleOverrides != null) {
            inferOverrides.putAll(possibleOverrides);
        }
        return inferOverrides;
    }

    public String endPoint() {
        return this.endPoint;
    }

    @Deprecated
    public String credentials() {
        return this.authValue();
    }

    public Properties overrides() {
        return this.overrides;
    }

    public String authValue() {
        return this.credentials.authValue();
    }

    public AuthenticationType authType() {
        return this.credentials.authType();
    }

    public ArtifactoryApi api() {
        return this.artifactoryApi;
    }

    public static Builder builder() {
        return new Builder();
    }

    @Override
    public void close() throws IOException {
        if(this.api() != null) {
            this.api().close();
        }
    }

    public static class Builder {

        private String endPoint;
        private ArtifactoryAuthentication.Builder authBuilder;
        private Properties overrides;

        /**
         * Define the base endpoint to connect to.
         *
         * @param endPoint Artifactory base endpoint.
         * @return this Builder.
         */
        public Builder endPoint(final String endPoint) {
            this.endPoint = endPoint;
            return this;
        }

        /**
         * Optional credentials to use for authentication. Must take the form of
         * `username:password` or its base64 encoded version.
         *
         * @param optionallyBase64EncodedCredentials authentication credentials.
         * @return this Builder.
         */
        public Builder credentials(final String optionallyBase64EncodedCredentials) {
            authBuilder = ArtifactoryAuthentication.builder()
                    .credentials(optionallyBase64EncodedCredentials);
            return this;
        }

        /**
         * Optional token to use for authentication.
         *
         * @param token authentication token.
         * @return this Builder.
         */
        public Builder token(final String token) {
            authBuilder = ArtifactoryAuthentication.builder()
                    .token(token);
            return this;
        }

        /**
         * Optional jclouds Properties to override. What can be overridden can
         * be found here:
         *
         * <p>https://github.com/jclouds/jclouds/blob/master/core/src/main/java/org/jclouds/Constants.java
         *
         * @param overrides optional jclouds Properties to override.
         * @return this Builder.
         */
        public Builder overrides(final Properties overrides) {
            this.overrides = overrides;
            return this;
        }

        /**
         * Build an instance of ArtifactoryClient.
         *
         * @return ArtifactoryClient
         */
        public ArtifactoryClient build() {

            // 1.) If user passed in some auth use/build that.
            final ArtifactoryAuthentication authentication = authBuilder != null
                    ? authBuilder.build()
                    : null;

            return new ArtifactoryClient(endPoint, authentication, overrides);
        }
    }
} @Test(groups = "live")
public class BaseArtifactoryApiLiveTest extends BaseApiLiveTest<ArtifactoryApi> {
    protected final ArtifactoryAuthentication artifactoryAuthentication;

    public BaseArtifactoryApiLiveTest() {
        provider = "artifactory";
        this.artifactoryAuthentication = TestUtilities.inferTestAuthentication();
    }

    @Override
    protected Iterable<Module> setupModules() {
        final ArtifactoryAuthenticationModule credsModule = new ArtifactoryAuthenticationModule(this.artifactoryAuthentication);
        return ImmutableSet.<Module> of(getLoggingModule(), credsModule);
    }

    @Override
    protected Properties setupProperties() {
        Properties overrides = super.setupProperties();
        overrides.setProperty(Constants.PROPERTY_MAX_RETRIES, "0");
        return overrides;
    }

    public String randomUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    public String randomPath() {
        return UUID.randomUUID().toString().replaceAll("-", "/");
    }

    public String randomString() {
        char[] chars = "abcdefghijklmnopqrstuvwxyz".toCharArray();
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 10; i++) {
           char c = chars[random.nextInt(chars.length)];
           sb.append(c);
        }
        return sb.toString();
    }

    public File randomFile() {
        File randomFile = null;
        PrintWriter writer = null;
        try {
            randomFile = new File(System.getProperty("java.io.tmpdir"), randomUUID() + ".txt");
            if (!randomFile.createNewFile()) {
                throw new RuntimeException("Could not create temporary file at " + randomFile.getAbsolutePath());
            }

            writer = new PrintWriter(randomFile, "UTF-8");
            writer.println("Hello, World!");
            writer.close();
        } catch (IOException e) {
            if (randomFile != null) {
               randomFile.delete();
            }
            throw Throwables.propagate(e);
        } finally {
            if (writer != null)
                writer.close();
        }
        return randomFile;
    }

    public static String getFileChecksum(MessageDigest digest, File file) throws IOException {
        //Get file input stream for reading the file content
        FileInputStream fis = new FileInputStream(file);

        //Create byte array to read data in chunks
        byte[] byteArray = new byte[1024];
        int bytesCount = 0;

        //Read file data and update in message digest
        while ((bytesCount = fis.read(byteArray)) != -1) {
            digest.update(byteArray, 0, bytesCount);
        };

        //close the stream; We don't need it now.
        fis.close();

        //Get the hash's bytes
        byte[] bytes = digest.digest();

        //This bytes[] has bytes in decimal format;
        //Convert it to hexadecimal format
        StringBuilder sb = new StringBuilder();
        for(int i=0; i< bytes.length ;i++) {
            sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
        }

        //return complete hash
        return sb.toString();
    }
} public class TestUtilities extends ArtifactoryUtils {

    public static final String TEST_CREDENTIALS_SYSTEM_PROPERTY = "test.artifactory.rest.credentials";
    public static final String TEST_CREDENTIALS_ENVIRONMENT_VARIABLE = TEST_CREDENTIALS_SYSTEM_PROPERTY.replaceAll("\\.", "_").toUpperCase();

    public static final String TEST_TOKEN_SYSTEM_PROPERTY = "test.artifactory.rest.token";
    public static final String TEST_TOKEN_ENVIRONMENT_VARIABLE = TEST_TOKEN_SYSTEM_PROPERTY.replaceAll("\\.", "_").toUpperCase();

    private static final char[] CHARS = "abcdefghijklmnopqrstuvwxyz".toCharArray();

    /**
     * Generate a random String with letters only.
     * 
     * @return random String.
     */
    public static String randomStringLettersOnly() {
        final StringBuilder sb = new StringBuilder();
        final Random random = new Random();
        for (int i = 0; i < 10; i++) {
            final char randomChar = CHARS[random.nextInt(CHARS.length)];
            sb.append(randomChar);
        }
        return sb.toString().toUpperCase();
    }

    /**
     * Generate a random String with numbers and letters.
     * 
     * @return random String.
     */
    public static String randomString() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * Find credentials (Basic, Bearer, or Anonymous) from system/environment.
     *
     * @return ArtifactoryCredentials
     */
    public static ArtifactoryAuthentication inferTestAuthentication() {

        // 1.) Check for "Basic" auth credentials.
        final ArtifactoryAuthentication.Builder inferAuth = ArtifactoryAuthentication.builder();
        String authValue = ArtifactoryUtils
                .retriveExternalValue(TEST_CREDENTIALS_SYSTEM_PROPERTY,
                        TEST_CREDENTIALS_ENVIRONMENT_VARIABLE);
        if (authValue != null) {
            inferAuth.credentials(authValue);
        } else {

            // 2.) Check for "Bearer" auth token.
            authValue = ArtifactoryUtils
                    .retriveExternalValue(TEST_TOKEN_SYSTEM_PROPERTY,
                            TEST_TOKEN_ENVIRONMENT_VARIABLE);
            if (authValue != null) {
                inferAuth.token(authValue);
            }
        }

        // 3.) If neither #1 or #2 find anything "Anonymous" access is assumed.
        return inferAuth.build();
    }

    /**
     * Migration from testng to assertj method to test for true.
     * 
     * @param value boolean that hopefully represents true.
     */
    public static void assertTrue(boolean value) {
        assertThat(value).isTrue();
    }

    /**
     * Migration from testng to assertj method to test for false.
     * 
     * @param value boolean that hopefully represents false.
     */
    public static void assertFalse(boolean value) {
        assertThat(value).isFalse();
    }

    /**
     * Migration from testng to assertj method to test for non-null.
     * 
     * @param value object which is hopefully non-null.
     */
    public static void assertNotNull(Object value) {
        assertThat(value).isNotNull();
    }

    /**
     * Migration from testng to assertj method to test for null.
     * 
     * @param value object which is hopefully null.
     */
    public static void assertNull(Object value) {
        assertThat(value).isNull();
    }

    private TestUtilities() {
        throw new UnsupportedOperationException("Purposefully not implemented");
    }
} public enum AuthenticationType {

    Basic("Basic"),
    Bearer("Bearer"),
    Anonymous("");

    private final String type;

    private AuthenticationType(final String type) {
        this.type = type;
    }

    @Override
    public String toString() {
        return type;
    }
} @AutoValue
public abstract class Version {

   public abstract String version();

   public abstract String revision();

   public abstract List<String> addons();

   public abstract String license();

   Version() {
   }

   @SerializedNames({ "version", "revision", "addons", "license" })
   public static Version create(String version, String revision, List<String> addons, String license) {
      return new AutoValue_Version(version, revision,
            addons != null ? ImmutableList.copyOf(addons) : ImmutableList.<String> of(), license);
   }
}
import static com.cdancy.artifactory.rest.ArtifactoryConstants.CREDENTIALS_ENVIRONMENT_VARIABLE;
import static com.cdancy.artifactory.rest.ArtifactoryConstants.CREDENTIALS_SYSTEM_PROPERTY;
import static com.cdancy.artifactory.rest.ArtifactoryConstants.ENDPOINT_ENVIRONMENT_VARIABLE;
import static com.cdancy.artifactory.rest.ArtifactoryConstants.ENDPOINT_SYSTEM_PROPERTY;
import static com.cdancy.artifactory.rest.ArtifactoryConstants.TOKEN_ENVIRONMENT_VARIABLE;
import static com.cdancy.artifactory.rest.ArtifactoryConstants.TOKEN_SYSTEM_PROPERTY;
import static org.assertj.core.api.Assertions.assertThat;
import org.testng.annotations.Test;
import com.cdancy.artifactory.rest.ArtifactoryAuthentication;
import com.cdancy.artifactory.rest.ArtifactoryClient;
import com.cdancy.artifactory.rest.BaseArtifactoryApiLiveTest;
import com.cdancy.artifactory.rest.TestUtilities;
import com.cdancy.artifactory.rest.auth.AuthenticationType;
import com.cdancy.artifactory.rest.domain.system.Version;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.jclouds.http.HttpResponseException;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.rest.AuthorizationException;
        client.api().systemApi().version();
    }

    @Test
    public void testCreateClientWithEndpointFromSystemProperties() {
        clearSystemProperties();

        System.setProperty(ENDPOINT_SYSTEM_PROPERTY, this.endpoint);
        final ArtifactoryClient client = new ArtifactoryClient(null, this.artifactoryAuthentication, null);
        assertThat(client.endPoint()).isEqualTo(this.endpoint);
        final Version version = client.api().systemApi().version();
        assertThat(version).isNotNull();
        clearSystemProperties();
    }

    @Test
    public void testCreateClientWithWrongEndpointFromSystemProperties() {
        clearSystemProperties();

        System.setProperty(ENDPOINT_SYSTEM_PROPERTY, DUMMY_ENDPOINT);
        final ArtifactoryClient client = new ArtifactoryClient(null, this.artifactoryAuthentication, null);
        assertThat(client.endPoint()).isEqualTo(DUMMY_ENDPOINT);
        boolean caughtException = false;
        try {
            client.api().systemApi().version();
        } catch (final HttpResponseException e) {
            caughtException = true;
        }
        assertThat(caughtException).isTrue();
        clearSystemProperties();
    }

    @Test
    public void testCreateClientWithAuthenticationFromSystemProperties() {
        clearSystemProperties();

        final AuthenticationType currentAuthType = this.artifactoryAuthentication.authType();
        final String correctAuth = this.artifactoryAuthentication.authValue();
        if (currentAuthType == AuthenticationType.Basic) {
            System.setProperty(CREDENTIALS_SYSTEM_PROPERTY, correctAuth);
        } else if (currentAuthType == AuthenticationType.Bearer) {
            System.setProperty(TOKEN_SYSTEM_PROPERTY, correctAuth);
        }

        final ArtifactoryClient client = new ArtifactoryClient(this.endpoint, null, null);
        assertThat(client.authType()).isEqualTo(currentAuthType);
        assertThat(client.authValue()).isEqualTo(correctAuth);
        final Version version = client.api().systemApi().version();
        assertThat(version).isNotNull();
        clearSystemProperties();
    }

    @Test
    public void testCreateClientWithWrongAuthenticationFromSystemProperties() {
        clearSystemProperties();

        final AuthenticationType currentAuthType = this.artifactoryAuthentication.authType();
        final String wrongAuth = TestUtilities.randomStringLettersOnly();
        if (currentAuthType == AuthenticationType.Basic) {
            System.setProperty(CREDENTIALS_SYSTEM_PROPERTY, wrongAuth);
        } else if (currentAuthType == AuthenticationType.Bearer) {
            System.setProperty(TOKEN_SYSTEM_PROPERTY, wrongAuth);
        }

        final ArtifactoryClient client = new ArtifactoryClient(this.endpoint, null, null);
        assertThat(client.authType()).isEqualTo(currentAuthType);
        assertThat(client.authValue()).isEqualTo(wrongAuth);

        boolean caughtException = false;
        try {
            client.api().systemApi().version();
        } catch (final AuthorizationException e) {
            caughtException = true;
        }
        assertThat(caughtException).isTrue();
        clearSystemProperties();
    }

    @Test
    public void testCreateClientWithEndpointFromEnvironmentVariables() {
        clearEnvironmentVariables(null);
        final Map<String, String> envVars = Maps.newHashMap();
        envVars.put(ENDPOINT_ENVIRONMENT_VARIABLE, this.endpoint);
        TestUtilities.addEnvironmentVariables(envVars);

        final ArtifactoryClient client = new ArtifactoryClient(null, this.artifactoryAuthentication, null);
        assertThat(client.endPoint()).isEqualTo(this.endpoint);
        final Version version = client.api().systemApi().version();
        assertThat(version).isNotNull();
        clearEnvironmentVariables(null);
    }

    @Test
    public void testCreateClientWithWrongEndpointFromEnvironmentVariables() {
        clearEnvironmentVariables(null);
        final Map<String, String> envVars = Maps.newHashMap();
        envVars.put(ENDPOINT_ENVIRONMENT_VARIABLE, DUMMY_ENDPOINT);
        TestUtilities.addEnvironmentVariables(envVars);

        final ArtifactoryClient client = new ArtifactoryClient(null, this.artifactoryAuthentication, null);
        assertThat(client.endPoint()).isEqualTo(DUMMY_ENDPOINT);
        boolean caughtException = false;
        try {
            client.api().systemApi().version();
        } catch (final HttpResponseException e) {
            caughtException = true;
        }
        assertThat(caughtException).isTrue();
        clearEnvironmentVariables(null);
    }

    @Test
    public void testCreateClientWithAuthenticationFromEnvironmentVariables() {
        clearEnvironmentVariables(null);

        final AuthenticationType currentAuthType = this.artifactoryAuthentication.authType();
        final String correctAuth = this.artifactoryAuthentication.authValue();
        final String correctAuthType;
        switch (currentAuthType) {
            case Basic:
                correctAuthType = CREDENTIALS_ENVIRONMENT_VARIABLE;