blob: 26d3d7cf4a9b089019ca4fc50b2f3a0a1e12ffa0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013-2015 LAAS-CNRS (www.laas.fr)
* 7 Colonel Roche 31077 Toulouse - France
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Thierry Monteil (Project co-founder) - Management and initial specification,
* conception and documentation.
* Mahdi Ben Alaya (Project co-founder) - Management and initial specification,
* conception, implementation, test and documentation.
* Christophe Chassot - Management and initial specification.
* Khalil Drira - Management and initial specification.
* Yassine Banouar - Initial specification, conception, implementation, test
* and documentation.
******************************************************************************/
package org.eclipse.om2m.comm.http;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.om2m.comm.service.RestClientService;
import org.eclipse.om2m.commons.resource.StatusCode;
import org.eclipse.om2m.commons.rest.RequestIndication;
import org.eclipse.om2m.commons.rest.ResponseConfirm;
/**
* Provides mapping from a protocol-independent request to a HTTP-specific request.
* @author <ul>
* <li> Mahdi Ben Alaya < ben.alaya@laas.fr > < benalaya.mahdi@gmail.com ></li>
* <li> Yassine Banouar < ybanouar@laas.fr > < yassine.banouar@gmail.com ></li>
* <li> Marouane El kiasse < melkiasse@laas.fr > < kiasmarouane@gmail.com ></li>
* </ul>
*/
public class RestHttpClient implements RestClientService {
/** Logger */
private static Log LOGGER = LogFactory.getLog(RestHttpClient.class);
/** implemented specific protocol name */
private static String protocol ="http";
/**
* gets the implemented specific protocol name
* @return protocol name
*/
public String getProtocol() {
return protocol;
}
/**
* Converts a protocol-independent {@link RequestIndication} object into a standard HTTP request and sends a standard HTTP request.
* Converts the received standard HTTP request into {@link ResponseConfirm} object and returns it back.
* @param requestIndication - protocol independent request.
* @return protocol independent response.
*/
public ResponseConfirm sendRequest(RequestIndication requestIndication) {
LOGGER.debug("Http Client > "+requestIndication);
HttpClient httpclient = new HttpClient();
ResponseConfirm responseConfirm = new ResponseConfirm();
HttpMethod httpMethod=null;
String url = requestIndication.getUrl();
if(!url.startsWith(protocol+"://")){
url=protocol+"://"+url;
}
try {
switch (requestIndication.getMethod()){
case "RETRIEVE" :
httpMethod = new GetMethod(url);
break;
case "CREATE":
httpMethod = new PostMethod(url);
((PostMethod)httpMethod).setRequestEntity(new StringRequestEntity(requestIndication.getRepresentation(),"application/xml", "UTF8"));
break;
case "UPDATE":
httpMethod = new PutMethod(url);
((PutMethod)httpMethod).setRequestEntity(new StringRequestEntity(requestIndication.getRepresentation(),"application/xml", "UTF8"));
break;
case "DELETE":
httpMethod =new DeleteMethod(url);
break;
case "EXECUTE":
httpMethod = new PostMethod(url);
break;
default: return new ResponseConfirm();
}
httpMethod.addRequestHeader("Authorization", "Basic "+new String(Base64.encodeBase64(requestIndication.getRequestingEntity().getBytes())));
httpMethod.setQueryString(getQueryFromParams(requestIndication.getParameters()));
int statusCode = httpclient.executeMethod(httpMethod);
responseConfirm.setStatusCode(getRestStatusCode(statusCode));
if(statusCode!=204){
if(httpMethod.getResponseBody()!=null){
responseConfirm.setRepresentation(new String(httpMethod.getResponseBody()));
}
}
if(statusCode==201){
Header location = httpMethod.getResponseHeader("Location");
if((location != null) && (location.getValue()!=null)){
responseConfirm.setResourceURI(httpMethod.getResponseHeader("Location").getValue());
}
}
LOGGER.debug("Http Client > "+responseConfirm);
}catch(IOException e){
LOGGER.error(url+ " Not Found"+responseConfirm,e);
} finally {
httpMethod.releaseConnection();
httpclient.getHttpConnectionManager().closeIdleConnections(0);
}
return responseConfirm;
}
/**
* Converts a standard HTTP status code into a protocol-independent {@link StatusCode} object.
* @param statusCode - standard HTTP status code.
* @return protocol independent status.
*/
public static StatusCode getRestStatusCode(int statusCode){
switch(statusCode){
case 200: return StatusCode.STATUS_OK;
case 204: return StatusCode.STATUS_OK;
case 202: return StatusCode.STATUS_ACCEPTED;
case 201: return StatusCode.STATUS_CREATED;
case 400: return StatusCode.STATUS_BAD_REQUEST;
case 401: return StatusCode.STATUS_PERMISSION_DENIED;
case 402: return StatusCode.STATUS_AUTHORIZATION_NOT_ADDED;
case 403: return StatusCode.STATUS_FORBIDDEN;
case 404: return StatusCode.STATUS_NOT_FOUND;
case 405: return StatusCode.STATUS_METHOD_NOT_ALLOWED;
case 406: return StatusCode.STATUS_NOT_ACCEPTABLE;
case 408: return StatusCode.STATUS_REQUEST_TIMEOUT;
case 409: return StatusCode.STATUS_CONFLICT;
case 415: return StatusCode.STATUS_UNSUPPORTED_MEDIA_TYPE;
case 500: return StatusCode.STATUS_INTERNAL_SERVER_ERROR;
case 501: return StatusCode.STATUS_NOT_IMPLEMENTED;
case 502: return StatusCode.STATUS_BAD_GATEWAY;
case 503: return StatusCode.STATUS_SERVICE_UNAVAILABLE;
case 504: return StatusCode.STATUS_GATEWAY_TIMEOUT;
case 410: return StatusCode.STATUS_EXPIRED;
default : return StatusCode.STATUS_INTERNAL_SERVER_ERROR;
}
}
/**
* Converts a protocol independent parameters into a standard HTTP parameters.
* @param params - protocol independent parameters map.
* @return standard HTTP query string.
*/
public static String getQueryFromParams(Map<String, List<String>> params){
String query;
List<String> values = new ArrayList<String>();
String name;
if (params != null) {
query="?";
Iterator<String> it = params.keySet().iterator();
while(it.hasNext()){
name = it.next().toString();
values = params.get(name);
for(int i=0;i<values.size();i++){
query = query+name+"="+values.get(i)+"&";
}
}
return query;
}
return null;
}
}