This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository observe. See http://git.codelutin.com/observe.git commit 65e8b19254abc65fad1d8beccf16d6bd0527e82c Author: Tony CHEMIT <chemit@codelutin.com> Date: Thu Aug 20 18:54:49 2015 +0200 Ajout de l'implantation du client rest (merci Arnaud) --- observe-services-rest/pom.xml | 24 + .../services/ObserveServiceContextRest.java | 10 + .../services/ObserveServiceFactoryRest.java | 129 ++++- .../ird/observe/services/http/RequestBuilder.java | 531 +++++++++++++++++++++ .../ird/observe/services/http/RequestResult.java | 112 +++++ .../services/service/ReferentialServiceRest.java | 53 -- .../service/ReferentialServiceRestTest.java | 44 -- pom.xml | 24 +- 8 files changed, 820 insertions(+), 107 deletions(-) diff --git a/observe-services-rest/pom.xml b/observe-services-rest/pom.xml index 52b344e..d294413 100644 --- a/observe-services-rest/pom.xml +++ b/observe-services-rest/pom.xml @@ -61,6 +61,30 @@ <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + </dependency> + + <!-- paranamer --> + <dependency> + <groupId>com.thoughtworks.paranamer</groupId> + <artifactId>paranamer</artifactId> + </dependency> + + <!-- httpcomponents --> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpcore</artifactId> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpmime</artifactId> + </dependency> <!-- Nuiton --> <dependency> diff --git a/observe-services-rest/src/main/java/fr/ird/observe/services/ObserveServiceContextRest.java b/observe-services-rest/src/main/java/fr/ird/observe/services/ObserveServiceContextRest.java index f742f0b..926a7dc 100644 --- a/observe-services-rest/src/main/java/fr/ird/observe/services/ObserveServiceContextRest.java +++ b/observe-services-rest/src/main/java/fr/ird/observe/services/ObserveServiceContextRest.java @@ -3,6 +3,7 @@ package fr.ird.observe.services; import fr.ird.observe.services.configuration.ObserveDataSourceConfigurationRest; import fr.ird.observe.services.dto.constants.ReferentialLocale; +import java.net.URL; import java.util.Date; /** @@ -34,4 +35,13 @@ public class ObserveServiceContextRest implements ObserveServiceContext { this.applicationContext = applicationContext; } + public URL getServicesRemoteBaseUrl() { + return dataSourceConfiguration.getServerUrl(); + } + + public String getAuthenticationToken() { + return dataSourceConfiguration.getAuthenticationToken(); + } + + } diff --git a/observe-services-rest/src/main/java/fr/ird/observe/services/ObserveServiceFactoryRest.java b/observe-services-rest/src/main/java/fr/ird/observe/services/ObserveServiceFactoryRest.java index cf14936..11fc3d3 100644 --- a/observe-services-rest/src/main/java/fr/ird/observe/services/ObserveServiceFactoryRest.java +++ b/observe-services-rest/src/main/java/fr/ird/observe/services/ObserveServiceFactoryRest.java @@ -1,9 +1,24 @@ package fr.ird.observe.services; import com.google.common.base.Preconditions; -import com.google.common.cache.LoadingCache; +import com.google.common.base.Strings; +import com.google.common.base.Supplier; +import com.google.common.reflect.Reflection; +import com.google.gson.Gson; +import com.thoughtworks.paranamer.CachingParanamer; +import com.thoughtworks.paranamer.Paranamer; import fr.ird.observe.services.configuration.ObserveDataSourceConfiguration; import fr.ird.observe.services.configuration.ObserveDataSourceConfigurationRest; +import fr.ird.observe.services.dto.gson.ObserveDtoGsonSupplier; +import fr.ird.observe.services.http.RequestBuilder; +import fr.ird.observe.services.spi.Write; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.net.URL; +import java.util.Collection; /** * Created on 16/08/15. @@ -12,7 +27,14 @@ import fr.ird.observe.services.configuration.ObserveDataSourceConfigurationRest; */ public class ObserveServiceFactoryRest extends ObserveServiceFactorySupport { - protected static final LoadingCache<Class<?>, Class<?>> serviceTypeCache = newServiceImplementationTypesCache("Rest"); + /** Logger. */ + private static final Log log = LogFactory.getLog(ObserveServiceFactoryRest.class); + + public static final String AUTHENTICATION_TOKEN = "authenticationToken"; + + protected final CachingParanamer paranamer = new CachingParanamer(); + + protected final Supplier<Gson> gsonSupplier = new ObserveDtoGsonSupplier(); @Override public <S extends ObserveService> boolean accept(ObserveDataSourceConfiguration dataSourceConfiguration, Class<S> serviceType) { @@ -29,16 +51,105 @@ public class ObserveServiceFactoryRest extends ObserveServiceFactorySupport { Preconditions.checkArgument(dataSourceConfiguration instanceof ObserveDataSourceConfigurationRest, "dataSourceConfiguration must be of type ObserveRestClientDataSourceConfiguration"); Preconditions.checkNotNull(serviceType, "serviceType can't be null."); - Class<S> serviceTypeImpl = getServiceClassType(serviceTypeCache, serviceType); - Preconditions.checkNotNull(serviceTypeImpl, "serviceTypeImpl not found for : " + serviceType.getName()); - - ObserveServiceContextRest serviceContext = new ObserveServiceContextRest(); - serviceContext.setApplicationContext(applicationContext); - serviceContext.setDataSourceConfiguration((ObserveDataSourceConfigurationRest) dataSourceConfiguration); + ObserveDataSourceConfigurationRest dataSourceConfigurationRest = (ObserveDataSourceConfigurationRest) dataSourceConfiguration; - S service = newServiceInstance(serviceTypeImpl, serviceContext); + S service = newRemoteProxyServiceInstance(serviceType, dataSourceConfigurationRest); return service; } + protected <S extends ObserveService> S newRemoteProxyServiceInstance(Class<S> serviceType, ObserveDataSourceConfigurationRest dataSourceConfigurationRest) { + + String authenticationToken = dataSourceConfigurationRest.getAuthenticationToken(); + URL serverUrl = dataSourceConfigurationRest.getServerUrl(); + + RemoteInvocationHandler handler = new RemoteInvocationHandler<>(paranamer, serviceType, serverUrl, authenticationToken, gsonSupplier); + S result = Reflection.newProxy(serviceType, handler); + return result; + } + + protected static class RemoteInvocationHandler<E extends ObserveService> implements InvocationHandler { + + protected final String authenticationToken; + + protected final Supplier<Gson> gsonSupplier; + + protected final Paranamer paranamer; + + protected final Class<E> serviceClass; + + protected final String serviceUrl; + + public RemoteInvocationHandler(Paranamer paranamer, Class<E> serviceClass, URL serverUrl, String authenticationToken, Supplier<Gson> gsonSupplier) { + this.paranamer = paranamer; + this.serviceClass = serviceClass; + this.authenticationToken = authenticationToken; + this.gsonSupplier = gsonSupplier; + serviceUrl = serverUrl + "/" + serviceClass.getSimpleName(); + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + String methodName = method.getName(); + if ("toString".equals(methodName)) { + return String.format("%s<%s>.toString()", RemoteInvocationHandler.class.getName(), serviceClass.getName()); + } + if ("hashcode".equals(methodName)) { + return String.format("%s<%s>.hashcode()", RemoteInvocationHandler.class.getName(), serviceClass.getName()).hashCode(); + } + if ("equals".equals(methodName)) { + return false; + } + if ("finalize".equals(methodName)) { + return null; + } + if ("clone".equals(methodName)) { + return null; + } + + String url = String.format("%s/%s", serviceUrl, methodName); + if (log.isDebugEnabled()) { + log.debug("Invoke remote service on endpoint: " + url); + } + RequestBuilder requestBuilder = new RequestBuilder(url, gsonSupplier); + String[] strings = paranamer.lookupParameterNames(method); + int index = 0; + for (String name : strings) { + if (args.length >= (index + 1)) { + Object value = args[index]; + if (value != null && value instanceof String) { + requestBuilder.addParameter(name, (String) value); // Make sure String is not converted to JSON + } else if (value != null && value instanceof Collection) { + requestBuilder.addParameter(name, (Collection) value); // Make sure List is not converted to JSON + } else { + requestBuilder.addParameter(name, value); + } + } + index++; + } + if (!Strings.isNullOrEmpty(authenticationToken)) { + requestBuilder.addHeader(AUTHENTICATION_TOKEN, authenticationToken); + } + Object result; + try { + + boolean writeData = method.isAnnotationPresent(Write.class); + + if (writeData) { + result = requestBuilder.postAndGetJsonAndCloseConnection(method.getGenericReturnType()); + } else { + result = requestBuilder.getJsonAndCloseConnection(method.getGenericReturnType()); + } + } catch (RuntimeException re) { + if (log.isWarnEnabled()) { + log.warn("An error occurred during remote service call", re); + } + throw re; + } + return result; + + } + + } + } diff --git a/observe-services-rest/src/main/java/fr/ird/observe/services/http/RequestBuilder.java b/observe-services-rest/src/main/java/fr/ird/observe/services/http/RequestBuilder.java new file mode 100644 index 0000000..8eb1e0b --- /dev/null +++ b/observe-services-rest/src/main/java/fr/ird/observe/services/http/RequestBuilder.java @@ -0,0 +1,531 @@ +package fr.ird.observe.services.http; + +import com.google.common.base.Charsets; +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.gson.Gson; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.client.utils.URLEncodedUtils; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.entity.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntity; +import org.apache.http.entity.mime.content.FileBody; +import org.apache.http.entity.mime.content.StringBody; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.conn.PoolingClientConnectionManager; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.params.BasicHttpParams; +import org.apache.http.params.CoreConnectionPNames; +import org.apache.http.params.HttpParams; + +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Type; +import java.net.URLEncoder; +import java.nio.charset.Charset; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @author Arnaud Thimel - thimel@codelutin.com + */ +public class RequestBuilder { + + private static final Log log = LogFactory.getLog(RequestBuilder.class); + + protected static final Supplier<Gson> DEFAULT_GSON_SUPPLIER = new Supplier<Gson>() { + + @Override + public Gson get() { + return new Gson(); + } + }; + + protected HttpClient client; + + protected Map<String, String> header; + + protected List<NameValuePair> params; + + protected String baseUrl; + + protected String requestBody; + + protected String contentType; + + protected Map<String, File> files = Maps.newHashMap(); + + protected Supplier<Gson> gsonSupplier; + + protected Gson gson; + + public RequestBuilder(String baseUrl, HttpClient client, Supplier<Gson> gsonSupplier) { + this.baseUrl = baseUrl; + this.client = client; + this.header = Maps.newHashMap(); + this.params = Lists.newArrayList(); + this.gsonSupplier = MoreObjects.firstNonNull(gsonSupplier, DEFAULT_GSON_SUPPLIER); + } + +// public RequestBuilder(String baseUrl, HttpClient client) { +// this(baseUrl, client, null); +// } + + public RequestBuilder(String baseUrl, Supplier<Gson> gsonSupplier) { + this(baseUrl, new DefaultHttpClient(new PoolingClientConnectionManager()), gsonSupplier); + } + +// public RequestBuilder(String baseUrl) { +// this(baseUrl, (Supplier) null); +// } + + public RequestBuilder addToUrl(Collection<?> toJsonList) throws IOException { + + // we must add values with same paramName to get List<?> in service + for (Object toJson : toJsonList) { + if (toJson instanceof String) { + + // don't serialize String objects + addToUrl((String) toJson); + } else { + addToUrl(toJson); + } + } + return this; + } + + public Gson getGson() { + if (gson == null) { + gson = gsonSupplier.get(); + } + return gson; + } + + public RequestBuilder addToUrl(Object toJson) throws IOException { + String json = getGson().toJson(toJson); + return addToUrl(json); + } + + public RequestBuilder addToUrl(String url) throws UnsupportedEncodingException { + baseUrl = baseUrl + "/" + URLEncoder.encode(url, Charsets.UTF_8.name()); + return this; + } + + public RequestBuilder addHeader(String key, String value) { + checkRequestNotNull(key, value); + header.put(key, value); + return this; + } + + public void setContentType(String contentType) { + this.contentType = contentType; + } + + public RequestBuilder addParameter(String paramName, File file) { + files.put(paramName, file); + return this; + } + + public RequestBuilder addParameter(String paramName, Collection<?> toJsonList) throws IOException { + + // we must add values with same paramName to get List<?> in service + for (Object toJson : toJsonList) { + if (toJson instanceof String) { + + // don't serialize String objects + addParameter(paramName, (String) toJson); + } else { + addParameter(paramName, toJson); + } + } + return this; + } + + public RequestBuilder addParameter(String paramName, Object toJson) throws IOException { + String json = getGson().toJson(toJson); + return addParameter(paramName, json); + } + + public RequestBuilder addParameter(String paramName, String value) { + checkParameterNotNull(paramName, value); + params.add(new BasicNameValuePair(paramName, value)); + return this; + } + + public RequestBuilder addParameter(String paramName, int value) { + return addParameter(paramName, String.valueOf(value)); + } + + public RequestBuilder addParameters(String paramName, String value, String... others) { + checkParameterNotNull(paramName, value); + params.add(new BasicNameValuePair(paramName, value)); + String name = null; + for (int i = 0; i < others.length; ) { + try { + name = others[i++]; + value = others[i++]; + checkParameterNotNull(paramName, value); + params.add(new BasicNameValuePair(name, value)); + } catch (ArrayIndexOutOfBoundsException eee) { + throw new IllegalArgumentException( + "Parameters number must be pair number : " + + (others.length + 2) + " Last parameter is : " + name, eee); + } + } + return this; + } + + public RequestBuilder setRequestBody(String requestBody) { + this.requestBody = requestBody; + return this; + } + + protected void checkParameterNotNull(String paramName, String value) { + checkKeyValueNotNull(paramName, value, "Parameter key must be not null", "Parameter value must be not null for paramName : " + paramName); + } + + protected void checkRequestNotNull(String key, String value) { + checkKeyValueNotNull(key, value, "Request key must be not null", "Request value must be not null for key : " + key); + } + + protected void checkKeyValueNotNull(String key, String value, String keyErrorMessage, String valueErrorMessage) { + Preconditions.checkNotNull(key, keyErrorMessage); + Preconditions.checkNotNull(value, valueErrorMessage); + } + + protected <M extends HttpRequestBase> M addHeaders(M httpMethod) { + for (Map.Entry<String, String> entry : header.entrySet()) { + httpMethod.setHeader(entry.getKey(), entry.getValue()); + } + return httpMethod; + } + + protected <M extends HttpEntityEnclosingRequestBase> M addParameters(M method) throws UnsupportedEncodingException { + UrlEncodedFormEntity encodedFormEntity = new UrlEncodedFormEntity(params, "UTF-8"); + if (StringUtils.isNotBlank(contentType)) { + encodedFormEntity.setContentType(contentType); + } + method.setEntity(encodedFormEntity); + return method; + } + + protected <M extends HttpEntityEnclosingRequestBase> M addRequestBody(M method) throws UnsupportedEncodingException { + if (StringUtils.isNotEmpty(requestBody)) { + if (StringUtils.isNotBlank(contentType)) { + method.setEntity(new StringEntity(requestBody, ContentType.parse(contentType))); + } else { + method.setEntity(new StringEntity(requestBody)); + } + } + return method; + } + + public String buildUrlWithParams(String baseUrl) { + return baseUrl + "?" + URLEncodedUtils.format(params, "UTF-8"); + } + + protected RequestResult get0() throws IOException { + + HttpGet getMethod = new HttpGet(buildUrlWithParams(baseUrl)); + + getMethod = addHeaders(getMethod); + + HttpResponse response = null; + try { + response = client.execute(getMethod); + + RequestResult result = new RequestResult(response); + if (log.isDebugEnabled()) { + log.debug("GET '" + baseUrl + "' return status code : " + result.getStatusCode()); + } + + return result; + } finally { + + if (response != null && response.getEntity() != null) { + response.getEntity().getContent().close(); + } + + // Release the connection. + getMethod.releaseConnection(); + } + } + + public RequestResult getAndCloseConnection() throws IOException { + + try { + RequestResult result = get0(); + return result; + } finally { + releaseConnections(); + } + } + + public <T> T getJsonAndCloseConnection(Type type) throws IOException { + RequestResult getResult = getAndCloseConnection(); + if (getResult.getStatusCode() != 200 && log.isWarnEnabled()) { + log.warn(String.format("Unexpected status code for url: %s%n%s", baseUrl, getResult)); + } + T result = convertJson(getResult.getResponse(), type, getGson()); + return result; + } + + protected RequestResult post0(Integer timeout) throws IOException { + + HttpPost postMethod = new HttpPost(baseUrl); + + if (timeout != null) { + HttpParams httpParams = new BasicHttpParams(); + httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, timeout); + httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeout); + postMethod.setParams(httpParams); + } + + if (files.isEmpty()) { + postMethod = addHeaders(postMethod); + postMethod = addParameters(postMethod); + postMethod = addRequestBody(postMethod); + } else { + postMethod = addHeaders(postMethod); + postMethod = addParameters(postMethod); + postMethod = addRequestBody(postMethod); + MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); + for (Map.Entry<String, File> paramFile : files.entrySet()) { + entity.addPart(paramFile.getKey(), new FileBody(paramFile.getValue())); + } + for (NameValuePair param : params) { + if (StringUtils.isBlank(contentType)) { + contentType = "text/plain"; + } + entity.addPart(param.getName(), new StringBody(param.getValue(), contentType, + Charset.forName("UTF-8"))); + } + postMethod.setEntity(entity); + } + + HttpResponse response = null; + try { + response = client.execute(postMethod); + + RequestResult result = new RequestResult(response); + if (log.isDebugEnabled()) { + log.debug("POST '" + baseUrl + "' return status code : " + result.getStatusCode()); + } + + return result; + } finally { + + if (response != null && response.getEntity() != null) { + response.getEntity().getContent().close(); + } + + // Release the connection. + postMethod.releaseConnection(); + } + } + + public RequestResult postAndCloseConnection() throws IOException { + RequestResult result = postAndCloseConnection(null); + return result; + } + + public RequestResult postAndCloseConnection(Integer timeout) throws IOException { + try { + RequestResult result = post0(timeout); + return result; +// } catch (ConnectTimeoutException cte) { +// throw new RemoteCallTimeoutException("Timeout (" + timeout + ") reached", cte); + } finally { + releaseConnections(); + } + } + + public <T> T postAndGetJsonAndCloseConnection(Type type) throws IOException { + RequestResult postResult = postAndCloseConnection(); + if (postResult.getStatusCode() != 200 && log.isWarnEnabled()) { + log.warn(String.format("Unexpected status code: %d%nResponse is: %s", postResult.getStatusCode(), postResult)); + } + T result = convertJson(postResult.getResponse(), type, getGson()); + return result; + } + + protected RequestResult put0() throws IOException { + + HttpPut putMethod = new HttpPut(baseUrl); + + putMethod = addHeaders(putMethod); + putMethod = addParameters(putMethod); + putMethod = addRequestBody(putMethod); + + HttpResponse response = null; + try { + response = client.execute(putMethod); + + RequestResult result = new RequestResult(response); + + if (log.isDebugEnabled()) { + log.debug("PUT '" + baseUrl + "' return status code : " + result.getStatusCode()); + if (result.getStatusCode() != HttpStatus.SC_OK) { + log.debug(result.getResponse()); + } + } + + return result; + } finally { + + if (response != null && response.getEntity() != null) { + response.getEntity().getContent().close(); + } + + // Release the connection. + putMethod.releaseConnection(); + } + } + + protected RequestResult delete0() throws IOException { + + HttpDelete deleteMethod = new HttpDelete(buildUrlWithParams(baseUrl)); + + deleteMethod = addHeaders(deleteMethod); + + HttpResponse response = null; + try { + response = client.execute(deleteMethod); + + RequestResult result = new RequestResult(response); + if (log.isDebugEnabled()) { + log.debug("DELETE '" + baseUrl + "' return status code : " + result.getStatusCode()); + } + + return result; + } finally { + + if (response != null && response.getEntity() != null) { + response.getEntity().getContent().close(); + } + + // Release the connection. + deleteMethod.releaseConnection(); + } + } + + public static <T> T convertJson(String json, Type type) throws IOException { + return convertJson(json, type, DEFAULT_GSON_SUPPLIER.get()); + } + + public static <T> T convertJson(String json, Type type, Gson gson) throws IOException { + + Preconditions.checkNotNull(json); + Preconditions.checkNotNull(gson); + + // we must try to convert json to a T instance + T result = null; + +// try { + + // let's first try to convert json to T + if (!Void.TYPE.equals(type)) { + result = gson.fromJson(json, type); + } + +// } catch (IOException e) { +// +// // conversion to T failed, we will throw a json exception +// RemoteCallUnexpectedJsonException remoteCallUnexpectedJsonException; +// +// try { +// +// // before, try to read json as an error message +// remoteCallUnexpectedJsonException = RemoteCallUnexpectedJsonException.newFromJson(json); +// +// if (log.isInfoEnabled()) { +// log.info("service returned a json showing an error occurred ", remoteCallUnexpectedJsonException); +// } +// +// } catch (IOException ee) { +// +// if (log.isErrorEnabled()) { +// log.error("json parsing failed, json=" + json, e); +// } +// +// // json is not of type T and not an error message, +// // throw the exception with e as cause cause it may be the real problem +// remoteCallUnexpectedJsonException = RemoteCallUnexpectedJsonException.newFromParsingException(e); +// +// } +// +// throw remoteCallUnexpectedJsonException; +// +// } + + if (log.isTraceEnabled()) { + log.trace("parsing json " + json + " returns " + result); + } + + + return result; + } + + @Override + public String toString() { + Objects.ToStringHelper helper = Objects.toStringHelper(this).add("url", baseUrl); + if (header != null) { + for (Map.Entry<String, String> entry : header.entrySet()) { + String key = String.format("Header [%s]", entry.getKey()); + String value = entry.getValue(); + helper.add(key, value); + } + } + if (params != null) { + for (NameValuePair pair : params) { + String key = String.format("Param [%s]", pair.getName()); + String value = pair.getValue(); + helper.add(key, value); + } + } + + if (StringUtils.isNotBlank(contentType)) { + helper.add("Content-type", contentType); + } + + String result = helper.toString(); + return result; + } + + public void releaseConnections() { + if (client != null && client.getConnectionManager() != null) { + client.getConnectionManager().shutdown(); + } + } + + @Override + protected void finalize() throws Throwable { + if (client != null && client.getConnectionManager() != null) { + client.getConnectionManager().closeExpiredConnections(); + client.getConnectionManager().closeIdleConnections(1, TimeUnit.MINUTES); + } + super.finalize(); + } + +} diff --git a/observe-services-rest/src/main/java/fr/ird/observe/services/http/RequestResult.java b/observe-services-rest/src/main/java/fr/ird/observe/services/http/RequestResult.java new file mode 100644 index 0000000..b83da5b --- /dev/null +++ b/observe-services-rest/src/main/java/fr/ird/observe/services/http/RequestResult.java @@ -0,0 +1,112 @@ +package fr.ird.observe.services.http; + +import org.apache.commons.io.IOUtils; +import org.apache.http.Header; +import org.apache.http.HttpResponse; + +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; + +/** + * @author Arnaud Thimel - thimel@codelutin.com + */ +public class RequestResult { + + protected int statusCode; + protected Header[] headers; + protected String responseAsString; + + public RequestResult(HttpResponse response) throws IOException { + this.statusCode = response.getStatusLine().getStatusCode(); + this.headers = response.getAllHeaders(); + response.getEntity(); + + StringWriter writer = new StringWriter(); + InputStream inputStream = response.getEntity().getContent(); + try { + IOUtils.copy(inputStream, writer, "UTF-8"); + inputStream.close(); + } finally { + IOUtils.closeQuietly(inputStream); + } + responseAsString = writer.toString(); + } + + public int getStatusCode() { + return statusCode; + } + + public Header[] getHeaders() { + return headers; + } + + public String getHeader(String key) { + return getHeader(key, headers); + } + + public boolean containsHeader(String key) { + for (Header header : headers) { + if (key.equals(header.getName())) { + return true; + } + } + return false; + } + + protected String getHeader(String key, Header[] headers) { + + for (Header header : headers) { + if (key.equals(header.getName())) { + return header.getValue(); + } + } + throw new IllegalArgumentException(key + " key is not found in header"); + } + +// public String getResponseAsString(String fieldName) throws IOException { +// if (responseAsString == null) { +// return null; +// } +// JsonNode jsonNodes = new Gson().(responseAsString).get(fieldName); +// if (jsonNodes == null) { +// return null; +// } +// return jsonNodes.asText(); +// } +// +// public Boolean getResponseAsBoolean(String fieldName) throws IOException { +// JsonNode jsonNodes = getResponseAsJsonNode(fieldName); +// if (jsonNodes == null) return null; +// return jsonNodes.asBoolean(); +// } +// +// public JsonNode getResponseAsJsonNode(String fieldName) throws IOException { +// if (responseAsString == null) { +// return null; +// } +// JsonNode jsonNodes = new ObjectMapper().readTree(responseAsString).get(fieldName); +// if (jsonNodes == null) { +// return null; +// } +// return jsonNodes; +// } + + public String getResponse() throws IOException { + return responseAsString; + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(). + append("HTTP ").append(statusCode).append('\n'); + if (headers != null) { + for (Header header : headers) { + buffer.append('[').append(header.getName()).append("] ").append(header.getValue()).append('\n'); + } + } + buffer.append('\n').append(responseAsString); + String result = buffer.toString(); + return result; + } +} diff --git a/observe-services-rest/src/main/java/fr/ird/observe/services/service/ReferentialServiceRest.java b/observe-services-rest/src/main/java/fr/ird/observe/services/service/ReferentialServiceRest.java deleted file mode 100644 index 153f6f6..0000000 --- a/observe-services-rest/src/main/java/fr/ird/observe/services/service/ReferentialServiceRest.java +++ /dev/null @@ -1,53 +0,0 @@ -package fr.ird.observe.services.service; - -import fr.ird.observe.services.ObserveServiceRest; -import fr.ird.observe.services.dto.FormDto; -import fr.ird.observe.services.dto.ReferenceSetDto; -import fr.ird.observe.services.dto.referential.ReferentialDto; - -import java.util.Collection; - -/** - * Created on 16/08/15. - * - * @author Tony Chemit - chemit@codelutin.com - */ -public class ReferentialServiceRest extends ObserveServiceRest implements ReferentialService { - - @Override - public <R extends ReferentialDto> ReferenceSetDto<R> getReferentialReferenceSet(Class<R> type) { - - return new ReferenceSetDto<>(type); - } - - @Override - public <R extends ReferentialDto> FormDto<R> loadToRead(Class<R> type, String id) { - return null; - } - - @Override - public <R extends ReferentialDto> FormDto<R> loadToEdit(Class<R> type, String id) { - return null; - } - - @Override - public <R extends ReferentialDto> FormDto<R> preCreate(Class<R> type) { - return null; - } - - @Override - public <R extends ReferentialDto> String save(FormDto<R> form) { - return null; - } - - @Override - public <R extends ReferentialDto> void delete(Class<R> type, String id) { - - } - - @Override - public <R extends ReferentialDto> void delete(Class<R> type, Collection<String> ids) { - - } - -} diff --git a/observe-services-rest/src/test/java/fr/ird/observe/services/service/ReferentialServiceRestTest.java b/observe-services-rest/src/test/java/fr/ird/observe/services/service/ReferentialServiceRestTest.java deleted file mode 100644 index dea122a..0000000 --- a/observe-services-rest/src/test/java/fr/ird/observe/services/service/ReferentialServiceRestTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package fr.ird.observe.services.service; - -import fr.ird.observe.services.ObserveServiceFactoryRest; -import fr.ird.observe.services.ObserveServiceApplicationContext; -import fr.ird.observe.services.configuration.ObserveDataSourceConfigurationRest; -import fr.ird.observe.services.dto.ReferenceSetDto; -import fr.ird.observe.services.dto.constants.ReferentialLocale; -import fr.ird.observe.services.dto.referential.SexDto; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -/** - * Created on 16/08/15. - * - * @author Tony Chemit - chemit@codelutin.com - */ -public class ReferentialServiceRestTest { - - protected ReferentialService service; - - @Before - public void setUp() throws Exception { - - ObserveDataSourceConfigurationRest dataSourceConfiguration = new ObserveDataSourceConfigurationRest(); - dataSourceConfiguration.setServerUrl(null); - dataSourceConfiguration.setAuthenticationToken(null); - - ObserveServiceApplicationContext serviceApplicationContext = new ObserveServiceApplicationContext(); - serviceApplicationContext.setReferentialLocale(ReferentialLocale.FR); - - service = new ObserveServiceFactoryRest().newService(serviceApplicationContext, dataSourceConfiguration, ReferentialService.class); - - } - - @Test - public void testGetReferentialLabelSet() throws Exception { - - ReferenceSetDto referentialLabelSet = service.getReferentialReferenceSet(SexDto.class); - Assert.assertNotNull(referentialLabelSet); - - } - -} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 2b8eb07..d75e223 100644 --- a/pom.xml +++ b/pom.xml @@ -131,6 +131,8 @@ <geoToolsVersion>13.2</geoToolsVersion> <webmotionVersion>2.5</webmotionVersion> + <paranamerVersion>2.7</paranamerVersion> + <httpComponentsVersion>4.3.5</httpComponentsVersion> <!-- license header configuration --> <license.licenseName>gpl_v3</license.licenseName> @@ -143,7 +145,6 @@ <!-- Site configuration --> <locales>fr</locales> - <paranamerVersion>2.7</paranamerVersion> </properties> <repositories> @@ -225,6 +226,27 @@ <artifactId>guava</artifactId> <version>18.0</version> </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.3</version> + </dependency> + + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>${httpComponentsVersion}</version> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpcore</artifactId> + <version>4.3.2</version> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpmime</artifactId> + <version>${httpComponentsVersion}</version> + </dependency> <dependency> <groupId>log4j</groupId> -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@list.forge.codelutin.com>.