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.api.utils;
021
022 import org.apache.commons.configuration.Configuration;
023 import org.apache.commons.io.IOUtils;
024 import org.apache.commons.lang.StringUtils;
025 import org.sonar.api.BatchComponent;
026
027 import java.io.IOException;
028 import java.io.InputStream;
029 import java.io.InputStreamReader;
030 import java.io.Reader;
031 import java.net.HttpURLConnection;
032 import java.net.URL;
033
034 /**
035 * @since 1.10
036 */
037 public class ServerHttpClient implements BatchComponent {
038
039 protected static final String SERVER_API_PATH = "/api/server";
040 private static final String KEY_PATH = SERVER_API_PATH + "/key";
041 private static final String VERSION_PATH = SERVER_API_PATH + "/version";
042 protected static final String MAVEN_PATH = "/deploy/maven";
043 private static final int CONNECT_TIMEOUT_MILLISECONDS = 30000;
044 private static final int READ_TIMEOUT_MILLISECONDS = 60000;
045
046 private String url;
047 private Integer connectTimeoutMiliseconds = CONNECT_TIMEOUT_MILLISECONDS;
048 private Integer readTimeoutMiliseconds = READ_TIMEOUT_MILLISECONDS;
049
050 public ServerHttpClient(String remoteServerUrl) {
051 this(remoteServerUrl, null, null);
052 }
053
054 public ServerHttpClient(String remoteServerUrl, Integer connectTimeoutMiliseconds, Integer readTimeoutMiliseconds) {
055 this.url = StringUtils.chomp(remoteServerUrl, "/");
056 if (connectTimeoutMiliseconds != null) {
057 this.connectTimeoutMiliseconds = connectTimeoutMiliseconds;
058 }
059 if (readTimeoutMiliseconds != null) {
060 this.readTimeoutMiliseconds = readTimeoutMiliseconds;
061 }
062
063 }
064
065 public ServerHttpClient(Configuration configuration) {
066 this(configuration.getString("sonar.host.url", "http://localhost:9000"),
067 configuration.getInteger("sonar.host.connectTimeoutMs", CONNECT_TIMEOUT_MILLISECONDS),
068 configuration.getInteger("sonar.host.readTimeoutMs", READ_TIMEOUT_MILLISECONDS));
069
070 }
071
072 /**
073 * Throws a runtime ServerConnectionException if it fails to connect Sonar server
074 */
075 public void checkUp() {
076 String exceptionLabel = "Sonar server at " + url +
077 " is unreacheable. Either start it or setup the sonar.host.url maven setting if the URL is incorrect";
078 if (getId() == null) {
079 throw new ServerConnectionException(exceptionLabel);
080 }
081 }
082
083 public String getId() {
084 return executeAction(KEY_PATH);
085 }
086
087 public String getVersion() {
088 return executeAction(VERSION_PATH);
089 }
090
091 public String getMavenRepositoryUrl() {
092 return this.url + MAVEN_PATH;
093 }
094
095 protected String executeAction(String action) {
096 String result = getRemoteContent(url + action);
097 if (result.trim().length() == 0) {
098 throw new ServerApiEmptyContentException("Empty " + action + " returned from server");
099 }
100 return result;
101 }
102
103 protected String getRemoteContent(String url) {
104 HttpURLConnection conn = null;
105 Reader reader = null;
106 try {
107 conn = getConnection(url, "GET");
108 reader = new InputStreamReader((InputStream) conn.getContent());
109
110 int statusCode = conn.getResponseCode();
111 if (statusCode != HttpURLConnection.HTTP_OK) {
112 throw new ServerConnectionException("Status returned by url : '" + url + "' is invalid : " + statusCode);
113 }
114
115 return IOUtils.toString(reader);
116 } catch (IOException e) {
117 throw new ServerConnectionException("url=" + url, e);
118
119 } finally {
120 IOUtils.closeQuietly(reader);
121 if (conn != null) {
122 conn.disconnect();
123 }
124 }
125 }
126
127 public String getUrl() {
128 return url;
129 }
130
131 private HttpURLConnection getConnection(String url, String method) throws IOException {
132 URL page = new URL(url);
133 HttpURLConnection conn = (HttpURLConnection) page.openConnection();
134 conn.setConnectTimeout(connectTimeoutMiliseconds);
135 conn.setReadTimeout(readTimeoutMiliseconds);
136
137 conn.setRequestMethod(method);
138 conn.connect();
139 return conn;
140 }
141
142 public static class ServerApiEmptyContentException extends SonarException {
143
144 public ServerApiEmptyContentException(String s) {
145 super(s);
146 }
147 }
148
149 public static class ServerConnectionException extends SonarException {
150
151 public ServerConnectionException(String msg) {
152 super(msg);
153 }
154
155 public ServerConnectionException(String msg, Throwable throwable) {
156 super(msg, throwable);
157 }
158
159 }
160 }