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.HTTP_CREATED;
031    import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
032    import static java.net.HttpURLConnection.HTTP_OK;
033    
034    /**
035     * Not an API. Please do not use this class, except maybe for unit tests.
036     */
037    public class HttpRequestFactory {
038    
039      private static final int[] RESPONSE_SUCCESS = {HTTP_OK, HTTP_CREATED, HTTP_NO_CONTENT};
040    
041      private final String baseUrl;
042      private String login, password, proxyHost, proxyLogin, proxyPassword;
043      private int proxyPort;
044      private int connectTimeoutInMilliseconds;
045      private int readTimeoutInMilliseconds;
046    
047      public HttpRequestFactory(String baseUrl) {
048        this.baseUrl = baseUrl;
049      }
050    
051      public HttpRequestFactory setLogin(@Nullable String login) {
052        this.login = login;
053        return this;
054      }
055    
056      public HttpRequestFactory setPassword(@Nullable String password) {
057        this.password = password;
058        return this;
059      }
060    
061      public HttpRequestFactory setProxyHost(@Nullable String proxyHost) {
062        this.proxyHost = proxyHost;
063        return this;
064      }
065    
066      public HttpRequestFactory setProxyLogin(@Nullable String proxyLogin) {
067        this.proxyLogin = proxyLogin;
068        return this;
069      }
070    
071      public HttpRequestFactory setProxyPassword(@Nullable String proxyPassword) {
072        this.proxyPassword = proxyPassword;
073        return this;
074      }
075    
076      public HttpRequestFactory setProxyPort(int proxyPort) {
077        this.proxyPort = proxyPort;
078        return this;
079      }
080    
081      public HttpRequestFactory setConnectTimeoutInMilliseconds(int connectTimeoutInMilliseconds) {
082        this.connectTimeoutInMilliseconds = connectTimeoutInMilliseconds;
083        return this;
084      }
085    
086      public HttpRequestFactory setReadTimeoutInMilliseconds(int readTimeoutInMilliseconds) {
087        this.readTimeoutInMilliseconds = readTimeoutInMilliseconds;
088        return this;
089      }
090    
091      public String getBaseUrl() {
092        return baseUrl;
093      }
094    
095      public String getLogin() {
096        return login;
097      }
098    
099      public String getPassword() {
100        return password;
101      }
102    
103      public String getProxyHost() {
104        return proxyHost;
105      }
106    
107      public String getProxyLogin() {
108        return proxyLogin;
109      }
110    
111      public String getProxyPassword() {
112        return proxyPassword;
113      }
114    
115      public int getProxyPort() {
116        return proxyPort;
117      }
118    
119      public int getConnectTimeoutInMilliseconds() {
120        return connectTimeoutInMilliseconds;
121      }
122    
123      public int getReadTimeoutInMilliseconds() {
124        return readTimeoutInMilliseconds;
125      }
126    
127      public String get(String wsUrl, Map<String, Object> queryParams) {
128        HttpRequest request = prepare(HttpRequest.get(buildUrl(wsUrl), queryParams, true));
129        return execute(request);
130      }
131    
132      public String post(String wsUrl, Map<String, Object> queryParams) {
133        HttpRequest request = prepare(HttpRequest.post(buildUrl(wsUrl), true)).form(queryParams, HttpRequest.CHARSET_UTF8);
134        return execute(request);
135      }
136    
137      private String buildUrl(String part) {
138        StringBuilder url = new StringBuilder();
139        url.append(baseUrl);
140        if (!part.startsWith("/")) {
141          url.append('/');
142        }
143        url.append(part);
144        return url.toString();
145      }
146    
147      private String execute(HttpRequest request) {
148        try {
149          if (isSuccess(request)) {
150            return request.body(HttpRequest.CHARSET_UTF8);
151          }
152          // TODO handle error messages
153          throw new HttpException(request.url().toString(), request.code());
154    
155        } catch (HttpRequest.HttpRequestException e) {
156          throw new IllegalStateException("Fail to request " + request.url(), e.getCause());
157        }
158      }
159    
160      private boolean isSuccess(HttpRequest request) {
161        return Arrays.binarySearch(RESPONSE_SUCCESS, request.code()) >= 0;
162      }
163    
164      private HttpRequest prepare(HttpRequest request) {
165        if (proxyHost != null) {
166          request.useProxy(proxyHost, proxyPort);
167          if (proxyLogin != null) {
168            request.proxyBasic(proxyLogin, proxyPassword);
169          }
170        }
171        request
172          .acceptGzipEncoding()
173          .uncompress(true)
174          .acceptJson()
175          .acceptCharset(HttpRequest.CHARSET_UTF8)
176          .connectTimeout(connectTimeoutInMilliseconds)
177          .readTimeout(readTimeoutInMilliseconds)
178          .trustAllCerts()
179          .trustAllHosts();
180        if (login != null) {
181          request.basic(login, password);
182        }
183        return request;
184      }
185    }