#---------------------------------------------------------
# The Update Center requires an internet connection to request http://update.sonarsource.org
-# If needed, HTTP proxy can be configured with standard Java environment variables : -Dhttp.proxyHost
-# and -Dhttp.proxyPort. System configuration can also be used with -Djava.net.useSystemProxies=true.
-# These properties can not be set in this file.
-
-# Update Center is activated by default.
+# It is activated by default:
#sonar.updatecenter.activate=true
+
+# HTTP proxy (default none)
+#http.proxyHost=
+#http.proxyPort=
+
+# NT domain name if NTLM proxy is used
+#http.auth.ntlm.domain=
+
+# SOCKS proxy (default none)
+#socksProxyHost=
+#socksProxyPort=
+
+# proxy authentication. The 2 following properties are used for HTTP and SOCKS proxies.
+#http.proxyUser=
+#http.proxyPassword=
\ No newline at end of file
*/
package org.sonar.api.utils;
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.LoggerFactory;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.URI;
+import java.net.*;
+import java.util.List;
/**
- * Simple class to download a file from a HTTP repository.
- *
+ * This component downloads HTTP files. It currently does not reuse maven proxy configuration on the batch side.
+ *
* @since 2.2
*/
public class HttpDownloader implements BatchComponent, ServerComponent {
public static final int TIMEOUT_MILLISECONDS = 20 * 1000;
+
+ private String userAgent;
+
+ public HttpDownloader(Server server, Configuration configuration) {
+ this(configuration, server.getVersion());
+ }
+
+ public HttpDownloader(Configuration configuration) {
+ this(configuration, null);
+ }
+
+ /**
+ * for unit tests
+ */
+ HttpDownloader() {
+ this(new PropertiesConfiguration(), null);
+ }
- private Server server = null;
+ private HttpDownloader(Configuration configuration, String userAgent) {
+ initProxy(configuration);
+ initUserAgent(userAgent);
+ }
+
+ private void initProxy(Configuration configuration) {
+ propagateProxySystemProperties(configuration);
+ if (requiresProxyAuthentication(configuration)) {
+ registerProxyCredentials(configuration);
+ }
+ }
- public HttpDownloader(Server server) {
- this.server = server;
+ private void initUserAgent(String sonarVersion) {
+ String userAgent = (sonarVersion == null ? "Sonar" : String.format("Sonar %s", sonarVersion));
+ System.setProperty("http.agent", userAgent);
+ this.userAgent = userAgent;
}
- public HttpDownloader() {
+ public String getProxySynthesis(URI uri) {
+ return getProxySynthesis(uri, ProxySelector.getDefault());
+ }
+
+ static String getProxySynthesis(URI uri, ProxySelector proxySelector) {
+ List<String> descriptions = Lists.newArrayList();
+ List<Proxy> proxies = proxySelector.select(uri);
+ if (proxies.size() == 1 && proxies.get(0).type().equals(Proxy.Type.DIRECT)) {
+ descriptions.add("no proxy");
+ } else {
+ for (Proxy proxy : proxies) {
+ if (!proxy.type().equals(Proxy.Type.DIRECT)) {
+ descriptions.add("proxy: " + proxy.address().toString());
+ }
+ }
+ }
+ return Joiner.on(", ").join(descriptions);
+ }
+
+ private void registerProxyCredentials(Configuration configuration) {
+ Authenticator.setDefault(new ProxyAuthenticator(configuration.getString("http.proxyUser"), configuration.getString("http.proxyPassword")));
+ }
+
+ private boolean requiresProxyAuthentication(Configuration configuration) {
+ return configuration.getString("http.proxyUser") != null;
+ }
+
+ private void propagateProxySystemProperties(Configuration configuration) {
+ propagateSystemProperty(configuration, "http.proxyHost");
+ propagateSystemProperty(configuration, "http.proxyPort");
+ propagateSystemProperty(configuration, "http.nonProxyHosts");
+ propagateSystemProperty(configuration, "http.auth.ntlm.domain");
+ propagateSystemProperty(configuration, "socksProxyHost");
+ propagateSystemProperty(configuration, "socksProxyPort");
+ }
+
+ private void propagateSystemProperty(Configuration configuration, String key) {
+ if (configuration.getString(key) != null) {
+ System.setProperty(key, configuration.getString(key));
+ }
}
public void download(URI uri, File toFile) {
} catch (Exception e) {
IOUtils.closeQuietly(output);
FileUtils.deleteQuietly(toFile);
- throw new SonarException("Fail to download the file: " + uri, e);
+ throw new SonarException("Fail to download the file: " + uri + getProxySynthesis(uri), e);
} finally {
IOUtils.closeQuietly(input);
return IOUtils.toByteArray(input);
} catch (Exception e) {
- throw new SonarException("Fail to download the file: " + uri, e);
+ throw new SonarException("Fail to download the file: " + uri + getProxySynthesis(uri), e);
} finally {
IOUtils.closeQuietly(input);
return connection.getInputStream();
} catch (Exception e) {
- throw new SonarException("Fail to download the file: " + uri, e);
+ throw new SonarException("Fail to download the file: " + uri + getProxySynthesis(uri), e);
}
}
private HttpURLConnection newHttpConnection(URI uri) throws IOException {
- LoggerFactory.getLogger(getClass()).info("Download: " + uri);
+ LoggerFactory.getLogger(getClass()).info("Download: " + uri + getProxySynthesis(uri));
HttpURLConnection connection = (HttpURLConnection) uri.toURL().openConnection();
connection.setConnectTimeout(TIMEOUT_MILLISECONDS);
connection.setReadTimeout(TIMEOUT_MILLISECONDS);
connection.setUseCaches(true);
- connection.setRequestProperty("User-Agent", getUserAgent());
connection.setInstanceFollowRedirects(true);
+ connection.setRequestProperty("User-Agent", userAgent);
return connection;
}
+}
+
+class ProxyAuthenticator extends Authenticator {
+ private PasswordAuthentication auth;
+
+ ProxyAuthenticator(String user, String password) {
+ auth = new PasswordAuthentication(user, password == null ? new char[0] : password.toCharArray());
+ }
- private String getUserAgent() {
- return (server != null ? "Sonar " + server.getVersion() : "Sonar");
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return auth;
}
}
*/
package org.sonar.api.utils;
+import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.junit.After;
import java.io.File;
import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
+import java.net.*;
+import java.util.Arrays;
import java.util.Properties;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.junit.internal.matchers.StringContains.containsString;
+import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
Server server = mock(Server.class);
when(server.getVersion()).thenReturn("2.2");
- byte[] bytes = new HttpDownloader(server).download(new URI(baseUrl));
+ byte[] bytes = new HttpDownloader(server, new PropertiesConfiguration()).download(new URI(baseUrl));
Properties props = new Properties();
props.load(IOUtils.toInputStream(new String(bytes)));
assertThat(props.getProperty("agent"), is("Sonar 2.2"));
public void followRedirect() throws URISyntaxException {
byte[] bytes = new HttpDownloader().download(new URI(baseUrl + "/redirect/"));
assertThat(new String(bytes), containsString("count"));
+ }
+
+ @Test
+ public void shouldGetDirectProxySynthesis() throws URISyntaxException {
+ ProxySelector proxySelector = mock(ProxySelector.class);
+ when(proxySelector.select((URI)anyObject())).thenReturn(Arrays.asList(Proxy.NO_PROXY));
+ assertThat(HttpDownloader.getProxySynthesis(new URI("http://an_url"), proxySelector), is("no proxy"));
+ }
+
+ @Test
+ public void shouldGetProxySynthesis() throws URISyntaxException {
+ ProxySelector proxySelector = mock(ProxySelector.class);
+ when(proxySelector.select((URI)anyObject())).thenReturn(Arrays.asList((Proxy)new FakeProxy()));
+ assertThat(HttpDownloader.getProxySynthesis(new URI("http://an_url"), proxySelector), is("proxy: http://proxy_url:4040"));
+ }
+}
+class FakeProxy extends Proxy {
+ public FakeProxy() {
+ super(Type.HTTP, new InetSocketAddress("http://proxy_url", 4040));
}
}
*/
package org.sonar.server.plugins;
-import com.google.common.base.Joiner;
-import com.google.common.collect.Lists;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.io.IOUtils;
import org.slf4j.LoggerFactory;
import org.sonar.api.ServerComponent;
import org.sonar.api.utils.HttpDownloader;
import org.sonar.api.utils.Logs;
-import org.sonar.api.utils.SonarException;
import org.sonar.updatecenter.common.UpdateCenter;
import org.sonar.updatecenter.common.UpdateCenterDeserializer;
import java.io.InputStream;
-import java.net.Proxy;
-import java.net.ProxySelector;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Date;
-import java.util.List;
import java.util.Properties;
/**
public static final String DEFAULT_URL = "http://update.sonarsource.org/update-center.properties";
public static final int PERIOD_IN_MILLISECONDS = 60 * 60 * 1000;
- private String url;
+ private URI uri;
private UpdateCenter center = null;
private long lastRefreshDate = 0;
private HttpDownloader downloader;
/**
* for unit tests
*/
- UpdateCenterClient(HttpDownloader downloader, String url) {
+ UpdateCenterClient(HttpDownloader downloader, URI uri) {
this.downloader = downloader;
- this.url = url;
- Logs.INFO.info("Update center: " + url + " (" + sumUpProxyConfiguration(url) + ")");
+ this.uri = uri;
+ Logs.INFO.info("Update center: " + uri + " (" + downloader.getProxySynthesis(uri) + ")");
}
- public UpdateCenterClient(HttpDownloader downloader, Configuration configuration) {
- this(downloader, configuration.getString(URL_PROPERTY, DEFAULT_URL));
+ public UpdateCenterClient(HttpDownloader downloader, Configuration configuration) throws URISyntaxException {
+ this(downloader, new URI(configuration.getString(URL_PROPERTY, DEFAULT_URL)));
}
public UpdateCenter getCenter() {
private UpdateCenter download() {
InputStream input = null;
try {
- input = downloader.openStream(new URI(url));
+ input = downloader.openStream(uri);
if (input != null) {
Properties properties = new Properties();
properties.load(input);
}
return null;
}
-
- private static String sumUpProxyConfiguration(String url) {
- return sumUpProxyConfiguration(url, ProxySelector.getDefault());
- }
-
- static String sumUpProxyConfiguration(String url, ProxySelector proxySelector) {
- try {
- List<String> descriptions = Lists.newArrayList();
- List<Proxy> proxies = proxySelector.select(new URI(url));
- if (proxies.size() == 1 && proxies.get(0).type().equals(Proxy.Type.DIRECT)) {
- descriptions.add("no HTTP proxy");
- } else {
- for (Proxy proxy : proxies) {
- if (!proxy.type().equals(Proxy.Type.DIRECT)) {
- descriptions.add("proxy: " + proxy.address().toString());
- }
- }
- }
- return Joiner.on(", ").join(descriptions);
-
- } catch (URISyntaxException e) {
- throw new SonarException("Can not load configuration of HTTP proxies");
- }
- }
}
import org.junit.Test;
import org.sonar.api.utils.HttpDownloader;
import org.sonar.api.utils.SonarException;
-import org.sonar.server.plugins.UpdateCenterClient;
import org.sonar.updatecenter.common.UpdateCenter;
import org.sonar.updatecenter.common.Version;
-import java.net.*;
-import java.util.Arrays;
+import java.net.URI;
+import java.net.URISyntaxException;
import static junit.framework.Assert.assertNull;
-import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.junit.internal.matchers.IsCollectionContaining.hasItems;
import static org.mockito.Matchers.anyObject;
@Before
public void startServer() throws Exception {
downloader = mock(HttpDownloader.class);
- client = new UpdateCenterClient(downloader, BASE_URL);
+ client = new UpdateCenterClient(downloader, new URI(BASE_URL));
}
@Test
verify(downloader, times(2)).openStream(new URI(BASE_URL));
}
-
- @Test
- public void shouldSumUpDirectProxyConfiguration() {
- ProxySelector proxySelector = mock(ProxySelector.class);
- when(proxySelector.select((URI)anyObject())).thenReturn(Arrays.asList(Proxy.NO_PROXY));
- assertThat(UpdateCenterClient.sumUpProxyConfiguration("http://updatecenter", proxySelector), is("no HTTP proxy"));
- }
-
- @Test
- public void shouldSumUpProxyConfiguration() {
- ProxySelector proxySelector = mock(ProxySelector.class);
- when(proxySelector.select((URI)anyObject())).thenReturn(Arrays.asList((Proxy)new FakeProxy()));
- assertThat(UpdateCenterClient.sumUpProxyConfiguration("http://updatecenter", proxySelector), is("proxy: http://updatecenter:80"));
- }
-
-
-}
-
-class FakeProxy extends Proxy {
-
- public FakeProxy() {
- super(Type.HTTP, new InetSocketAddress("http://updatecenter", 80));
- }
-}
+}
\ No newline at end of file