/** * Copyright 2012 Terremark Worldwide Inc. * * Licensed 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. */ package com.terremark.config; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import org.apache.commons.lang3.StringUtils; import org.apache.http.client.HttpClient; import com.terremark.impl.ClientConfiguration; /** * Properties necessary to instantiate Terremark client. Most of the property use appropriate default values. At a * minimum {@link #setEndPoint(String)}, {@link #setAccessKey(String)} and {@link #setPrivateKey(String)} should be set. * * @author <a href="mailto:spasam@terremark.com">Seshu Pasam</a> * @see com.terremark.TerremarkFactory#getClient(PropertiesBuilder) */ public class PropertiesBuilder { /** Default Terremark eCloud API end point URL */ public static final String ENDPOINT_URL = "https://services.enterprisecloud.terremark.com/cloudapi/ecloud"; /** API end point URL */ private String uri; /** User name for basic authentication */ private String userName; /** Password for basic authentication */ private transient String password; /** Access key for Cloud API authentication */ private String accessKey; /** Private key for Cloud API authentication */ private transient String privateKey; /** Content type */ private ContentType contentType; /** Signature algorithm */ private SignatureAlgorithm signatureAlgorithm; /** API version */ private Version version; /** Proxy host name */ private String proxyHost; /** Proxy port */ private int proxyPort; /** Apache HttpClient */ private HttpClient httpClient; /** Retry handler for retrying failed GET calls */ private RetryHandler retryHandler; /** * Default constructor. Sets the context type to {@link ContentType#XML}, signature algorithm to * {@link SignatureAlgorithm#HMAC_SHA256} and API version to {@link Version#VERSION_2_13}. API end point URL is set * to the default value (https://services.enterprisecloud.terremark.com/cloudapi/ecloud). */ public PropertiesBuilder() { this.uri = ENDPOINT_URL; this.contentType = ContentType.XML; this.signatureAlgorithm = SignatureAlgorithm.HMAC_SHA256; this.version = Version.VERSION_2_13; } /** * Used internally to retrieve the configuration set by the user. Validates the arguments and throws * {@link IllegalArgumentException} if the arguments are invalid or missing. * * @return Client configuration. * @throws MalformedURLException If the API end point URL is invalid. */ public final ClientConfiguration build() throws MalformedURLException { if (httpClient == null) { throw new IllegalArgumentException("Invalid HTTP client"); } if (StringUtils.isEmpty(uri)) { throw new IllegalArgumentException("Invalid endpoint URI"); } if (!StringUtils.isEmpty(userName) && StringUtils.isEmpty(password)) { throw new IllegalArgumentException("Invalid password"); } if (!StringUtils.isEmpty(accessKey) && StringUtils.isEmpty(privateKey)) { throw new IllegalArgumentException("Invalid private key"); } if (StringUtils.isEmpty(userName) && StringUtils.isEmpty(accessKey)) { throw new IllegalArgumentException("Either username/password or access/private keys must be specified"); } if (contentType == null) { throw new IllegalArgumentException("Invalid content type"); } if (signatureAlgorithm == null) { throw new IllegalArgumentException("Invalid signature algorithm"); } if (!"https".equalsIgnoreCase(new URL(uri).getProtocol())) { throw new IllegalArgumentException("API end point URL must use 'https' protocol"); } return new ClientConfiguration(uri, userName, password, accessKey, privateKey, contentType, signatureAlgorithm, version, proxyHost, proxyPort, httpClient, retryHandler); } /** * Set the API end point URL. This is required property. * * @param uri API end point URL. * @return The builder object reference. */ public final PropertiesBuilder setEndPoint(final String uri) { if (StringUtils.isEmpty(uri)) { throw new IllegalArgumentException("Invalid endpoint URI"); } URI.create(uri); // Validate this.uri = uri; return this; } /** * Set the proxy host (name or IP address) to use, when connecting to the API end point. This is optional property. * * @param proxyHost Proxy host (name or IP address). * @return The builder object reference. * @see #setProxyPort(int) */ public final PropertiesBuilder setProxyHost(final String proxyHost) { this.proxyHost = proxyHost; return this; } /** * Set the proxy port to use, when connecting to the API end point. This is optional property, but required if * {@code proxy host} is set. * * @param proxyPort Proxy port number. * @return The builder object reference. * @see #setProxyHost(String) */ public final PropertiesBuilder setProxyPort(final int proxyPort) { this.proxyPort = proxyPort; return this; } /** * Set the access key for performing the Cloud API authentication. This is required, if Cloud API authentication * should be used. Either this or {@code user name} are required. * * @param accessKey Access key for Cloud API authentication. * @return The builder object reference. * @see #setPrivateKey(String) * @see #setUserName(String) */ public final PropertiesBuilder setAccessKey(final String accessKey) { this.accessKey = accessKey; return this; } /** * Set the private key for performing the Cloud API authentication. This is required, if the {@code access key} is * set. * * @param privateKey Private key for Cloud API authentication. * @return The builder object reference. * @see #setAccessKey(String) */ public final PropertiesBuilder setPrivateKey(final String privateKey) { this.privateKey = privateKey; return this; } /** * Set the content type to use. Currently only {@link ContentType#XML} is valid. This is optional and defaults to * {@link ContentType#XML}. * * @param contentType Content type to use. * @return The builder object reference. * @see ContentType */ public final PropertiesBuilder setContentType(final ContentType contentType) { this.contentType = contentType; return this; } /** * Signature algorithm to use when Cloud API authentication is configured. This is optional and defaults to * {@link SignatureAlgorithm#HMAC_SHA256}. This is not applicable when basic user name/password authentication is * used. * * @param signatureAlgorithm Signature algorithm to use. * @return The builder object reference. */ public final PropertiesBuilder setSignatureAlgorithm(final SignatureAlgorithm signatureAlgorithm) { this.signatureAlgorithm = signatureAlgorithm; return this; } /** * {@code Apache HttpClient} to use for connecting to the API end point. It is recommended to configure connection * pooling on the client. This is required. * * @param httpClient HttpClient to use for connecting to the API end point. * @return The builder object reference. */ public final PropertiesBuilder setHttpClient(final HttpClient httpClient) { this.httpClient = httpClient; return this; } /** * Retry handler to use for determining if failed {@code GET} calls should be retried. Only {@code HTTP GET} calls * can be retried. This handler will not be invoked for other types of HTTP requests (POST, PUT, DELETE). This is * optional. If not specified, HTTP GET calls that fail with 500+ error codes will not be retried. * * @param retryHandler Retry handler. * @return The builder object reference. */ public final PropertiesBuilder setRetryHandler(final RetryHandler retryHandler) { this.retryHandler = retryHandler; return this; } /** * Set the user name to use for performing basic authentication. This is not recommended authentication method. * Instead Cloud API authentication should be used. * * @param userName User name for basic authentication. * @return The builder object reference. * @see #setAccessKey(String) * @see #setPassword(String) */ public final PropertiesBuilder setUserName(final String userName) { this.userName = userName; return this; } /** * Set the user password for performing basic authentication. This is not recommended authentication method. Instead * Cloud API authentication should be used. * * @param password Password for basic authentication. * @return The builder object reference. * @see #setUserName(String) */ public final PropertiesBuilder setPassword(final String password) { this.password = password; return this; } /** * Set the API version to use. This is optional. If not specified, {@link Version#VERSION_2_13} will be used. * * @param version API version to use. * @return The builder object reference. * @see Version */ public final PropertiesBuilder setAPIVersion(final Version version) { this.version = version; return this; } }