From 4236968a3d7aac3abf0ad58f80e2628f400b352e Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Tue, 16 Apr 2013 16:54:42 +0200 Subject: Move org.eclipse.ecf.remoteservice.rest to httpclient 4 Currently, the o.e.e.remoteservice.rest bundles is dependent upon httpclient 3.1 API. It should be moved to use httpclient 4. Bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=403675 --- .../META-INF/MANIFEST.MF | 17 ++- .../rest/client/AbstractEntityRequestType.java | 24 ++-- .../rest/client/RestClientService.java | 123 ++++++++++++--------- 3 files changed, 96 insertions(+), 68 deletions(-) diff --git a/framework/bundles/org.eclipse.ecf.remoteservice.rest/META-INF/MANIFEST.MF b/framework/bundles/org.eclipse.ecf.remoteservice.rest/META-INF/MANIFEST.MF index d4004550e..f3f2e2bf6 100644 --- a/framework/bundles/org.eclipse.ecf.remoteservice.rest/META-INF/MANIFEST.MF +++ b/framework/bundles/org.eclipse.ecf.remoteservice.rest/META-INF/MANIFEST.MF @@ -14,11 +14,18 @@ Export-Package: org.eclipse.ecf.internal.remoteservice.rest;x-internal:=true, org.eclipse.ecf.remoteservice.rest.client;version="2.2.200", org.eclipse.ecf.remoteservice.rest.identity;version="2.2.200", org.eclipse.ecf.remoteservice.rest.util;version="2.2.200" -Import-Package: org.apache.commons.httpclient;version="3.0.1", - org.apache.commons.httpclient.auth;version="3.0.1", - org.apache.commons.httpclient.methods;version="3.1.0", - org.apache.commons.httpclient.params;version="3.0.1", - org.apache.commons.httpclient.util, +Import-Package: org.apache.http;version="4.1.2", + org.apache.http.client;version="4.1.2", + org.apache.http.client.entity;version="4.1.2", + org.apache.http.client.params;version="4.1.2", + org.apache.http.impl.auth;version="4.1.2", + org.apache.http.impl.client;version="4.1.2", + org.apache.http.entity;version="4.1.2", + org.apache.http.message;version="4.1.2", + org.apache.http.auth;version="4.1.2", + org.apache.http.client.methods;version="4.1.2", + org.apache.http.params;version="4.1.2", + org.apache.http.util, org.eclipse.ecf.remoteservice;version="6.0.0", org.eclipse.ecf.remoteservice.client, org.eclipse.ecf.remoteservice.events, diff --git a/framework/bundles/org.eclipse.ecf.remoteservice.rest/src/org/eclipse/ecf/remoteservice/rest/client/AbstractEntityRequestType.java b/framework/bundles/org.eclipse.ecf.remoteservice.rest/src/org/eclipse/ecf/remoteservice/rest/client/AbstractEntityRequestType.java index 7bf44ad2b..d10e4d45d 100644 --- a/framework/bundles/org.eclipse.ecf.remoteservice.rest/src/org/eclipse/ecf/remoteservice/rest/client/AbstractEntityRequestType.java +++ b/framework/bundles/org.eclipse.ecf.remoteservice.rest/src/org/eclipse/ecf/remoteservice/rest/client/AbstractEntityRequestType.java @@ -11,7 +11,8 @@ package org.eclipse.ecf.remoteservice.rest.client; import java.io.*; import java.util.Map; -import org.apache.commons.httpclient.methods.*; +import org.apache.http.HttpEntity; +import org.apache.http.entity.*; import org.eclipse.ecf.remoteservice.IRemoteCall; import org.eclipse.ecf.remoteservice.client.IRemoteCallParameter; import org.eclipse.ecf.remoteservice.client.IRemoteCallable; @@ -23,13 +24,14 @@ public abstract class AbstractEntityRequestType extends AbstractRequestType { public static final int STRING_REQUEST_ENTITY = 1; public static final int BYTEARRAY_REQUEST_ENTITY = 2; public static final int FILE_REQUEST_ENTITY = 3; + public static final long CONTENT_LENGTH_AUTO = -2; public static final String CHARSET_PARAM_NAME = "charset"; //$NON-NLS-1$ public static final String CONTENT_TYPE_PARAM_NAME = "contentType"; //$NON-NLS-1$ public static final String CONTENT_LENGTH_PARAM_NAME = "contentLength"; //$NON-NLS-1$ protected int requestEntityType = NO_REQUEST_ENTITY; - protected long defaultContentLength = InputStreamRequestEntity.CONTENT_LENGTH_AUTO; + protected long defaultContentLength = AbstractEntityRequestType.CONTENT_LENGTH_AUTO; protected String defaultContentType = null; protected String defaultCharset = null; @@ -54,7 +56,7 @@ public abstract class AbstractEntityRequestType extends AbstractRequestType { } public AbstractEntityRequestType(int requestEntityType, String defaultContentType, Map defaultRequestHeaders) { - this(requestEntityType, defaultContentType, InputStreamRequestEntity.CONTENT_LENGTH_AUTO, null, defaultRequestHeaders); + this(requestEntityType, defaultContentType, AbstractEntityRequestType.CONTENT_LENGTH_AUTO, null, defaultRequestHeaders); } public AbstractEntityRequestType(int requestEntityType, String defaultContentType) { @@ -77,19 +79,19 @@ public abstract class AbstractEntityRequestType extends AbstractRequestType { return requestEntityType > -1; } - public RequestEntity generateRequestEntity(String uri, IRemoteCall call, IRemoteCallable callable, IRemoteCallParameter paramDefault, Object paramToSerialize) throws NotSerializableException { - if (paramToSerialize instanceof RequestEntity) - return (RequestEntity) paramToSerialize; + public HttpEntity generateRequestEntity(String uri, IRemoteCall call, IRemoteCallable callable, IRemoteCallParameter paramDefault, Object paramToSerialize) throws NotSerializableException { + if (paramToSerialize instanceof HttpEntity) + return (HttpEntity) paramToSerialize; switch (requestEntityType) { case INPUT_STREAM_REQUEST_ENTITY : if (paramToSerialize instanceof InputStream) { - return new InputStreamRequestEntity((InputStream) paramToSerialize, getContentLength(call, callable, paramDefault), getContentType(call, callable, paramDefault)); + return new InputStreamEntity((InputStream) paramToSerialize, getContentLength(call, callable, paramDefault)); } throw new NotSerializableException("Cannot generate request entity. Expecting InputStream and got class=" + paramToSerialize.getClass().getName()); //$NON-NLS-1$ case STRING_REQUEST_ENTITY : if (paramToSerialize instanceof String) { try { - return new StringRequestEntity((String) paramToSerialize, getContentType(call, callable, paramDefault), getCharset(call, callable, paramDefault)); + return new StringEntity((String) paramToSerialize, getContentType(call, callable, paramDefault), getCharset(call, callable, paramDefault)); } catch (UnsupportedEncodingException e) { throw new NotSerializableException("Could not create request entity from call parameters: " + e.getMessage()); //$NON-NLS-1$ } @@ -97,12 +99,12 @@ public abstract class AbstractEntityRequestType extends AbstractRequestType { throw new NotSerializableException("Cannot generate request entity. Expecting String and got class=" + paramToSerialize.getClass().getName()); //$NON-NLS-1$ case BYTEARRAY_REQUEST_ENTITY : if (paramToSerialize instanceof byte[]) { - return new ByteArrayRequestEntity((byte[]) paramToSerialize, getContentType(call, callable, paramDefault)); + return new ByteArrayEntity((byte[]) paramToSerialize); } throw new NotSerializableException("Cannot generate request entity. Expecting byte[] and got class=" + paramToSerialize.getClass().getName()); //$NON-NLS-1$ case FILE_REQUEST_ENTITY : if (paramToSerialize instanceof File) { - return new FileRequestEntity((File) paramToSerialize, getContentType(call, callable, paramDefault)); + return new FileEntity((File) paramToSerialize, getContentType(call, callable, paramDefault)); } throw new NotSerializableException("Remote call parameter with name=" + paramDefault.getName() + " is incorrect type for creating request entity."); //$NON-NLS-1$ //$NON-NLS-2$ default : @@ -139,7 +141,7 @@ public abstract class AbstractEntityRequestType extends AbstractRequestType { try { return Integer.parseInt((String) o); } catch (NumberFormatException e) { - return InputStreamRequestEntity.CONTENT_LENGTH_AUTO; + return AbstractEntityRequestType.CONTENT_LENGTH_AUTO; } } } diff --git a/framework/bundles/org.eclipse.ecf.remoteservice.rest/src/org/eclipse/ecf/remoteservice/rest/client/RestClientService.java b/framework/bundles/org.eclipse.ecf.remoteservice.rest/src/org/eclipse/ecf/remoteservice/rest/client/RestClientService.java index 970aeb806..14cfd503b 100644 --- a/framework/bundles/org.eclipse.ecf.remoteservice.rest/src/org/eclipse/ecf/remoteservice/rest/client/RestClientService.java +++ b/framework/bundles/org.eclipse.ecf.remoteservice.rest/src/org/eclipse/ecf/remoteservice/rest/client/RestClientService.java @@ -9,14 +9,20 @@ *******************************************************************************/ package org.eclipse.ecf.remoteservice.rest.client; -import java.io.IOException; -import java.io.NotSerializableException; +import java.io.*; import java.util.*; -import org.apache.commons.httpclient.*; -import org.apache.commons.httpclient.auth.AuthScope; -import org.apache.commons.httpclient.methods.*; -import org.apache.commons.httpclient.params.HttpClientParams; -import org.apache.commons.httpclient.params.HttpMethodParams; +import org.apache.http.*; +import org.apache.http.auth.*; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.*; +import org.apache.http.client.params.ClientPNames; +import org.apache.http.impl.auth.BasicScheme; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.AbstractHttpMessage; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.params.CoreConnectionPNames; +import org.apache.http.params.CoreProtocolPNames; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.ecf.core.security.*; @@ -39,16 +45,18 @@ public class RestClientService extends AbstractClientService { protected final static String DEFAULT_HTTP_CONTENT_CHARSET = "UTF-8"; //$NON-NLS-1$ + private static final String CONNECTION_MANAGER_TIMEOUT = "http.connection-manager.timeout"; //$NON-NLS-1$ + protected HttpClient httpClient; protected int responseBufferSize = DEFAULT_RESPONSE_BUFFER_SIZE; public RestClientService(RestClientContainer container, RemoteServiceClientRegistration registration) { super(container, registration); - this.httpClient = new HttpClient(); + this.httpClient = new DefaultHttpClient(); } - private boolean isResponseOk(int httpResponseCode) { - int isOkCode = httpResponseCode - 200; + private boolean isResponseOk(HttpResponse response) { + int isOkCode = response.getStatusLine().getStatusCode() - 200; return (isOkCode >= 0 && isOkCode < 100); } @@ -65,44 +73,46 @@ public class RestClientService extends AbstractClientService { */ protected Object invokeRemoteCall(final IRemoteCall call, final IRemoteCallable callable) throws ECFException { String uri = prepareEndpointAddress(call, callable); - HttpMethod httpMethod = createAndPrepareHttpMethod(uri, call, callable); + HttpRequestBase httpMethod = createAndPrepareHttpMethod(uri, call, callable); // execute method byte[] responseBody = null; - int responseCode = -1; + int responseCode = 500; + HttpResponse response = null; try { - responseCode = httpClient.executeMethod(httpMethod); - if (isResponseOk(responseCode)) { + response = httpClient.execute(httpMethod); + responseCode = response.getStatusLine().getStatusCode(); + if (isResponseOk(response)) { // Get responseBody as String - responseBody = getResponseAsBytes(httpMethod); + responseBody = getResponseAsBytes(response); } else { // If this method returns true, we should retrieve the response body - if (retrieveErrorResponseBody(responseCode)) { - responseBody = getResponseAsBytes(httpMethod); + if (retrieveErrorResponseBody(response)) { + responseBody = getResponseAsBytes(response); } // Now pass to the exception handler handleException("Http response not OK. URL=" + uri + " responseCode=" + new Integer(responseCode), null, responseCode, responseBody); //$NON-NLS-1$ //$NON-NLS-2$ } - } catch (HttpException e) { - handleException("Transport HttpException", e, responseCode); //$NON-NLS-1$ } catch (IOException e) { handleException("Transport IOException", e, responseCode); //$NON-NLS-1$ } Object result = null; try { - result = processResponse(uri, call, callable, convertResponseHeaders(httpMethod.getResponseHeaders()), responseBody); + result = processResponse(uri, call, callable, convertResponseHeaders(response.getAllHeaders()), responseBody); } catch (NotSerializableException e) { handleException("Exception deserializing response. URL=" + uri + " responseCode=" + new Integer(responseCode), e, responseCode); //$NON-NLS-1$ //$NON-NLS-2$ } return result; } - protected boolean retrieveErrorResponseBody(int responseCode) { + protected boolean retrieveErrorResponseBody(HttpResponse response) { // XXX this needs to be defined differently for return false; } - protected byte[] getResponseAsBytes(HttpMethod httpMethod) throws IOException { - return httpMethod.getResponseBody(); + protected byte[] getResponseAsBytes(HttpResponse response) throws IOException { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + response.getEntity().writeTo(os); + return os.toByteArray(); } protected void handleException(String message, Throwable e, int responseCode, byte[] responseBody) throws RestException { @@ -120,9 +130,9 @@ public class RestClientService extends AbstractClientService { callTimeout = callable.getDefaultTimeout(); int timeout = (int) callTimeout; - httpClient.getHttpConnectionManager().getParams().setSoTimeout(timeout); - httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(timeout); - httpClient.getParams().setConnectionManagerTimeout(timeout); + httpClient.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, timeout); + httpClient.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeout); + httpClient.getParams().setIntParameter(CONNECTION_MANAGER_TIMEOUT, timeout); } private Map convertResponseHeaders(Header[] headers) { @@ -137,7 +147,7 @@ public class RestClientService extends AbstractClientService { return result; } - protected void addRequestHeaders(HttpMethod httpMethod, IRemoteCall call, IRemoteCallable callable) { + protected void addRequestHeaders(AbstractHttpMessage httpMethod, IRemoteCall call, IRemoteCallable callable) { // Add request headers from the callable Map requestHeaders = (callable.getRequestType() instanceof AbstractRequestType) ? ((AbstractRequestType) callable.getRequestType()).getDefaultRequestHeaders() : new HashMap(); if (requestHeaders == null) @@ -154,12 +164,12 @@ public class RestClientService extends AbstractClientService { for (int i = 0; i < headers.length; i++) { String key = (String) headers[i]; String value = (String) requestHeaders.get(key); - httpMethod.addRequestHeader(key, value); + httpMethod.addHeader(key, value); } } - protected HttpMethod createAndPrepareHttpMethod(String uri, IRemoteCall call, IRemoteCallable callable) throws RestException { - HttpMethod httpMethod = null; + protected HttpRequestBase createAndPrepareHttpMethod(String uri, IRemoteCall call, IRemoteCallable callable) throws RestException { + HttpRequestBase httpMethod = null; IRemoteCallableRequestType requestType = callable.getRequestType(); if (requestType == null) @@ -180,14 +190,18 @@ public class RestClientService extends AbstractClientService { String message = "Could not serialize parameters for uri=" + uri + " call=" + call + " callable=" + callable; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ logException(message, e); throw new RestException(message); + } catch (UnsupportedEncodingException e) { + String message = "Could not serialize parameters for uri=" + uri + " call=" + call + " callable=" + callable; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + logException(message, e); + throw new RestException(message); } // add additional request headers addRequestHeaders(httpMethod, call, callable); // handle authentication setupAuthenticaton(httpClient, httpMethod); // needed because a resource can link to another resource - httpClient.getParams().setParameter(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS, new Boolean(true)); - httpClient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, DEFAULT_HTTP_CONTENT_CHARSET); + httpClient.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, new Boolean(true)); + httpClient.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, DEFAULT_HTTP_CONTENT_CHARSET); setupTimeouts(httpClient, call, callable); return httpMethod; } @@ -195,12 +209,12 @@ public class RestClientService extends AbstractClientService { /** * @throws RestException */ - protected HttpMethod prepareDeleteMethod(String uri, IRemoteCall call, IRemoteCallable callable) throws RestException { - return new DeleteMethod(uri); + protected HttpRequestBase prepareDeleteMethod(String uri, IRemoteCall call, IRemoteCallable callable) throws RestException { + return new HttpDelete(uri); } - protected HttpMethod preparePutMethod(String uri, IRemoteCall call, IRemoteCallable callable) throws NotSerializableException { - PutMethod result = new PutMethod(uri); + protected HttpRequestBase preparePutMethod(String uri, IRemoteCall call, IRemoteCallable callable) throws NotSerializableException, UnsupportedEncodingException { + HttpPut result = new HttpPut(uri); HttpPutRequestType putRequestType = (HttpPutRequestType) callable.getRequestType(); IRemoteCallParameter[] defaultParameters = callable.getDefaultParameters(); @@ -208,35 +222,37 @@ public class RestClientService extends AbstractClientService { if (putRequestType.useRequestEntity()) { if (defaultParameters != null && defaultParameters.length > 0 && parameters != null && parameters.length > 0) { - RequestEntity requestEntity = putRequestType.generateRequestEntity(uri, call, callable, defaultParameters[0], parameters[0]); - result.setRequestEntity(requestEntity); + HttpEntity requestEntity = putRequestType.generateRequestEntity(uri, call, callable, defaultParameters[0], parameters[0]); + result.setEntity(requestEntity); } } else { NameValuePair[] params = toNameValuePairs(uri, call, callable); - if (params != null) - result.setQueryString(params); + if (params != null) { + result.setEntity(new UrlEncodedFormEntity(Arrays.asList(params))); + } } return result; } /** + * @throws UnsupportedEncodingException * @throws ECFException */ - protected HttpMethod preparePostMethod(String uri, IRemoteCall call, IRemoteCallable callable) throws NotSerializableException { - PostMethod result = new PostMethod(uri); + protected HttpRequestBase preparePostMethod(String uri, IRemoteCall call, IRemoteCallable callable) throws NotSerializableException, UnsupportedEncodingException { + HttpPost result = new HttpPost(uri); HttpPostRequestType postRequestType = (HttpPostRequestType) callable.getRequestType(); IRemoteCallParameter[] defaultParameters = callable.getDefaultParameters(); Object[] parameters = call.getParameters(); if (postRequestType.useRequestEntity()) { if (defaultParameters != null && defaultParameters.length > 0 && parameters != null && parameters.length > 0) { - RequestEntity requestEntity = postRequestType.generateRequestEntity(uri, call, callable, defaultParameters[0], parameters[0]); - result.setRequestEntity(requestEntity); + HttpEntity requestEntity = postRequestType.generateRequestEntity(uri, call, callable, defaultParameters[0], parameters[0]); + result.setEntity(requestEntity); } } else { NameValuePair[] params = toNameValuePairs(uri, call, callable); if (params != null) - result.setQueryString(params); + result.setEntity(new UrlEncodedFormEntity(Arrays.asList(params))); } return result; } @@ -244,11 +260,14 @@ public class RestClientService extends AbstractClientService { /** * @throws ECFException */ - protected HttpMethod prepareGetMethod(String uri, IRemoteCall call, IRemoteCallable callable) throws NotSerializableException { - HttpMethod result = new GetMethod(uri); + protected HttpRequestBase prepareGetMethod(String uri, IRemoteCall call, IRemoteCallable callable) { + HttpRequestBase result = new HttpGet(uri); + /** + * FIXME: is this still supported in httpclient 4.0? NameValuePair[] params = toNameValuePairs(uri, call, callable); if (params != null) result.setQueryString(params); + **/ return result; } @@ -265,14 +284,14 @@ public class RestClientService extends AbstractClientService { parameterValue = o.toString(); } if (parameterValue != null) { - nameValueList.add(new NameValuePair(restParameters[i].getName(), parameterValue)); + nameValueList.add(new BasicNameValuePair(restParameters[i].getName(), parameterValue)); } } } return (NameValuePair[]) nameValueList.toArray(new NameValuePair[nameValueList.size()]); } - protected void setupAuthenticaton(HttpClient httpClient, HttpMethod method) { + protected void setupAuthenticaton(HttpClient httpClient, HttpRequestBase method) { IConnectContext connectContext = container.getConnectContextForAuthentication(); if (connectContext != null) { NameCallback nameCallback = new NameCallback(""); //$NON-NLS-1$ @@ -285,14 +304,14 @@ public class RestClientService extends AbstractClientService { callbackHandler.handle(callbacks); String username = nameCallback.getName(); String password = (String) passwordCallback.getObject(); - AuthScope authscope = new AuthScope(null, -1); Credentials credentials = new UsernamePasswordCredentials(username, password); - httpClient.getState().setCredentials(authscope, credentials); - method.setDoAuthentication(true); + method.addHeader(new BasicScheme().authenticate(credentials, method)); } catch (IOException e) { logException("IOException setting credentials for rest httpclient", e); //$NON-NLS-1$ } catch (UnsupportedCallbackException e) { logException("UnsupportedCallbackException setting credentials for rest httpclient", e); //$NON-NLS-1$ + } catch (AuthenticationException e) { + logException("AuthenticationException setting credentials for rest httpclient", e); //$NON-NLS-1$ } } -- cgit v1.2.3