001    /*
002     * SonarQube, open source software quality management tool.
003     * Copyright (C) 2008-2014 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * SonarQube 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     * SonarQube 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 License
017     * along with this program; if not, write to the Free Software Foundation,
018     * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019     */
020    package org.sonar.wsclient.internal;
021    
022    import com.github.kevinsawicki.http.HttpRequest;
023    import org.sonar.wsclient.base.HttpException;
024    
025    import javax.annotation.Nullable;
026    
027    import java.util.Arrays;
028    import java.util.Map;
029    
030    import static java.net.HttpURLConnection.*;
031    
032    /**
033     * Not an API. Please do not use this class, except maybe for unit tests.
034     */
035    public class HttpRequestFactory {
036    
037      private static final int[] RESPONSE_SUCCESS = {HTTP_OK, HTTP_CREATED, HTTP_NO_CONTENT};
038    
039      private final String baseUrl;
040      private String login, password, proxyHost, proxyLogin, proxyPassword;
041      private int proxyPort;
042      private int connectTimeoutInMilliseconds;
043      private int readTimeoutInMilliseconds;
044    
045      public HttpRequestFactory(String baseUrl) {
046        this.baseUrl = baseUrl;
047      }
048    
049      public HttpRequestFactory setLogin(@Nullable String login) {
050        this.login = login;
051        return this;
052      }
053    
054      public HttpRequestFactory setPassword(@Nullable String password) {
055        this.password = password;
056        return this;
057      }
058    
059      public HttpRequestFactory setProxyHost(@Nullable String proxyHost) {
060        this.proxyHost = proxyHost;
061        return this;
062      }
063    
064      public HttpRequestFactory setProxyLogin(@Nullable String proxyLogin) {
065        this.proxyLogin = proxyLogin;
066        return this;
067      }
068    
069      public HttpRequestFactory setProxyPassword(@Nullable String proxyPassword) {
070        this.proxyPassword = proxyPassword;
071        return this;
072      }
073    
074      public HttpRequestFactory setProxyPort(int proxyPort) {
075        this.proxyPort = proxyPort;
076        return this;
077      }
078    
079      public HttpRequestFactory setConnectTimeoutInMilliseconds(int connectTimeoutInMilliseconds) {
080        this.connectTimeoutInMilliseconds = connectTimeoutInMilliseconds;
081        return this;
082      }
083    
084      public HttpRequestFactory setReadTimeoutInMilliseconds(int readTimeoutInMilliseconds) {
085        this.readTimeoutInMilliseconds = readTimeoutInMilliseconds;
086        return this;
087      }
088    
089      public String getBaseUrl() {
090        return baseUrl;
091      }
092    
093      public String getLogin() {
094        return login;
095      }
096    
097      public String getPassword() {
098        return password;
099      }
100    
101      public String getProxyHost() {
102        return proxyHost;
103      }
104    
105      public String getProxyLogin() {
106        return proxyLogin;
107      }
108    
109      public String getProxyPassword() {
110        return proxyPassword;
111      }
112    
113      public int getProxyPort() {
114        return proxyPort;
115      }
116    
117      public int getConnectTimeoutInMilliseconds() {
118        return connectTimeoutInMilliseconds;
119      }
120    
121      public int getReadTimeoutInMilliseconds() {
122        return readTimeoutInMilliseconds;
123      }
124    
125      public String get(String wsUrl, Map<String, Object> queryParams) {
126        HttpRequest request = prepare(HttpRequest.get(buildUrl(wsUrl), queryParams, true));
127        return execute(request);
128      }
129    
130      public String post(String wsUrl, Map<String, Object> queryParams) {
131        HttpRequest request = prepare(HttpRequest.post(buildUrl(wsUrl), true)).form(queryParams, HttpRequest.CHARSET_UTF8);
132        return execute(request);
133      }
134    
135      private String buildUrl(String part) {
136        StringBuilder url = new StringBuilder();
137        url.append(baseUrl);
138        if (!part.startsWith("/")) {
139          url.append('/');
140        }
141        url.append(part);
142        return url.toString();
143      }
144    
145      private String execute(HttpRequest request) {
146        try {
147          if (isSuccess(request)) {
148            return request.body(HttpRequest.CHARSET_UTF8);
149          }
150          // TODO better handle error messages
151          throw new HttpException(request.url().toString(), request.code(), request.body());
152    
153        } catch (HttpRequest.HttpRequestException e) {
154          throw new IllegalStateException("Fail to request " + request.url(), e.getCause());
155        }
156      }
157    
158      private boolean isSuccess(HttpRequest request) {
159        return Arrays.binarySearch(RESPONSE_SUCCESS, request.code()) >= 0;
160      }
161    
162      private HttpRequest prepare(HttpRequest request) {
163        if (proxyHost != null) {
164          request.useProxy(proxyHost, proxyPort);
165          if (proxyLogin != null) {
166            request.proxyBasic(proxyLogin, proxyPassword);
167          }
168        }
169        request
170          .acceptGzipEncoding()
171          .uncompress(true)
172          .acceptJson()
173          .acceptCharset(HttpRequest.CHARSET_UTF8)
174          .connectTimeout(connectTimeoutInMilliseconds)
175          .readTimeout(readTimeoutInMilliseconds)
176          .trustAllCerts()
177          .trustAllHosts();
178        if (login != null) {
179          request.basic(login, password);
180        }
181        return request;
182      }
183    }