org.conqat.engine.service.shared.client.ServiceClientUtils Maven / Gradle / Ivy
/*
* Copyright (c) CQSE GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.conqat.engine.service.shared.client;
import java.io.File;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.SecureRandom;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.auth.AuthProtocolState;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.AuthState;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.FormBodyPart;
import org.apache.http.entity.mime.FormBodyPartBuilder;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpCoreContext;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.conqat.engine.service.shared.EMimeType;
import org.conqat.lib.commons.collections.CollectionUtils;
import org.conqat.lib.commons.net.TrustAllCertificatesManager;
import org.conqat.lib.commons.resources.Resource;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
/**
* Provides utility methods for ServiceClient and IdeServiceClient.
*/
public class ServiceClientUtils {
/**
* Sets up the HTTP client and returns it. The caller of this method is
* responsible for closing the client when it is no longer needed.
*/
public static CloseableHttpClient getHttpClient(ServerDetails serverDetails) throws ServiceCallException {
try {
SSLContext sslContext = SSLContexts.createDefault();
sslContext.init(null, new TrustManager[] { new TrustAllCertificatesManager() }, new SecureRandom());
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(serverDetails.getUsername(), serverDetails.getPassword()));
RequestConfig.Builder requestBuilder = RequestConfig.custom();
int timeoutMilliseconds = (int) TimeUnit.SECONDS.toMillis(serverDetails.getTimeoutSeconds());
requestBuilder = requestBuilder.setConnectTimeout(timeoutMilliseconds);
requestBuilder = requestBuilder.setSocketTimeout(timeoutMilliseconds);
requestBuilder = requestBuilder.setConnectionRequestTimeout(timeoutMilliseconds);
RequestConfig requestConfig = requestBuilder.build();
return HttpClients.custom() //
.setSSLSocketFactory(socketFactory) //
.setDefaultCredentialsProvider(credentialsProvider) //
.addInterceptorFirst(new PreemptiveAuthenticationInterceptor()) //
.setDefaultRequestConfig(requestConfig) //
.build();
} catch (KeyManagementException e) {
throw new ServiceCallException("Error creating HTTP client: " + e.getMessage(), e);
}
}
/**
* Implements preemptive authentication, i.e., will send {@code Authorization}
* even if unchallenged by the server.
*
* see Stack
* Overflow: Preemptive Basic authentication with Apache HttpClient 4
*/
private static class PreemptiveAuthenticationInterceptor implements HttpRequestInterceptor {
@Override
public void process(HttpRequest request, HttpContext context) {
AuthState authState = (AuthState) context.getAttribute(HttpClientContext.TARGET_AUTH_STATE);
// We are doing preemptive authentication, i.e., if unchallenged we set Basic
// authentication credentials
if (authState.getState() == AuthProtocolState.UNCHALLENGED) {
CredentialsProvider credentialsProvider = (CredentialsProvider) context
.getAttribute(HttpClientContext.CREDS_PROVIDER);
HttpHost targetHost = (HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());
Credentials credentials = credentialsProvider.getCredentials(authScope);
if (credentials != null) {
authState.update(new BasicScheme(), credentials);
}
}
}
}
/**
* Creates a multi-part entity that uploads the given files under the given
* request parameter.
*/
public static HttpEntity createMultiPartEntity(String parameterName, List files) {
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
for (Resource file : files) {
FormBodyPart bodyPart = FormBodyPartBuilder.create(parameterName,
new ByteArrayBody(file.getAsByteArray(), ContentType.APPLICATION_OCTET_STREAM, file.getName()))
.build();
multipartEntityBuilder.addPart(bodyPart);
}
return multipartEntityBuilder.build();
}
/**
* Creates a multi-part entity that uploads the given files under the given
* request parameter.
*/
public static HttpEntity createMultiPartEntityForFiles(String parameterName, List files) {
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
for (File file : files) {
FormBodyPart bodyPart = FormBodyPartBuilder
.create(parameterName, new FileBody(file, ContentType.APPLICATION_OCTET_STREAM)).build();
multipartEntityBuilder.addPart(bodyPart);
}
return multipartEntityBuilder.build();
}
/**
* Executes a request and handles the response. The request's header is not set
* to accept any specific type. Returns null in case of a "not found" HTTP
* return code.
*/
public static T executeRequest(HttpClient client, HttpRequestBase request, EMimeType contentType,
CollectionUtils.FunctionWithException deserializeFunction)
throws ServiceCallException {
if (contentType != null) {
request.setHeader(HttpHeaders.ACCEPT, contentType.getType());
}
try {
HttpResponse response = client.execute(request);
int statusCode = response.getStatusLine().getStatusCode();
switch (statusCode) {
case HttpStatus.SC_OK:
case HttpStatus.SC_ACCEPTED:
return deserializeFunction.apply(EntityUtils.toString(response.getEntity()));
case HttpStatus.SC_NO_CONTENT:
case HttpStatus.SC_NOT_FOUND:
return null;
default:
String responseBody = EntityUtils.toString(response.getEntity());
throw new ServiceCallException(request.getURI(), response.getStatusLine().getReasonPhrase(), statusCode,
responseBody);
}
} catch (IOException | IllegalArgumentException e) {
// IllegalArgumentException raised when the server port is illegal. Note that
// this will also catch IllegalArgumentExceptions thrown for other reasons.
throw new ServiceCallException("Service call " + request.getURI() + " failed:" + e.getMessage(), e);
}
}
/**
* Copies the given array elements into a list, with {@code null} arrays being
* represented as the empty list.
*/
public static List arrayToList(T[] array) {
if (array == null) {
return Collections.emptyList();
}
return ImmutableList.copyOf(array);
}
/**
* Copies the given array elements into a set, with {@code null} arrays being
* represented as the empty set.
*/
public static Set arrayToSet(T[] array) {
if (array == null) {
return Collections.emptySet();
}
return ImmutableSet.copyOf(array);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy