001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2011 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 package org.sonar.wsclient.connectors; 021 022 import org.apache.commons.httpclient.*; 023 import org.apache.commons.httpclient.auth.AuthScope; 024 import org.apache.commons.httpclient.methods.DeleteMethod; 025 import org.apache.commons.httpclient.methods.GetMethod; 026 import org.apache.commons.httpclient.methods.PostMethod; 027 import org.apache.commons.httpclient.methods.PutMethod; 028 import org.apache.commons.httpclient.methods.StringRequestEntity; 029 import org.apache.commons.httpclient.params.HttpConnectionManagerParams; 030 import org.apache.commons.httpclient.util.URIUtil; 031 import org.sonar.wsclient.Host; 032 import org.sonar.wsclient.services.CreateQuery; 033 import org.sonar.wsclient.services.DeleteQuery; 034 import org.sonar.wsclient.services.Query; 035 import org.sonar.wsclient.services.UpdateQuery; 036 037 import java.io.BufferedReader; 038 import java.io.IOException; 039 import java.io.InputStream; 040 import java.io.InputStreamReader; 041 import java.io.UnsupportedEncodingException; 042 043 /** 044 * @since 2.1 045 */ 046 public class HttpClient3Connector extends Connector { 047 048 private static final int MAX_TOTAL_CONNECTIONS = 40; 049 private static final int MAX_HOST_CONNECTIONS = 4; 050 051 private final Host server; 052 private HttpClient httpClient; 053 054 public HttpClient3Connector(final Host server) { 055 this.server = server; 056 createClient(); 057 } 058 059 public HttpClient3Connector(Host server, HttpClient httpClient) { 060 this.httpClient = httpClient; 061 this.server = server; 062 } 063 064 private void createClient() { 065 final HttpConnectionManagerParams params = new HttpConnectionManagerParams(); 066 params.setConnectionTimeout(TIMEOUT_MS); 067 params.setSoTimeout(TIMEOUT_MS); 068 params.setDefaultMaxConnectionsPerHost(MAX_HOST_CONNECTIONS); 069 params.setMaxTotalConnections(MAX_TOTAL_CONNECTIONS); 070 final MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); 071 connectionManager.setParams(params); 072 this.httpClient = new HttpClient(connectionManager); 073 configureCredentials(); 074 } 075 076 private void configureCredentials() { 077 if (server.getUsername() != null) { 078 httpClient.getParams().setAuthenticationPreemptive(true); 079 Credentials defaultcreds = new UsernamePasswordCredentials(server.getUsername(), server.getPassword()); 080 httpClient.getState().setCredentials(AuthScope.ANY, defaultcreds); 081 } 082 } 083 084 public String execute(Query<?> query) { 085 return executeRequest(newGetRequest(query)); 086 } 087 088 public String execute(CreateQuery<?> query) { 089 return executeRequest(newPostRequest(query)); 090 } 091 092 public String execute(UpdateQuery<?> query) { 093 return executeRequest(newPutRequest(query)); 094 } 095 096 public String execute(DeleteQuery<?> query) { 097 return executeRequest(newDeleteRequest(query)); 098 } 099 100 private String executeRequest(HttpMethodBase method) { 101 String json = null; 102 try { 103 httpClient.executeMethod(method); 104 if (method.getStatusCode() == HttpStatus.SC_OK) { 105 json = getResponseBodyAsString(method); 106 107 } else if (method.getStatusCode() != HttpStatus.SC_NOT_FOUND) { 108 throw new ConnectionException("HTTP error: " + method.getStatusCode() + ", msg: " + method.getStatusText() + ", query: " + method); 109 } 110 111 } catch (HttpException e) { 112 throw new ConnectionException("Query: " + method, e); 113 114 } catch (IOException e) { 115 throw new ConnectionException("Query: " + method, e); 116 117 } finally { 118 if (method != null) { 119 method.releaseConnection(); 120 } 121 } 122 return json; 123 } 124 125 private HttpMethodBase newGetRequest(Query<?> query) { 126 try { 127 String url = server.getHost() + URIUtil.encodeQuery(query.getUrl()); 128 HttpMethodBase method = new GetMethod(url); 129 method.setRequestHeader("Accept", "application/json"); 130 return method; 131 132 } catch (URIException e) { 133 throw new ConnectionException("Query: " + query, e); 134 } 135 } 136 137 private HttpMethodBase newPostRequest(CreateQuery<?> query) { 138 try { 139 String url = server.getHost() + URIUtil.encodeQuery(query.getUrl()); 140 PostMethod method = new PostMethod(url); 141 method.setRequestHeader("Accept", "application/json"); 142 if (query.getBody() != null) { 143 method.setRequestEntity(new StringRequestEntity(query.getBody(), "text/plain; charset=UTF-8", "UTF-8")); 144 } 145 return method; 146 147 } catch (URIException e) { 148 throw new ConnectionException("Query: " + query, e); 149 } catch (UnsupportedEncodingException e) { 150 throw new ConnectionException("Unsupported encoding", e); 151 } 152 } 153 154 private HttpMethodBase newPutRequest(UpdateQuery<?> query) { 155 try { 156 String url = server.getHost() + URIUtil.encodeQuery(query.getUrl()); 157 PutMethod method = new PutMethod(url); 158 method.setRequestHeader("Accept", "application/json"); 159 if (query.getBody() != null) { 160 method.setRequestEntity(new StringRequestEntity(query.getBody(), "text/plain; charset=UTF-8", "UTF-8")); 161 } 162 return method; 163 164 } catch (URIException e) { 165 throw new ConnectionException("Query: " + query, e); 166 } catch (UnsupportedEncodingException e) { 167 throw new ConnectionException("Unsupported encoding", e); 168 } 169 } 170 171 private HttpMethodBase newDeleteRequest(DeleteQuery<?> query) { 172 try { 173 String url = server.getHost() + URIUtil.encodeQuery(query.getUrl()); 174 HttpMethodBase method = new DeleteMethod(url); 175 method.setRequestHeader("Accept", "application/json"); 176 return method; 177 178 } catch (URIException e) { 179 throw new ConnectionException("Query: " + query, e); 180 } 181 } 182 183 private String getResponseBodyAsString(HttpMethod method) { 184 BufferedReader reader = null; 185 try { 186 final InputStream inputStream = method.getResponseBodyAsStream(); 187 reader = new BufferedReader(new InputStreamReader(inputStream)); 188 final StringBuilder sb = new StringBuilder(); 189 String line; 190 191 while ((line = reader.readLine()) != null) { 192 sb.append(line).append("\n"); 193 } 194 return sb.toString(); 195 196 } catch (IOException e) { 197 throw new ConnectionException("Can not read response", e); 198 199 } finally { 200 if (reader != null) { 201 try { 202 reader.close(); 203 204 } catch (Exception e) { 205 // TODO 206 } 207 } 208 } 209 } 210 }