From 3ded7d2623b4a4a5aa99e882b1b83fbf17454b2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Weing=C3=A4rtner?= Date: Thu, 19 Oct 2017 19:23:19 -0200 Subject: [PATCH 1/2] Addition of toString to ApacheCloudStackClient --- .../client/ApacheCloudStackClient.java | 936 ++++++++--------- .../client/ApacheCloudStackClientTest.java | 958 +++++++++--------- 2 files changed, 953 insertions(+), 941 deletions(-) diff --git a/src/main/java/br/com/autonomiccs/apacheCloudStack/client/ApacheCloudStackClient.java b/src/main/java/br/com/autonomiccs/apacheCloudStack/client/ApacheCloudStackClient.java index f61ce95..bf4e550 100644 --- a/src/main/java/br/com/autonomiccs/apacheCloudStack/client/ApacheCloudStackClient.java +++ b/src/main/java/br/com/autonomiccs/apacheCloudStack/client/ApacheCloudStackClient.java @@ -93,469 +93,475 @@ * The client is a pair of URL and user credentials ({@link #apacheCloudStackUser}). */ public class ApacheCloudStackClient { - /** - * This flag indicates if we are going to validate the server certificate in case of HTTPS connections. - * The default value is 'true', meaning that we always validate the server HTTPS certificate. - */ - protected boolean validateServerHttpsCertificate = true; - - /** - * This flag is highly dangerous and should never be used with production environments. - * It will accept every single SSL certificates when creating HTTPS connections. Not even the commons name will be checked. - * Therefore, it should be kept only during development phase. - */ - protected boolean acceptAllKindsOfCertificates = false; - - /** - * The validity time of the ACS request. - * The default value is {@value #requestValidity} . - */ - private int requestValidity = 30; - - /** - * The http client connection timeout - * The default value is {@value #connectionTimeout} seconds . - */ - private int connectionTimeout = 60; - - /** - * This parameter controls if the expiration of requests is activated or not. - * It is activated by default. The validity of requests if defined by {@value #requestValidity} property. - */ - private boolean shouldRequestsExpire = true; - - private Gson gson = new GsonBuilder().create(); - private Logger logger = LoggerFactory.getLogger(getClass()); - - /** - * The API URL used to access Apache CloudStack API. - * Ex: https://cloud.domain.com/client/api - */ - private String url; - - /** - * User credentials that can be used to access ApacheCloudStack. - * They can be either a pair of secret key and API key or a triple of username, password and domain - */ - protected ApacheCloudStackUser apacheCloudStackUser; - - public ApacheCloudStackClient(String url, ApacheCloudStackUser apacheCloudStackUser) { - this.url = url; - this.apacheCloudStackUser = apacheCloudStackUser; - - } - - /** - * This method executes the given {@link ApacheCloudStackRequest}. - * It will return the response as a plain {@link String}. - * You should have in mind that if the parameter 'response' is not set, the default is 'XML'. - */ - public String executeRequest(ApacheCloudStackRequest request) { - boolean isSecretKeyApiKeyAuthenticationMechanism = StringUtils.isNotBlank(this.apacheCloudStackUser.getApiKey()); - String urlRequest = createApacheCloudStackApiUrlRequest(request, isSecretKeyApiKeyAuthenticationMechanism); - logger.debug(String.format("Executing request[%s].", urlRequest)); - CloseableHttpClient httpClient = createHttpClient(); - HttpContext httpContext = createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(httpClient, isSecretKeyApiKeyAuthenticationMechanism); - try { - return executeRequestGetResponseAsString(urlRequest, httpClient, httpContext); - } finally { - if (!isSecretKeyApiKeyAuthenticationMechanism) { - executeUserLogout(httpClient, httpContext); - } - HttpClientUtils.closeQuietly(httpClient); - } - } - - /** - * Executes the request with the given {@link HttpContext}. - */ - protected String executeRequestGetResponseAsString(String urlRequest, CloseableHttpClient httpClient, HttpContext httpContext) { - try { - HttpRequestBase httpGetRequest = new HttpGet(urlRequest); - CloseableHttpResponse response = httpClient.execute(httpGetRequest, httpContext); - StatusLine requestStatus = response.getStatusLine(); - if (requestStatus.getStatusCode() == HttpStatus.SC_OK) { - return getResponseAsString(response); - } - throw new ApacheCloudStackClientRequestRuntimeException(requestStatus.getStatusCode(), getResponseAsString(response), urlRequest.toString()); - } catch (IOException e) { - logger.error(String.format("Error while executing request [%s]", urlRequest)); - throw new ApacheCloudStackClientRuntimeException(e); - } - } - - /** - * This method executes the user logout when using username/password/domain authentication. - * The logout is executed calling the 'logout' command of the Apache CloudStack API. - */ - protected void executeUserLogout(CloseableHttpClient httpClient, HttpContext httpContext) { - String urlRequest = createApacheCloudStackApiUrlRequest(new ApacheCloudStackRequest("logout").addParameter("response", "json"), false); - String returnOfLogout = executeRequestGetResponseAsString(urlRequest, httpClient, httpContext); - logger.debug(String.format("Logout result[%s]", returnOfLogout)); - } - - /** - * According to the 'isSecretKeyApiKey AuthenticationMechanism' parameter this method creates an HttpContext that is used when executing requests. - * If the user has provided his/her API/secret keys, we return a {@link BasicHttpContext} object. Otherwise, we authenticate the user with his/her username/password/domain and return an {@link HttpContext} object that contains the authenticated session Id configured as a cookie. - */ - protected HttpContext createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(CloseableHttpClient httpClient, boolean isSecretKeyApiKeyAuthenticationMechanism) { - if (isSecretKeyApiKeyAuthenticationMechanism) { - return new BasicHttpContext(); - } - return createHttpContextWithAuthenticatedSessionUsingUserCredentials(httpClient); - } - - /** - * It creates a {@link RequestConfig} object with configured {@link #connectionTimeout} value. - * This can be used to set on a HttpClient its connect timeout, connection request timeout and socket timeout. - * @return returns the created RequestConfig object - */ - protected RequestConfig createRequestConfig() { - return RequestConfig.custom().setConnectTimeout(connectionTimeout * (int)DateUtils.MILLIS_PER_SECOND) - .setConnectionRequestTimeout(connectionTimeout * (int)DateUtils.MILLIS_PER_SECOND).setSocketTimeout(connectionTimeout * (int)DateUtils.MILLIS_PER_SECOND).build(); - } - - /** - * It creates an {@link CloseableHttpClient} object. - * If {@link #validateServerHttpsCertificate} indicates that we should not validate HTTPS server certificate, we use an insecure SSL factory; the insecure factory is created using {@link #createInsecureSslFactory()}. - */ - protected CloseableHttpClient createHttpClient() { - HttpClientBuilder httpClientBuilder = HttpClientBuilder.create().setDefaultRequestConfig(createRequestConfig()); - if (!validateServerHttpsCertificate) { - SSLConnectionSocketFactory sslsf = createInsecureSslFactory(); - httpClientBuilder.setSSLSocketFactory(sslsf); - } - return httpClientBuilder.build(); - } - - /** - * This method creates an {@link HttpContext} with an authenticated JSESSIONID. - * The authentication is performed using username, password and domain that are provided by the user. - */ - protected HttpContext createHttpContextWithAuthenticatedSessionUsingUserCredentials(CloseableHttpClient httpClient) { - HttpPost httpPost = createHttpPost(); - List params = getParametersForLogin(); - - try { - UrlEncodedFormEntity postParams = new UrlEncodedFormEntity(params, "UTF-8"); - httpPost.setEntity(postParams); - - CloseableHttpResponse loginResponse = httpClient.execute(httpPost); - int statusCode = loginResponse.getStatusLine().getStatusCode(); - if (statusCode != HttpStatus.SC_OK) { - throw new ApacheCloudStackClientRequestRuntimeException(statusCode, getResponseAsString(loginResponse), "login"); - } - logger.debug(String.format("Authentication response:[%s]", getResponseAsString(loginResponse))); - - return createHttpContextWithCookies(loginResponse); - } catch (IOException e) { - throw new ApacheCloudStackClientRuntimeException(e); - } - } - - /** - * It creates an {@link HttpContext} object with a cookie store that will contain the cookies returned by the user in the {@link CloseableHttpResponse} that is received as parameter. - */ - protected HttpContext createHttpContextWithCookies(CloseableHttpResponse loginResponse) { - CookieStore cookieStore = new BasicCookieStore(); - createAndAddCookiesOnStoreForHeaders(cookieStore, loginResponse.getAllHeaders()); - HttpContext httpContext = new BasicHttpContext(); - httpContext.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore); - return httpContext; - } - - /** - * For every header that contains the command 'Set-Cookie' it will call the method {@link #createAndAddCookiesOnStoreForHeader(CookieStore, Header)} - */ - protected void createAndAddCookiesOnStoreForHeaders(CookieStore cookieStore, Header[] allHeaders) { - for (Header header : allHeaders) { - if (StringUtils.startsWithIgnoreCase(header.getName(), "Set-Cookie")) { - createAndAddCookiesOnStoreForHeader(cookieStore, header); - } - } - } - - /** - * This method creates a cookie for every {@link HeaderElement} of the {@link Header} given as parameter. - * Then, it adds this newly created cookie into the {@link CookieStore} provided as parameter. - */ - protected void createAndAddCookiesOnStoreForHeader(CookieStore cookieStore, Header header) { - for (HeaderElement element : header.getElements()) { - BasicClientCookie cookie = createCookieForHeaderElement(element); - cookieStore.addCookie(cookie); - } - } - - /** - * This method will create a {@link BasicClientCookie} with the given {@link HeaderElement}. - * It sill set the cookie's name and value according to the {@link HeaderElement#getName()} and {@link HeaderElement#getValue()} methods. - * Moreover, it will transport every {@link HeaderElement} parameter to the cookie using the {@link BasicClientCookie#setAttribute(String, String)}. - * Additionally, it configures the cookie path ({@link BasicClientCookie#setPath(String)}) to value '/client/api' and the cookie domain using {@link #configureDomainForCookie(BasicClientCookie)} method. - */ - protected BasicClientCookie createCookieForHeaderElement(HeaderElement element) { - BasicClientCookie cookie = new BasicClientCookie(element.getName(), element.getValue()); - for (NameValuePair parameter : element.getParameters()) { - cookie.setAttribute(parameter.getName(), parameter.getValue()); - } - cookie.setPath("/client/api"); - configureDomainForCookie(cookie); - return cookie; - } - - /** - * It configures the cookie domain with the domain of the Apache CloudStack that is being accessed. - * The domain is extracted from {@link #url} variable. - */ - protected void configureDomainForCookie(BasicClientCookie cookie) { - try { - HttpHost httpHost = URIUtils.extractHost(new URI(url)); - String domain = httpHost.getHostName(); - cookie.setDomain(domain); - } catch (URISyntaxException e) { - throw new ApacheCloudStackClientRuntimeException(e); - } - } - - /** - * Creates an {@link HttpPost} object to be sent to Apache CloudStack API. - * The content type configured for this request is 'application/x-www-form-urlencoded'. - */ - protected HttpPost createHttpPost() { - HttpPost httpPost = new HttpPost(url); - httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded"); - return httpPost; - } - - /** - * This method creates a list of {@link NameValuePair} and returns the data for login using username and password. - */ - protected List getParametersForLogin() { - List params = new ArrayList<>(4); - params.add(new BasicNameValuePair("command", "login")); - params.add(new BasicNameValuePair("username", this.apacheCloudStackUser.getUsername())); - params.add(new BasicNameValuePair("password", this.apacheCloudStackUser.getPassword())); - params.add(new BasicNameValuePair("domain", this.apacheCloudStackUser.getDomain())); - return params; - } - - /** - * This method creates an insecure SSL factory that will trust on self signed certificates. - * For that we use {@link TrustSelfSignedStrategy}. - */ - protected SSLConnectionSocketFactory createInsecureSslFactory() { - try { - SSLContextBuilder builder = new SSLContextBuilder(); - builder.loadTrustMaterial(new TrustSelfSignedStrategy()); - SSLContext sc = builder.build(); - - if (acceptAllKindsOfCertificates) { - TrustManager[] trustAllCerts = new TrustManager[1]; - TrustManager tm = new TrustAllManager(); - trustAllCerts[0] = tm; - sc.init(null, trustAllCerts, null); - - HostnameVerifier hostnameVerifier = createInsecureHostNameVerifier(); - return new SSLConnectionSocketFactory(sc, hostnameVerifier); - } - return new SSLConnectionSocketFactory(sc); - } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) { - throw new ApacheCloudStackClientRuntimeException(e); - } - } - - protected HostnameVerifier createInsecureHostNameVerifier() { - HostnameVerifier hostnameVerifier = new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; - } - }; - return hostnameVerifier; - } - - /** - * This class is used when {@link ApacheCloudStackClient#acceptAllKindsOfCertificates} is set to true. - */ - @SuppressWarnings("unused") - private class TrustAllManager implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager { - @Override - public java.security.cert.X509Certificate[] getAcceptedIssuers() { - return null; - } - - public boolean isServerTrusted(final X509Certificate[] certs) { - return true; - } - - public boolean isClientTrusted(final X509Certificate[] certs) { - return true; - } - - @Override - public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { - return; - } - - @Override - public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { - return; - } - } - - /** - * It retrieves the response status as a {@link String} - */ - protected String getResponseAsString(CloseableHttpResponse response) throws IOException { - InputStream responseContent = response.getEntity().getContent(); - StringWriter writer = new StringWriter(); - IOUtils.copy(responseContent, writer, Charset.defaultCharset()); - - responseContent.close(); - response.close(); - return writer.toString(); - } - - /** - * This method creates transforms the given {@link ApacheCloudStackRequest} into a URL requeest for the Apache CloudStack API. - * Therefore, it will create a command query string following the CloudStack specifications using method {@link #createCommandString(ApacheCloudStackRequest)}; - * and then, if it needs, it creates the signature using the method {@link #createSignature(String)} and append it to the URL. - */ - protected String createApacheCloudStackApiUrlRequest(ApacheCloudStackRequest request, boolean shouldSignAppendSignature) { - StringBuilder urlRequest = new StringBuilder(url).append("?"); - - String queryString = createCommandString(request); - urlRequest.append(queryString); - - if (shouldSignAppendSignature) { - String signature = createSignature(queryString); - urlRequest.append("&signature=").append(getUrlEncodedValue(signature)); - } - return urlRequest.toString(); - } - - /** - * Creates a signature (HMAC-sha1) with the {@link #ApacheCloudStackUser#getSecretKey()} and the given queryString - * The returner signature is encoded in Base64. - */ - protected String createSignature(String queryString) { - byte[] signatureBytes = HmacUtils.hmacSha1(apacheCloudStackUser.getSecretKey(), queryString.toLowerCase()); - return Base64.encodeBase64String(signatureBytes); - } - - /** - * It creates the command query string, placing the parameters in alphabetical order. - * To execute the sorting, it uses the {@link #createSortedCommandQueryList(ApacheCloudStackRequest)} method. - */ - protected String createCommandString(ApacheCloudStackRequest request) { - List queryCommand = createSortedCommandQueryList(request); - - StringBuilder commandString = new StringBuilder(); - for (ApacheCloudStackApiCommandParameter param : queryCommand) { - String value = getUrlEncodedValue(param.getValue()); - commandString.append(String.format("%s=%s&", param.getName(), value)); - } - return commandString.toString().substring(0, commandString.length() - 1); - } - - /** - * This method encodes the parameter value as specified by Apache CloudStack - */ - protected String getUrlEncodedValue(Object paramValue) { - String value = Objects.toString(paramValue); - try { - value = URLEncoder.encode(value, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new ApacheCloudStackClientRuntimeException(e); - } - return value.replaceAll("\\+", "%20"); - } - - /** - * This methods adds the final data needed to the command query. - * It will add a parameter called 'command' with the value of {@link ApacheCloudStackRequest#getCommand()} as value. - * It also adds a parameter called 'apiKey', with the value of {@link #ApacheCloudStackUser#getApiKey()} as value. - * Then, it will sort the parameters that are in a list in alphabetical order. - */ - protected List createSortedCommandQueryList(ApacheCloudStackRequest request) { - List queryCommand = new ArrayList<>(); - queryCommand.addAll(request.getParameters()); - queryCommand.add(new ApacheCloudStackApiCommandParameter("command", request.getCommand())); - if (StringUtils.isNotBlank(this.apacheCloudStackUser.getApiKey())) { - queryCommand.add(new ApacheCloudStackApiCommandParameter("apiKey", this.apacheCloudStackUser.getApiKey())); - } - configureRequestExpiration(queryCommand); - Collections.sort(queryCommand); - return queryCommand; - } - - /** - * This method configures the request expiration if needed. - * It uses the value defined at {@link #requestValidity} to determine until when the request is valid. - * It also uses the parameter {@link #shouldRequestsExpire} to decide if it has to configure or not the validity of the request. - * Moreover, if the 'apacheCloudStackRequestList' contains the 'expires' it will only add a parameter called 'signatureVersion=3', in order to enable that override. - */ - protected void configureRequestExpiration(List apacheCloudStackRequestList) { - boolean isOverridingExpirationConfigs = apacheCloudStackRequestList.contains(new ApacheCloudStackApiCommandParameter("expires", StringUtils.EMPTY)); - if (!isOverridingExpirationConfigs && !shouldRequestsExpire) { - return; - } - apacheCloudStackRequestList.add(new ApacheCloudStackApiCommandParameter("signatureVersion", 3)); - if (isOverridingExpirationConfigs) { - return; - } - String expirationDataAsSring = createExpirationDate(); - apacheCloudStackRequestList.add(new ApacheCloudStackApiCommandParameter("expires", expirationDataAsSring)); - } - - /** - * This method creates the expiration date as a string according to the ISO 8601. - */ - protected String createExpirationDate() { - DateFormat acsIso8601DateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); - return acsIso8601DateFormat.format(getExpirationDate()); - } - - /** - * Creates the expiration date, by adding the {@link #requestValidity} to the current time. - */ - protected Date getExpirationDate() { - Calendar now = Calendar.getInstance(); - now.add(Calendar.SECOND, requestValidity); - return now.getTime(); - } - - /** - * It executes the given request and converts the result into an object of the given type. - * This method will change the response type to 'JSON'. To execute the request, it uses the method {@link #executeRequest(ApacheCloudStackRequest)}. - * To convert the result into an object, it will use {@link Gson#fromJson(String, Class)} - */ - public T executeRequest(ApacheCloudStackRequest request, Class clazz) { - request.addParameter("response", "json"); - String response = executeRequest(request); - return gson.fromJson(response, clazz); - } - - /** - * This configuration enables or disables the HTTPS certification validation. If set to 'false', we will accept self-signed certificates. - * However, this does not mean that we accept certificates that are signed by an untrusted certificated authority. - */ - public void setValidateServerHttpsCertificate(boolean validateServerHttpsCertificate) { - this.validateServerHttpsCertificate = validateServerHttpsCertificate; - } - - public void setRequestValidity(int requestValidity) { - this.requestValidity = requestValidity; - } - - public void setShouldRequestsExpire(boolean shouldRequestsExpire) { - this.shouldRequestsExpire = shouldRequestsExpire; - } - - public void setConnectionTimeout(int connectionTimeout) { - this.connectionTimeout = connectionTimeout; - } - - public void setAcceptAllKindsOfCertificates(boolean acceptAllKindOfCertificates) { - this.acceptAllKindsOfCertificates = acceptAllKindOfCertificates; - } + /** + * This flag indicates if we are going to validate the server certificate in case of HTTPS connections. + * The default value is 'true', meaning that we always validate the server HTTPS certificate. + */ + protected boolean validateServerHttpsCertificate = true; + + /** + * This flag is highly dangerous and should never be used with production environments. + * It will accept every single SSL certificates when creating HTTPS connections. Not even the commons name will be checked. + * Therefore, it should be kept only during development phase. + */ + protected boolean acceptAllKindsOfCertificates = false; + + /** + * The validity time of the ACS request. + * The default value is {@value #requestValidity} . + */ + private int requestValidity = 30; + + /** + * The http client connection timeout + * The default value is {@value #connectionTimeout} seconds . + */ + private int connectionTimeout = 60; + + /** + * This parameter controls if the expiration of requests is activated or not. + * It is activated by default. The validity of requests if defined by {@value #requestValidity} property. + */ + private boolean shouldRequestsExpire = true; + + private Gson gson = new GsonBuilder().create(); + private Logger logger = LoggerFactory.getLogger(getClass()); + + /** + * The API URL used to access Apache CloudStack API. + * Ex: https://cloud.domain.com/client/api + */ + private String url; + + /** + * User credentials that can be used to access ApacheCloudStack. + * They can be either a pair of secret key and API key or a triple of username, password and domain + */ + protected ApacheCloudStackUser apacheCloudStackUser; + + public ApacheCloudStackClient(String url, ApacheCloudStackUser apacheCloudStackUser) { + this.url = url; + this.apacheCloudStackUser = apacheCloudStackUser; + + } + + /** + * This method executes the given {@link ApacheCloudStackRequest}. + * It will return the response as a plain {@link String}. + * You should have in mind that if the parameter 'response' is not set, the default is 'XML'. + */ + public String executeRequest(ApacheCloudStackRequest request) { + boolean isSecretKeyApiKeyAuthenticationMechanism = StringUtils.isNotBlank(this.apacheCloudStackUser.getApiKey()); + String urlRequest = createApacheCloudStackApiUrlRequest(request, isSecretKeyApiKeyAuthenticationMechanism); + logger.debug(String.format("Executing request[%s].", urlRequest)); + CloseableHttpClient httpClient = createHttpClient(); + HttpContext httpContext = createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(httpClient, isSecretKeyApiKeyAuthenticationMechanism); + try { + return executeRequestGetResponseAsString(urlRequest, httpClient, httpContext); + } finally { + if (!isSecretKeyApiKeyAuthenticationMechanism) { + executeUserLogout(httpClient, httpContext); + } + HttpClientUtils.closeQuietly(httpClient); + } + } + + /** + * Executes the request with the given {@link HttpContext}. + */ + protected String executeRequestGetResponseAsString(String urlRequest, CloseableHttpClient httpClient, HttpContext httpContext) { + try { + HttpRequestBase httpGetRequest = new HttpGet(urlRequest); + CloseableHttpResponse response = httpClient.execute(httpGetRequest, httpContext); + StatusLine requestStatus = response.getStatusLine(); + if (requestStatus.getStatusCode() == HttpStatus.SC_OK) { + return getResponseAsString(response); + } + throw new ApacheCloudStackClientRequestRuntimeException(requestStatus.getStatusCode(), getResponseAsString(response), urlRequest.toString()); + } catch (IOException e) { + logger.error(String.format("Error while executing request [%s]", urlRequest)); + throw new ApacheCloudStackClientRuntimeException(e); + } + } + + /** + * This method executes the user logout when using username/password/domain authentication. + * The logout is executed calling the 'logout' command of the Apache CloudStack API. + */ + protected void executeUserLogout(CloseableHttpClient httpClient, HttpContext httpContext) { + String urlRequest = createApacheCloudStackApiUrlRequest(new ApacheCloudStackRequest("logout").addParameter("response", "json"), false); + String returnOfLogout = executeRequestGetResponseAsString(urlRequest, httpClient, httpContext); + logger.debug(String.format("Logout result[%s]", returnOfLogout)); + } + + /** + * According to the 'isSecretKeyApiKey AuthenticationMechanism' parameter this method creates an HttpContext that is used when executing requests. + * If the user has provided his/her API/secret keys, we return a {@link BasicHttpContext} object. Otherwise, we authenticate the user with his/her username/password/domain and return an {@link HttpContext} object that contains the authenticated session Id configured as a cookie. + */ + protected HttpContext createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(CloseableHttpClient httpClient, boolean isSecretKeyApiKeyAuthenticationMechanism) { + if (isSecretKeyApiKeyAuthenticationMechanism) { + return new BasicHttpContext(); + } + return createHttpContextWithAuthenticatedSessionUsingUserCredentials(httpClient); + } + + /** + * It creates a {@link RequestConfig} object with configured {@link #connectionTimeout} value. + * This can be used to set on a HttpClient its connect timeout, connection request timeout and socket timeout. + * @return returns the created RequestConfig object + */ + protected RequestConfig createRequestConfig() { + return RequestConfig.custom().setConnectTimeout(connectionTimeout * (int)DateUtils.MILLIS_PER_SECOND) + .setConnectionRequestTimeout(connectionTimeout * (int)DateUtils.MILLIS_PER_SECOND).setSocketTimeout(connectionTimeout * (int)DateUtils.MILLIS_PER_SECOND).build(); + } + + /** + * It creates an {@link CloseableHttpClient} object. + * If {@link #validateServerHttpsCertificate} indicates that we should not validate HTTPS server certificate, we use an insecure SSL factory; the insecure factory is created using {@link #createInsecureSslFactory()}. + */ + protected CloseableHttpClient createHttpClient() { + HttpClientBuilder httpClientBuilder = HttpClientBuilder.create().setDefaultRequestConfig(createRequestConfig()); + if (!validateServerHttpsCertificate) { + SSLConnectionSocketFactory sslsf = createInsecureSslFactory(); + httpClientBuilder.setSSLSocketFactory(sslsf); + } + return httpClientBuilder.build(); + } + + /** + * This method creates an {@link HttpContext} with an authenticated JSESSIONID. + * The authentication is performed using username, password and domain that are provided by the user. + */ + protected HttpContext createHttpContextWithAuthenticatedSessionUsingUserCredentials(CloseableHttpClient httpClient) { + HttpPost httpPost = createHttpPost(); + List params = getParametersForLogin(); + + try { + UrlEncodedFormEntity postParams = new UrlEncodedFormEntity(params, "UTF-8"); + httpPost.setEntity(postParams); + + CloseableHttpResponse loginResponse = httpClient.execute(httpPost); + int statusCode = loginResponse.getStatusLine().getStatusCode(); + if (statusCode != HttpStatus.SC_OK) { + throw new ApacheCloudStackClientRequestRuntimeException(statusCode, getResponseAsString(loginResponse), "login"); + } + logger.debug(String.format("Authentication response:[%s]", getResponseAsString(loginResponse))); + + return createHttpContextWithCookies(loginResponse); + } catch (IOException e) { + throw new ApacheCloudStackClientRuntimeException(e); + } + } + + /** + * It creates an {@link HttpContext} object with a cookie store that will contain the cookies returned by the user in the {@link CloseableHttpResponse} that is received as parameter. + */ + protected HttpContext createHttpContextWithCookies(CloseableHttpResponse loginResponse) { + CookieStore cookieStore = new BasicCookieStore(); + createAndAddCookiesOnStoreForHeaders(cookieStore, loginResponse.getAllHeaders()); + HttpContext httpContext = new BasicHttpContext(); + httpContext.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore); + return httpContext; + } + + /** + * For every header that contains the command 'Set-Cookie' it will call the method {@link #createAndAddCookiesOnStoreForHeader(CookieStore, Header)} + */ + protected void createAndAddCookiesOnStoreForHeaders(CookieStore cookieStore, Header[] allHeaders) { + for (Header header : allHeaders) { + if (StringUtils.startsWithIgnoreCase(header.getName(), "Set-Cookie")) { + createAndAddCookiesOnStoreForHeader(cookieStore, header); + } + } + } + + /** + * This method creates a cookie for every {@link HeaderElement} of the {@link Header} given as parameter. + * Then, it adds this newly created cookie into the {@link CookieStore} provided as parameter. + */ + protected void createAndAddCookiesOnStoreForHeader(CookieStore cookieStore, Header header) { + for (HeaderElement element : header.getElements()) { + BasicClientCookie cookie = createCookieForHeaderElement(element); + cookieStore.addCookie(cookie); + } + } + + /** + * This method will create a {@link BasicClientCookie} with the given {@link HeaderElement}. + * It sill set the cookie's name and value according to the {@link HeaderElement#getName()} and {@link HeaderElement#getValue()} methods. + * Moreover, it will transport every {@link HeaderElement} parameter to the cookie using the {@link BasicClientCookie#setAttribute(String, String)}. + * Additionally, it configures the cookie path ({@link BasicClientCookie#setPath(String)}) to value '/client/api' and the cookie domain using {@link #configureDomainForCookie(BasicClientCookie)} method. + */ + protected BasicClientCookie createCookieForHeaderElement(HeaderElement element) { + BasicClientCookie cookie = new BasicClientCookie(element.getName(), element.getValue()); + for (NameValuePair parameter : element.getParameters()) { + cookie.setAttribute(parameter.getName(), parameter.getValue()); + } + cookie.setPath("/client/api"); + configureDomainForCookie(cookie); + return cookie; + } + + /** + * It configures the cookie domain with the domain of the Apache CloudStack that is being accessed. + * The domain is extracted from {@link #url} variable. + */ + protected void configureDomainForCookie(BasicClientCookie cookie) { + try { + HttpHost httpHost = URIUtils.extractHost(new URI(url)); + String domain = httpHost.getHostName(); + cookie.setDomain(domain); + } catch (URISyntaxException e) { + throw new ApacheCloudStackClientRuntimeException(e); + } + } + + /** + * Creates an {@link HttpPost} object to be sent to Apache CloudStack API. + * The content type configured for this request is 'application/x-www-form-urlencoded'. + */ + protected HttpPost createHttpPost() { + HttpPost httpPost = new HttpPost(url); + httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded"); + return httpPost; + } + + /** + * This method creates a list of {@link NameValuePair} and returns the data for login using username and password. + */ + protected List getParametersForLogin() { + List params = new ArrayList<>(4); + params.add(new BasicNameValuePair("command", "login")); + params.add(new BasicNameValuePair("username", this.apacheCloudStackUser.getUsername())); + params.add(new BasicNameValuePair("password", this.apacheCloudStackUser.getPassword())); + params.add(new BasicNameValuePair("domain", this.apacheCloudStackUser.getDomain())); + return params; + } + + /** + * This method creates an insecure SSL factory that will trust on self signed certificates. + * For that we use {@link TrustSelfSignedStrategy}. + */ + protected SSLConnectionSocketFactory createInsecureSslFactory() { + try { + SSLContextBuilder builder = new SSLContextBuilder(); + builder.loadTrustMaterial(new TrustSelfSignedStrategy()); + SSLContext sc = builder.build(); + + if (acceptAllKindsOfCertificates) { + TrustManager[] trustAllCerts = new TrustManager[1]; + TrustManager tm = new TrustAllManager(); + trustAllCerts[0] = tm; + sc.init(null, trustAllCerts, null); + + HostnameVerifier hostnameVerifier = createInsecureHostNameVerifier(); + return new SSLConnectionSocketFactory(sc, hostnameVerifier); + } + return new SSLConnectionSocketFactory(sc); + } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) { + throw new ApacheCloudStackClientRuntimeException(e); + } + } + + protected HostnameVerifier createInsecureHostNameVerifier() { + HostnameVerifier hostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + return hostnameVerifier; + } + + /** + * This class is used when {@link ApacheCloudStackClient#acceptAllKindsOfCertificates} is set to true. + */ + @SuppressWarnings("unused") + private class TrustAllManager implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager { + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + + public boolean isServerTrusted(final X509Certificate[] certs) { + return true; + } + + public boolean isClientTrusted(final X509Certificate[] certs) { + return true; + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { + return; + } + + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { + return; + } + } + + /** + * It retrieves the response status as a {@link String} + */ + protected String getResponseAsString(CloseableHttpResponse response) throws IOException { + InputStream responseContent = response.getEntity().getContent(); + StringWriter writer = new StringWriter(); + IOUtils.copy(responseContent, writer, Charset.defaultCharset()); + + responseContent.close(); + response.close(); + return writer.toString(); + } + + /** + * This method creates transforms the given {@link ApacheCloudStackRequest} into a URL requeest for the Apache CloudStack API. + * Therefore, it will create a command query string following the CloudStack specifications using method {@link #createCommandString(ApacheCloudStackRequest)}; + * and then, if it needs, it creates the signature using the method {@link #createSignature(String)} and append it to the URL. + */ + protected String createApacheCloudStackApiUrlRequest(ApacheCloudStackRequest request, boolean shouldSignAppendSignature) { + StringBuilder urlRequest = new StringBuilder(url).append("?"); + + String queryString = createCommandString(request); + urlRequest.append(queryString); + + if (shouldSignAppendSignature) { + String signature = createSignature(queryString); + urlRequest.append("&signature=").append(getUrlEncodedValue(signature)); + } + return urlRequest.toString(); + } + + /** + * Creates a signature (HMAC-sha1) with the {@link #ApacheCloudStackUser#getSecretKey()} and the given queryString + * The returner signature is encoded in Base64. + */ + protected String createSignature(String queryString) { + byte[] signatureBytes = HmacUtils.hmacSha1(apacheCloudStackUser.getSecretKey(), queryString.toLowerCase()); + return Base64.encodeBase64String(signatureBytes); + } + + /** + * It creates the command query string, placing the parameters in alphabetical order. + * To execute the sorting, it uses the {@link #createSortedCommandQueryList(ApacheCloudStackRequest)} method. + */ + protected String createCommandString(ApacheCloudStackRequest request) { + List queryCommand = createSortedCommandQueryList(request); + + StringBuilder commandString = new StringBuilder(); + for (ApacheCloudStackApiCommandParameter param : queryCommand) { + String value = getUrlEncodedValue(param.getValue()); + commandString.append(String.format("%s=%s&", param.getName(), value)); + } + return commandString.toString().substring(0, commandString.length() - 1); + } + + /** + * This method encodes the parameter value as specified by Apache CloudStack + */ + protected String getUrlEncodedValue(Object paramValue) { + String value = Objects.toString(paramValue); + try { + value = URLEncoder.encode(value, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new ApacheCloudStackClientRuntimeException(e); + } + return value.replaceAll("\\+", "%20"); + } + + /** + * This methods adds the final data needed to the command query. + * It will add a parameter called 'command' with the value of {@link ApacheCloudStackRequest#getCommand()} as value. + * It also adds a parameter called 'apiKey', with the value of {@link #ApacheCloudStackUser#getApiKey()} as value. + * Then, it will sort the parameters that are in a list in alphabetical order. + */ + protected List createSortedCommandQueryList(ApacheCloudStackRequest request) { + List queryCommand = new ArrayList<>(); + queryCommand.addAll(request.getParameters()); + queryCommand.add(new ApacheCloudStackApiCommandParameter("command", request.getCommand())); + if (StringUtils.isNotBlank(this.apacheCloudStackUser.getApiKey())) { + queryCommand.add(new ApacheCloudStackApiCommandParameter("apiKey", this.apacheCloudStackUser.getApiKey())); + } + configureRequestExpiration(queryCommand); + Collections.sort(queryCommand); + return queryCommand; + } + + /** + * This method configures the request expiration if needed. + * It uses the value defined at {@link #requestValidity} to determine until when the request is valid. + * It also uses the parameter {@link #shouldRequestsExpire} to decide if it has to configure or not the validity of the request. + * Moreover, if the 'apacheCloudStackRequestList' contains the 'expires' it will only add a parameter called 'signatureVersion=3', in order to enable that override. + */ + protected void configureRequestExpiration(List apacheCloudStackRequestList) { + boolean isOverridingExpirationConfigs = apacheCloudStackRequestList.contains(new ApacheCloudStackApiCommandParameter("expires", StringUtils.EMPTY)); + if (!isOverridingExpirationConfigs && !shouldRequestsExpire) { + return; + } + apacheCloudStackRequestList.add(new ApacheCloudStackApiCommandParameter("signatureVersion", 3)); + if (isOverridingExpirationConfigs) { + return; + } + String expirationDataAsSring = createExpirationDate(); + apacheCloudStackRequestList.add(new ApacheCloudStackApiCommandParameter("expires", expirationDataAsSring)); + } + + /** + * This method creates the expiration date as a string according to the ISO 8601. + */ + protected String createExpirationDate() { + DateFormat acsIso8601DateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + return acsIso8601DateFormat.format(getExpirationDate()); + } + + /** + * Creates the expiration date, by adding the {@link #requestValidity} to the current time. + */ + protected Date getExpirationDate() { + Calendar now = Calendar.getInstance(); + now.add(Calendar.SECOND, requestValidity); + return now.getTime(); + } + + /** + * It executes the given request and converts the result into an object of the given type. + * This method will change the response type to 'JSON'. To execute the request, it uses the method {@link #executeRequest(ApacheCloudStackRequest)}. + * To convert the result into an object, it will use {@link Gson#fromJson(String, Class)} + */ + public T executeRequest(ApacheCloudStackRequest request, Class clazz) { + request.addParameter("response", "json"); + String response = executeRequest(request); + return gson.fromJson(response, clazz); + } + + /** + * This configuration enables or disables the HTTPS certification validation. If set to 'false', we will accept self-signed certificates. + * However, this does not mean that we accept certificates that are signed by an untrusted certificated authority. + */ + public void setValidateServerHttpsCertificate(boolean validateServerHttpsCertificate) { + this.validateServerHttpsCertificate = validateServerHttpsCertificate; + } + + public void setRequestValidity(int requestValidity) { + this.requestValidity = requestValidity; + } + + public void setShouldRequestsExpire(boolean shouldRequestsExpire) { + this.shouldRequestsExpire = shouldRequestsExpire; + } + + public void setConnectionTimeout(int connectionTimeout) { + this.connectionTimeout = connectionTimeout; + } + + public void setAcceptAllKindsOfCertificates(boolean acceptAllKindOfCertificates) { + this.acceptAllKindsOfCertificates = acceptAllKindOfCertificates; + } + + @Override + public String toString() { + return String.format("Apache CloudSTackClient for site[%s], parameters: [connectionTimeout=%s, acceptAllKindsOfCertificates=%s, validateServerHttpsCertificate=%s, requestValidity=%d, shouldRequestsExpire=%s]", this.url, + this.connectionTimeout, this.acceptAllKindsOfCertificates, this.validateServerHttpsCertificate, this.requestValidity, this.shouldRequestsExpire); + } } diff --git a/src/test/java/br/com/autonomiccs/apacheCloudStack/client/ApacheCloudStackClientTest.java b/src/test/java/br/com/autonomiccs/apacheCloudStack/client/ApacheCloudStackClientTest.java index 5d0620d..ae97118 100644 --- a/src/test/java/br/com/autonomiccs/apacheCloudStack/client/ApacheCloudStackClientTest.java +++ b/src/test/java/br/com/autonomiccs/apacheCloudStack/client/ApacheCloudStackClientTest.java @@ -3,19 +3,19 @@ * Copyright (C) 2016 Autonomiccs, Inc. * * Licensed to the Autonomiccs, Inc. under one - * or more contributor license agreements. See the NOTICE file + * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The Autonomiccs, Inc. 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 + * with the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 + * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ @@ -72,584 +72,590 @@ @RunWith(MockitoJUnitRunner.class) public class ApacheCloudStackClientTest { - private ApacheCloudStackClient apacheCloudStackClient; - - @Mock - private ApacheCloudStackUser apacheCloudStackUser; - - private String cloudStackDomain = "cloud.domain.com"; - private String cloudStackUrl = "https://" + cloudStackDomain + "/client/api"; - - @Before - public void setup() { - apacheCloudStackClient = Mockito.spy(new ApacheCloudStackClient(cloudStackUrl, apacheCloudStackUser)); - } - - @Test - public void executeRequestTest() throws ClientProtocolException, IOException { - configureMocksExecuteTestAndVerifyForMethodExecuteRequest(200); - } - - @Test(expected = ApacheCloudStackClientRequestRuntimeException.class) - public void executeRequestTestRequestStatusDifferentFromHttpStatusOk() throws ClientProtocolException, IOException { - configureMocksExecuteTestAndVerifyForMethodExecuteRequest(500); - } - - private void configureMocksExecuteTestAndVerifyForMethodExecuteRequest(int requestStatusCode) throws IOException, ClientProtocolException { - Mockito.doReturn(cloudStackUrl).when(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(true)); - - CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); - HttpContext httpContextMock = Mockito.mock(HttpContext.class); - CloseableHttpResponse closeableHttpResponseMock = Mockito.mock(CloseableHttpResponse.class); - StatusLine statusLineMock = Mockito.mock(StatusLine.class); - - Mockito.when(statusLineMock.getStatusCode()).thenReturn(requestStatusCode); - Mockito.when(closeableHttpResponseMock.getStatusLine()).thenReturn(statusLineMock); - Mockito.when(httpClientMock.execute(Mockito.any(HttpGet.class), Mockito.eq(httpContextMock))).thenReturn(closeableHttpResponseMock); - Mockito.when(apacheCloudStackClient.createHttpClient()).thenReturn(httpClientMock); - Mockito.when(apacheCloudStackClient.apacheCloudStackUser.getApiKey()).thenReturn("apiKey"); - Mockito.doReturn(httpContextMock).when(apacheCloudStackClient).createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(Mockito.eq(httpClientMock), - Mockito.eq(true)); - String responseString = "responseAsString"; - Mockito.doReturn(responseString).when(apacheCloudStackClient).getResponseAsString(Mockito.eq(closeableHttpResponseMock)); - - String returnOfExecuteRequest = apacheCloudStackClient.executeRequest(Mockito.mock(ApacheCloudStackRequest.class)); - Assert.assertEquals(responseString, returnOfExecuteRequest); - - InOrder inOrder = Mockito.inOrder(apacheCloudStackClient, httpClientMock, closeableHttpResponseMock, statusLineMock); - inOrder.verify(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(true)); - inOrder.verify(apacheCloudStackClient).createHttpClient(); - inOrder.verify(httpClientMock).execute(Mockito.any(HttpGet.class), Mockito.eq(httpContextMock)); - inOrder.verify(closeableHttpResponseMock).getStatusLine(); - inOrder.verify(statusLineMock).getStatusCode(); - inOrder.verify(httpClientMock).close(); - } - - @Test(expected = ApacheCloudStackClientRuntimeException.class) - public void executeRequestTestExceptionWhenExecutingRequest() throws IOException, ClientProtocolException { - Mockito.doReturn(cloudStackUrl).when(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(true)); - - CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); - - Mockito.when(httpClientMock.execute(Mockito.any(HttpGet.class))).thenThrow(new IOException()); - Mockito.when(apacheCloudStackClient.createHttpClient()).thenReturn(httpClientMock); - - apacheCloudStackClient.executeRequest(Mockito.mock(ApacheCloudStackRequest.class)); - Mockito.verify(httpClientMock).close(); - } - - private void testRequestConfig(final RequestConfig config, final int timeout) { - Assert.assertEquals(config.getConnectTimeout(), timeout * (int) DateUtils.MILLIS_PER_SECOND); - Assert.assertEquals(config.getConnectionRequestTimeout(), timeout * (int) DateUtils.MILLIS_PER_SECOND); - Assert.assertEquals(config.getSocketTimeout(), timeout * (int) DateUtils.MILLIS_PER_SECOND); - } - - @Test - public void createRequestConfigDefaultTest() { - RequestConfig config = apacheCloudStackClient.createRequestConfig(); - testRequestConfig(config, 60); - } - - @Test - public void createRequestConfigCustomValueTest() { - int timeout = 30; - apacheCloudStackClient.setConnectionTimeout(timeout); - RequestConfig config = apacheCloudStackClient.createRequestConfig(); - testRequestConfig(config, timeout); - } - - @Test - public void createHttpClientTestValidateServerHttpsCertificateTrueAndTotalInsecureFalse() { - configureExecuteAndVerifyTestForCreateHttpClient(true, 0, false, 0); - } - - @Test - public void createHttpClientTestValidateServerHttpsCertificateTrueAndTotalInsecureTrue() { - configureExecuteAndVerifyTestForCreateHttpClient(true, 0, true, 0); - } - - @Test - public void createHttpClientTestValidateServerHttpsCertificateFalseAndTotalInsecureFalse() { - configureExecuteAndVerifyTestForCreateHttpClient(false, 1, false, 0); - } - - @Test - public void createHttpClientTestValidateServerHttpsCertificateFalseAndTotalInsecureTrue() { - configureExecuteAndVerifyTestForCreateHttpClient(false, 1, true, 1); - } - - private void configureExecuteAndVerifyTestForCreateHttpClient(boolean shouldVerifyServerCertificates, int numberOfCreateUnsecureSslFactoryCalls, boolean totalInsecure, - int expectedCallForInsecureHostNameCheck) { - apacheCloudStackClient.validateServerHttpsCertificate = shouldVerifyServerCertificates; - apacheCloudStackClient.acceptAllKindsOfCertificates = totalInsecure; - - CloseableHttpClient httpClient = apacheCloudStackClient.createHttpClient(); - - Assert.assertNotNull(httpClient); - Mockito.verify(apacheCloudStackClient, Mockito.times(1)).createRequestConfig(); - Mockito.verify(apacheCloudStackClient, Mockito.times(expectedCallForInsecureHostNameCheck)).createInsecureHostNameVerifier(); - Mockito.verify(apacheCloudStackClient, Mockito.times(numberOfCreateUnsecureSslFactoryCalls)).createInsecureSslFactory(); - } - - @Test - public void getResponseAsStringTest() throws UnsupportedOperationException, IOException { - String responseTest = "teste response"; - - CloseableHttpResponse closeableHttpResponseMock = Mockito.mock(CloseableHttpResponse.class); - HttpEntity httpEntityMock = Mockito.mock(HttpEntity.class); - - InputStream is = new ByteArrayInputStream(responseTest.getBytes()); - - Mockito.doReturn(is).when(httpEntityMock).getContent(); - Mockito.doReturn(httpEntityMock).when(closeableHttpResponseMock).getEntity(); - - String responseAsString = apacheCloudStackClient.getResponseAsString(closeableHttpResponseMock); - - Assert.assertEquals(responseTest, responseAsString); - } - - @Test - public void createApacheCloudStackApiUrlRequestTestWithSignature() { - ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); - - String queryString = "queryString"; - Mockito.doReturn(queryString).when(apacheCloudStackClient).createCommandString(Mockito.eq(apacheCloudStackRequestMock)); - - String signatureValue = "signatureValue"; - Mockito.doReturn(signatureValue).when(apacheCloudStackClient).createSignature(Mockito.eq(queryString)); - - String urlRequestReturned = apacheCloudStackClient.createApacheCloudStackApiUrlRequest(apacheCloudStackRequestMock, true); - Assert.assertEquals(cloudStackUrl + "?" + queryString + "&signature=" + signatureValue, urlRequestReturned); - - InOrder inOrder = Mockito.inOrder(apacheCloudStackClient); - inOrder.verify(apacheCloudStackClient).createCommandString(Mockito.eq(apacheCloudStackRequestMock)); - inOrder.verify(apacheCloudStackClient).createSignature(Mockito.eq(queryString)); - inOrder.verify(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(signatureValue)); - } - - @Test - public void createApacheCloudStackApiUrlRequestTestWithoutSignature() { - ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); - - String queryString = "queryString"; - Mockito.doReturn(queryString).when(apacheCloudStackClient).createCommandString(Mockito.eq(apacheCloudStackRequestMock)); - - String urlRequestReturned = apacheCloudStackClient.createApacheCloudStackApiUrlRequest(apacheCloudStackRequestMock, false); - Assert.assertEquals(cloudStackUrl + "?" + queryString, urlRequestReturned); - - InOrder inOrder = Mockito.inOrder(apacheCloudStackClient); - inOrder.verify(apacheCloudStackClient).createCommandString(Mockito.eq(apacheCloudStackRequestMock)); - inOrder.verify(apacheCloudStackClient, Mockito.times(0)).createSignature(Mockito.eq(queryString)); - inOrder.verify(apacheCloudStackClient, Mockito.times(0)).getUrlEncodedValue(Mockito.anyString()); - } - - @Test - public void createSignatureTest() { - String expectedSignature = "wqtSA/cANcWnWlh/ukfnaExyM54="; - Mockito.doReturn("secretKey").when(apacheCloudStackUser).getSecretKey(); - - String signature = apacheCloudStackClient.createSignature("queryString"); + private ApacheCloudStackClient apacheCloudStackClient; + + @Mock + private ApacheCloudStackUser apacheCloudStackUser; + + private String cloudStackDomain = "cloud.domain.com"; + private String cloudStackUrl = "https://" + cloudStackDomain + "/client/api"; + + @Before + public void setup() { + apacheCloudStackClient = Mockito.spy(new ApacheCloudStackClient(cloudStackUrl, apacheCloudStackUser)); + } + + @Test + public void executeRequestTest() throws ClientProtocolException, IOException { + configureMocksExecuteTestAndVerifyForMethodExecuteRequest(200); + } + + @Test(expected = ApacheCloudStackClientRequestRuntimeException.class) + public void executeRequestTestRequestStatusDifferentFromHttpStatusOk() throws ClientProtocolException, IOException { + configureMocksExecuteTestAndVerifyForMethodExecuteRequest(500); + } + + private void configureMocksExecuteTestAndVerifyForMethodExecuteRequest(int requestStatusCode) throws IOException, ClientProtocolException { + Mockito.doReturn(cloudStackUrl).when(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(true)); + + CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); + HttpContext httpContextMock = Mockito.mock(HttpContext.class); + CloseableHttpResponse closeableHttpResponseMock = Mockito.mock(CloseableHttpResponse.class); + StatusLine statusLineMock = Mockito.mock(StatusLine.class); + + Mockito.when(statusLineMock.getStatusCode()).thenReturn(requestStatusCode); + Mockito.when(closeableHttpResponseMock.getStatusLine()).thenReturn(statusLineMock); + Mockito.when(httpClientMock.execute(Mockito.any(HttpGet.class), Mockito.eq(httpContextMock))).thenReturn(closeableHttpResponseMock); + Mockito.when(apacheCloudStackClient.createHttpClient()).thenReturn(httpClientMock); + Mockito.when(apacheCloudStackClient.apacheCloudStackUser.getApiKey()).thenReturn("apiKey"); + Mockito.doReturn(httpContextMock).when(apacheCloudStackClient).createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(Mockito.eq(httpClientMock), Mockito.eq(true)); + String responseString = "responseAsString"; + Mockito.doReturn(responseString).when(apacheCloudStackClient).getResponseAsString(Mockito.eq(closeableHttpResponseMock)); + + String returnOfExecuteRequest = apacheCloudStackClient.executeRequest(Mockito.mock(ApacheCloudStackRequest.class)); + Assert.assertEquals(responseString, returnOfExecuteRequest); + + InOrder inOrder = Mockito.inOrder(apacheCloudStackClient, httpClientMock, closeableHttpResponseMock, statusLineMock); + inOrder.verify(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(true)); + inOrder.verify(apacheCloudStackClient).createHttpClient(); + inOrder.verify(httpClientMock).execute(Mockito.any(HttpGet.class), Mockito.eq(httpContextMock)); + inOrder.verify(closeableHttpResponseMock).getStatusLine(); + inOrder.verify(statusLineMock).getStatusCode(); + inOrder.verify(httpClientMock).close(); + } + + @Test(expected = ApacheCloudStackClientRuntimeException.class) + public void executeRequestTestExceptionWhenExecutingRequest() throws IOException, ClientProtocolException { + Mockito.doReturn(cloudStackUrl).when(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(true)); + + CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); + + Mockito.when(httpClientMock.execute(Mockito.any(HttpGet.class))).thenThrow(new IOException()); + Mockito.when(apacheCloudStackClient.createHttpClient()).thenReturn(httpClientMock); + + apacheCloudStackClient.executeRequest(Mockito.mock(ApacheCloudStackRequest.class)); + Mockito.verify(httpClientMock).close(); + } + + private void testRequestConfig(final RequestConfig config, final int timeout) { + Assert.assertEquals(config.getConnectTimeout(), timeout * (int)DateUtils.MILLIS_PER_SECOND); + Assert.assertEquals(config.getConnectionRequestTimeout(), timeout * (int)DateUtils.MILLIS_PER_SECOND); + Assert.assertEquals(config.getSocketTimeout(), timeout * (int)DateUtils.MILLIS_PER_SECOND); + } + + @Test + public void createRequestConfigDefaultTest() { + RequestConfig config = apacheCloudStackClient.createRequestConfig(); + testRequestConfig(config, 60); + } + + @Test + public void createRequestConfigCustomValueTest() { + int timeout = 30; + apacheCloudStackClient.setConnectionTimeout(timeout); + RequestConfig config = apacheCloudStackClient.createRequestConfig(); + testRequestConfig(config, timeout); + } + + @Test + public void createHttpClientTestValidateServerHttpsCertificateTrueAndTotalInsecureFalse() { + configureExecuteAndVerifyTestForCreateHttpClient(true, 0, false, 0); + } + + @Test + public void createHttpClientTestValidateServerHttpsCertificateTrueAndTotalInsecureTrue() { + configureExecuteAndVerifyTestForCreateHttpClient(true, 0, true, 0); + } + + @Test + public void createHttpClientTestValidateServerHttpsCertificateFalseAndTotalInsecureFalse() { + configureExecuteAndVerifyTestForCreateHttpClient(false, 1, false, 0); + } + + @Test + public void createHttpClientTestValidateServerHttpsCertificateFalseAndTotalInsecureTrue() { + configureExecuteAndVerifyTestForCreateHttpClient(false, 1, true, 1); + } + + private void configureExecuteAndVerifyTestForCreateHttpClient(boolean shouldVerifyServerCertificates, int numberOfCreateUnsecureSslFactoryCalls, boolean totalInsecure, int expectedCallForInsecureHostNameCheck) { + apacheCloudStackClient.validateServerHttpsCertificate = shouldVerifyServerCertificates; + apacheCloudStackClient.acceptAllKindsOfCertificates = totalInsecure; + + CloseableHttpClient httpClient = apacheCloudStackClient.createHttpClient(); + + Assert.assertNotNull(httpClient); + Mockito.verify(apacheCloudStackClient, Mockito.times(1)).createRequestConfig(); + Mockito.verify(apacheCloudStackClient, Mockito.times(expectedCallForInsecureHostNameCheck)).createInsecureHostNameVerifier(); + Mockito.verify(apacheCloudStackClient, Mockito.times(numberOfCreateUnsecureSslFactoryCalls)).createInsecureSslFactory(); + } + + @Test + public void getResponseAsStringTest() throws UnsupportedOperationException, IOException { + String responseTest = "teste response"; + + CloseableHttpResponse closeableHttpResponseMock = Mockito.mock(CloseableHttpResponse.class); + HttpEntity httpEntityMock = Mockito.mock(HttpEntity.class); + + InputStream is = new ByteArrayInputStream(responseTest.getBytes()); + + Mockito.doReturn(is).when(httpEntityMock).getContent(); + Mockito.doReturn(httpEntityMock).when(closeableHttpResponseMock).getEntity(); + + String responseAsString = apacheCloudStackClient.getResponseAsString(closeableHttpResponseMock); + + Assert.assertEquals(responseTest, responseAsString); + } + + @Test + public void createApacheCloudStackApiUrlRequestTestWithSignature() { + ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); + + String queryString = "queryString"; + Mockito.doReturn(queryString).when(apacheCloudStackClient).createCommandString(Mockito.eq(apacheCloudStackRequestMock)); + + String signatureValue = "signatureValue"; + Mockito.doReturn(signatureValue).when(apacheCloudStackClient).createSignature(Mockito.eq(queryString)); + + String urlRequestReturned = apacheCloudStackClient.createApacheCloudStackApiUrlRequest(apacheCloudStackRequestMock, true); + Assert.assertEquals(cloudStackUrl + "?" + queryString + "&signature=" + signatureValue, urlRequestReturned); + + InOrder inOrder = Mockito.inOrder(apacheCloudStackClient); + inOrder.verify(apacheCloudStackClient).createCommandString(Mockito.eq(apacheCloudStackRequestMock)); + inOrder.verify(apacheCloudStackClient).createSignature(Mockito.eq(queryString)); + inOrder.verify(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(signatureValue)); + } + + @Test + public void createApacheCloudStackApiUrlRequestTestWithoutSignature() { + ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); + + String queryString = "queryString"; + Mockito.doReturn(queryString).when(apacheCloudStackClient).createCommandString(Mockito.eq(apacheCloudStackRequestMock)); + + String urlRequestReturned = apacheCloudStackClient.createApacheCloudStackApiUrlRequest(apacheCloudStackRequestMock, false); + Assert.assertEquals(cloudStackUrl + "?" + queryString, urlRequestReturned); + + InOrder inOrder = Mockito.inOrder(apacheCloudStackClient); + inOrder.verify(apacheCloudStackClient).createCommandString(Mockito.eq(apacheCloudStackRequestMock)); + inOrder.verify(apacheCloudStackClient, Mockito.times(0)).createSignature(Mockito.eq(queryString)); + inOrder.verify(apacheCloudStackClient, Mockito.times(0)).getUrlEncodedValue(Mockito.anyString()); + } + + @Test + public void createSignatureTest() { + String expectedSignature = "wqtSA/cANcWnWlh/ukfnaExyM54="; + Mockito.doReturn("secretKey").when(apacheCloudStackUser).getSecretKey(); + + String signature = apacheCloudStackClient.createSignature("queryString"); - Assert.assertEquals(expectedSignature, signature); - } + Assert.assertEquals(expectedSignature, signature); + } - @Test - public void createCommandStringTest() { - List params = new ArrayList<>(); - String valueParam1 = "value1"; - String valueParam2 = "value2 espaço"; - params.add(new ApacheCloudStackApiCommandParameter("param1", valueParam1)); - params.add(new ApacheCloudStackApiCommandParameter("param2", valueParam2)); + @Test + public void createCommandStringTest() { + List params = new ArrayList<>(); + String valueParam1 = "value1"; + String valueParam2 = "value2 espaço"; + params.add(new ApacheCloudStackApiCommandParameter("param1", valueParam1)); + params.add(new ApacheCloudStackApiCommandParameter("param2", valueParam2)); - String expectedCommandSrting = "param1=value1¶m2=value2 espaço"; + String expectedCommandSrting = "param1=value1¶m2=value2 espaço"; - ApacheCloudStackRequest ApacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); - Mockito.doReturn(params).when(apacheCloudStackClient).createSortedCommandQueryList(Mockito.eq(ApacheCloudStackRequestMock)); - Mockito.doReturn(valueParam1).when(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(valueParam1)); - Mockito.doReturn(valueParam2).when(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(valueParam2)); + ApacheCloudStackRequest ApacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); + Mockito.doReturn(params).when(apacheCloudStackClient).createSortedCommandQueryList(Mockito.eq(ApacheCloudStackRequestMock)); + Mockito.doReturn(valueParam1).when(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(valueParam1)); + Mockito.doReturn(valueParam2).when(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(valueParam2)); - String commandStringReturned = apacheCloudStackClient.createCommandString(ApacheCloudStackRequestMock); - Assert.assertEquals(expectedCommandSrting, commandStringReturned); + String commandStringReturned = apacheCloudStackClient.createCommandString(ApacheCloudStackRequestMock); + Assert.assertEquals(expectedCommandSrting, commandStringReturned); - InOrder inOrder = Mockito.inOrder(apacheCloudStackClient); - inOrder.verify(apacheCloudStackClient).createSortedCommandQueryList(Mockito.eq(ApacheCloudStackRequestMock)); - inOrder.verify(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(valueParam1)); - inOrder.verify(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(valueParam2)); + InOrder inOrder = Mockito.inOrder(apacheCloudStackClient); + inOrder.verify(apacheCloudStackClient).createSortedCommandQueryList(Mockito.eq(ApacheCloudStackRequestMock)); + inOrder.verify(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(valueParam1)); + inOrder.verify(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(valueParam2)); - } + } - @Test - public void getUrlEncodedValueTestNullValue() { - String urlEncodedValueReturned = apacheCloudStackClient.getUrlEncodedValue(null); - Assert.assertEquals("null", urlEncodedValueReturned); - } + @Test + public void getUrlEncodedValueTestNullValue() { + String urlEncodedValueReturned = apacheCloudStackClient.getUrlEncodedValue(null); + Assert.assertEquals("null", urlEncodedValueReturned); + } - @Test - public void getUrlEncodedValueTestNonSpecialCharactersValue() { - String urlEncodedValueReturned = apacheCloudStackClient.getUrlEncodedValue("test"); - Assert.assertEquals("test", urlEncodedValueReturned); - } + @Test + public void getUrlEncodedValueTestNonSpecialCharactersValue() { + String urlEncodedValueReturned = apacheCloudStackClient.getUrlEncodedValue("test"); + Assert.assertEquals("test", urlEncodedValueReturned); + } - @Test - public void getUrlEncodedValueTestValueWithSpaces() { - String urlEncodedValueReturned = apacheCloudStackClient.getUrlEncodedValue("test value"); - Assert.assertEquals("test%20value", urlEncodedValueReturned); - } + @Test + public void getUrlEncodedValueTestValueWithSpaces() { + String urlEncodedValueReturned = apacheCloudStackClient.getUrlEncodedValue("test value"); + Assert.assertEquals("test%20value", urlEncodedValueReturned); + } - @Test - @SuppressWarnings("unchecked") - public void createSortedCommandQueryListTestWithApiKey() { - ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); - Set params = new HashSet<>(); + @Test + @SuppressWarnings("unchecked") + public void createSortedCommandQueryListTestWithApiKey() { + ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); + Set params = new HashSet<>(); - params.add(new ApacheCloudStackApiCommandParameter("param1", "value1")); - Mockito.doReturn(params).when(apacheCloudStackRequestMock).getParameters(); - Mockito.when(apacheCloudStackClient.apacheCloudStackUser.getApiKey()).thenReturn("apiKey"); - Mockito.doNothing().when(apacheCloudStackClient).configureRequestExpiration(Mockito.anyList()); + params.add(new ApacheCloudStackApiCommandParameter("param1", "value1")); + Mockito.doReturn(params).when(apacheCloudStackRequestMock).getParameters(); + Mockito.when(apacheCloudStackClient.apacheCloudStackUser.getApiKey()).thenReturn("apiKey"); + Mockito.doNothing().when(apacheCloudStackClient).configureRequestExpiration(Mockito.anyList()); - List sortedCommandQueryList = apacheCloudStackClient.createSortedCommandQueryList(apacheCloudStackRequestMock); + List sortedCommandQueryList = apacheCloudStackClient.createSortedCommandQueryList(apacheCloudStackRequestMock); - Mockito.verify(apacheCloudStackRequestMock).getParameters(); - Mockito.verify(apacheCloudStackClient).configureRequestExpiration(Mockito.anyList()); + Mockito.verify(apacheCloudStackRequestMock).getParameters(); + Mockito.verify(apacheCloudStackClient).configureRequestExpiration(Mockito.anyList()); - Assert.assertEquals(3, sortedCommandQueryList.size()); - Assert.assertEquals("apiKey", sortedCommandQueryList.get(0).getName()); - Assert.assertEquals("command", sortedCommandQueryList.get(1).getName()); - Assert.assertEquals("param1", sortedCommandQueryList.get(2).getName()); - } + Assert.assertEquals(3, sortedCommandQueryList.size()); + Assert.assertEquals("apiKey", sortedCommandQueryList.get(0).getName()); + Assert.assertEquals("command", sortedCommandQueryList.get(1).getName()); + Assert.assertEquals("param1", sortedCommandQueryList.get(2).getName()); + } - @Test - @SuppressWarnings("unchecked") - public void createSortedCommandQueryListTestWithourApiKey() { - ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); - Set params = new HashSet<>(); - - params.add(new ApacheCloudStackApiCommandParameter("param1", "value1")); - Mockito.doReturn(params).when(apacheCloudStackRequestMock).getParameters(); - Mockito.when(apacheCloudStackClient.apacheCloudStackUser.getApiKey()).thenReturn(null); - Mockito.doNothing().when(apacheCloudStackClient).configureRequestExpiration(Mockito.anyList()); - - List sortedCommandQueryList = apacheCloudStackClient.createSortedCommandQueryList(apacheCloudStackRequestMock); - - Mockito.verify(apacheCloudStackRequestMock).getParameters(); - Mockito.verify(apacheCloudStackClient).configureRequestExpiration(Mockito.anyList()); + @Test + @SuppressWarnings("unchecked") + public void createSortedCommandQueryListTestWithourApiKey() { + ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); + Set params = new HashSet<>(); + + params.add(new ApacheCloudStackApiCommandParameter("param1", "value1")); + Mockito.doReturn(params).when(apacheCloudStackRequestMock).getParameters(); + Mockito.when(apacheCloudStackClient.apacheCloudStackUser.getApiKey()).thenReturn(null); + Mockito.doNothing().when(apacheCloudStackClient).configureRequestExpiration(Mockito.anyList()); + + List sortedCommandQueryList = apacheCloudStackClient.createSortedCommandQueryList(apacheCloudStackRequestMock); + + Mockito.verify(apacheCloudStackRequestMock).getParameters(); + Mockito.verify(apacheCloudStackClient).configureRequestExpiration(Mockito.anyList()); - Assert.assertEquals(2, sortedCommandQueryList.size()); - Assert.assertEquals("command", sortedCommandQueryList.get(0).getName()); - Assert.assertEquals("param1", sortedCommandQueryList.get(1).getName()); - } + Assert.assertEquals(2, sortedCommandQueryList.size()); + Assert.assertEquals("command", sortedCommandQueryList.get(0).getName()); + Assert.assertEquals("param1", sortedCommandQueryList.get(1).getName()); + } - @Test - public void executeRequestAutoConvertReturnToJavaObject() { - String jsonTest = "{attr1: 1, attr2: 'test'}"; + @Test + public void executeRequestAutoConvertReturnToJavaObject() { + String jsonTest = "{attr1: 1, attr2: 'test'}"; - ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); - Mockito.doReturn(jsonTest).when(apacheCloudStackClient).executeRequest(Mockito.eq(apacheCloudStackRequestMock)); + ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); + Mockito.doReturn(jsonTest).when(apacheCloudStackClient).executeRequest(Mockito.eq(apacheCloudStackRequestMock)); - TestExecuteReturnObject returnedObject = apacheCloudStackClient.executeRequest(apacheCloudStackRequestMock, TestExecuteReturnObject.class); + TestExecuteReturnObject returnedObject = apacheCloudStackClient.executeRequest(apacheCloudStackRequestMock, TestExecuteReturnObject.class); - Mockito.verify(apacheCloudStackClient).executeRequest(Mockito.eq(apacheCloudStackRequestMock)); + Mockito.verify(apacheCloudStackClient).executeRequest(Mockito.eq(apacheCloudStackRequestMock)); - Assert.assertNotNull(returnedObject); - Assert.assertTrue(returnedObject instanceof TestExecuteReturnObject); + Assert.assertNotNull(returnedObject); + Assert.assertTrue(returnedObject instanceof TestExecuteReturnObject); - Assert.assertEquals(1, returnedObject.attr1); - Assert.assertEquals("test", returnedObject.attr2); + Assert.assertEquals(1, returnedObject.attr1); + Assert.assertEquals("test", returnedObject.attr2); - } + } - private class TestExecuteReturnObject { - private int attr1; - private String attr2; - } + private class TestExecuteReturnObject { + private int attr1; + private String attr2; + } - @Test - public void createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeededTestAuthenticationWithApiKeyAndSecretKey() { - CloseableHttpClient closeableHttpClientMock = Mockito.mock(CloseableHttpClient.class); - HttpContext basicHttpContext = apacheCloudStackClient.createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(closeableHttpClientMock, true); + @Test + public void createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeededTestAuthenticationWithApiKeyAndSecretKey() { + CloseableHttpClient closeableHttpClientMock = Mockito.mock(CloseableHttpClient.class); + HttpContext basicHttpContext = apacheCloudStackClient.createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(closeableHttpClientMock, true); - Mockito.verify(apacheCloudStackClient, Mockito.times(0)).createHttpContextWithAuthenticatedSessionUsingUserCredentials(Mockito.any(closeableHttpClientMock.getClass())); - Assert.assertNotNull(basicHttpContext); - } + Mockito.verify(apacheCloudStackClient, Mockito.times(0)).createHttpContextWithAuthenticatedSessionUsingUserCredentials(Mockito.any(closeableHttpClientMock.getClass())); + Assert.assertNotNull(basicHttpContext); + } - @Test - public void createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeededTestAuthenticationWithUsernameAndPassword() { - CloseableHttpClient closeableHttpClientMock = Mockito.mock(CloseableHttpClient.class); - HttpContext httpContextMock = Mockito.mock(HttpContext.class); - Mockito.doReturn(httpContextMock).when(apacheCloudStackClient).createHttpContextWithAuthenticatedSessionUsingUserCredentials(Mockito.any(closeableHttpClientMock.getClass())); - HttpContext basicHttpContext = apacheCloudStackClient.createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(closeableHttpClientMock, false); + @Test + public void createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeededTestAuthenticationWithUsernameAndPassword() { + CloseableHttpClient closeableHttpClientMock = Mockito.mock(CloseableHttpClient.class); + HttpContext httpContextMock = Mockito.mock(HttpContext.class); + Mockito.doReturn(httpContextMock).when(apacheCloudStackClient).createHttpContextWithAuthenticatedSessionUsingUserCredentials(Mockito.any(closeableHttpClientMock.getClass())); + HttpContext basicHttpContext = apacheCloudStackClient.createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(closeableHttpClientMock, false); - Mockito.verify(apacheCloudStackClient, Mockito.times(1)).createHttpContextWithAuthenticatedSessionUsingUserCredentials(Mockito.eq(closeableHttpClientMock)); + Mockito.verify(apacheCloudStackClient, Mockito.times(1)).createHttpContextWithAuthenticatedSessionUsingUserCredentials(Mockito.eq(closeableHttpClientMock)); - Assert.assertNotNull(basicHttpContext); - Assert.assertEquals(httpContextMock, basicHttpContext); - } + Assert.assertNotNull(basicHttpContext); + Assert.assertEquals(httpContextMock, basicHttpContext); + } - @Test - public void createHttpContextWithAuthenticatedSessionUsingUserCredentialsTest() throws ClientProtocolException, IOException { - HttpPost httpPostMock = Mockito.mock(HttpPost.class); - Mockito.doReturn(httpPostMock).when(apacheCloudStackClient).createHttpPost(); + @Test + public void createHttpContextWithAuthenticatedSessionUsingUserCredentialsTest() throws ClientProtocolException, IOException { + HttpPost httpPostMock = Mockito.mock(HttpPost.class); + Mockito.doReturn(httpPostMock).when(apacheCloudStackClient).createHttpPost(); - NameValuePair nameValuePairMock = Mockito.mock(NameValuePair.class); - ArrayList paramsMock = new ArrayList<>(1); - paramsMock.add(nameValuePairMock); + NameValuePair nameValuePairMock = Mockito.mock(NameValuePair.class); + ArrayList paramsMock = new ArrayList<>(1); + paramsMock.add(nameValuePairMock); - Mockito.doReturn(paramsMock).when(apacheCloudStackClient).getParametersForLogin(); + Mockito.doReturn(paramsMock).when(apacheCloudStackClient).getParametersForLogin(); - StatusLine statusLineMock = Mockito.mock(StatusLine.class); - CloseableHttpResponse closeableHttpResponseMock = Mockito.mock(CloseableHttpResponse.class); - CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); + StatusLine statusLineMock = Mockito.mock(StatusLine.class); + CloseableHttpResponse closeableHttpResponseMock = Mockito.mock(CloseableHttpResponse.class); + CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); - Mockito.doReturn(200).when(statusLineMock).getStatusCode(); - Mockito.doReturn(statusLineMock).when(closeableHttpResponseMock).getStatusLine(); - Mockito.doReturn(closeableHttpResponseMock).when(httpClientMock).execute(Mockito.eq(httpPostMock)); + Mockito.doReturn(200).when(statusLineMock).getStatusCode(); + Mockito.doReturn(statusLineMock).when(closeableHttpResponseMock).getStatusLine(); + Mockito.doReturn(closeableHttpResponseMock).when(httpClientMock).execute(Mockito.eq(httpPostMock)); - HttpContext httpContextMock = Mockito.mock(HttpContext.class); - Mockito.doReturn(httpContextMock).when(apacheCloudStackClient).createHttpContextWithCookies(Mockito.eq(closeableHttpResponseMock)); - Mockito.doReturn("responseAsString").when(apacheCloudStackClient).getResponseAsString(Mockito.eq(closeableHttpResponseMock)); + HttpContext httpContextMock = Mockito.mock(HttpContext.class); + Mockito.doReturn(httpContextMock).when(apacheCloudStackClient).createHttpContextWithCookies(Mockito.eq(closeableHttpResponseMock)); + Mockito.doReturn("responseAsString").when(apacheCloudStackClient).getResponseAsString(Mockito.eq(closeableHttpResponseMock)); - HttpContext httpContextAuthenticatedWithUsernamePassword = apacheCloudStackClient.createHttpContextWithAuthenticatedSessionUsingUserCredentials(httpClientMock); + HttpContext httpContextAuthenticatedWithUsernamePassword = apacheCloudStackClient.createHttpContextWithAuthenticatedSessionUsingUserCredentials(httpClientMock); - Assert.assertEquals(httpContextMock, httpContextAuthenticatedWithUsernamePassword); + Assert.assertEquals(httpContextMock, httpContextAuthenticatedWithUsernamePassword); - InOrder inOrder = Mockito.inOrder(httpPostMock, apacheCloudStackClient, statusLineMock, closeableHttpResponseMock, httpClientMock); - inOrder.verify(apacheCloudStackClient).createHttpPost(); - inOrder.verify(apacheCloudStackClient).getParametersForLogin(); - inOrder.verify(httpPostMock).setEntity(Mockito.any(UrlEncodedFormEntity.class)); - inOrder.verify(httpClientMock).execute(Mockito.eq(httpPostMock)); - inOrder.verify(closeableHttpResponseMock).getStatusLine(); - inOrder.verify(statusLineMock).getStatusCode(); - inOrder.verify(apacheCloudStackClient).getResponseAsString(Mockito.eq(closeableHttpResponseMock)); - inOrder.verify(apacheCloudStackClient).createHttpContextWithCookies(Mockito.eq(closeableHttpResponseMock)); - } + InOrder inOrder = Mockito.inOrder(httpPostMock, apacheCloudStackClient, statusLineMock, closeableHttpResponseMock, httpClientMock); + inOrder.verify(apacheCloudStackClient).createHttpPost(); + inOrder.verify(apacheCloudStackClient).getParametersForLogin(); + inOrder.verify(httpPostMock).setEntity(Mockito.any(UrlEncodedFormEntity.class)); + inOrder.verify(httpClientMock).execute(Mockito.eq(httpPostMock)); + inOrder.verify(closeableHttpResponseMock).getStatusLine(); + inOrder.verify(statusLineMock).getStatusCode(); + inOrder.verify(apacheCloudStackClient).getResponseAsString(Mockito.eq(closeableHttpResponseMock)); + inOrder.verify(apacheCloudStackClient).createHttpContextWithCookies(Mockito.eq(closeableHttpResponseMock)); + } - @Test(expected = ApacheCloudStackClientRuntimeException.class) - public void createHttpContextWithAuthenticatedSessionUsingUserCredentialsTestExceptionExecutingRequest() throws ClientProtocolException, IOException { - HttpPost httpPostMock = Mockito.mock(HttpPost.class); - Mockito.doReturn(httpPostMock).when(apacheCloudStackClient).createHttpPost(); + @Test(expected = ApacheCloudStackClientRuntimeException.class) + public void createHttpContextWithAuthenticatedSessionUsingUserCredentialsTestExceptionExecutingRequest() throws ClientProtocolException, IOException { + HttpPost httpPostMock = Mockito.mock(HttpPost.class); + Mockito.doReturn(httpPostMock).when(apacheCloudStackClient).createHttpPost(); - NameValuePair nameValuePairMock = Mockito.mock(NameValuePair.class); - ArrayList paramsMock = new ArrayList<>(1); - paramsMock.add(nameValuePairMock); + NameValuePair nameValuePairMock = Mockito.mock(NameValuePair.class); + ArrayList paramsMock = new ArrayList<>(1); + paramsMock.add(nameValuePairMock); - Mockito.doReturn(paramsMock).when(apacheCloudStackClient).getParametersForLogin(); + Mockito.doReturn(paramsMock).when(apacheCloudStackClient).getParametersForLogin(); - CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); + CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); - Mockito.doThrow(IOException.class).when(httpClientMock).execute(Mockito.eq(httpPostMock)); + Mockito.doThrow(IOException.class).when(httpClientMock).execute(Mockito.eq(httpPostMock)); - apacheCloudStackClient.createHttpContextWithAuthenticatedSessionUsingUserCredentials(httpClientMock); - } + apacheCloudStackClient.createHttpContextWithAuthenticatedSessionUsingUserCredentials(httpClientMock); + } - @Test - public void createHttpContextWithCookiesTest() { - CloseableHttpResponse closeableHttpResponseMock = Mockito.mock(CloseableHttpResponse.class); + @Test + public void createHttpContextWithCookiesTest() { + CloseableHttpResponse closeableHttpResponseMock = Mockito.mock(CloseableHttpResponse.class); - Header[] headers = new Header[1]; - Mockito.doReturn(headers).when(closeableHttpResponseMock).getAllHeaders(); + Header[] headers = new Header[1]; + Mockito.doReturn(headers).when(closeableHttpResponseMock).getAllHeaders(); - Mockito.doNothing().when(apacheCloudStackClient).createAndAddCookiesOnStoreForHeaders(Mockito.any(BasicCookieStore.class), Mockito.eq(headers)); - HttpContext httpContextWithCookies = apacheCloudStackClient.createHttpContextWithCookies(closeableHttpResponseMock); + Mockito.doNothing().when(apacheCloudStackClient).createAndAddCookiesOnStoreForHeaders(Mockito.any(BasicCookieStore.class), Mockito.eq(headers)); + HttpContext httpContextWithCookies = apacheCloudStackClient.createHttpContextWithCookies(closeableHttpResponseMock); - Assert.assertNotNull(httpContextWithCookies); - Assert.assertNotNull(httpContextWithCookies.getAttribute(HttpClientContext.COOKIE_STORE)); + Assert.assertNotNull(httpContextWithCookies); + Assert.assertNotNull(httpContextWithCookies.getAttribute(HttpClientContext.COOKIE_STORE)); - Mockito.verify(apacheCloudStackClient).createAndAddCookiesOnStoreForHeaders(Mockito.any(BasicCookieStore.class), Mockito.eq(headers)); + Mockito.verify(apacheCloudStackClient).createAndAddCookiesOnStoreForHeaders(Mockito.any(BasicCookieStore.class), Mockito.eq(headers)); - } + } - @Test - public void createAndAddCookiesOnStoreForHeadersTest() { - Header[] headers = new Header[2]; - headers[0] = new BasicHeader("Set-Cookie cookieName", "value1"); - headers[1] = new BasicHeader("anyOtherCookie", "value2"); + @Test + public void createAndAddCookiesOnStoreForHeadersTest() { + Header[] headers = new Header[2]; + headers[0] = new BasicHeader("Set-Cookie cookieName", "value1"); + headers[1] = new BasicHeader("anyOtherCookie", "value2"); - CookieStore cookieStoreMock = Mockito.mock(CookieStore.class); + CookieStore cookieStoreMock = Mockito.mock(CookieStore.class); - Mockito.doNothing().when(apacheCloudStackClient).createAndAddCookiesOnStoreForHeader(Mockito.eq(cookieStoreMock), Mockito.any(Header.class)); - apacheCloudStackClient.createAndAddCookiesOnStoreForHeaders(cookieStoreMock, headers); + Mockito.doNothing().when(apacheCloudStackClient).createAndAddCookiesOnStoreForHeader(Mockito.eq(cookieStoreMock), Mockito.any(Header.class)); + apacheCloudStackClient.createAndAddCookiesOnStoreForHeaders(cookieStoreMock, headers); - Mockito.verify(apacheCloudStackClient).createAndAddCookiesOnStoreForHeader(Mockito.eq(cookieStoreMock), Mockito.eq(headers[0])); - } + Mockito.verify(apacheCloudStackClient).createAndAddCookiesOnStoreForHeader(Mockito.eq(cookieStoreMock), Mockito.eq(headers[0])); + } - public void createAndAddCookiesOnStoreForHeaderTest() { - CookieStore cookieStoreMock = Mockito.mock(CookieStore.class); - Header headerMock = Mockito.mock(Header.class); + public void createAndAddCookiesOnStoreForHeaderTest() { + CookieStore cookieStoreMock = Mockito.mock(CookieStore.class); + Header headerMock = Mockito.mock(Header.class); - HeaderElement headerElementMock1 = Mockito.mock(HeaderElement.class); + HeaderElement headerElementMock1 = Mockito.mock(HeaderElement.class); - List headerElements = new ArrayList<>(1); - headerElements.add(headerElementMock1); + List headerElements = new ArrayList<>(1); + headerElements.add(headerElementMock1); - Mockito.doReturn(headerElements).when(headerMock).getElements(); + Mockito.doReturn(headerElements).when(headerMock).getElements(); - Cookie cookieMock = Mockito.mock(Cookie.class); - Mockito.doReturn(cookieMock).when(apacheCloudStackClient).createCookieForHeaderElement(Mockito.eq(headerElementMock1)); + Cookie cookieMock = Mockito.mock(Cookie.class); + Mockito.doReturn(cookieMock).when(apacheCloudStackClient).createCookieForHeaderElement(Mockito.eq(headerElementMock1)); - apacheCloudStackClient.createAndAddCookiesOnStoreForHeader(cookieStoreMock, headerMock); + apacheCloudStackClient.createAndAddCookiesOnStoreForHeader(cookieStoreMock, headerMock); - Mockito.verify(headerMock).getElements(); - Mockito.verify(apacheCloudStackClient).createCookieForHeaderElement(Mockito.eq(headerElementMock1)); - } + Mockito.verify(headerMock).getElements(); + Mockito.verify(apacheCloudStackClient).createCookieForHeaderElement(Mockito.eq(headerElementMock1)); + } - @Test - public void createCookieForHeaderElementTest() { - String cookiePath = "/client/api"; + @Test + public void createCookieForHeaderElementTest() { + String cookiePath = "/client/api"; - String paramName = "paramName1"; - String paramValue = "paramVale1"; - NameValuePair[] parameters = new NameValuePair[1]; - parameters[0] = new BasicNameValuePair(paramName, paramValue); + String paramName = "paramName1"; + String paramValue = "paramVale1"; + NameValuePair[] parameters = new NameValuePair[1]; + parameters[0] = new BasicNameValuePair(paramName, paramValue); - String headerName = "headerElementName"; - String headerValue = "headerElementValue"; - HeaderElement headerElement = new BasicHeaderElement(headerName, headerValue, parameters); + String headerName = "headerElementName"; + String headerValue = "headerElementValue"; + HeaderElement headerElement = new BasicHeaderElement(headerName, headerValue, parameters); - Mockito.doNothing().when(apacheCloudStackClient).configureDomainForCookie(Mockito.any(BasicClientCookie.class)); + Mockito.doNothing().when(apacheCloudStackClient).configureDomainForCookie(Mockito.any(BasicClientCookie.class)); - BasicClientCookie cookieForHeaderElement = apacheCloudStackClient.createCookieForHeaderElement(headerElement); + BasicClientCookie cookieForHeaderElement = apacheCloudStackClient.createCookieForHeaderElement(headerElement); - Assert.assertNotNull(cookieForHeaderElement); - Assert.assertEquals(headerName, cookieForHeaderElement.getName()); - Assert.assertEquals(headerValue, cookieForHeaderElement.getValue()); - Assert.assertEquals(paramValue, cookieForHeaderElement.getAttribute(paramName)); - Assert.assertEquals(cookiePath, cookieForHeaderElement.getPath()); + Assert.assertNotNull(cookieForHeaderElement); + Assert.assertEquals(headerName, cookieForHeaderElement.getName()); + Assert.assertEquals(headerValue, cookieForHeaderElement.getValue()); + Assert.assertEquals(paramValue, cookieForHeaderElement.getAttribute(paramName)); + Assert.assertEquals(cookiePath, cookieForHeaderElement.getPath()); - Mockito.verify(apacheCloudStackClient).configureDomainForCookie(Mockito.eq(cookieForHeaderElement)); - } + Mockito.verify(apacheCloudStackClient).configureDomainForCookie(Mockito.eq(cookieForHeaderElement)); + } - @Test - public void configureDomainForCookieTest() { - BasicClientCookie basicClientCookie = new BasicClientCookie("name", "value"); - apacheCloudStackClient.configureDomainForCookie(basicClientCookie); + @Test + public void configureDomainForCookieTest() { + BasicClientCookie basicClientCookie = new BasicClientCookie("name", "value"); + apacheCloudStackClient.configureDomainForCookie(basicClientCookie); - Assert.assertEquals(cloudStackDomain, basicClientCookie.getDomain()); - } + Assert.assertEquals(cloudStackDomain, basicClientCookie.getDomain()); + } - @Test - public void createHttpPostTest() throws MalformedURLException { - HttpPost httpPost = apacheCloudStackClient.createHttpPost(); + @Test + public void createHttpPostTest() throws MalformedURLException { + HttpPost httpPost = apacheCloudStackClient.createHttpPost(); - Assert.assertEquals(cloudStackUrl, httpPost.getURI().toURL().toString()); - Assert.assertEquals("application/x-www-form-urlencoded", httpPost.getFirstHeader("Content-Type").getValue()); - } + Assert.assertEquals(cloudStackUrl, httpPost.getURI().toURL().toString()); + Assert.assertEquals("application/x-www-form-urlencoded", httpPost.getFirstHeader("Content-Type").getValue()); + } - public void getParametersForLoginTest() { - Mockito.doReturn("userName").when(apacheCloudStackUser).getUsername(); - Mockito.doReturn("password").when(apacheCloudStackUser).getPassword(); - Mockito.doReturn("domain").when(apacheCloudStackUser).getDomain(); + public void getParametersForLoginTest() { + Mockito.doReturn("userName").when(apacheCloudStackUser).getUsername(); + Mockito.doReturn("password").when(apacheCloudStackUser).getPassword(); + Mockito.doReturn("domain").when(apacheCloudStackUser).getDomain(); - List parametersForLogin = apacheCloudStackClient.getParametersForLogin(); + List parametersForLogin = apacheCloudStackClient.getParametersForLogin(); - Assert.assertNotNull(parametersForLogin); - Assert.assertEquals(4, parametersForLogin.size()); + Assert.assertNotNull(parametersForLogin); + Assert.assertEquals(4, parametersForLogin.size()); - Assert.assertEquals("command", parametersForLogin.get(0).getValue()); - Assert.assertEquals("login", parametersForLogin.get(0).getName()); + Assert.assertEquals("command", parametersForLogin.get(0).getValue()); + Assert.assertEquals("login", parametersForLogin.get(0).getName()); - Assert.assertEquals("username", parametersForLogin.get(1).getValue()); - Assert.assertEquals("userName", parametersForLogin.get(1).getName()); + Assert.assertEquals("username", parametersForLogin.get(1).getValue()); + Assert.assertEquals("userName", parametersForLogin.get(1).getName()); - Assert.assertEquals("password", parametersForLogin.get(2).getValue()); - Assert.assertEquals("password", parametersForLogin.get(2).getName()); + Assert.assertEquals("password", parametersForLogin.get(2).getValue()); + Assert.assertEquals("password", parametersForLogin.get(2).getName()); - Assert.assertEquals("domain", parametersForLogin.get(3).getValue()); - Assert.assertEquals("domain", parametersForLogin.get(3).getName()); - } + Assert.assertEquals("domain", parametersForLogin.get(3).getValue()); + Assert.assertEquals("domain", parametersForLogin.get(3).getName()); + } - @Test - public void executeUserLogoutTest() { - String urlRequest = "urlRequest"; + @Test + public void executeUserLogoutTest() { + String urlRequest = "urlRequest"; - Mockito.doReturn(urlRequest).when(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(false)); - Mockito.doReturn("response").when(apacheCloudStackClient).executeRequestGetResponseAsString(Mockito.eq(urlRequest), Mockito.any(CloseableHttpClient.class), Mockito.any(HttpContext.class)); + Mockito.doReturn(urlRequest).when(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(false)); + Mockito.doReturn("response").when(apacheCloudStackClient).executeRequestGetResponseAsString(Mockito.eq(urlRequest), Mockito.any(CloseableHttpClient.class), Mockito.any(HttpContext.class)); - apacheCloudStackClient.executeUserLogout(Mockito.mock(CloseableHttpClient.class), Mockito.mock(HttpContext.class)); + apacheCloudStackClient.executeUserLogout(Mockito.mock(CloseableHttpClient.class), Mockito.mock(HttpContext.class)); - InOrder inOrder = Mockito.inOrder(apacheCloudStackClient); - inOrder.verify(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(false)); - inOrder.verify(apacheCloudStackClient).executeRequestGetResponseAsString(Mockito.eq(urlRequest), Mockito.any(CloseableHttpClient.class), Mockito.any(HttpContext.class)); - } + InOrder inOrder = Mockito.inOrder(apacheCloudStackClient); + inOrder.verify(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(false)); + inOrder.verify(apacheCloudStackClient).executeRequestGetResponseAsString(Mockito.eq(urlRequest), Mockito.any(CloseableHttpClient.class), Mockito.any(HttpContext.class)); + } - @Test - public void configureRequestExpirationTestRequestsShouldNotExpire() { - apacheCloudStackClient.setShouldRequestsExpire(false); + @Test + public void configureRequestExpirationTestRequestsShouldNotExpire() { + apacheCloudStackClient.setShouldRequestsExpire(false); - ArrayList arrayList = new ArrayList<>(); - apacheCloudStackClient.configureRequestExpiration(arrayList); + ArrayList arrayList = new ArrayList<>(); + apacheCloudStackClient.configureRequestExpiration(arrayList); - Assert.assertEquals(0, arrayList.size()); - } + Assert.assertEquals(0, arrayList.size()); + } - @Test - public void configureRequestExpirationTestRequestsShouldNotExpireUsingOverride() { - apacheCloudStackClient.setShouldRequestsExpire(false); + @Test + public void configureRequestExpirationTestRequestsShouldNotExpireUsingOverride() { + apacheCloudStackClient.setShouldRequestsExpire(false); - ArrayList arrayList = new ArrayList<>(); - arrayList.add(new ApacheCloudStackApiCommandParameter("expires", "2011-10-10T12:00:00+0530")); + ArrayList arrayList = new ArrayList<>(); + arrayList.add(new ApacheCloudStackApiCommandParameter("expires", "2011-10-10T12:00:00+0530")); - apacheCloudStackClient.configureRequestExpiration(arrayList); + apacheCloudStackClient.configureRequestExpiration(arrayList); - Assert.assertEquals(2, arrayList.size()); - Mockito.verify(apacheCloudStackClient, Mockito.never()).createExpirationDate(); - } + Assert.assertEquals(2, arrayList.size()); + Mockito.verify(apacheCloudStackClient, Mockito.never()).createExpirationDate(); + } - @Test - public void configureRequestExpirationTestRequestsShouldExpireUsingOverride() { - apacheCloudStackClient.setShouldRequestsExpire(true); + @Test + public void configureRequestExpirationTestRequestsShouldExpireUsingOverride() { + apacheCloudStackClient.setShouldRequestsExpire(true); - ArrayList arrayList = new ArrayList<>(); - ApacheCloudStackApiCommandParameter expirationParameter = new ApacheCloudStackApiCommandParameter("expires", "2011-10-10T12:00:00+0530"); - arrayList.add(expirationParameter); + ArrayList arrayList = new ArrayList<>(); + ApacheCloudStackApiCommandParameter expirationParameter = new ApacheCloudStackApiCommandParameter("expires", "2011-10-10T12:00:00+0530"); + arrayList.add(expirationParameter); - apacheCloudStackClient.configureRequestExpiration(arrayList); + apacheCloudStackClient.configureRequestExpiration(arrayList); - Assert.assertEquals(2, arrayList.size()); - Assert.assertEquals(expirationParameter, arrayList.get(0)); - Mockito.verify(apacheCloudStackClient, Mockito.never()).createExpirationDate(); - } + Assert.assertEquals(2, arrayList.size()); + Assert.assertEquals(expirationParameter, arrayList.get(0)); + Mockito.verify(apacheCloudStackClient, Mockito.never()).createExpirationDate(); + } - @Test - public void configureRequestExpirationTestRequestsShouldExpireWithoutOverride() { - apacheCloudStackClient.setShouldRequestsExpire(true); + @Test + public void configureRequestExpirationTestRequestsShouldExpireWithoutOverride() { + apacheCloudStackClient.setShouldRequestsExpire(true); - ArrayList arrayList = new ArrayList<>(); + ArrayList arrayList = new ArrayList<>(); - String expirationDate = "2011-10-10T12:00:00+0530"; - Mockito.doReturn(expirationDate).when(apacheCloudStackClient).createExpirationDate(); + String expirationDate = "2011-10-10T12:00:00+0530"; + Mockito.doReturn(expirationDate).when(apacheCloudStackClient).createExpirationDate(); - apacheCloudStackClient.configureRequestExpiration(arrayList); + apacheCloudStackClient.configureRequestExpiration(arrayList); - Assert.assertEquals(2, arrayList.size()); - Assert.assertEquals("signatureVersion", arrayList.get(0).getName()); - Assert.assertEquals(3, arrayList.get(0).getValue()); - Assert.assertEquals("expires", arrayList.get(1).getName()); - Assert.assertEquals(expirationDate, arrayList.get(1).getValue()); + Assert.assertEquals(2, arrayList.size()); + Assert.assertEquals("signatureVersion", arrayList.get(0).getName()); + Assert.assertEquals(3, arrayList.get(0).getValue()); + Assert.assertEquals("expires", arrayList.get(1).getName()); + Assert.assertEquals(expirationDate, arrayList.get(1).getValue()); - Mockito.verify(apacheCloudStackClient).createExpirationDate(); - } + Mockito.verify(apacheCloudStackClient).createExpirationDate(); + } - @Test - public void createExpirationDateTest() { - Calendar someMomentInTimeSpace = Calendar.getInstance(); - someMomentInTimeSpace.set(1999, 12, 31, 23, 59, 59); - someMomentInTimeSpace.set(Calendar.MILLISECOND, 0); - Mockito.doReturn(someMomentInTimeSpace.getTime()).when(apacheCloudStackClient).getExpirationDate(); + @Test + public void createExpirationDateTest() { + Calendar someMomentInTimeSpace = Calendar.getInstance(); + someMomentInTimeSpace.set(1999, 12, 31, 23, 59, 59); + someMomentInTimeSpace.set(Calendar.MILLISECOND, 0); + Mockito.doReturn(someMomentInTimeSpace.getTime()).when(apacheCloudStackClient).getExpirationDate(); - String expirationDate = apacheCloudStackClient.createExpirationDate(); + String expirationDate = apacheCloudStackClient.createExpirationDate(); - String expectedExpirationDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(someMomentInTimeSpace.getTime()); - Assert.assertEquals(expectedExpirationDate, expirationDate); + String expectedExpirationDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(someMomentInTimeSpace.getTime()); + Assert.assertEquals(expectedExpirationDate, expirationDate); - Mockito.verify(apacheCloudStackClient).getExpirationDate(); - } + Mockito.verify(apacheCloudStackClient).getExpirationDate(); + } - @Test - public void createInsecureHostNameVerifierTest() { - HostnameVerifier hostNameVerifier = apacheCloudStackClient.createInsecureHostNameVerifier(); + @Test + public void createInsecureHostNameVerifierTest() { + HostnameVerifier hostNameVerifier = apacheCloudStackClient.createInsecureHostNameVerifier(); - Assert.assertTrue(hostNameVerifier.verify("...", null)); - Assert.assertTrue(hostNameVerifier.verify("Any other thing", null)); + Assert.assertTrue(hostNameVerifier.verify("...", null)); + Assert.assertTrue(hostNameVerifier.verify("Any other thing", null)); - } + } + + @Test + public void toStringTest() { + String toStringValue = apacheCloudStackClient.toString(); + + String expectedToStringValue = "Apache CloudSTackClient for site[https://cloud.domain.com/client/api], parameters: [connectionTimeout=60, acceptAllKindsOfCertificates=false, validateServerHttpsCertificate=true, requestValidity=30, shouldRequestsExpire=true]"; + Assert.assertEquals(expectedToStringValue, toStringValue); + } } From f3b863065e6bef8e3cd91d22783c3c7289e0d26b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Weing=C3=A4rtner?= Date: Thu, 19 Oct 2017 19:25:09 -0200 Subject: [PATCH 2/2] fix formatter --- .../client/ApacheCloudStackClient.java | 943 ++++++++--------- .../client/ApacheCloudStackClientTest.java | 958 +++++++++--------- 2 files changed, 953 insertions(+), 948 deletions(-) diff --git a/src/main/java/br/com/autonomiccs/apacheCloudStack/client/ApacheCloudStackClient.java b/src/main/java/br/com/autonomiccs/apacheCloudStack/client/ApacheCloudStackClient.java index bf4e550..d89f53f 100644 --- a/src/main/java/br/com/autonomiccs/apacheCloudStack/client/ApacheCloudStackClient.java +++ b/src/main/java/br/com/autonomiccs/apacheCloudStack/client/ApacheCloudStackClient.java @@ -93,475 +93,476 @@ * The client is a pair of URL and user credentials ({@link #apacheCloudStackUser}). */ public class ApacheCloudStackClient { - /** - * This flag indicates if we are going to validate the server certificate in case of HTTPS connections. - * The default value is 'true', meaning that we always validate the server HTTPS certificate. - */ - protected boolean validateServerHttpsCertificate = true; - - /** - * This flag is highly dangerous and should never be used with production environments. - * It will accept every single SSL certificates when creating HTTPS connections. Not even the commons name will be checked. - * Therefore, it should be kept only during development phase. - */ - protected boolean acceptAllKindsOfCertificates = false; - - /** - * The validity time of the ACS request. - * The default value is {@value #requestValidity} . - */ - private int requestValidity = 30; - - /** - * The http client connection timeout - * The default value is {@value #connectionTimeout} seconds . - */ - private int connectionTimeout = 60; - - /** - * This parameter controls if the expiration of requests is activated or not. - * It is activated by default. The validity of requests if defined by {@value #requestValidity} property. - */ - private boolean shouldRequestsExpire = true; - - private Gson gson = new GsonBuilder().create(); - private Logger logger = LoggerFactory.getLogger(getClass()); - - /** - * The API URL used to access Apache CloudStack API. - * Ex: https://cloud.domain.com/client/api - */ - private String url; - - /** - * User credentials that can be used to access ApacheCloudStack. - * They can be either a pair of secret key and API key or a triple of username, password and domain - */ - protected ApacheCloudStackUser apacheCloudStackUser; - - public ApacheCloudStackClient(String url, ApacheCloudStackUser apacheCloudStackUser) { - this.url = url; - this.apacheCloudStackUser = apacheCloudStackUser; - - } - - /** - * This method executes the given {@link ApacheCloudStackRequest}. - * It will return the response as a plain {@link String}. - * You should have in mind that if the parameter 'response' is not set, the default is 'XML'. - */ - public String executeRequest(ApacheCloudStackRequest request) { - boolean isSecretKeyApiKeyAuthenticationMechanism = StringUtils.isNotBlank(this.apacheCloudStackUser.getApiKey()); - String urlRequest = createApacheCloudStackApiUrlRequest(request, isSecretKeyApiKeyAuthenticationMechanism); - logger.debug(String.format("Executing request[%s].", urlRequest)); - CloseableHttpClient httpClient = createHttpClient(); - HttpContext httpContext = createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(httpClient, isSecretKeyApiKeyAuthenticationMechanism); - try { - return executeRequestGetResponseAsString(urlRequest, httpClient, httpContext); - } finally { - if (!isSecretKeyApiKeyAuthenticationMechanism) { - executeUserLogout(httpClient, httpContext); - } - HttpClientUtils.closeQuietly(httpClient); - } - } - - /** - * Executes the request with the given {@link HttpContext}. - */ - protected String executeRequestGetResponseAsString(String urlRequest, CloseableHttpClient httpClient, HttpContext httpContext) { - try { - HttpRequestBase httpGetRequest = new HttpGet(urlRequest); - CloseableHttpResponse response = httpClient.execute(httpGetRequest, httpContext); - StatusLine requestStatus = response.getStatusLine(); - if (requestStatus.getStatusCode() == HttpStatus.SC_OK) { - return getResponseAsString(response); - } - throw new ApacheCloudStackClientRequestRuntimeException(requestStatus.getStatusCode(), getResponseAsString(response), urlRequest.toString()); - } catch (IOException e) { - logger.error(String.format("Error while executing request [%s]", urlRequest)); - throw new ApacheCloudStackClientRuntimeException(e); - } - } - - /** - * This method executes the user logout when using username/password/domain authentication. - * The logout is executed calling the 'logout' command of the Apache CloudStack API. - */ - protected void executeUserLogout(CloseableHttpClient httpClient, HttpContext httpContext) { - String urlRequest = createApacheCloudStackApiUrlRequest(new ApacheCloudStackRequest("logout").addParameter("response", "json"), false); - String returnOfLogout = executeRequestGetResponseAsString(urlRequest, httpClient, httpContext); - logger.debug(String.format("Logout result[%s]", returnOfLogout)); - } - - /** - * According to the 'isSecretKeyApiKey AuthenticationMechanism' parameter this method creates an HttpContext that is used when executing requests. - * If the user has provided his/her API/secret keys, we return a {@link BasicHttpContext} object. Otherwise, we authenticate the user with his/her username/password/domain and return an {@link HttpContext} object that contains the authenticated session Id configured as a cookie. - */ - protected HttpContext createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(CloseableHttpClient httpClient, boolean isSecretKeyApiKeyAuthenticationMechanism) { - if (isSecretKeyApiKeyAuthenticationMechanism) { - return new BasicHttpContext(); - } - return createHttpContextWithAuthenticatedSessionUsingUserCredentials(httpClient); - } - - /** - * It creates a {@link RequestConfig} object with configured {@link #connectionTimeout} value. - * This can be used to set on a HttpClient its connect timeout, connection request timeout and socket timeout. - * @return returns the created RequestConfig object - */ - protected RequestConfig createRequestConfig() { - return RequestConfig.custom().setConnectTimeout(connectionTimeout * (int)DateUtils.MILLIS_PER_SECOND) - .setConnectionRequestTimeout(connectionTimeout * (int)DateUtils.MILLIS_PER_SECOND).setSocketTimeout(connectionTimeout * (int)DateUtils.MILLIS_PER_SECOND).build(); - } - - /** - * It creates an {@link CloseableHttpClient} object. - * If {@link #validateServerHttpsCertificate} indicates that we should not validate HTTPS server certificate, we use an insecure SSL factory; the insecure factory is created using {@link #createInsecureSslFactory()}. - */ - protected CloseableHttpClient createHttpClient() { - HttpClientBuilder httpClientBuilder = HttpClientBuilder.create().setDefaultRequestConfig(createRequestConfig()); - if (!validateServerHttpsCertificate) { - SSLConnectionSocketFactory sslsf = createInsecureSslFactory(); - httpClientBuilder.setSSLSocketFactory(sslsf); - } - return httpClientBuilder.build(); - } - - /** - * This method creates an {@link HttpContext} with an authenticated JSESSIONID. - * The authentication is performed using username, password and domain that are provided by the user. - */ - protected HttpContext createHttpContextWithAuthenticatedSessionUsingUserCredentials(CloseableHttpClient httpClient) { - HttpPost httpPost = createHttpPost(); - List params = getParametersForLogin(); - - try { - UrlEncodedFormEntity postParams = new UrlEncodedFormEntity(params, "UTF-8"); - httpPost.setEntity(postParams); - - CloseableHttpResponse loginResponse = httpClient.execute(httpPost); - int statusCode = loginResponse.getStatusLine().getStatusCode(); - if (statusCode != HttpStatus.SC_OK) { - throw new ApacheCloudStackClientRequestRuntimeException(statusCode, getResponseAsString(loginResponse), "login"); - } - logger.debug(String.format("Authentication response:[%s]", getResponseAsString(loginResponse))); - - return createHttpContextWithCookies(loginResponse); - } catch (IOException e) { - throw new ApacheCloudStackClientRuntimeException(e); - } - } - - /** - * It creates an {@link HttpContext} object with a cookie store that will contain the cookies returned by the user in the {@link CloseableHttpResponse} that is received as parameter. - */ - protected HttpContext createHttpContextWithCookies(CloseableHttpResponse loginResponse) { - CookieStore cookieStore = new BasicCookieStore(); - createAndAddCookiesOnStoreForHeaders(cookieStore, loginResponse.getAllHeaders()); - HttpContext httpContext = new BasicHttpContext(); - httpContext.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore); - return httpContext; - } - - /** - * For every header that contains the command 'Set-Cookie' it will call the method {@link #createAndAddCookiesOnStoreForHeader(CookieStore, Header)} - */ - protected void createAndAddCookiesOnStoreForHeaders(CookieStore cookieStore, Header[] allHeaders) { - for (Header header : allHeaders) { - if (StringUtils.startsWithIgnoreCase(header.getName(), "Set-Cookie")) { - createAndAddCookiesOnStoreForHeader(cookieStore, header); - } - } - } - - /** - * This method creates a cookie for every {@link HeaderElement} of the {@link Header} given as parameter. - * Then, it adds this newly created cookie into the {@link CookieStore} provided as parameter. - */ - protected void createAndAddCookiesOnStoreForHeader(CookieStore cookieStore, Header header) { - for (HeaderElement element : header.getElements()) { - BasicClientCookie cookie = createCookieForHeaderElement(element); - cookieStore.addCookie(cookie); - } - } - - /** - * This method will create a {@link BasicClientCookie} with the given {@link HeaderElement}. - * It sill set the cookie's name and value according to the {@link HeaderElement#getName()} and {@link HeaderElement#getValue()} methods. - * Moreover, it will transport every {@link HeaderElement} parameter to the cookie using the {@link BasicClientCookie#setAttribute(String, String)}. - * Additionally, it configures the cookie path ({@link BasicClientCookie#setPath(String)}) to value '/client/api' and the cookie domain using {@link #configureDomainForCookie(BasicClientCookie)} method. - */ - protected BasicClientCookie createCookieForHeaderElement(HeaderElement element) { - BasicClientCookie cookie = new BasicClientCookie(element.getName(), element.getValue()); - for (NameValuePair parameter : element.getParameters()) { - cookie.setAttribute(parameter.getName(), parameter.getValue()); - } - cookie.setPath("/client/api"); - configureDomainForCookie(cookie); - return cookie; - } - - /** - * It configures the cookie domain with the domain of the Apache CloudStack that is being accessed. - * The domain is extracted from {@link #url} variable. - */ - protected void configureDomainForCookie(BasicClientCookie cookie) { - try { - HttpHost httpHost = URIUtils.extractHost(new URI(url)); - String domain = httpHost.getHostName(); - cookie.setDomain(domain); - } catch (URISyntaxException e) { - throw new ApacheCloudStackClientRuntimeException(e); - } - } - - /** - * Creates an {@link HttpPost} object to be sent to Apache CloudStack API. - * The content type configured for this request is 'application/x-www-form-urlencoded'. - */ - protected HttpPost createHttpPost() { - HttpPost httpPost = new HttpPost(url); - httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded"); - return httpPost; - } - - /** - * This method creates a list of {@link NameValuePair} and returns the data for login using username and password. - */ - protected List getParametersForLogin() { - List params = new ArrayList<>(4); - params.add(new BasicNameValuePair("command", "login")); - params.add(new BasicNameValuePair("username", this.apacheCloudStackUser.getUsername())); - params.add(new BasicNameValuePair("password", this.apacheCloudStackUser.getPassword())); - params.add(new BasicNameValuePair("domain", this.apacheCloudStackUser.getDomain())); - return params; - } - - /** - * This method creates an insecure SSL factory that will trust on self signed certificates. - * For that we use {@link TrustSelfSignedStrategy}. - */ - protected SSLConnectionSocketFactory createInsecureSslFactory() { - try { - SSLContextBuilder builder = new SSLContextBuilder(); - builder.loadTrustMaterial(new TrustSelfSignedStrategy()); - SSLContext sc = builder.build(); - - if (acceptAllKindsOfCertificates) { - TrustManager[] trustAllCerts = new TrustManager[1]; - TrustManager tm = new TrustAllManager(); - trustAllCerts[0] = tm; - sc.init(null, trustAllCerts, null); - - HostnameVerifier hostnameVerifier = createInsecureHostNameVerifier(); - return new SSLConnectionSocketFactory(sc, hostnameVerifier); - } - return new SSLConnectionSocketFactory(sc); - } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) { - throw new ApacheCloudStackClientRuntimeException(e); - } - } - - protected HostnameVerifier createInsecureHostNameVerifier() { - HostnameVerifier hostnameVerifier = new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; - } - }; - return hostnameVerifier; - } - - /** - * This class is used when {@link ApacheCloudStackClient#acceptAllKindsOfCertificates} is set to true. - */ - @SuppressWarnings("unused") - private class TrustAllManager implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager { - @Override - public java.security.cert.X509Certificate[] getAcceptedIssuers() { - return null; - } - - public boolean isServerTrusted(final X509Certificate[] certs) { - return true; - } - - public boolean isClientTrusted(final X509Certificate[] certs) { - return true; - } - - @Override - public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { - return; - } - - @Override - public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { - return; - } - } - - /** - * It retrieves the response status as a {@link String} - */ - protected String getResponseAsString(CloseableHttpResponse response) throws IOException { - InputStream responseContent = response.getEntity().getContent(); - StringWriter writer = new StringWriter(); - IOUtils.copy(responseContent, writer, Charset.defaultCharset()); - - responseContent.close(); - response.close(); - return writer.toString(); - } - - /** - * This method creates transforms the given {@link ApacheCloudStackRequest} into a URL requeest for the Apache CloudStack API. - * Therefore, it will create a command query string following the CloudStack specifications using method {@link #createCommandString(ApacheCloudStackRequest)}; - * and then, if it needs, it creates the signature using the method {@link #createSignature(String)} and append it to the URL. - */ - protected String createApacheCloudStackApiUrlRequest(ApacheCloudStackRequest request, boolean shouldSignAppendSignature) { - StringBuilder urlRequest = new StringBuilder(url).append("?"); - - String queryString = createCommandString(request); - urlRequest.append(queryString); - - if (shouldSignAppendSignature) { - String signature = createSignature(queryString); - urlRequest.append("&signature=").append(getUrlEncodedValue(signature)); - } - return urlRequest.toString(); - } - - /** - * Creates a signature (HMAC-sha1) with the {@link #ApacheCloudStackUser#getSecretKey()} and the given queryString - * The returner signature is encoded in Base64. - */ - protected String createSignature(String queryString) { - byte[] signatureBytes = HmacUtils.hmacSha1(apacheCloudStackUser.getSecretKey(), queryString.toLowerCase()); - return Base64.encodeBase64String(signatureBytes); - } - - /** - * It creates the command query string, placing the parameters in alphabetical order. - * To execute the sorting, it uses the {@link #createSortedCommandQueryList(ApacheCloudStackRequest)} method. - */ - protected String createCommandString(ApacheCloudStackRequest request) { - List queryCommand = createSortedCommandQueryList(request); - - StringBuilder commandString = new StringBuilder(); - for (ApacheCloudStackApiCommandParameter param : queryCommand) { - String value = getUrlEncodedValue(param.getValue()); - commandString.append(String.format("%s=%s&", param.getName(), value)); - } - return commandString.toString().substring(0, commandString.length() - 1); - } - - /** - * This method encodes the parameter value as specified by Apache CloudStack - */ - protected String getUrlEncodedValue(Object paramValue) { - String value = Objects.toString(paramValue); - try { - value = URLEncoder.encode(value, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new ApacheCloudStackClientRuntimeException(e); - } - return value.replaceAll("\\+", "%20"); - } - - /** - * This methods adds the final data needed to the command query. - * It will add a parameter called 'command' with the value of {@link ApacheCloudStackRequest#getCommand()} as value. - * It also adds a parameter called 'apiKey', with the value of {@link #ApacheCloudStackUser#getApiKey()} as value. - * Then, it will sort the parameters that are in a list in alphabetical order. - */ - protected List createSortedCommandQueryList(ApacheCloudStackRequest request) { - List queryCommand = new ArrayList<>(); - queryCommand.addAll(request.getParameters()); - queryCommand.add(new ApacheCloudStackApiCommandParameter("command", request.getCommand())); - if (StringUtils.isNotBlank(this.apacheCloudStackUser.getApiKey())) { - queryCommand.add(new ApacheCloudStackApiCommandParameter("apiKey", this.apacheCloudStackUser.getApiKey())); - } - configureRequestExpiration(queryCommand); - Collections.sort(queryCommand); - return queryCommand; - } - - /** - * This method configures the request expiration if needed. - * It uses the value defined at {@link #requestValidity} to determine until when the request is valid. - * It also uses the parameter {@link #shouldRequestsExpire} to decide if it has to configure or not the validity of the request. - * Moreover, if the 'apacheCloudStackRequestList' contains the 'expires' it will only add a parameter called 'signatureVersion=3', in order to enable that override. - */ - protected void configureRequestExpiration(List apacheCloudStackRequestList) { - boolean isOverridingExpirationConfigs = apacheCloudStackRequestList.contains(new ApacheCloudStackApiCommandParameter("expires", StringUtils.EMPTY)); - if (!isOverridingExpirationConfigs && !shouldRequestsExpire) { - return; - } - apacheCloudStackRequestList.add(new ApacheCloudStackApiCommandParameter("signatureVersion", 3)); - if (isOverridingExpirationConfigs) { - return; - } - String expirationDataAsSring = createExpirationDate(); - apacheCloudStackRequestList.add(new ApacheCloudStackApiCommandParameter("expires", expirationDataAsSring)); - } - - /** - * This method creates the expiration date as a string according to the ISO 8601. - */ - protected String createExpirationDate() { - DateFormat acsIso8601DateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); - return acsIso8601DateFormat.format(getExpirationDate()); - } - - /** - * Creates the expiration date, by adding the {@link #requestValidity} to the current time. - */ - protected Date getExpirationDate() { - Calendar now = Calendar.getInstance(); - now.add(Calendar.SECOND, requestValidity); - return now.getTime(); - } - - /** - * It executes the given request and converts the result into an object of the given type. - * This method will change the response type to 'JSON'. To execute the request, it uses the method {@link #executeRequest(ApacheCloudStackRequest)}. - * To convert the result into an object, it will use {@link Gson#fromJson(String, Class)} - */ - public T executeRequest(ApacheCloudStackRequest request, Class clazz) { - request.addParameter("response", "json"); - String response = executeRequest(request); - return gson.fromJson(response, clazz); - } - - /** - * This configuration enables or disables the HTTPS certification validation. If set to 'false', we will accept self-signed certificates. - * However, this does not mean that we accept certificates that are signed by an untrusted certificated authority. - */ - public void setValidateServerHttpsCertificate(boolean validateServerHttpsCertificate) { - this.validateServerHttpsCertificate = validateServerHttpsCertificate; - } - - public void setRequestValidity(int requestValidity) { - this.requestValidity = requestValidity; - } - - public void setShouldRequestsExpire(boolean shouldRequestsExpire) { - this.shouldRequestsExpire = shouldRequestsExpire; - } - - public void setConnectionTimeout(int connectionTimeout) { - this.connectionTimeout = connectionTimeout; - } - - public void setAcceptAllKindsOfCertificates(boolean acceptAllKindOfCertificates) { - this.acceptAllKindsOfCertificates = acceptAllKindOfCertificates; - } - - @Override - public String toString() { - return String.format("Apache CloudSTackClient for site[%s], parameters: [connectionTimeout=%s, acceptAllKindsOfCertificates=%s, validateServerHttpsCertificate=%s, requestValidity=%d, shouldRequestsExpire=%s]", this.url, - this.connectionTimeout, this.acceptAllKindsOfCertificates, this.validateServerHttpsCertificate, this.requestValidity, this.shouldRequestsExpire); - } + /** + * This flag indicates if we are going to validate the server certificate in case of HTTPS connections. + * The default value is 'true', meaning that we always validate the server HTTPS certificate. + */ + protected boolean validateServerHttpsCertificate = true; + + /** + * This flag is highly dangerous and should never be used with production environments. + * It will accept every single SSL certificates when creating HTTPS connections. Not even the commons name will be checked. + * Therefore, it should be kept only during development phase. + */ + protected boolean acceptAllKindsOfCertificates = false; + + /** + * The validity time of the ACS request. + * The default value is {@value #requestValidity} . + */ + private int requestValidity = 30; + + /** + * The http client connection timeout + * The default value is {@value #connectionTimeout} seconds . + */ + private int connectionTimeout = 60; + + /** + * This parameter controls if the expiration of requests is activated or not. + * It is activated by default. The validity of requests if defined by {@value #requestValidity} property. + */ + private boolean shouldRequestsExpire = true; + + private Gson gson = new GsonBuilder().create(); + private Logger logger = LoggerFactory.getLogger(getClass()); + + /** + * The API URL used to access Apache CloudStack API. + * Ex: https://cloud.domain.com/client/api + */ + private String url; + + /** + * User credentials that can be used to access ApacheCloudStack. + * They can be either a pair of secret key and API key or a triple of username, password and domain + */ + protected ApacheCloudStackUser apacheCloudStackUser; + + public ApacheCloudStackClient(String url, ApacheCloudStackUser apacheCloudStackUser) { + this.url = url; + this.apacheCloudStackUser = apacheCloudStackUser; + + } + + /** + * This method executes the given {@link ApacheCloudStackRequest}. + * It will return the response as a plain {@link String}. + * You should have in mind that if the parameter 'response' is not set, the default is 'XML'. + */ + public String executeRequest(ApacheCloudStackRequest request) { + boolean isSecretKeyApiKeyAuthenticationMechanism = StringUtils.isNotBlank(this.apacheCloudStackUser.getApiKey()); + String urlRequest = createApacheCloudStackApiUrlRequest(request, isSecretKeyApiKeyAuthenticationMechanism); + logger.debug(String.format("Executing request[%s].", urlRequest)); + CloseableHttpClient httpClient = createHttpClient(); + HttpContext httpContext = createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(httpClient, isSecretKeyApiKeyAuthenticationMechanism); + try { + return executeRequestGetResponseAsString(urlRequest, httpClient, httpContext); + } finally { + if (!isSecretKeyApiKeyAuthenticationMechanism) { + executeUserLogout(httpClient, httpContext); + } + HttpClientUtils.closeQuietly(httpClient); + } + } + + /** + * Executes the request with the given {@link HttpContext}. + */ + protected String executeRequestGetResponseAsString(String urlRequest, CloseableHttpClient httpClient, HttpContext httpContext) { + try { + HttpRequestBase httpGetRequest = new HttpGet(urlRequest); + CloseableHttpResponse response = httpClient.execute(httpGetRequest, httpContext); + StatusLine requestStatus = response.getStatusLine(); + if (requestStatus.getStatusCode() == HttpStatus.SC_OK) { + return getResponseAsString(response); + } + throw new ApacheCloudStackClientRequestRuntimeException(requestStatus.getStatusCode(), getResponseAsString(response), urlRequest.toString()); + } catch (IOException e) { + logger.error(String.format("Error while executing request [%s]", urlRequest)); + throw new ApacheCloudStackClientRuntimeException(e); + } + } + + /** + * This method executes the user logout when using username/password/domain authentication. + * The logout is executed calling the 'logout' command of the Apache CloudStack API. + */ + protected void executeUserLogout(CloseableHttpClient httpClient, HttpContext httpContext) { + String urlRequest = createApacheCloudStackApiUrlRequest(new ApacheCloudStackRequest("logout").addParameter("response", "json"), false); + String returnOfLogout = executeRequestGetResponseAsString(urlRequest, httpClient, httpContext); + logger.debug(String.format("Logout result[%s]", returnOfLogout)); + } + + /** + * According to the 'isSecretKeyApiKey AuthenticationMechanism' parameter this method creates an HttpContext that is used when executing requests. + * If the user has provided his/her API/secret keys, we return a {@link BasicHttpContext} object. Otherwise, we authenticate the user with his/her username/password/domain and return an {@link HttpContext} object that contains the authenticated session Id configured as a cookie. + */ + protected HttpContext createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(CloseableHttpClient httpClient, boolean isSecretKeyApiKeyAuthenticationMechanism) { + if (isSecretKeyApiKeyAuthenticationMechanism) { + return new BasicHttpContext(); + } + return createHttpContextWithAuthenticatedSessionUsingUserCredentials(httpClient); + } + + /** + * It creates a {@link RequestConfig} object with configured {@link #connectionTimeout} value. + * This can be used to set on a HttpClient its connect timeout, connection request timeout and socket timeout. + * @return returns the created RequestConfig object + */ + protected RequestConfig createRequestConfig() { + return RequestConfig.custom().setConnectTimeout(connectionTimeout * (int)DateUtils.MILLIS_PER_SECOND) + .setConnectionRequestTimeout(connectionTimeout * (int)DateUtils.MILLIS_PER_SECOND).setSocketTimeout(connectionTimeout * (int)DateUtils.MILLIS_PER_SECOND).build(); + } + + /** + * It creates an {@link CloseableHttpClient} object. + * If {@link #validateServerHttpsCertificate} indicates that we should not validate HTTPS server certificate, we use an insecure SSL factory; the insecure factory is created using {@link #createInsecureSslFactory()}. + */ + protected CloseableHttpClient createHttpClient() { + HttpClientBuilder httpClientBuilder = HttpClientBuilder.create().setDefaultRequestConfig(createRequestConfig()); + if (!validateServerHttpsCertificate) { + SSLConnectionSocketFactory sslsf = createInsecureSslFactory(); + httpClientBuilder.setSSLSocketFactory(sslsf); + } + return httpClientBuilder.build(); + } + + /** + * This method creates an {@link HttpContext} with an authenticated JSESSIONID. + * The authentication is performed using username, password and domain that are provided by the user. + */ + protected HttpContext createHttpContextWithAuthenticatedSessionUsingUserCredentials(CloseableHttpClient httpClient) { + HttpPost httpPost = createHttpPost(); + List params = getParametersForLogin(); + + try { + UrlEncodedFormEntity postParams = new UrlEncodedFormEntity(params, "UTF-8"); + httpPost.setEntity(postParams); + + CloseableHttpResponse loginResponse = httpClient.execute(httpPost); + int statusCode = loginResponse.getStatusLine().getStatusCode(); + if (statusCode != HttpStatus.SC_OK) { + throw new ApacheCloudStackClientRequestRuntimeException(statusCode, getResponseAsString(loginResponse), "login"); + } + logger.debug(String.format("Authentication response:[%s]", getResponseAsString(loginResponse))); + + return createHttpContextWithCookies(loginResponse); + } catch (IOException e) { + throw new ApacheCloudStackClientRuntimeException(e); + } + } + + /** + * It creates an {@link HttpContext} object with a cookie store that will contain the cookies returned by the user in the {@link CloseableHttpResponse} that is received as parameter. + */ + protected HttpContext createHttpContextWithCookies(CloseableHttpResponse loginResponse) { + CookieStore cookieStore = new BasicCookieStore(); + createAndAddCookiesOnStoreForHeaders(cookieStore, loginResponse.getAllHeaders()); + HttpContext httpContext = new BasicHttpContext(); + httpContext.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore); + return httpContext; + } + + /** + * For every header that contains the command 'Set-Cookie' it will call the method {@link #createAndAddCookiesOnStoreForHeader(CookieStore, Header)} + */ + protected void createAndAddCookiesOnStoreForHeaders(CookieStore cookieStore, Header[] allHeaders) { + for (Header header : allHeaders) { + if (StringUtils.startsWithIgnoreCase(header.getName(), "Set-Cookie")) { + createAndAddCookiesOnStoreForHeader(cookieStore, header); + } + } + } + + /** + * This method creates a cookie for every {@link HeaderElement} of the {@link Header} given as parameter. + * Then, it adds this newly created cookie into the {@link CookieStore} provided as parameter. + */ + protected void createAndAddCookiesOnStoreForHeader(CookieStore cookieStore, Header header) { + for (HeaderElement element : header.getElements()) { + BasicClientCookie cookie = createCookieForHeaderElement(element); + cookieStore.addCookie(cookie); + } + } + + /** + * This method will create a {@link BasicClientCookie} with the given {@link HeaderElement}. + * It sill set the cookie's name and value according to the {@link HeaderElement#getName()} and {@link HeaderElement#getValue()} methods. + * Moreover, it will transport every {@link HeaderElement} parameter to the cookie using the {@link BasicClientCookie#setAttribute(String, String)}. + * Additionally, it configures the cookie path ({@link BasicClientCookie#setPath(String)}) to value '/client/api' and the cookie domain using {@link #configureDomainForCookie(BasicClientCookie)} method. + */ + protected BasicClientCookie createCookieForHeaderElement(HeaderElement element) { + BasicClientCookie cookie = new BasicClientCookie(element.getName(), element.getValue()); + for (NameValuePair parameter : element.getParameters()) { + cookie.setAttribute(parameter.getName(), parameter.getValue()); + } + cookie.setPath("/client/api"); + configureDomainForCookie(cookie); + return cookie; + } + + /** + * It configures the cookie domain with the domain of the Apache CloudStack that is being accessed. + * The domain is extracted from {@link #url} variable. + */ + protected void configureDomainForCookie(BasicClientCookie cookie) { + try { + HttpHost httpHost = URIUtils.extractHost(new URI(url)); + String domain = httpHost.getHostName(); + cookie.setDomain(domain); + } catch (URISyntaxException e) { + throw new ApacheCloudStackClientRuntimeException(e); + } + } + + /** + * Creates an {@link HttpPost} object to be sent to Apache CloudStack API. + * The content type configured for this request is 'application/x-www-form-urlencoded'. + */ + protected HttpPost createHttpPost() { + HttpPost httpPost = new HttpPost(url); + httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded"); + return httpPost; + } + + /** + * This method creates a list of {@link NameValuePair} and returns the data for login using username and password. + */ + protected List getParametersForLogin() { + List params = new ArrayList<>(4); + params.add(new BasicNameValuePair("command", "login")); + params.add(new BasicNameValuePair("username", this.apacheCloudStackUser.getUsername())); + params.add(new BasicNameValuePair("password", this.apacheCloudStackUser.getPassword())); + params.add(new BasicNameValuePair("domain", this.apacheCloudStackUser.getDomain())); + return params; + } + + /** + * This method creates an insecure SSL factory that will trust on self signed certificates. + * For that we use {@link TrustSelfSignedStrategy}. + */ + protected SSLConnectionSocketFactory createInsecureSslFactory() { + try { + SSLContextBuilder builder = new SSLContextBuilder(); + builder.loadTrustMaterial(new TrustSelfSignedStrategy()); + SSLContext sc = builder.build(); + + if (acceptAllKindsOfCertificates) { + TrustManager[] trustAllCerts = new TrustManager[1]; + TrustManager tm = new TrustAllManager(); + trustAllCerts[0] = tm; + sc.init(null, trustAllCerts, null); + + HostnameVerifier hostnameVerifier = createInsecureHostNameVerifier(); + return new SSLConnectionSocketFactory(sc, hostnameVerifier); + } + return new SSLConnectionSocketFactory(sc); + } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) { + throw new ApacheCloudStackClientRuntimeException(e); + } + } + + protected HostnameVerifier createInsecureHostNameVerifier() { + HostnameVerifier hostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + return hostnameVerifier; + } + + /** + * This class is used when {@link ApacheCloudStackClient#acceptAllKindsOfCertificates} is set to true. + */ + @SuppressWarnings("unused") + private class TrustAllManager implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager { + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + + public boolean isServerTrusted(final X509Certificate[] certs) { + return true; + } + + public boolean isClientTrusted(final X509Certificate[] certs) { + return true; + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { + return; + } + + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { + return; + } + } + + /** + * It retrieves the response status as a {@link String} + */ + protected String getResponseAsString(CloseableHttpResponse response) throws IOException { + InputStream responseContent = response.getEntity().getContent(); + StringWriter writer = new StringWriter(); + IOUtils.copy(responseContent, writer, Charset.defaultCharset()); + + responseContent.close(); + response.close(); + return writer.toString(); + } + + /** + * This method creates transforms the given {@link ApacheCloudStackRequest} into a URL requeest for the Apache CloudStack API. + * Therefore, it will create a command query string following the CloudStack specifications using method {@link #createCommandString(ApacheCloudStackRequest)}; + * and then, if it needs, it creates the signature using the method {@link #createSignature(String)} and append it to the URL. + */ + protected String createApacheCloudStackApiUrlRequest(ApacheCloudStackRequest request, boolean shouldSignAppendSignature) { + StringBuilder urlRequest = new StringBuilder(url).append("?"); + + String queryString = createCommandString(request); + urlRequest.append(queryString); + + if (shouldSignAppendSignature) { + String signature = createSignature(queryString); + urlRequest.append("&signature=").append(getUrlEncodedValue(signature)); + } + return urlRequest.toString(); + } + + /** + * Creates a signature (HMAC-sha1) with the {@link #ApacheCloudStackUser#getSecretKey()} and the given queryString + * The returner signature is encoded in Base64. + */ + protected String createSignature(String queryString) { + byte[] signatureBytes = HmacUtils.hmacSha1(apacheCloudStackUser.getSecretKey(), queryString.toLowerCase()); + return Base64.encodeBase64String(signatureBytes); + } + + /** + * It creates the command query string, placing the parameters in alphabetical order. + * To execute the sorting, it uses the {@link #createSortedCommandQueryList(ApacheCloudStackRequest)} method. + */ + protected String createCommandString(ApacheCloudStackRequest request) { + List queryCommand = createSortedCommandQueryList(request); + + StringBuilder commandString = new StringBuilder(); + for (ApacheCloudStackApiCommandParameter param : queryCommand) { + String value = getUrlEncodedValue(param.getValue()); + commandString.append(String.format("%s=%s&", param.getName(), value)); + } + return commandString.toString().substring(0, commandString.length() - 1); + } + + /** + * This method encodes the parameter value as specified by Apache CloudStack + */ + protected String getUrlEncodedValue(Object paramValue) { + String value = Objects.toString(paramValue); + try { + value = URLEncoder.encode(value, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new ApacheCloudStackClientRuntimeException(e); + } + return value.replaceAll("\\+", "%20"); + } + + /** + * This methods adds the final data needed to the command query. + * It will add a parameter called 'command' with the value of {@link ApacheCloudStackRequest#getCommand()} as value. + * It also adds a parameter called 'apiKey', with the value of {@link #ApacheCloudStackUser#getApiKey()} as value. + * Then, it will sort the parameters that are in a list in alphabetical order. + */ + protected List createSortedCommandQueryList(ApacheCloudStackRequest request) { + List queryCommand = new ArrayList<>(); + queryCommand.addAll(request.getParameters()); + queryCommand.add(new ApacheCloudStackApiCommandParameter("command", request.getCommand())); + if (StringUtils.isNotBlank(this.apacheCloudStackUser.getApiKey())) { + queryCommand.add(new ApacheCloudStackApiCommandParameter("apiKey", this.apacheCloudStackUser.getApiKey())); + } + configureRequestExpiration(queryCommand); + Collections.sort(queryCommand); + return queryCommand; + } + + /** + * This method configures the request expiration if needed. + * It uses the value defined at {@link #requestValidity} to determine until when the request is valid. + * It also uses the parameter {@link #shouldRequestsExpire} to decide if it has to configure or not the validity of the request. + * Moreover, if the 'apacheCloudStackRequestList' contains the 'expires' it will only add a parameter called 'signatureVersion=3', in order to enable that override. + */ + protected void configureRequestExpiration(List apacheCloudStackRequestList) { + boolean isOverridingExpirationConfigs = apacheCloudStackRequestList.contains(new ApacheCloudStackApiCommandParameter("expires", StringUtils.EMPTY)); + if (!isOverridingExpirationConfigs && !shouldRequestsExpire) { + return; + } + apacheCloudStackRequestList.add(new ApacheCloudStackApiCommandParameter("signatureVersion", 3)); + if (isOverridingExpirationConfigs) { + return; + } + String expirationDataAsSring = createExpirationDate(); + apacheCloudStackRequestList.add(new ApacheCloudStackApiCommandParameter("expires", expirationDataAsSring)); + } + + /** + * This method creates the expiration date as a string according to the ISO 8601. + */ + protected String createExpirationDate() { + DateFormat acsIso8601DateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + return acsIso8601DateFormat.format(getExpirationDate()); + } + + /** + * Creates the expiration date, by adding the {@link #requestValidity} to the current time. + */ + protected Date getExpirationDate() { + Calendar now = Calendar.getInstance(); + now.add(Calendar.SECOND, requestValidity); + return now.getTime(); + } + + /** + * It executes the given request and converts the result into an object of the given type. + * This method will change the response type to 'JSON'. To execute the request, it uses the method {@link #executeRequest(ApacheCloudStackRequest)}. + * To convert the result into an object, it will use {@link Gson#fromJson(String, Class)} + */ + public T executeRequest(ApacheCloudStackRequest request, Class clazz) { + request.addParameter("response", "json"); + String response = executeRequest(request); + return gson.fromJson(response, clazz); + } + + /** + * This configuration enables or disables the HTTPS certification validation. If set to 'false', we will accept self-signed certificates. + * However, this does not mean that we accept certificates that are signed by an untrusted certificated authority. + */ + public void setValidateServerHttpsCertificate(boolean validateServerHttpsCertificate) { + this.validateServerHttpsCertificate = validateServerHttpsCertificate; + } + + public void setRequestValidity(int requestValidity) { + this.requestValidity = requestValidity; + } + + public void setShouldRequestsExpire(boolean shouldRequestsExpire) { + this.shouldRequestsExpire = shouldRequestsExpire; + } + + public void setConnectionTimeout(int connectionTimeout) { + this.connectionTimeout = connectionTimeout; + } + + public void setAcceptAllKindsOfCertificates(boolean acceptAllKindOfCertificates) { + this.acceptAllKindsOfCertificates = acceptAllKindOfCertificates; + } + + @Override + public String toString() { + return String.format( + "Apache CloudSTackClient for site[%s], parameters: [connectionTimeout=%s, acceptAllKindsOfCertificates=%s, validateServerHttpsCertificate=%s, requestValidity=%d, shouldRequestsExpire=%s]", + this.url, this.connectionTimeout, this.acceptAllKindsOfCertificates, this.validateServerHttpsCertificate, this.requestValidity, this.shouldRequestsExpire); + } } diff --git a/src/test/java/br/com/autonomiccs/apacheCloudStack/client/ApacheCloudStackClientTest.java b/src/test/java/br/com/autonomiccs/apacheCloudStack/client/ApacheCloudStackClientTest.java index ae97118..992668c 100644 --- a/src/test/java/br/com/autonomiccs/apacheCloudStack/client/ApacheCloudStackClientTest.java +++ b/src/test/java/br/com/autonomiccs/apacheCloudStack/client/ApacheCloudStackClientTest.java @@ -72,590 +72,594 @@ @RunWith(MockitoJUnitRunner.class) public class ApacheCloudStackClientTest { - private ApacheCloudStackClient apacheCloudStackClient; - - @Mock - private ApacheCloudStackUser apacheCloudStackUser; - - private String cloudStackDomain = "cloud.domain.com"; - private String cloudStackUrl = "https://" + cloudStackDomain + "/client/api"; - - @Before - public void setup() { - apacheCloudStackClient = Mockito.spy(new ApacheCloudStackClient(cloudStackUrl, apacheCloudStackUser)); - } - - @Test - public void executeRequestTest() throws ClientProtocolException, IOException { - configureMocksExecuteTestAndVerifyForMethodExecuteRequest(200); - } - - @Test(expected = ApacheCloudStackClientRequestRuntimeException.class) - public void executeRequestTestRequestStatusDifferentFromHttpStatusOk() throws ClientProtocolException, IOException { - configureMocksExecuteTestAndVerifyForMethodExecuteRequest(500); - } - - private void configureMocksExecuteTestAndVerifyForMethodExecuteRequest(int requestStatusCode) throws IOException, ClientProtocolException { - Mockito.doReturn(cloudStackUrl).when(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(true)); - - CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); - HttpContext httpContextMock = Mockito.mock(HttpContext.class); - CloseableHttpResponse closeableHttpResponseMock = Mockito.mock(CloseableHttpResponse.class); - StatusLine statusLineMock = Mockito.mock(StatusLine.class); - - Mockito.when(statusLineMock.getStatusCode()).thenReturn(requestStatusCode); - Mockito.when(closeableHttpResponseMock.getStatusLine()).thenReturn(statusLineMock); - Mockito.when(httpClientMock.execute(Mockito.any(HttpGet.class), Mockito.eq(httpContextMock))).thenReturn(closeableHttpResponseMock); - Mockito.when(apacheCloudStackClient.createHttpClient()).thenReturn(httpClientMock); - Mockito.when(apacheCloudStackClient.apacheCloudStackUser.getApiKey()).thenReturn("apiKey"); - Mockito.doReturn(httpContextMock).when(apacheCloudStackClient).createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(Mockito.eq(httpClientMock), Mockito.eq(true)); - String responseString = "responseAsString"; - Mockito.doReturn(responseString).when(apacheCloudStackClient).getResponseAsString(Mockito.eq(closeableHttpResponseMock)); - - String returnOfExecuteRequest = apacheCloudStackClient.executeRequest(Mockito.mock(ApacheCloudStackRequest.class)); - Assert.assertEquals(responseString, returnOfExecuteRequest); - - InOrder inOrder = Mockito.inOrder(apacheCloudStackClient, httpClientMock, closeableHttpResponseMock, statusLineMock); - inOrder.verify(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(true)); - inOrder.verify(apacheCloudStackClient).createHttpClient(); - inOrder.verify(httpClientMock).execute(Mockito.any(HttpGet.class), Mockito.eq(httpContextMock)); - inOrder.verify(closeableHttpResponseMock).getStatusLine(); - inOrder.verify(statusLineMock).getStatusCode(); - inOrder.verify(httpClientMock).close(); - } - - @Test(expected = ApacheCloudStackClientRuntimeException.class) - public void executeRequestTestExceptionWhenExecutingRequest() throws IOException, ClientProtocolException { - Mockito.doReturn(cloudStackUrl).when(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(true)); - - CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); - - Mockito.when(httpClientMock.execute(Mockito.any(HttpGet.class))).thenThrow(new IOException()); - Mockito.when(apacheCloudStackClient.createHttpClient()).thenReturn(httpClientMock); - - apacheCloudStackClient.executeRequest(Mockito.mock(ApacheCloudStackRequest.class)); - Mockito.verify(httpClientMock).close(); - } - - private void testRequestConfig(final RequestConfig config, final int timeout) { - Assert.assertEquals(config.getConnectTimeout(), timeout * (int)DateUtils.MILLIS_PER_SECOND); - Assert.assertEquals(config.getConnectionRequestTimeout(), timeout * (int)DateUtils.MILLIS_PER_SECOND); - Assert.assertEquals(config.getSocketTimeout(), timeout * (int)DateUtils.MILLIS_PER_SECOND); - } - - @Test - public void createRequestConfigDefaultTest() { - RequestConfig config = apacheCloudStackClient.createRequestConfig(); - testRequestConfig(config, 60); - } - - @Test - public void createRequestConfigCustomValueTest() { - int timeout = 30; - apacheCloudStackClient.setConnectionTimeout(timeout); - RequestConfig config = apacheCloudStackClient.createRequestConfig(); - testRequestConfig(config, timeout); - } - - @Test - public void createHttpClientTestValidateServerHttpsCertificateTrueAndTotalInsecureFalse() { - configureExecuteAndVerifyTestForCreateHttpClient(true, 0, false, 0); - } - - @Test - public void createHttpClientTestValidateServerHttpsCertificateTrueAndTotalInsecureTrue() { - configureExecuteAndVerifyTestForCreateHttpClient(true, 0, true, 0); - } - - @Test - public void createHttpClientTestValidateServerHttpsCertificateFalseAndTotalInsecureFalse() { - configureExecuteAndVerifyTestForCreateHttpClient(false, 1, false, 0); - } - - @Test - public void createHttpClientTestValidateServerHttpsCertificateFalseAndTotalInsecureTrue() { - configureExecuteAndVerifyTestForCreateHttpClient(false, 1, true, 1); - } - - private void configureExecuteAndVerifyTestForCreateHttpClient(boolean shouldVerifyServerCertificates, int numberOfCreateUnsecureSslFactoryCalls, boolean totalInsecure, int expectedCallForInsecureHostNameCheck) { - apacheCloudStackClient.validateServerHttpsCertificate = shouldVerifyServerCertificates; - apacheCloudStackClient.acceptAllKindsOfCertificates = totalInsecure; - - CloseableHttpClient httpClient = apacheCloudStackClient.createHttpClient(); - - Assert.assertNotNull(httpClient); - Mockito.verify(apacheCloudStackClient, Mockito.times(1)).createRequestConfig(); - Mockito.verify(apacheCloudStackClient, Mockito.times(expectedCallForInsecureHostNameCheck)).createInsecureHostNameVerifier(); - Mockito.verify(apacheCloudStackClient, Mockito.times(numberOfCreateUnsecureSslFactoryCalls)).createInsecureSslFactory(); - } - - @Test - public void getResponseAsStringTest() throws UnsupportedOperationException, IOException { - String responseTest = "teste response"; - - CloseableHttpResponse closeableHttpResponseMock = Mockito.mock(CloseableHttpResponse.class); - HttpEntity httpEntityMock = Mockito.mock(HttpEntity.class); - - InputStream is = new ByteArrayInputStream(responseTest.getBytes()); - - Mockito.doReturn(is).when(httpEntityMock).getContent(); - Mockito.doReturn(httpEntityMock).when(closeableHttpResponseMock).getEntity(); - - String responseAsString = apacheCloudStackClient.getResponseAsString(closeableHttpResponseMock); - - Assert.assertEquals(responseTest, responseAsString); - } - - @Test - public void createApacheCloudStackApiUrlRequestTestWithSignature() { - ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); - - String queryString = "queryString"; - Mockito.doReturn(queryString).when(apacheCloudStackClient).createCommandString(Mockito.eq(apacheCloudStackRequestMock)); - - String signatureValue = "signatureValue"; - Mockito.doReturn(signatureValue).when(apacheCloudStackClient).createSignature(Mockito.eq(queryString)); - - String urlRequestReturned = apacheCloudStackClient.createApacheCloudStackApiUrlRequest(apacheCloudStackRequestMock, true); - Assert.assertEquals(cloudStackUrl + "?" + queryString + "&signature=" + signatureValue, urlRequestReturned); - - InOrder inOrder = Mockito.inOrder(apacheCloudStackClient); - inOrder.verify(apacheCloudStackClient).createCommandString(Mockito.eq(apacheCloudStackRequestMock)); - inOrder.verify(apacheCloudStackClient).createSignature(Mockito.eq(queryString)); - inOrder.verify(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(signatureValue)); - } - - @Test - public void createApacheCloudStackApiUrlRequestTestWithoutSignature() { - ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); - - String queryString = "queryString"; - Mockito.doReturn(queryString).when(apacheCloudStackClient).createCommandString(Mockito.eq(apacheCloudStackRequestMock)); - - String urlRequestReturned = apacheCloudStackClient.createApacheCloudStackApiUrlRequest(apacheCloudStackRequestMock, false); - Assert.assertEquals(cloudStackUrl + "?" + queryString, urlRequestReturned); - - InOrder inOrder = Mockito.inOrder(apacheCloudStackClient); - inOrder.verify(apacheCloudStackClient).createCommandString(Mockito.eq(apacheCloudStackRequestMock)); - inOrder.verify(apacheCloudStackClient, Mockito.times(0)).createSignature(Mockito.eq(queryString)); - inOrder.verify(apacheCloudStackClient, Mockito.times(0)).getUrlEncodedValue(Mockito.anyString()); - } - - @Test - public void createSignatureTest() { - String expectedSignature = "wqtSA/cANcWnWlh/ukfnaExyM54="; - Mockito.doReturn("secretKey").when(apacheCloudStackUser).getSecretKey(); - - String signature = apacheCloudStackClient.createSignature("queryString"); + private ApacheCloudStackClient apacheCloudStackClient; + + @Mock + private ApacheCloudStackUser apacheCloudStackUser; + + private String cloudStackDomain = "cloud.domain.com"; + private String cloudStackUrl = "https://" + cloudStackDomain + "/client/api"; + + @Before + public void setup() { + apacheCloudStackClient = Mockito.spy(new ApacheCloudStackClient(cloudStackUrl, apacheCloudStackUser)); + } + + @Test + public void executeRequestTest() throws ClientProtocolException, IOException { + configureMocksExecuteTestAndVerifyForMethodExecuteRequest(200); + } + + @Test(expected = ApacheCloudStackClientRequestRuntimeException.class) + public void executeRequestTestRequestStatusDifferentFromHttpStatusOk() throws ClientProtocolException, IOException { + configureMocksExecuteTestAndVerifyForMethodExecuteRequest(500); + } + + private void configureMocksExecuteTestAndVerifyForMethodExecuteRequest(int requestStatusCode) throws IOException, ClientProtocolException { + Mockito.doReturn(cloudStackUrl).when(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(true)); + + CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); + HttpContext httpContextMock = Mockito.mock(HttpContext.class); + CloseableHttpResponse closeableHttpResponseMock = Mockito.mock(CloseableHttpResponse.class); + StatusLine statusLineMock = Mockito.mock(StatusLine.class); + + Mockito.when(statusLineMock.getStatusCode()).thenReturn(requestStatusCode); + Mockito.when(closeableHttpResponseMock.getStatusLine()).thenReturn(statusLineMock); + Mockito.when(httpClientMock.execute(Mockito.any(HttpGet.class), Mockito.eq(httpContextMock))).thenReturn(closeableHttpResponseMock); + Mockito.when(apacheCloudStackClient.createHttpClient()).thenReturn(httpClientMock); + Mockito.when(apacheCloudStackClient.apacheCloudStackUser.getApiKey()).thenReturn("apiKey"); + Mockito.doReturn(httpContextMock).when(apacheCloudStackClient).createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(Mockito.eq(httpClientMock), + Mockito.eq(true)); + String responseString = "responseAsString"; + Mockito.doReturn(responseString).when(apacheCloudStackClient).getResponseAsString(Mockito.eq(closeableHttpResponseMock)); + + String returnOfExecuteRequest = apacheCloudStackClient.executeRequest(Mockito.mock(ApacheCloudStackRequest.class)); + Assert.assertEquals(responseString, returnOfExecuteRequest); + + InOrder inOrder = Mockito.inOrder(apacheCloudStackClient, httpClientMock, closeableHttpResponseMock, statusLineMock); + inOrder.verify(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(true)); + inOrder.verify(apacheCloudStackClient).createHttpClient(); + inOrder.verify(httpClientMock).execute(Mockito.any(HttpGet.class), Mockito.eq(httpContextMock)); + inOrder.verify(closeableHttpResponseMock).getStatusLine(); + inOrder.verify(statusLineMock).getStatusCode(); + inOrder.verify(httpClientMock).close(); + } + + @Test(expected = ApacheCloudStackClientRuntimeException.class) + public void executeRequestTestExceptionWhenExecutingRequest() throws IOException, ClientProtocolException { + Mockito.doReturn(cloudStackUrl).when(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(true)); + + CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); + + Mockito.when(httpClientMock.execute(Mockito.any(HttpGet.class))).thenThrow(new IOException()); + Mockito.when(apacheCloudStackClient.createHttpClient()).thenReturn(httpClientMock); + + apacheCloudStackClient.executeRequest(Mockito.mock(ApacheCloudStackRequest.class)); + Mockito.verify(httpClientMock).close(); + } + + private void testRequestConfig(final RequestConfig config, final int timeout) { + Assert.assertEquals(config.getConnectTimeout(), timeout * (int)DateUtils.MILLIS_PER_SECOND); + Assert.assertEquals(config.getConnectionRequestTimeout(), timeout * (int)DateUtils.MILLIS_PER_SECOND); + Assert.assertEquals(config.getSocketTimeout(), timeout * (int)DateUtils.MILLIS_PER_SECOND); + } + + @Test + public void createRequestConfigDefaultTest() { + RequestConfig config = apacheCloudStackClient.createRequestConfig(); + testRequestConfig(config, 60); + } + + @Test + public void createRequestConfigCustomValueTest() { + int timeout = 30; + apacheCloudStackClient.setConnectionTimeout(timeout); + RequestConfig config = apacheCloudStackClient.createRequestConfig(); + testRequestConfig(config, timeout); + } + + @Test + public void createHttpClientTestValidateServerHttpsCertificateTrueAndTotalInsecureFalse() { + configureExecuteAndVerifyTestForCreateHttpClient(true, 0, false, 0); + } + + @Test + public void createHttpClientTestValidateServerHttpsCertificateTrueAndTotalInsecureTrue() { + configureExecuteAndVerifyTestForCreateHttpClient(true, 0, true, 0); + } + + @Test + public void createHttpClientTestValidateServerHttpsCertificateFalseAndTotalInsecureFalse() { + configureExecuteAndVerifyTestForCreateHttpClient(false, 1, false, 0); + } + + @Test + public void createHttpClientTestValidateServerHttpsCertificateFalseAndTotalInsecureTrue() { + configureExecuteAndVerifyTestForCreateHttpClient(false, 1, true, 1); + } + + private void configureExecuteAndVerifyTestForCreateHttpClient(boolean shouldVerifyServerCertificates, int numberOfCreateUnsecureSslFactoryCalls, boolean totalInsecure, + int expectedCallForInsecureHostNameCheck) { + apacheCloudStackClient.validateServerHttpsCertificate = shouldVerifyServerCertificates; + apacheCloudStackClient.acceptAllKindsOfCertificates = totalInsecure; + + CloseableHttpClient httpClient = apacheCloudStackClient.createHttpClient(); + + Assert.assertNotNull(httpClient); + Mockito.verify(apacheCloudStackClient, Mockito.times(1)).createRequestConfig(); + Mockito.verify(apacheCloudStackClient, Mockito.times(expectedCallForInsecureHostNameCheck)).createInsecureHostNameVerifier(); + Mockito.verify(apacheCloudStackClient, Mockito.times(numberOfCreateUnsecureSslFactoryCalls)).createInsecureSslFactory(); + } + + @Test + public void getResponseAsStringTest() throws UnsupportedOperationException, IOException { + String responseTest = "teste response"; + + CloseableHttpResponse closeableHttpResponseMock = Mockito.mock(CloseableHttpResponse.class); + HttpEntity httpEntityMock = Mockito.mock(HttpEntity.class); + + InputStream is = new ByteArrayInputStream(responseTest.getBytes()); + + Mockito.doReturn(is).when(httpEntityMock).getContent(); + Mockito.doReturn(httpEntityMock).when(closeableHttpResponseMock).getEntity(); + + String responseAsString = apacheCloudStackClient.getResponseAsString(closeableHttpResponseMock); + + Assert.assertEquals(responseTest, responseAsString); + } + + @Test + public void createApacheCloudStackApiUrlRequestTestWithSignature() { + ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); + + String queryString = "queryString"; + Mockito.doReturn(queryString).when(apacheCloudStackClient).createCommandString(Mockito.eq(apacheCloudStackRequestMock)); + + String signatureValue = "signatureValue"; + Mockito.doReturn(signatureValue).when(apacheCloudStackClient).createSignature(Mockito.eq(queryString)); + + String urlRequestReturned = apacheCloudStackClient.createApacheCloudStackApiUrlRequest(apacheCloudStackRequestMock, true); + Assert.assertEquals(cloudStackUrl + "?" + queryString + "&signature=" + signatureValue, urlRequestReturned); + + InOrder inOrder = Mockito.inOrder(apacheCloudStackClient); + inOrder.verify(apacheCloudStackClient).createCommandString(Mockito.eq(apacheCloudStackRequestMock)); + inOrder.verify(apacheCloudStackClient).createSignature(Mockito.eq(queryString)); + inOrder.verify(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(signatureValue)); + } + + @Test + public void createApacheCloudStackApiUrlRequestTestWithoutSignature() { + ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); + + String queryString = "queryString"; + Mockito.doReturn(queryString).when(apacheCloudStackClient).createCommandString(Mockito.eq(apacheCloudStackRequestMock)); + + String urlRequestReturned = apacheCloudStackClient.createApacheCloudStackApiUrlRequest(apacheCloudStackRequestMock, false); + Assert.assertEquals(cloudStackUrl + "?" + queryString, urlRequestReturned); + + InOrder inOrder = Mockito.inOrder(apacheCloudStackClient); + inOrder.verify(apacheCloudStackClient).createCommandString(Mockito.eq(apacheCloudStackRequestMock)); + inOrder.verify(apacheCloudStackClient, Mockito.times(0)).createSignature(Mockito.eq(queryString)); + inOrder.verify(apacheCloudStackClient, Mockito.times(0)).getUrlEncodedValue(Mockito.anyString()); + } + + @Test + public void createSignatureTest() { + String expectedSignature = "wqtSA/cANcWnWlh/ukfnaExyM54="; + Mockito.doReturn("secretKey").when(apacheCloudStackUser).getSecretKey(); + + String signature = apacheCloudStackClient.createSignature("queryString"); - Assert.assertEquals(expectedSignature, signature); - } + Assert.assertEquals(expectedSignature, signature); + } - @Test - public void createCommandStringTest() { - List params = new ArrayList<>(); - String valueParam1 = "value1"; - String valueParam2 = "value2 espaço"; - params.add(new ApacheCloudStackApiCommandParameter("param1", valueParam1)); - params.add(new ApacheCloudStackApiCommandParameter("param2", valueParam2)); + @Test + public void createCommandStringTest() { + List params = new ArrayList<>(); + String valueParam1 = "value1"; + String valueParam2 = "value2 espaço"; + params.add(new ApacheCloudStackApiCommandParameter("param1", valueParam1)); + params.add(new ApacheCloudStackApiCommandParameter("param2", valueParam2)); - String expectedCommandSrting = "param1=value1¶m2=value2 espaço"; + String expectedCommandSrting = "param1=value1¶m2=value2 espaço"; - ApacheCloudStackRequest ApacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); - Mockito.doReturn(params).when(apacheCloudStackClient).createSortedCommandQueryList(Mockito.eq(ApacheCloudStackRequestMock)); - Mockito.doReturn(valueParam1).when(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(valueParam1)); - Mockito.doReturn(valueParam2).when(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(valueParam2)); + ApacheCloudStackRequest ApacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); + Mockito.doReturn(params).when(apacheCloudStackClient).createSortedCommandQueryList(Mockito.eq(ApacheCloudStackRequestMock)); + Mockito.doReturn(valueParam1).when(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(valueParam1)); + Mockito.doReturn(valueParam2).when(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(valueParam2)); - String commandStringReturned = apacheCloudStackClient.createCommandString(ApacheCloudStackRequestMock); - Assert.assertEquals(expectedCommandSrting, commandStringReturned); + String commandStringReturned = apacheCloudStackClient.createCommandString(ApacheCloudStackRequestMock); + Assert.assertEquals(expectedCommandSrting, commandStringReturned); - InOrder inOrder = Mockito.inOrder(apacheCloudStackClient); - inOrder.verify(apacheCloudStackClient).createSortedCommandQueryList(Mockito.eq(ApacheCloudStackRequestMock)); - inOrder.verify(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(valueParam1)); - inOrder.verify(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(valueParam2)); + InOrder inOrder = Mockito.inOrder(apacheCloudStackClient); + inOrder.verify(apacheCloudStackClient).createSortedCommandQueryList(Mockito.eq(ApacheCloudStackRequestMock)); + inOrder.verify(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(valueParam1)); + inOrder.verify(apacheCloudStackClient).getUrlEncodedValue(Mockito.eq(valueParam2)); - } + } - @Test - public void getUrlEncodedValueTestNullValue() { - String urlEncodedValueReturned = apacheCloudStackClient.getUrlEncodedValue(null); - Assert.assertEquals("null", urlEncodedValueReturned); - } + @Test + public void getUrlEncodedValueTestNullValue() { + String urlEncodedValueReturned = apacheCloudStackClient.getUrlEncodedValue(null); + Assert.assertEquals("null", urlEncodedValueReturned); + } - @Test - public void getUrlEncodedValueTestNonSpecialCharactersValue() { - String urlEncodedValueReturned = apacheCloudStackClient.getUrlEncodedValue("test"); - Assert.assertEquals("test", urlEncodedValueReturned); - } + @Test + public void getUrlEncodedValueTestNonSpecialCharactersValue() { + String urlEncodedValueReturned = apacheCloudStackClient.getUrlEncodedValue("test"); + Assert.assertEquals("test", urlEncodedValueReturned); + } - @Test - public void getUrlEncodedValueTestValueWithSpaces() { - String urlEncodedValueReturned = apacheCloudStackClient.getUrlEncodedValue("test value"); - Assert.assertEquals("test%20value", urlEncodedValueReturned); - } + @Test + public void getUrlEncodedValueTestValueWithSpaces() { + String urlEncodedValueReturned = apacheCloudStackClient.getUrlEncodedValue("test value"); + Assert.assertEquals("test%20value", urlEncodedValueReturned); + } - @Test - @SuppressWarnings("unchecked") - public void createSortedCommandQueryListTestWithApiKey() { - ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); - Set params = new HashSet<>(); + @Test + @SuppressWarnings("unchecked") + public void createSortedCommandQueryListTestWithApiKey() { + ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); + Set params = new HashSet<>(); - params.add(new ApacheCloudStackApiCommandParameter("param1", "value1")); - Mockito.doReturn(params).when(apacheCloudStackRequestMock).getParameters(); - Mockito.when(apacheCloudStackClient.apacheCloudStackUser.getApiKey()).thenReturn("apiKey"); - Mockito.doNothing().when(apacheCloudStackClient).configureRequestExpiration(Mockito.anyList()); + params.add(new ApacheCloudStackApiCommandParameter("param1", "value1")); + Mockito.doReturn(params).when(apacheCloudStackRequestMock).getParameters(); + Mockito.when(apacheCloudStackClient.apacheCloudStackUser.getApiKey()).thenReturn("apiKey"); + Mockito.doNothing().when(apacheCloudStackClient).configureRequestExpiration(Mockito.anyList()); - List sortedCommandQueryList = apacheCloudStackClient.createSortedCommandQueryList(apacheCloudStackRequestMock); + List sortedCommandQueryList = apacheCloudStackClient.createSortedCommandQueryList(apacheCloudStackRequestMock); - Mockito.verify(apacheCloudStackRequestMock).getParameters(); - Mockito.verify(apacheCloudStackClient).configureRequestExpiration(Mockito.anyList()); + Mockito.verify(apacheCloudStackRequestMock).getParameters(); + Mockito.verify(apacheCloudStackClient).configureRequestExpiration(Mockito.anyList()); - Assert.assertEquals(3, sortedCommandQueryList.size()); - Assert.assertEquals("apiKey", sortedCommandQueryList.get(0).getName()); - Assert.assertEquals("command", sortedCommandQueryList.get(1).getName()); - Assert.assertEquals("param1", sortedCommandQueryList.get(2).getName()); - } + Assert.assertEquals(3, sortedCommandQueryList.size()); + Assert.assertEquals("apiKey", sortedCommandQueryList.get(0).getName()); + Assert.assertEquals("command", sortedCommandQueryList.get(1).getName()); + Assert.assertEquals("param1", sortedCommandQueryList.get(2).getName()); + } - @Test - @SuppressWarnings("unchecked") - public void createSortedCommandQueryListTestWithourApiKey() { - ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); - Set params = new HashSet<>(); - - params.add(new ApacheCloudStackApiCommandParameter("param1", "value1")); - Mockito.doReturn(params).when(apacheCloudStackRequestMock).getParameters(); - Mockito.when(apacheCloudStackClient.apacheCloudStackUser.getApiKey()).thenReturn(null); - Mockito.doNothing().when(apacheCloudStackClient).configureRequestExpiration(Mockito.anyList()); - - List sortedCommandQueryList = apacheCloudStackClient.createSortedCommandQueryList(apacheCloudStackRequestMock); - - Mockito.verify(apacheCloudStackRequestMock).getParameters(); - Mockito.verify(apacheCloudStackClient).configureRequestExpiration(Mockito.anyList()); + @Test + @SuppressWarnings("unchecked") + public void createSortedCommandQueryListTestWithourApiKey() { + ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); + Set params = new HashSet<>(); + + params.add(new ApacheCloudStackApiCommandParameter("param1", "value1")); + Mockito.doReturn(params).when(apacheCloudStackRequestMock).getParameters(); + Mockito.when(apacheCloudStackClient.apacheCloudStackUser.getApiKey()).thenReturn(null); + Mockito.doNothing().when(apacheCloudStackClient).configureRequestExpiration(Mockito.anyList()); + + List sortedCommandQueryList = apacheCloudStackClient.createSortedCommandQueryList(apacheCloudStackRequestMock); + + Mockito.verify(apacheCloudStackRequestMock).getParameters(); + Mockito.verify(apacheCloudStackClient).configureRequestExpiration(Mockito.anyList()); + + Assert.assertEquals(2, sortedCommandQueryList.size()); + Assert.assertEquals("command", sortedCommandQueryList.get(0).getName()); + Assert.assertEquals("param1", sortedCommandQueryList.get(1).getName()); + } - Assert.assertEquals(2, sortedCommandQueryList.size()); - Assert.assertEquals("command", sortedCommandQueryList.get(0).getName()); - Assert.assertEquals("param1", sortedCommandQueryList.get(1).getName()); - } + @Test + public void executeRequestAutoConvertReturnToJavaObject() { + String jsonTest = "{attr1: 1, attr2: 'test'}"; - @Test - public void executeRequestAutoConvertReturnToJavaObject() { - String jsonTest = "{attr1: 1, attr2: 'test'}"; + ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); + Mockito.doReturn(jsonTest).when(apacheCloudStackClient).executeRequest(Mockito.eq(apacheCloudStackRequestMock)); - ApacheCloudStackRequest apacheCloudStackRequestMock = Mockito.mock(ApacheCloudStackRequest.class); - Mockito.doReturn(jsonTest).when(apacheCloudStackClient).executeRequest(Mockito.eq(apacheCloudStackRequestMock)); + TestExecuteReturnObject returnedObject = apacheCloudStackClient.executeRequest(apacheCloudStackRequestMock, TestExecuteReturnObject.class); - TestExecuteReturnObject returnedObject = apacheCloudStackClient.executeRequest(apacheCloudStackRequestMock, TestExecuteReturnObject.class); + Mockito.verify(apacheCloudStackClient).executeRequest(Mockito.eq(apacheCloudStackRequestMock)); - Mockito.verify(apacheCloudStackClient).executeRequest(Mockito.eq(apacheCloudStackRequestMock)); + Assert.assertNotNull(returnedObject); + Assert.assertTrue(returnedObject instanceof TestExecuteReturnObject); - Assert.assertNotNull(returnedObject); - Assert.assertTrue(returnedObject instanceof TestExecuteReturnObject); + Assert.assertEquals(1, returnedObject.attr1); + Assert.assertEquals("test", returnedObject.attr2); - Assert.assertEquals(1, returnedObject.attr1); - Assert.assertEquals("test", returnedObject.attr2); + } - } + private class TestExecuteReturnObject { + private int attr1; + private String attr2; + } - private class TestExecuteReturnObject { - private int attr1; - private String attr2; - } + @Test + public void createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeededTestAuthenticationWithApiKeyAndSecretKey() { + CloseableHttpClient closeableHttpClientMock = Mockito.mock(CloseableHttpClient.class); + HttpContext basicHttpContext = apacheCloudStackClient.createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(closeableHttpClientMock, true); - @Test - public void createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeededTestAuthenticationWithApiKeyAndSecretKey() { - CloseableHttpClient closeableHttpClientMock = Mockito.mock(CloseableHttpClient.class); - HttpContext basicHttpContext = apacheCloudStackClient.createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(closeableHttpClientMock, true); + Mockito.verify(apacheCloudStackClient, Mockito.times(0)).createHttpContextWithAuthenticatedSessionUsingUserCredentials(Mockito.any(closeableHttpClientMock.getClass())); + Assert.assertNotNull(basicHttpContext); + } - Mockito.verify(apacheCloudStackClient, Mockito.times(0)).createHttpContextWithAuthenticatedSessionUsingUserCredentials(Mockito.any(closeableHttpClientMock.getClass())); - Assert.assertNotNull(basicHttpContext); - } + @Test + public void createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeededTestAuthenticationWithUsernameAndPassword() { + CloseableHttpClient closeableHttpClientMock = Mockito.mock(CloseableHttpClient.class); + HttpContext httpContextMock = Mockito.mock(HttpContext.class); + Mockito.doReturn(httpContextMock).when(apacheCloudStackClient) + .createHttpContextWithAuthenticatedSessionUsingUserCredentials(Mockito.any(closeableHttpClientMock.getClass())); + HttpContext basicHttpContext = apacheCloudStackClient.createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(closeableHttpClientMock, false); - @Test - public void createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeededTestAuthenticationWithUsernameAndPassword() { - CloseableHttpClient closeableHttpClientMock = Mockito.mock(CloseableHttpClient.class); - HttpContext httpContextMock = Mockito.mock(HttpContext.class); - Mockito.doReturn(httpContextMock).when(apacheCloudStackClient).createHttpContextWithAuthenticatedSessionUsingUserCredentials(Mockito.any(closeableHttpClientMock.getClass())); - HttpContext basicHttpContext = apacheCloudStackClient.createHttpContextWithAuthenticatedSessionUsingUserCredentialsIfNeeded(closeableHttpClientMock, false); + Mockito.verify(apacheCloudStackClient, Mockito.times(1)).createHttpContextWithAuthenticatedSessionUsingUserCredentials(Mockito.eq(closeableHttpClientMock)); - Mockito.verify(apacheCloudStackClient, Mockito.times(1)).createHttpContextWithAuthenticatedSessionUsingUserCredentials(Mockito.eq(closeableHttpClientMock)); + Assert.assertNotNull(basicHttpContext); + Assert.assertEquals(httpContextMock, basicHttpContext); + } - Assert.assertNotNull(basicHttpContext); - Assert.assertEquals(httpContextMock, basicHttpContext); - } + @Test + public void createHttpContextWithAuthenticatedSessionUsingUserCredentialsTest() throws ClientProtocolException, IOException { + HttpPost httpPostMock = Mockito.mock(HttpPost.class); + Mockito.doReturn(httpPostMock).when(apacheCloudStackClient).createHttpPost(); - @Test - public void createHttpContextWithAuthenticatedSessionUsingUserCredentialsTest() throws ClientProtocolException, IOException { - HttpPost httpPostMock = Mockito.mock(HttpPost.class); - Mockito.doReturn(httpPostMock).when(apacheCloudStackClient).createHttpPost(); + NameValuePair nameValuePairMock = Mockito.mock(NameValuePair.class); + ArrayList paramsMock = new ArrayList<>(1); + paramsMock.add(nameValuePairMock); - NameValuePair nameValuePairMock = Mockito.mock(NameValuePair.class); - ArrayList paramsMock = new ArrayList<>(1); - paramsMock.add(nameValuePairMock); + Mockito.doReturn(paramsMock).when(apacheCloudStackClient).getParametersForLogin(); - Mockito.doReturn(paramsMock).when(apacheCloudStackClient).getParametersForLogin(); + StatusLine statusLineMock = Mockito.mock(StatusLine.class); + CloseableHttpResponse closeableHttpResponseMock = Mockito.mock(CloseableHttpResponse.class); + CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); - StatusLine statusLineMock = Mockito.mock(StatusLine.class); - CloseableHttpResponse closeableHttpResponseMock = Mockito.mock(CloseableHttpResponse.class); - CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); + Mockito.doReturn(200).when(statusLineMock).getStatusCode(); + Mockito.doReturn(statusLineMock).when(closeableHttpResponseMock).getStatusLine(); + Mockito.doReturn(closeableHttpResponseMock).when(httpClientMock).execute(Mockito.eq(httpPostMock)); - Mockito.doReturn(200).when(statusLineMock).getStatusCode(); - Mockito.doReturn(statusLineMock).when(closeableHttpResponseMock).getStatusLine(); - Mockito.doReturn(closeableHttpResponseMock).when(httpClientMock).execute(Mockito.eq(httpPostMock)); + HttpContext httpContextMock = Mockito.mock(HttpContext.class); + Mockito.doReturn(httpContextMock).when(apacheCloudStackClient).createHttpContextWithCookies(Mockito.eq(closeableHttpResponseMock)); + Mockito.doReturn("responseAsString").when(apacheCloudStackClient).getResponseAsString(Mockito.eq(closeableHttpResponseMock)); - HttpContext httpContextMock = Mockito.mock(HttpContext.class); - Mockito.doReturn(httpContextMock).when(apacheCloudStackClient).createHttpContextWithCookies(Mockito.eq(closeableHttpResponseMock)); - Mockito.doReturn("responseAsString").when(apacheCloudStackClient).getResponseAsString(Mockito.eq(closeableHttpResponseMock)); + HttpContext httpContextAuthenticatedWithUsernamePassword = apacheCloudStackClient.createHttpContextWithAuthenticatedSessionUsingUserCredentials(httpClientMock); - HttpContext httpContextAuthenticatedWithUsernamePassword = apacheCloudStackClient.createHttpContextWithAuthenticatedSessionUsingUserCredentials(httpClientMock); + Assert.assertEquals(httpContextMock, httpContextAuthenticatedWithUsernamePassword); - Assert.assertEquals(httpContextMock, httpContextAuthenticatedWithUsernamePassword); + InOrder inOrder = Mockito.inOrder(httpPostMock, apacheCloudStackClient, statusLineMock, closeableHttpResponseMock, httpClientMock); + inOrder.verify(apacheCloudStackClient).createHttpPost(); + inOrder.verify(apacheCloudStackClient).getParametersForLogin(); + inOrder.verify(httpPostMock).setEntity(Mockito.any(UrlEncodedFormEntity.class)); + inOrder.verify(httpClientMock).execute(Mockito.eq(httpPostMock)); + inOrder.verify(closeableHttpResponseMock).getStatusLine(); + inOrder.verify(statusLineMock).getStatusCode(); + inOrder.verify(apacheCloudStackClient).getResponseAsString(Mockito.eq(closeableHttpResponseMock)); + inOrder.verify(apacheCloudStackClient).createHttpContextWithCookies(Mockito.eq(closeableHttpResponseMock)); + } - InOrder inOrder = Mockito.inOrder(httpPostMock, apacheCloudStackClient, statusLineMock, closeableHttpResponseMock, httpClientMock); - inOrder.verify(apacheCloudStackClient).createHttpPost(); - inOrder.verify(apacheCloudStackClient).getParametersForLogin(); - inOrder.verify(httpPostMock).setEntity(Mockito.any(UrlEncodedFormEntity.class)); - inOrder.verify(httpClientMock).execute(Mockito.eq(httpPostMock)); - inOrder.verify(closeableHttpResponseMock).getStatusLine(); - inOrder.verify(statusLineMock).getStatusCode(); - inOrder.verify(apacheCloudStackClient).getResponseAsString(Mockito.eq(closeableHttpResponseMock)); - inOrder.verify(apacheCloudStackClient).createHttpContextWithCookies(Mockito.eq(closeableHttpResponseMock)); - } + @Test(expected = ApacheCloudStackClientRuntimeException.class) + public void createHttpContextWithAuthenticatedSessionUsingUserCredentialsTestExceptionExecutingRequest() throws ClientProtocolException, IOException { + HttpPost httpPostMock = Mockito.mock(HttpPost.class); + Mockito.doReturn(httpPostMock).when(apacheCloudStackClient).createHttpPost(); - @Test(expected = ApacheCloudStackClientRuntimeException.class) - public void createHttpContextWithAuthenticatedSessionUsingUserCredentialsTestExceptionExecutingRequest() throws ClientProtocolException, IOException { - HttpPost httpPostMock = Mockito.mock(HttpPost.class); - Mockito.doReturn(httpPostMock).when(apacheCloudStackClient).createHttpPost(); + NameValuePair nameValuePairMock = Mockito.mock(NameValuePair.class); + ArrayList paramsMock = new ArrayList<>(1); + paramsMock.add(nameValuePairMock); - NameValuePair nameValuePairMock = Mockito.mock(NameValuePair.class); - ArrayList paramsMock = new ArrayList<>(1); - paramsMock.add(nameValuePairMock); + Mockito.doReturn(paramsMock).when(apacheCloudStackClient).getParametersForLogin(); - Mockito.doReturn(paramsMock).when(apacheCloudStackClient).getParametersForLogin(); + CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); - CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); + Mockito.doThrow(IOException.class).when(httpClientMock).execute(Mockito.eq(httpPostMock)); - Mockito.doThrow(IOException.class).when(httpClientMock).execute(Mockito.eq(httpPostMock)); + apacheCloudStackClient.createHttpContextWithAuthenticatedSessionUsingUserCredentials(httpClientMock); + } - apacheCloudStackClient.createHttpContextWithAuthenticatedSessionUsingUserCredentials(httpClientMock); - } + @Test + public void createHttpContextWithCookiesTest() { + CloseableHttpResponse closeableHttpResponseMock = Mockito.mock(CloseableHttpResponse.class); - @Test - public void createHttpContextWithCookiesTest() { - CloseableHttpResponse closeableHttpResponseMock = Mockito.mock(CloseableHttpResponse.class); + Header[] headers = new Header[1]; + Mockito.doReturn(headers).when(closeableHttpResponseMock).getAllHeaders(); - Header[] headers = new Header[1]; - Mockito.doReturn(headers).when(closeableHttpResponseMock).getAllHeaders(); + Mockito.doNothing().when(apacheCloudStackClient).createAndAddCookiesOnStoreForHeaders(Mockito.any(BasicCookieStore.class), Mockito.eq(headers)); + HttpContext httpContextWithCookies = apacheCloudStackClient.createHttpContextWithCookies(closeableHttpResponseMock); - Mockito.doNothing().when(apacheCloudStackClient).createAndAddCookiesOnStoreForHeaders(Mockito.any(BasicCookieStore.class), Mockito.eq(headers)); - HttpContext httpContextWithCookies = apacheCloudStackClient.createHttpContextWithCookies(closeableHttpResponseMock); + Assert.assertNotNull(httpContextWithCookies); + Assert.assertNotNull(httpContextWithCookies.getAttribute(HttpClientContext.COOKIE_STORE)); - Assert.assertNotNull(httpContextWithCookies); - Assert.assertNotNull(httpContextWithCookies.getAttribute(HttpClientContext.COOKIE_STORE)); + Mockito.verify(apacheCloudStackClient).createAndAddCookiesOnStoreForHeaders(Mockito.any(BasicCookieStore.class), Mockito.eq(headers)); - Mockito.verify(apacheCloudStackClient).createAndAddCookiesOnStoreForHeaders(Mockito.any(BasicCookieStore.class), Mockito.eq(headers)); + } - } + @Test + public void createAndAddCookiesOnStoreForHeadersTest() { + Header[] headers = new Header[2]; + headers[0] = new BasicHeader("Set-Cookie cookieName", "value1"); + headers[1] = new BasicHeader("anyOtherCookie", "value2"); - @Test - public void createAndAddCookiesOnStoreForHeadersTest() { - Header[] headers = new Header[2]; - headers[0] = new BasicHeader("Set-Cookie cookieName", "value1"); - headers[1] = new BasicHeader("anyOtherCookie", "value2"); + CookieStore cookieStoreMock = Mockito.mock(CookieStore.class); - CookieStore cookieStoreMock = Mockito.mock(CookieStore.class); + Mockito.doNothing().when(apacheCloudStackClient).createAndAddCookiesOnStoreForHeader(Mockito.eq(cookieStoreMock), Mockito.any(Header.class)); + apacheCloudStackClient.createAndAddCookiesOnStoreForHeaders(cookieStoreMock, headers); - Mockito.doNothing().when(apacheCloudStackClient).createAndAddCookiesOnStoreForHeader(Mockito.eq(cookieStoreMock), Mockito.any(Header.class)); - apacheCloudStackClient.createAndAddCookiesOnStoreForHeaders(cookieStoreMock, headers); + Mockito.verify(apacheCloudStackClient).createAndAddCookiesOnStoreForHeader(Mockito.eq(cookieStoreMock), Mockito.eq(headers[0])); + } - Mockito.verify(apacheCloudStackClient).createAndAddCookiesOnStoreForHeader(Mockito.eq(cookieStoreMock), Mockito.eq(headers[0])); - } + public void createAndAddCookiesOnStoreForHeaderTest() { + CookieStore cookieStoreMock = Mockito.mock(CookieStore.class); + Header headerMock = Mockito.mock(Header.class); - public void createAndAddCookiesOnStoreForHeaderTest() { - CookieStore cookieStoreMock = Mockito.mock(CookieStore.class); - Header headerMock = Mockito.mock(Header.class); + HeaderElement headerElementMock1 = Mockito.mock(HeaderElement.class); - HeaderElement headerElementMock1 = Mockito.mock(HeaderElement.class); + List headerElements = new ArrayList<>(1); + headerElements.add(headerElementMock1); - List headerElements = new ArrayList<>(1); - headerElements.add(headerElementMock1); + Mockito.doReturn(headerElements).when(headerMock).getElements(); - Mockito.doReturn(headerElements).when(headerMock).getElements(); + Cookie cookieMock = Mockito.mock(Cookie.class); + Mockito.doReturn(cookieMock).when(apacheCloudStackClient).createCookieForHeaderElement(Mockito.eq(headerElementMock1)); - Cookie cookieMock = Mockito.mock(Cookie.class); - Mockito.doReturn(cookieMock).when(apacheCloudStackClient).createCookieForHeaderElement(Mockito.eq(headerElementMock1)); + apacheCloudStackClient.createAndAddCookiesOnStoreForHeader(cookieStoreMock, headerMock); - apacheCloudStackClient.createAndAddCookiesOnStoreForHeader(cookieStoreMock, headerMock); + Mockito.verify(headerMock).getElements(); + Mockito.verify(apacheCloudStackClient).createCookieForHeaderElement(Mockito.eq(headerElementMock1)); + } - Mockito.verify(headerMock).getElements(); - Mockito.verify(apacheCloudStackClient).createCookieForHeaderElement(Mockito.eq(headerElementMock1)); - } + @Test + public void createCookieForHeaderElementTest() { + String cookiePath = "/client/api"; - @Test - public void createCookieForHeaderElementTest() { - String cookiePath = "/client/api"; + String paramName = "paramName1"; + String paramValue = "paramVale1"; + NameValuePair[] parameters = new NameValuePair[1]; + parameters[0] = new BasicNameValuePair(paramName, paramValue); - String paramName = "paramName1"; - String paramValue = "paramVale1"; - NameValuePair[] parameters = new NameValuePair[1]; - parameters[0] = new BasicNameValuePair(paramName, paramValue); + String headerName = "headerElementName"; + String headerValue = "headerElementValue"; + HeaderElement headerElement = new BasicHeaderElement(headerName, headerValue, parameters); - String headerName = "headerElementName"; - String headerValue = "headerElementValue"; - HeaderElement headerElement = new BasicHeaderElement(headerName, headerValue, parameters); + Mockito.doNothing().when(apacheCloudStackClient).configureDomainForCookie(Mockito.any(BasicClientCookie.class)); - Mockito.doNothing().when(apacheCloudStackClient).configureDomainForCookie(Mockito.any(BasicClientCookie.class)); + BasicClientCookie cookieForHeaderElement = apacheCloudStackClient.createCookieForHeaderElement(headerElement); - BasicClientCookie cookieForHeaderElement = apacheCloudStackClient.createCookieForHeaderElement(headerElement); + Assert.assertNotNull(cookieForHeaderElement); + Assert.assertEquals(headerName, cookieForHeaderElement.getName()); + Assert.assertEquals(headerValue, cookieForHeaderElement.getValue()); + Assert.assertEquals(paramValue, cookieForHeaderElement.getAttribute(paramName)); + Assert.assertEquals(cookiePath, cookieForHeaderElement.getPath()); - Assert.assertNotNull(cookieForHeaderElement); - Assert.assertEquals(headerName, cookieForHeaderElement.getName()); - Assert.assertEquals(headerValue, cookieForHeaderElement.getValue()); - Assert.assertEquals(paramValue, cookieForHeaderElement.getAttribute(paramName)); - Assert.assertEquals(cookiePath, cookieForHeaderElement.getPath()); + Mockito.verify(apacheCloudStackClient).configureDomainForCookie(Mockito.eq(cookieForHeaderElement)); + } - Mockito.verify(apacheCloudStackClient).configureDomainForCookie(Mockito.eq(cookieForHeaderElement)); - } + @Test + public void configureDomainForCookieTest() { + BasicClientCookie basicClientCookie = new BasicClientCookie("name", "value"); + apacheCloudStackClient.configureDomainForCookie(basicClientCookie); - @Test - public void configureDomainForCookieTest() { - BasicClientCookie basicClientCookie = new BasicClientCookie("name", "value"); - apacheCloudStackClient.configureDomainForCookie(basicClientCookie); + Assert.assertEquals(cloudStackDomain, basicClientCookie.getDomain()); + } - Assert.assertEquals(cloudStackDomain, basicClientCookie.getDomain()); - } + @Test + public void createHttpPostTest() throws MalformedURLException { + HttpPost httpPost = apacheCloudStackClient.createHttpPost(); - @Test - public void createHttpPostTest() throws MalformedURLException { - HttpPost httpPost = apacheCloudStackClient.createHttpPost(); + Assert.assertEquals(cloudStackUrl, httpPost.getURI().toURL().toString()); + Assert.assertEquals("application/x-www-form-urlencoded", httpPost.getFirstHeader("Content-Type").getValue()); + } - Assert.assertEquals(cloudStackUrl, httpPost.getURI().toURL().toString()); - Assert.assertEquals("application/x-www-form-urlencoded", httpPost.getFirstHeader("Content-Type").getValue()); - } + public void getParametersForLoginTest() { + Mockito.doReturn("userName").when(apacheCloudStackUser).getUsername(); + Mockito.doReturn("password").when(apacheCloudStackUser).getPassword(); + Mockito.doReturn("domain").when(apacheCloudStackUser).getDomain(); - public void getParametersForLoginTest() { - Mockito.doReturn("userName").when(apacheCloudStackUser).getUsername(); - Mockito.doReturn("password").when(apacheCloudStackUser).getPassword(); - Mockito.doReturn("domain").when(apacheCloudStackUser).getDomain(); + List parametersForLogin = apacheCloudStackClient.getParametersForLogin(); - List parametersForLogin = apacheCloudStackClient.getParametersForLogin(); + Assert.assertNotNull(parametersForLogin); + Assert.assertEquals(4, parametersForLogin.size()); - Assert.assertNotNull(parametersForLogin); - Assert.assertEquals(4, parametersForLogin.size()); + Assert.assertEquals("command", parametersForLogin.get(0).getValue()); + Assert.assertEquals("login", parametersForLogin.get(0).getName()); - Assert.assertEquals("command", parametersForLogin.get(0).getValue()); - Assert.assertEquals("login", parametersForLogin.get(0).getName()); + Assert.assertEquals("username", parametersForLogin.get(1).getValue()); + Assert.assertEquals("userName", parametersForLogin.get(1).getName()); - Assert.assertEquals("username", parametersForLogin.get(1).getValue()); - Assert.assertEquals("userName", parametersForLogin.get(1).getName()); + Assert.assertEquals("password", parametersForLogin.get(2).getValue()); + Assert.assertEquals("password", parametersForLogin.get(2).getName()); - Assert.assertEquals("password", parametersForLogin.get(2).getValue()); - Assert.assertEquals("password", parametersForLogin.get(2).getName()); + Assert.assertEquals("domain", parametersForLogin.get(3).getValue()); + Assert.assertEquals("domain", parametersForLogin.get(3).getName()); + } - Assert.assertEquals("domain", parametersForLogin.get(3).getValue()); - Assert.assertEquals("domain", parametersForLogin.get(3).getName()); - } + @Test + public void executeUserLogoutTest() { + String urlRequest = "urlRequest"; - @Test - public void executeUserLogoutTest() { - String urlRequest = "urlRequest"; + Mockito.doReturn(urlRequest).when(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(false)); + Mockito.doReturn("response").when(apacheCloudStackClient).executeRequestGetResponseAsString(Mockito.eq(urlRequest), Mockito.any(CloseableHttpClient.class), + Mockito.any(HttpContext.class)); - Mockito.doReturn(urlRequest).when(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(false)); - Mockito.doReturn("response").when(apacheCloudStackClient).executeRequestGetResponseAsString(Mockito.eq(urlRequest), Mockito.any(CloseableHttpClient.class), Mockito.any(HttpContext.class)); + apacheCloudStackClient.executeUserLogout(Mockito.mock(CloseableHttpClient.class), Mockito.mock(HttpContext.class)); - apacheCloudStackClient.executeUserLogout(Mockito.mock(CloseableHttpClient.class), Mockito.mock(HttpContext.class)); + InOrder inOrder = Mockito.inOrder(apacheCloudStackClient); + inOrder.verify(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(false)); + inOrder.verify(apacheCloudStackClient).executeRequestGetResponseAsString(Mockito.eq(urlRequest), Mockito.any(CloseableHttpClient.class), Mockito.any(HttpContext.class)); + } - InOrder inOrder = Mockito.inOrder(apacheCloudStackClient); - inOrder.verify(apacheCloudStackClient).createApacheCloudStackApiUrlRequest(Mockito.any(ApacheCloudStackRequest.class), Mockito.eq(false)); - inOrder.verify(apacheCloudStackClient).executeRequestGetResponseAsString(Mockito.eq(urlRequest), Mockito.any(CloseableHttpClient.class), Mockito.any(HttpContext.class)); - } + @Test + public void configureRequestExpirationTestRequestsShouldNotExpire() { + apacheCloudStackClient.setShouldRequestsExpire(false); - @Test - public void configureRequestExpirationTestRequestsShouldNotExpire() { - apacheCloudStackClient.setShouldRequestsExpire(false); + ArrayList arrayList = new ArrayList<>(); + apacheCloudStackClient.configureRequestExpiration(arrayList); - ArrayList arrayList = new ArrayList<>(); - apacheCloudStackClient.configureRequestExpiration(arrayList); + Assert.assertEquals(0, arrayList.size()); + } - Assert.assertEquals(0, arrayList.size()); - } + @Test + public void configureRequestExpirationTestRequestsShouldNotExpireUsingOverride() { + apacheCloudStackClient.setShouldRequestsExpire(false); - @Test - public void configureRequestExpirationTestRequestsShouldNotExpireUsingOverride() { - apacheCloudStackClient.setShouldRequestsExpire(false); + ArrayList arrayList = new ArrayList<>(); + arrayList.add(new ApacheCloudStackApiCommandParameter("expires", "2011-10-10T12:00:00+0530")); - ArrayList arrayList = new ArrayList<>(); - arrayList.add(new ApacheCloudStackApiCommandParameter("expires", "2011-10-10T12:00:00+0530")); + apacheCloudStackClient.configureRequestExpiration(arrayList); - apacheCloudStackClient.configureRequestExpiration(arrayList); + Assert.assertEquals(2, arrayList.size()); + Mockito.verify(apacheCloudStackClient, Mockito.never()).createExpirationDate(); + } - Assert.assertEquals(2, arrayList.size()); - Mockito.verify(apacheCloudStackClient, Mockito.never()).createExpirationDate(); - } + @Test + public void configureRequestExpirationTestRequestsShouldExpireUsingOverride() { + apacheCloudStackClient.setShouldRequestsExpire(true); - @Test - public void configureRequestExpirationTestRequestsShouldExpireUsingOverride() { - apacheCloudStackClient.setShouldRequestsExpire(true); + ArrayList arrayList = new ArrayList<>(); + ApacheCloudStackApiCommandParameter expirationParameter = new ApacheCloudStackApiCommandParameter("expires", "2011-10-10T12:00:00+0530"); + arrayList.add(expirationParameter); - ArrayList arrayList = new ArrayList<>(); - ApacheCloudStackApiCommandParameter expirationParameter = new ApacheCloudStackApiCommandParameter("expires", "2011-10-10T12:00:00+0530"); - arrayList.add(expirationParameter); + apacheCloudStackClient.configureRequestExpiration(arrayList); - apacheCloudStackClient.configureRequestExpiration(arrayList); + Assert.assertEquals(2, arrayList.size()); + Assert.assertEquals(expirationParameter, arrayList.get(0)); + Mockito.verify(apacheCloudStackClient, Mockito.never()).createExpirationDate(); + } - Assert.assertEquals(2, arrayList.size()); - Assert.assertEquals(expirationParameter, arrayList.get(0)); - Mockito.verify(apacheCloudStackClient, Mockito.never()).createExpirationDate(); - } + @Test + public void configureRequestExpirationTestRequestsShouldExpireWithoutOverride() { + apacheCloudStackClient.setShouldRequestsExpire(true); - @Test - public void configureRequestExpirationTestRequestsShouldExpireWithoutOverride() { - apacheCloudStackClient.setShouldRequestsExpire(true); + ArrayList arrayList = new ArrayList<>(); - ArrayList arrayList = new ArrayList<>(); + String expirationDate = "2011-10-10T12:00:00+0530"; + Mockito.doReturn(expirationDate).when(apacheCloudStackClient).createExpirationDate(); - String expirationDate = "2011-10-10T12:00:00+0530"; - Mockito.doReturn(expirationDate).when(apacheCloudStackClient).createExpirationDate(); + apacheCloudStackClient.configureRequestExpiration(arrayList); - apacheCloudStackClient.configureRequestExpiration(arrayList); + Assert.assertEquals(2, arrayList.size()); + Assert.assertEquals("signatureVersion", arrayList.get(0).getName()); + Assert.assertEquals(3, arrayList.get(0).getValue()); + Assert.assertEquals("expires", arrayList.get(1).getName()); + Assert.assertEquals(expirationDate, arrayList.get(1).getValue()); - Assert.assertEquals(2, arrayList.size()); - Assert.assertEquals("signatureVersion", arrayList.get(0).getName()); - Assert.assertEquals(3, arrayList.get(0).getValue()); - Assert.assertEquals("expires", arrayList.get(1).getName()); - Assert.assertEquals(expirationDate, arrayList.get(1).getValue()); + Mockito.verify(apacheCloudStackClient).createExpirationDate(); + } - Mockito.verify(apacheCloudStackClient).createExpirationDate(); - } + @Test + public void createExpirationDateTest() { + Calendar someMomentInTimeSpace = Calendar.getInstance(); + someMomentInTimeSpace.set(1999, 12, 31, 23, 59, 59); + someMomentInTimeSpace.set(Calendar.MILLISECOND, 0); + Mockito.doReturn(someMomentInTimeSpace.getTime()).when(apacheCloudStackClient).getExpirationDate(); - @Test - public void createExpirationDateTest() { - Calendar someMomentInTimeSpace = Calendar.getInstance(); - someMomentInTimeSpace.set(1999, 12, 31, 23, 59, 59); - someMomentInTimeSpace.set(Calendar.MILLISECOND, 0); - Mockito.doReturn(someMomentInTimeSpace.getTime()).when(apacheCloudStackClient).getExpirationDate(); + String expirationDate = apacheCloudStackClient.createExpirationDate(); - String expirationDate = apacheCloudStackClient.createExpirationDate(); + String expectedExpirationDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(someMomentInTimeSpace.getTime()); + Assert.assertEquals(expectedExpirationDate, expirationDate); - String expectedExpirationDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(someMomentInTimeSpace.getTime()); - Assert.assertEquals(expectedExpirationDate, expirationDate); + Mockito.verify(apacheCloudStackClient).getExpirationDate(); + } - Mockito.verify(apacheCloudStackClient).getExpirationDate(); - } + @Test + public void createInsecureHostNameVerifierTest() { + HostnameVerifier hostNameVerifier = apacheCloudStackClient.createInsecureHostNameVerifier(); - @Test - public void createInsecureHostNameVerifierTest() { - HostnameVerifier hostNameVerifier = apacheCloudStackClient.createInsecureHostNameVerifier(); + Assert.assertTrue(hostNameVerifier.verify("...", null)); + Assert.assertTrue(hostNameVerifier.verify("Any other thing", null)); - Assert.assertTrue(hostNameVerifier.verify("...", null)); - Assert.assertTrue(hostNameVerifier.verify("Any other thing", null)); + } - } + @Test + public void toStringTest() { + String toStringValue = apacheCloudStackClient.toString(); - @Test - public void toStringTest() { - String toStringValue = apacheCloudStackClient.toString(); - - String expectedToStringValue = "Apache CloudSTackClient for site[https://cloud.domain.com/client/api], parameters: [connectionTimeout=60, acceptAllKindsOfCertificates=false, validateServerHttpsCertificate=true, requestValidity=30, shouldRequestsExpire=true]"; - Assert.assertEquals(expectedToStringValue, toStringValue); - } + String expectedToStringValue = "Apache CloudSTackClient for site[https://cloud.domain.com/client/api], parameters: [connectionTimeout=60, acceptAllKindsOfCertificates=false, validateServerHttpsCertificate=true, requestValidity=30, shouldRequestsExpire=true]"; + Assert.assertEquals(expectedToStringValue, toStringValue); + } }