diff --git a/core/src/main/java/org/jclouds/Constants.java b/core/src/main/java/org/jclouds/Constants.java
index 9204863fe7..110d74732d 100644
--- a/core/src/main/java/org/jclouds/Constants.java
+++ b/core/src/main/java/org/jclouds/Constants.java
@@ -145,6 +145,14 @@ public interface Constants {
*/
public static final String PROPERTY_PROXY_PASSWORD = "jclouds.proxy-password";
+ /**
+ * Boolean property. Default true.
+ *
+ * If a proxy server is configured, it will be used for all types of schemes.
+ * Set to false to not use a proxy server for sockets (such as ssh access).
+ */
+ public static final String PROPERTY_PROXY_FOR_SOCKETS = "jclouds.proxy-for-sockets";
+
/**
* Integer property.
*
diff --git a/core/src/main/java/org/jclouds/proxy/ProxyForURI.java b/core/src/main/java/org/jclouds/proxy/ProxyForURI.java
index 09e046429d..e2e4220233 100644
--- a/core/src/main/java/org/jclouds/proxy/ProxyForURI.java
+++ b/core/src/main/java/org/jclouds/proxy/ProxyForURI.java
@@ -20,6 +20,7 @@ package org.jclouds.proxy;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.getLast;
+import static org.jclouds.Constants.PROPERTY_PROXY_FOR_SOCKETS;
import java.net.Authenticator;
import java.net.InetSocketAddress;
@@ -29,6 +30,7 @@ import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
+import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.domain.Credentials;
@@ -45,6 +47,10 @@ import com.google.inject.Inject;
public class ProxyForURI implements Function {
private final ProxyConfig config;
+ @Inject(optional = true)
+ @Named(PROPERTY_PROXY_FOR_SOCKETS)
+ private boolean useProxyForSockets = true;
+
@VisibleForTesting
@Inject
ProxyForURI(ProxyConfig config) {
@@ -62,7 +68,9 @@ public class ProxyForURI implements Function {
*/
@Override
public Proxy apply(URI endpoint) {
- if (config.useSystem()) {
+ if (!useProxyForSockets && "socket".equals(endpoint.getScheme())) {
+ return Proxy.NO_PROXY;
+ } else if (config.useSystem()) {
System.setProperty("java.net.useSystemProxies", "true");
Iterable proxies = ProxySelector.getDefault().select(endpoint);
return getLast(proxies);
diff --git a/core/src/test/java/org/jclouds/proxy/ProxyForURITest.java b/core/src/test/java/org/jclouds/proxy/ProxyForURITest.java
new file mode 100644
index 0000000000..f6a0218615
--- /dev/null
+++ b/core/src/test/java/org/jclouds/proxy/ProxyForURITest.java
@@ -0,0 +1,153 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.proxy;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.lang.reflect.Field;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.Proxy.Type;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.jclouds.domain.Credentials;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Optional;
+import com.google.common.net.HostAndPort;
+
+public class ProxyForURITest {
+
+ private Optional noHostAndPort = Optional.absent();
+ private Optional noCreds = Optional.absent();
+ private Optional hostAndPort = Optional.of(HostAndPort.fromParts("proxy.example.com", 8080));
+ private Optional creds = Optional.of(new Credentials("user", "pwd"));
+
+ private class MyProxyConfig implements ProxyConfig {
+ private boolean useSystem;
+ private Type type;
+ private Optional proxy;
+ private Optional credentials;
+
+ MyProxyConfig(boolean useSystem, Type type, Optional proxy, Optional credentials) {
+ this.useSystem = useSystem;
+ this.type = type;
+ this.proxy = proxy;
+ this.credentials = credentials;
+ }
+
+ @Override
+ public boolean useSystem() {
+ return useSystem;
+ }
+
+ @Override
+ public Type getType() {
+ return type;
+ }
+
+ @Override
+ public Optional getProxy() {
+ return proxy;
+ }
+
+ @Override
+ public Optional getCredentials() {
+ return credentials;
+ }
+ }
+
+ @Test
+ public void testDontUseProxyForSockets() throws Exception {
+ ProxyConfig config = new MyProxyConfig(false, Proxy.Type.HTTP, hostAndPort, creds);
+ ProxyForURI proxy = new ProxyForURI(config);
+ Field useProxyForSockets = proxy.getClass().getDeclaredField("useProxyForSockets");
+ useProxyForSockets.setAccessible(true);
+ useProxyForSockets.setBoolean(proxy, false);
+ URI uri = new URI("socket://ssh.example.com:22");
+ assertEquals(proxy.apply(uri), Proxy.NO_PROXY);
+ }
+
+ @Test
+ public void testUseProxyForSockets() throws Exception {
+ ProxyConfig config = new MyProxyConfig(false, Proxy.Type.HTTP, hostAndPort, creds);
+ ProxyForURI proxy = new ProxyForURI(config);
+ URI uri = new URI("socket://ssh.example.com:22");
+ assertEquals(proxy.apply(uri), new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.example.com", 8080)));
+ }
+
+ @Test
+ public void testUseProxyForSocketsSettingShouldntAffectHTTP() throws Exception {
+ ProxyConfig config = new MyProxyConfig(false, Proxy.Type.HTTP, hostAndPort, creds);
+ ProxyForURI proxy = new ProxyForURI(config);
+ Field useProxyForSockets = proxy.getClass().getDeclaredField("useProxyForSockets");
+ useProxyForSockets.setAccessible(true);
+ useProxyForSockets.setBoolean(proxy, false);
+ URI uri = new URI("http://example.com/file");
+ assertEquals(proxy.apply(uri), new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.example.com", 8080)));
+ }
+
+ @Test
+ public void testHTTPDirect() throws URISyntaxException {
+ ProxyConfig config = new MyProxyConfig(false, Proxy.Type.DIRECT, noHostAndPort, noCreds);
+ URI uri = new URI("http://example.com/file");
+ assertEquals(new ProxyForURI(config).apply(uri), Proxy.NO_PROXY);
+ }
+
+ @Test
+ public void testHTTPSDirect() throws URISyntaxException {
+ ProxyConfig config = new MyProxyConfig(false, Proxy.Type.DIRECT, noHostAndPort, noCreds);
+ URI uri = new URI("https://example.com/file");
+ assertEquals(new ProxyForURI(config).apply(uri), Proxy.NO_PROXY);
+ }
+
+ @Test
+ public void testFTPDirect() throws URISyntaxException {
+ ProxyConfig config = new MyProxyConfig(false, Proxy.Type.DIRECT, noHostAndPort, noCreds);
+ URI uri = new URI("ftp://ftp.example.com/file");
+ assertEquals(new ProxyForURI(config).apply(uri), Proxy.NO_PROXY);
+ }
+
+ @Test
+ public void testSocketDirect() throws URISyntaxException {
+ ProxyConfig config = new MyProxyConfig(false, Proxy.Type.DIRECT, noHostAndPort, noCreds);
+ URI uri = new URI("socket://ssh.example.com:22");
+ assertEquals(new ProxyForURI(config).apply(uri), Proxy.NO_PROXY);
+ }
+
+ @Test
+ public void testHTTPThroughHTTPProxy() throws URISyntaxException {
+ ProxyConfig config = new MyProxyConfig(false, Proxy.Type.HTTP, hostAndPort, creds);
+ URI uri = new URI("http://example.com/file");
+ assertEquals(new ProxyForURI(config).apply(uri), new Proxy(Proxy.Type.HTTP, new InetSocketAddress(
+ "proxy.example.com", 8080)));
+ }
+
+ @Test
+ public void testHTTPThroughSystemProxy() throws URISyntaxException {
+ ProxyConfig config = new MyProxyConfig(true, Proxy.Type.DIRECT, noHostAndPort, noCreds);
+ URI uri = new URI("http://example.com/file");
+ // could return a proxy, could return NO_PROXY, depends on the tester's
+ // environment
+ assertNotNull(new ProxyForURI(config).apply(uri));
+ }
+
+}