001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2009 SonarSource SA
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.params.HttpConnectionManagerParams;
028 import org.apache.commons.httpclient.util.URIUtil;
029 import org.sonar.wsclient.Host;
030 import org.sonar.wsclient.services.CreateQuery;
031 import org.sonar.wsclient.services.DeleteQuery;
032 import org.sonar.wsclient.services.Query;
033
034 import java.io.BufferedReader;
035 import java.io.IOException;
036 import java.io.InputStream;
037 import java.io.InputStreamReader;
038
039 /**
040 * @since 2.1
041 */
042 public class HttpClient3Connector extends Connector {
043
044 private static final int MAX_TOTAL_CONNECTIONS = 40;
045 private static final int MAX_HOST_CONNECTIONS = 4;
046
047 private final Host server;
048 private HttpClient httpClient;
049
050 public HttpClient3Connector(final Host server) {
051 this.server = server;
052 createClient();
053 }
054
055 public HttpClient3Connector(Host server, HttpClient httpClient) {
056 this.httpClient = httpClient;
057 this.server = server;
058 }
059
060 private void createClient() {
061 final HttpConnectionManagerParams params = new HttpConnectionManagerParams();
062 params.setConnectionTimeout(TIMEOUT_MS);
063 params.setSoTimeout(TIMEOUT_MS);
064 params.setDefaultMaxConnectionsPerHost(MAX_HOST_CONNECTIONS);
065 params.setMaxTotalConnections(MAX_TOTAL_CONNECTIONS);
066 final MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
067 connectionManager.setParams(params);
068 this.httpClient = new HttpClient(connectionManager);
069 configureCredentials();
070 }
071
072 private void configureCredentials() {
073 if (server.getUsername() != null) {
074 httpClient.getParams().setAuthenticationPreemptive(true);
075 Credentials defaultcreds = new UsernamePasswordCredentials(server.getUsername(), server.getPassword());
076 httpClient.getState().setCredentials(AuthScope.ANY, defaultcreds);
077 }
078 }
079
080 public String execute(Query query) {
081 return executeRequest(newGetRequest(query));
082 }
083
084 public String execute(CreateQuery query) {
085 return executeRequest(newPostRequest(query));
086 }
087
088 public String execute(DeleteQuery query) {
089 return executeRequest(newDeleteRequest(query));
090 }
091
092 private String executeRequest(HttpMethodBase method) {
093 String json = null;
094 try {
095 httpClient.executeMethod(method);
096 if (method.getStatusCode() == HttpStatus.SC_OK) {
097 json = getResponseBodyAsString(method);
098
099 } else if (method.getStatusCode() != HttpStatus.SC_NOT_FOUND) {
100 throw new ConnectionException("HTTP error: " + method.getStatusCode() + ", msg: " + method.getStatusText() + ", query: " + method);
101 }
102
103 } catch (HttpException e) {
104 throw new ConnectionException("Query: " + method, e);
105
106 } catch (IOException e) {
107 throw new ConnectionException("Query: " + method, e);
108
109 } finally {
110 if (method != null) {
111 method.releaseConnection();
112 }
113 }
114 return json;
115 }
116
117 private HttpMethodBase newGetRequest(Query query) {
118 try {
119 String url = server.getHost() + URIUtil.encodeQuery(query.getUrl());
120 HttpMethodBase method = new GetMethod(url);
121 method.setRequestHeader("Accept", "application/json");
122 return method;
123
124 } catch (URIException e) {
125 throw new ConnectionException("Query: " + query, e);
126 }
127 }
128
129 private HttpMethodBase newPostRequest(CreateQuery query) {
130 try {
131 String url = server.getHost() + URIUtil.encodeQuery(query.getUrl());
132 HttpMethodBase method = new PostMethod(url);
133 method.setRequestHeader("Accept", "application/json");
134 return method;
135
136 } catch (URIException e) {
137 throw new ConnectionException("Query: " + query, e);
138 }
139 }
140
141 private HttpMethodBase newDeleteRequest(DeleteQuery query) {
142 try {
143 String url = server.getHost() + URIUtil.encodeQuery(query.getUrl());
144 HttpMethodBase method = new DeleteMethod(url);
145 method.setRequestHeader("Accept", "application/json");
146 return method;
147
148 } catch (URIException e) {
149 throw new ConnectionException("Query: " + query, e);
150 }
151 }
152
153 private String getResponseBodyAsString(HttpMethod method) {
154 BufferedReader reader = null;
155 try {
156 final InputStream inputStream = method.getResponseBodyAsStream();
157 reader = new BufferedReader(new InputStreamReader(inputStream));
158 final StringBuilder sb = new StringBuilder();
159 String line;
160
161 while ((line = reader.readLine()) != null) {
162 sb.append(line).append("\n");
163 }
164 return sb.toString();
165
166 } catch (IOException e) {
167 throw new ConnectionException("Can not read response", e);
168
169 } finally {
170 if (reader != null) {
171 try {
172 reader.close();
173
174 } catch (Exception e) {
175 // TODO
176 }
177 }
178 }
179 }
180 }