/******************************************************************************* * Gisgraphy Project * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA * * Copyright 2008 Gisgraphy project * David Masclet <davidmasclet@gisgraphy.com> * * *******************************************************************************/ package com.gisgraphy.rest; import static java.lang.String.format; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Map; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; 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.httpclient.params.HttpClientParams; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.gisgraphy.fulltext.service.exception.FullTextSearchException; import com.gisgraphy.serializer.OutputFormat; import com.gisgraphy.serializer.SerializerException; import com.gisgraphy.serializer.UniversalSerializer; /** * Default (threadsafe) implementation of {@link IRestClient} * * @author <a href="mailto:david.masclet@gisgraphy.com">David Masclet</a> */ public class RestClient implements IRestClient { private HttpClient httpClient; private static Logger logger = LoggerFactory.getLogger(RestClient.class); /** * Default constructor */ public RestClient() { this(new MultiThreadedHttpConnectionManager()); } /** /** * @param multiThreadedHttpConnectionManager * The * @link {@link MultiThreadedHttpConnectionManager} that the fulltext search * engine will use * @throws FullTextSearchException * If an error occured */ public RestClient(MultiThreadedHttpConnectionManager multiThreadedHttpConnectionManager) throws RestClientException { if (multiThreadedHttpConnectionManager == null) { throw new RestClientException("multiThreadedHttpConnectionManager can not be null"); } this.httpClient = new HttpClient(multiThreadedHttpConnectionManager); HttpClientParams httpClientParams = new HttpClientParams(); httpClientParams.setHttpElementCharset("utf8"); httpClientParams.setConnectionManagerTimeout(15000); httpClient.setParams(httpClientParams); if (this.httpClient == null) { throw new RestClientException("Can not instanciate http client with multiThreadedHttpConnectionManager : " + multiThreadedHttpConnectionManager); } } /* (non-Javadoc) * @see com.gisgraphy.rest.IRestClient#get(java.lang.String, java.lang.Class, com.gisgraphy.serializer.OutputFormat) */ public <T> T get(String url, Class<T> classToBeBound, OutputFormat format) throws RestClientException { if (url == null) { throw new RestClientException("Can not call a null url"); } GetMethod getMethod = null; try { if (classToBeBound == null) { throw new RestClientException("Can not bound a null class"); } logger.info("will call url : "+url); getMethod = new GetMethod(url); InputStream inputStream = executeMethod(getMethod); T obj = UniversalSerializer.getInstance().read(inputStream, classToBeBound, format); return obj; } catch (SerializerException e) { throw new RestClientException("an error occured during de-serialization of the http stream " + e.getMessage(), e); } finally { if (getMethod != null) { getMethod.releaseConnection(); } } } public void get(String url, OutputStream outputStream, OutputFormat format) throws RestClientException { if (url == null) { throw new RestClientException("Can not call a null url"); } GetMethod getMethod = null; try { if (outputStream == null) { throw new RestClientException("Can not serialize in a null outputStream"); } logger.info("will call url : "+url); getMethod = new GetMethod(url); InputStream inputStream = executeMethod(getMethod); int numRead; byte[] buf =new byte[256]; while ( (numRead = inputStream.read(buf) ) >= 0) { outputStream.write(buf, 0, numRead); } } catch (IOException e) { throw new RestClientException("An error occured during writing of the stream" + e.getMessage(), e); } finally { if (getMethod != null) { getMethod.releaseConnection(); } try { outputStream.flush(); outputStream.close(); } catch (IOException e) { } } } private InputStream executeMethod(HttpMethod httpMethod) throws RestClientException { int statusCode = -1; try { statusCode = executeAndCheckStatusCode(httpMethod); logger.info("URL "+httpMethod.getURI()+" returns http status :"+statusCode); return httpMethod.getResponseBodyAsStream(); } catch (HttpException e) { throw new RestClientException(statusCode, e.getMessage()); } catch (IOException e) { throw new RestClientException(statusCode, e.getMessage()); } } private int executeAndCheckStatusCode(HttpMethod httpMethod) throws IOException, HttpException, RestClientException { int statusCode = httpClient.executeMethod(httpMethod); if (statusCode != HttpStatus.SC_OK && statusCode != HttpStatus.SC_CREATED && statusCode != HttpStatus.SC_NO_CONTENT) { throw new RestClientException(statusCode, HttpStatus.getStatusText(statusCode)); } return statusCode; } private HttpMethod createPostMethod(String url, Map<String, Object> map) throws RestClientException { PostMethod httpMethod = new PostMethod(url); if (map != null) { for (String key : map.keySet()) { if (map.get(key) != null) { httpMethod.addParameter(key, map.get(key).toString()); } } } httpMethod.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); return httpMethod; } private HttpMethod createPutMethod(String url, Map<String, Object> map) throws RestClientException { PutMethod httpMethod = new PutMethod(url); StringBuilder responseBody = new StringBuilder(); if (map != null) { for (String key : map.keySet()) { if (map.get(key) != null) { responseBody.append(format("%s=%s\n", key, map.get(key).toString())); } } } String responseBodyAsString = responseBody.toString(); httpMethod.setRequestEntity(new StringRequestEntity(responseBodyAsString.substring(0, responseBody.length()))); httpMethod.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); return httpMethod; } }