From 21ab1ae836314b958b97d5b6cab8392b1f60f46a Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Sat, 8 Dec 2012 13:03:58 -0800 Subject: [PATCH 1/3] switched to use SocketOpen from guice --- .../org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java | 5 +++-- .../internal/BaseCloudStackClientLiveTest.java | 5 +++-- .../jclouds/elasticstack/ElasticStackClientLiveTest.java | 5 +++-- .../vcloud_0_8/internal/BaseTerremarkClientLiveTest.java | 5 +++-- .../cloudapi/v6_5/features/MachineApiLiveTest.java | 5 +++-- .../org/jclouds/rds/features/InstanceApiLiveTest.java | 5 +++-- .../org/jclouds/savvis/vpdc/features/VMApiLiveTest.java | 5 +++-- .../java/org/jclouds/gogrid/GoGridLiveTestDisabled.java | 9 ++++----- 8 files changed, 25 insertions(+), 19 deletions(-) diff --git a/apis/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java b/apis/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java index e73df50d64..a36e097ee8 100644 --- a/apis/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java +++ b/apis/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java @@ -46,7 +46,7 @@ import org.jclouds.cloudsigma.util.Servers; import org.jclouds.compute.domain.ExecResponse; import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; import org.jclouds.domain.LoginCredentials; -import org.jclouds.predicates.InetSocketAddressConnect; +import org.jclouds.predicates.SocketOpen; import org.jclouds.rest.RestContext; import org.jclouds.ssh.SshClient; import org.jclouds.sshj.config.SshjSshClientModule; @@ -92,7 +92,8 @@ public class CloudSigmaClientLiveTest extends BaseComputeServiceContextLiveTest client = cloudSigmaContext.getApi(); driveNotClaimed = retry(Predicates.not(new DriveClaimed(client)), maxDriveImageTime, 1, SECONDS); - socketTester = retry(new InetSocketAddressConnect(), maxDriveImageTime, 1, SECONDS); + SocketOpen socketOpten = context.utils().injector().getInstance(SocketOpen.class); + socketTester = retry(socketOpten, maxDriveImageTime, 1, SECONDS); if (template == null || template.getImageId() == null) { imageId = view.getComputeService().templateBuilder().build().getImage().getId(); diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/internal/BaseCloudStackClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/internal/BaseCloudStackClientLiveTest.java index 1bda9c5f41..5cd97be5f8 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/internal/BaseCloudStackClientLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/internal/BaseCloudStackClientLiveTest.java @@ -54,7 +54,7 @@ import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult; import org.jclouds.compute.ComputeService; import org.jclouds.compute.domain.ExecResponse; import org.jclouds.compute.internal.BaseGenericComputeServiceContextLiveTest; -import org.jclouds.predicates.InetSocketAddressConnect; +import org.jclouds.predicates.SocketOpen; import org.jclouds.rest.RestContext; import org.jclouds.ssh.SshClient; import org.jclouds.sshj.config.SshjSshClientModule; @@ -224,7 +224,8 @@ public class BaseCloudStackClientLiveTest extends BaseGenericComputeServiceConte injector = cloudStackContext.utils().injector(); sshFactory = injector.getInstance(SshClient.Factory.class); - socketTester = retry(new InetSocketAddressConnect(), 180, 1, 1, SECONDS); + SocketOpen socketOpen = context.utils().injector().getInstance(SocketOpen.class); + socketTester = retry(socketOpen, 180, 1, 1, SECONDS); injector.injectMembers(socketTester); jobComplete = retry(new JobComplete(client), 1200, 1, 5, SECONDS); diff --git a/apis/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java b/apis/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java index f6769be965..e723212bd2 100644 --- a/apis/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java +++ b/apis/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java @@ -43,7 +43,7 @@ import org.jclouds.elasticstack.domain.ServerStatus; import org.jclouds.elasticstack.predicates.DriveClaimed; import org.jclouds.elasticstack.util.Servers; import org.jclouds.io.Payloads; -import org.jclouds.predicates.InetSocketAddressConnect; +import org.jclouds.predicates.SocketOpen; import org.jclouds.rest.RestContext; import org.jclouds.ssh.SshClient; import org.jclouds.sshj.config.SshjSshClientModule; @@ -89,7 +89,8 @@ public class ElasticStackClientLiveTest extends BaseComputeServiceContextLiveTes client = view.unwrap(ElasticStackApiMetadata.CONTEXT_TOKEN).getApi(); driveNotClaimed = retry(Predicates.not(new DriveClaimed(client)), maxDriveImageTime, 1, SECONDS); - socketTester = retry(new InetSocketAddressConnect(), maxDriveImageTime, 1, SECONDS); + SocketOpen socketOpen = context.utils().injector().getInstance(SocketOpen.class); + socketTester = retry(socketOpen, maxDriveImageTime, 1, SECONDS); } @Test diff --git a/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/internal/BaseTerremarkClientLiveTest.java b/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/internal/BaseTerremarkClientLiveTest.java index 25fd5e9f50..95ce36e4ad 100644 --- a/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/internal/BaseTerremarkClientLiveTest.java +++ b/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/internal/BaseTerremarkClientLiveTest.java @@ -23,7 +23,7 @@ import static org.jclouds.util.Predicates2.retry; import org.jclouds.compute.ComputeService; import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; -import org.jclouds.predicates.InetSocketAddressConnect; +import org.jclouds.predicates.SocketOpen; import org.jclouds.rest.RestContext; import org.jclouds.ssh.SshClient.Factory; import org.jclouds.sshj.config.SshjSshClientModule; @@ -62,7 +62,8 @@ public abstract class BaseTerremarkClientLiveTest() { public boolean apply(Machine input) { return api.get(input.getId()).getState() == Machine.State.RUNNING; diff --git a/labs/rds/src/test/java/org/jclouds/rds/features/InstanceApiLiveTest.java b/labs/rds/src/test/java/org/jclouds/rds/features/InstanceApiLiveTest.java index 0aa0d900f6..dcd0d1236e 100644 --- a/labs/rds/src/test/java/org/jclouds/rds/features/InstanceApiLiveTest.java +++ b/labs/rds/src/test/java/org/jclouds/rds/features/InstanceApiLiveTest.java @@ -29,7 +29,7 @@ import static org.testng.Assert.assertTrue; import java.util.logging.Logger; import org.jclouds.collect.IterableWithMarker; -import org.jclouds.predicates.InetSocketAddressConnect; +import org.jclouds.predicates.SocketOpen; import org.jclouds.rds.domain.Authorization; import org.jclouds.rds.domain.Authorization.Status; import org.jclouds.rds.domain.Instance; @@ -64,7 +64,8 @@ public class InstanceApiLiveTest extends BaseRDSApiLiveTest { public void setupContext() { super.setupContext(); securityGroup = createSecurityGroupAndAuthorizeIngressToAll(INSTANCE); - socketTester = retry(new InetSocketAddressConnect(), 180, 1, 1, SECONDS); + SocketOpen socketOpen = context.utils().injector().getInstance(SocketOpen.class); + socketTester = retry(socketOpen, 180, 1, 1, SECONDS); instanceAvailable = retry(new Predicate() { public boolean apply(Instance input) { return api().get(input.getId()).getStatus() == Instance.Status.AVAILABLE; diff --git a/labs/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/VMApiLiveTest.java b/labs/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/VMApiLiveTest.java index 3d335d7659..9d45548b91 100644 --- a/labs/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/VMApiLiveTest.java +++ b/labs/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/VMApiLiveTest.java @@ -29,7 +29,7 @@ import org.jclouds.cim.OSType; import org.jclouds.compute.domain.CIMOperatingSystem; import org.jclouds.compute.domain.ExecResponse; import org.jclouds.domain.LoginCredentials; -import org.jclouds.predicates.InetSocketAddressConnect; +import org.jclouds.predicates.SocketOpen; import org.jclouds.savvis.vpdc.domain.Network; import org.jclouds.savvis.vpdc.domain.Resource; import org.jclouds.savvis.vpdc.domain.Task; @@ -66,7 +66,8 @@ public class VMApiLiveTest extends BaseVPDCApiLiveTest { public void setupContext() { super.setupContext(); api = restContext.getApi().getVMApi(); - socketTester = retry(new InetSocketAddressConnect(), 130, 10, SECONDS);// make + SocketOpen socketOpen = context.utils().injector().getInstance(SocketOpen.class); + socketTester = retry(socketOpen, 130, 10, SECONDS);// make } private String billingSiteId; diff --git a/providers/gogrid/src/test/java/org/jclouds/gogrid/GoGridLiveTestDisabled.java b/providers/gogrid/src/test/java/org/jclouds/gogrid/GoGridLiveTestDisabled.java index bc92bfb652..5e5b54a5a5 100644 --- a/providers/gogrid/src/test/java/org/jclouds/gogrid/GoGridLiveTestDisabled.java +++ b/providers/gogrid/src/test/java/org/jclouds/gogrid/GoGridLiveTestDisabled.java @@ -53,7 +53,7 @@ import org.jclouds.gogrid.options.GetImageListOptions; import org.jclouds.gogrid.predicates.LoadBalancerLatestJobCompleted; import org.jclouds.gogrid.predicates.ServerLatestJobCompleted; import org.jclouds.javax.annotation.Nullable; -import org.jclouds.predicates.InetSocketAddressConnect; +import org.jclouds.predicates.SocketOpen; import org.jclouds.rest.RestContext; import org.jclouds.ssh.SshClient; import org.testng.SkipException; @@ -342,10 +342,9 @@ public class GoGridLiveTestDisabled extends BaseComputeServiceContextLiveTest { assertNotNull(instanceCredentials); HostAndPort socket = HostAndPort.fromParts(createdServer.getIp().getIp(), 22); - - Predicate socketOpen = retry(new InetSocketAddressConnect(), 180, 5, SECONDS); - - socketOpen.apply(socket); + SocketOpen socketOpen = context.utils().injector().getInstance(SocketOpen.class); + Predicate socketTester = retry(socketOpen, 180, 5, SECONDS); + socketTester.apply(socket); SshClient sshClient = gocontext.utils().injector().getInstance(SshClient.Factory.class).create(socket, instanceCredentials); sshClient.connect(); From c5e3b24d3e0ed4e2c30e55b65d81be774516681a Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Sat, 8 Dec 2012 13:04:49 -0800 Subject: [PATCH 2/3] decoupled ProxyConfig and introduced PROPERTY_PROXY_TYPE --- core/src/main/java/org/jclouds/Constants.java | 23 +++- .../main/java/org/jclouds/http/HttpUtils.java | 50 +------ .../JavaUrlHttpCommandExecutorService.java | 36 ++--- .../predicates/InetSocketAddressConnect.java | 17 ++- .../java/org/jclouds/proxy/ProxyConfig.java | 62 +++++++++ .../java/org/jclouds/proxy/ProxyForURI.java | 89 +++++++++++++ .../proxy/internal/GuiceProxyConfig.java | 123 ++++++++++++++++++ .../org/jclouds/rest/config/RestModule.java | 8 +- ...kingJavaUrlHttpCommandExecutorService.java | 9 +- ...cheHCHttpCommandExecutorServiceModule.java | 5 +- 10 files changed, 333 insertions(+), 89 deletions(-) create mode 100644 core/src/main/java/org/jclouds/proxy/ProxyConfig.java create mode 100644 core/src/main/java/org/jclouds/proxy/ProxyForURI.java create mode 100644 core/src/main/java/org/jclouds/proxy/internal/GuiceProxyConfig.java diff --git a/core/src/main/java/org/jclouds/Constants.java b/core/src/main/java/org/jclouds/Constants.java index 1b0d770378..9204863fe7 100644 --- a/core/src/main/java/org/jclouds/Constants.java +++ b/core/src/main/java/org/jclouds/Constants.java @@ -18,6 +18,9 @@ */ package org.jclouds; +import java.net.Proxy; + +import org.jclouds.domain.Location; import org.jclouds.location.reference.LocationConstants; /** @@ -103,24 +106,38 @@ public interface Constants { * Whether or not to use the proxy setup from the underlying operating system. */ public static final String PROPERTY_PROXY_SYSTEM = "jclouds.use-system-proxy"; + /** * String property. *

- *Explicitly sets the host name of a HTTP proxy server. + *Explicitly sets the host name of a proxy server. */ public static final String PROPERTY_PROXY_HOST = "jclouds.proxy-host"; + /** - * Integer property. + * Integer property. default is 80 when {@link #PROPERTY_PROXY_TYPE} is + * {@code HTTP}, and 1080 when {@link #PROPERTY_PROXY_TYPE} is {@code SOCKS}. *

- * Explicitly sets the port number of a HTTP proxy server. + * Explicitly sets the port number of a proxy server. */ public static final String PROPERTY_PROXY_PORT = "jclouds.proxy-port"; + + /** + * String property. default {@code HTTP}, valid options: {@code HTTP}, {@code SOCKS}. + *

+ * Explicitly sets the type of a proxy server. + * + * @see Proxy.Type + */ + public static final String PROPERTY_PROXY_TYPE = "jclouds.proxy-type"; + /** * String property. *

* Explicitly sets the user name credential for proxy authentication. */ public static final String PROPERTY_PROXY_USER = "jclouds.proxy-user"; + /** * String property. *

diff --git a/core/src/main/java/org/jclouds/http/HttpUtils.java b/core/src/main/java/org/jclouds/http/HttpUtils.java index d173a2fb32..860fc712a7 100644 --- a/core/src/main/java/org/jclouds/http/HttpUtils.java +++ b/core/src/main/java/org/jclouds/http/HttpUtils.java @@ -79,27 +79,11 @@ public class HttpUtils { @Named(Constants.PROPERTY_RELAX_HOSTNAME) private boolean relaxHostname = false; - @Inject(optional = true) - @Named(Constants.PROPERTY_PROXY_SYSTEM) - private boolean systemProxies = System.getProperty("java.net.useSystemProxies") != null ? Boolean - .parseBoolean(System.getProperty("java.net.useSystemProxies")) : false; - private final int globalMaxConnections; private final int globalMaxConnectionsPerHost; private final int connectionTimeout; private final int soTimeout; - @Inject(optional = true) - @Named(Constants.PROPERTY_PROXY_HOST) - private String proxyHost; - @Inject(optional = true) - @Named(Constants.PROPERTY_PROXY_PORT) - private Integer proxyPort; - @Inject(optional = true) - @Named(Constants.PROPERTY_PROXY_USER) - private String proxyUser; - @Inject(optional = true) - @Named(Constants.PROPERTY_PROXY_PASSWORD) - private String proxyPassword; + @Inject(optional = true) @Named(Constants.PROPERTY_TRUST_ALL_CERTS) private boolean trustAllCerts; @@ -115,34 +99,6 @@ public class HttpUtils { this.globalMaxConnectionsPerHost = globalMaxConnectionsPerHost; } - /** - * @see org.jclouds.Constants.PROPERTY_PROXY_HOST - */ - public String getProxyHost() { - return proxyHost; - } - - /** - * @see org.jclouds.Constants.PROPERTY_PROXY_PORT - */ - public Integer getProxyPort() { - return proxyPort; - } - - /** - * @see org.jclouds.Constants.PROPERTY_PROXY_USER - */ - public String getProxyUser() { - return proxyUser; - } - - /** - * @see org.jclouds.Constants.PROPERTY_PROXY_PASSWORD - */ - public String getProxyPassword() { - return proxyPassword; - } - public int getSocketOpenTimeout() { return soTimeout; } @@ -159,10 +115,6 @@ public class HttpUtils { return trustAllCerts; } - public boolean useSystemProxies() { - return systemProxies; - } - public int getMaxConnections() { return globalMaxConnections; } diff --git a/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java b/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java index 7cba6f6afb..bf17b3c099 100644 --- a/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java +++ b/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java @@ -20,7 +20,6 @@ package org.jclouds.http.internal; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Throwables.propagate; -import static com.google.common.collect.Iterables.getLast; import static com.google.common.io.ByteStreams.toByteArray; import static com.google.common.io.Closeables.closeQuietly; import static com.google.common.net.HttpHeaders.CONTENT_LENGTH; @@ -33,14 +32,10 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; -import java.net.Authenticator; import java.net.HttpURLConnection; -import java.net.InetSocketAddress; -import java.net.PasswordAuthentication; import java.net.ProtocolException; import java.net.Proxy; -import java.net.ProxySelector; -import java.net.SocketAddress; +import java.net.URI; import java.net.URL; import java.util.List; import java.util.Map; @@ -64,6 +59,7 @@ import org.jclouds.io.ContentMetadataCodec; import org.jclouds.io.MutableContentMetadata; import org.jclouds.io.Payload; +import com.google.common.base.Function; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap.Builder; @@ -83,23 +79,26 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe .getProperty("java.version")); private final Supplier untrustedSSLContextProvider; + private final Function proxyForURI; private final HostnameVerifier verifier; private final Field methodField; @Inject(optional = true) Supplier sslContextSupplier; + @Inject public JavaUrlHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec, @Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor, DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler, DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier, - @Named("untrusted") Supplier untrustedSSLContextProvider) throws SecurityException, - NoSuchFieldException { + @Named("untrusted") Supplier untrustedSSLContextProvider, Function proxyForURI) + throws SecurityException, NoSuchFieldException { super(utils, contentMetadataCodec, ioExecutor, retryHandler, ioRetryHandler, errorHandler, wire); if (utils.getMaxConnections() > 0) System.setProperty("http.maxConnections", String.valueOf(checkNotNull(utils, "utils").getMaxConnections())); this.untrustedSSLContextProvider = checkNotNull(untrustedSSLContextProvider, "untrustedSSLContextProvider"); this.verifier = checkNotNull(verifier, "verifier"); + this.proxyForURI = checkNotNull(proxyForURI, "proxyForURI"); this.methodField = HttpURLConnection.class.getDeclaredField("method"); methodField.setAccessible(true); } @@ -159,26 +158,7 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe boolean chunked = "chunked".equals(request.getFirstHeaderOrNull("Transfer-Encoding")); URL url = request.getEndpoint().toURL(); - HttpURLConnection connection; - - if (utils.useSystemProxies()) { - System.setProperty("java.net.useSystemProxies", "true"); - Iterable proxies = ProxySelector.getDefault().select(request.getEndpoint()); - Proxy proxy = getLast(proxies); - connection = (HttpURLConnection) url.openConnection(proxy); - } else if (utils.getProxyHost() != null) { - SocketAddress addr = new InetSocketAddress(utils.getProxyHost(), utils.getProxyPort()); - Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); - Authenticator authenticator = new Authenticator() { - public PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(utils.getProxyUser(), utils.getProxyPassword().toCharArray()); - } - }; - Authenticator.setDefault(authenticator); - connection = (HttpURLConnection) url.openConnection(proxy); - } else { - connection = (HttpURLConnection) url.openConnection(); - } + HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxyForURI.apply(request.getEndpoint())); if (connection instanceof HttpsURLConnection) { HttpsURLConnection sslCon = (HttpsURLConnection) connection; if (utils.relaxHostname()) diff --git a/core/src/main/java/org/jclouds/predicates/InetSocketAddressConnect.java b/core/src/main/java/org/jclouds/predicates/InetSocketAddressConnect.java index de95e5c2ff..14deef1375 100644 --- a/core/src/main/java/org/jclouds/predicates/InetSocketAddressConnect.java +++ b/core/src/main/java/org/jclouds/predicates/InetSocketAddressConnect.java @@ -18,9 +18,13 @@ */ package org.jclouds.predicates; +import static com.google.common.base.Preconditions.checkNotNull; + import java.io.IOException; import java.net.InetSocketAddress; +import java.net.Proxy; import java.net.Socket; +import java.net.URI; import javax.annotation.Resource; import javax.inject.Named; @@ -28,6 +32,8 @@ import javax.inject.Singleton; import org.jclouds.logging.Logger; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; import com.google.common.net.HostAndPort; import com.google.inject.Inject; @@ -47,6 +53,14 @@ public class InetSocketAddressConnect implements SocketOpen { @Named("org.jclouds.socket_timeout") private int timeout = 2000; + private final Function proxyForURI; + + @VisibleForTesting + @Inject + InetSocketAddressConnect(Function proxyForURI) { + this.proxyForURI = checkNotNull(proxyForURI, "proxyForURI"); + } + @Override public boolean apply(HostAndPort socketA) { InetSocketAddress socketAddress = new InetSocketAddress(socketA.getHostText(), socketA @@ -54,7 +68,8 @@ public class InetSocketAddressConnect implements SocketOpen { Socket socket = null; try { logger.trace("testing socket %s", socketAddress); - socket = new Socket(); + socket = new Socket( + proxyForURI.apply(URI.create("socket://" + socketA.getHostText() + ":" + socketA.getPort()))); socket.setReuseAddress(false); socket.setSoLinger(false, 1); socket.setSoTimeout(timeout); diff --git a/core/src/main/java/org/jclouds/proxy/ProxyConfig.java b/core/src/main/java/org/jclouds/proxy/ProxyConfig.java new file mode 100644 index 0000000000..c13a1692a4 --- /dev/null +++ b/core/src/main/java/org/jclouds/proxy/ProxyConfig.java @@ -0,0 +1,62 @@ +/** + * 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 java.net.Proxy.Type; + +import org.jclouds.domain.Credentials; +import org.jclouds.proxy.internal.GuiceProxyConfig; + +import com.google.common.base.Optional; +import com.google.common.net.HostAndPort; +import com.google.inject.ImplementedBy; + +/** + * parameters needed to configure {@link java.net.Proxy}. Check presence of + * {@link #getProxyHost()} to decide if proxy support should even be attempted. + * + * @author Adrian Cole + * + */ +@ImplementedBy(GuiceProxyConfig.class) +public interface ProxyConfig { + + /** + * @see org.jclouds.Constants#PROPERTY_PROXY_SYSTEM + */ + boolean useSystem(); + + /** + * @see org.jclouds.Constants#PROPERTY_PROXY_TYPE + */ + Type getType(); + + /** + * @see org.jclouds.Constants#PROPERTY_PROXY_HOST + * @see org.jclouds.Constants#PROPERTY_PROXY_PORT + */ + Optional getProxy(); + + /** + * @see org.jclouds.Constants#PROPERTY_PROXY_USER + * @see org.jclouds.Constants#PROPERTY_PROXY_PASSWORD + */ + Optional getCredentials(); + +} \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/proxy/ProxyForURI.java b/core/src/main/java/org/jclouds/proxy/ProxyForURI.java new file mode 100644 index 0000000000..09e046429d --- /dev/null +++ b/core/src/main/java/org/jclouds/proxy/ProxyForURI.java @@ -0,0 +1,89 @@ +/** + * 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 com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Iterables.getLast; + +import java.net.Authenticator; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.Proxy; +import java.net.ProxySelector; +import java.net.SocketAddress; +import java.net.URI; + +import javax.inject.Singleton; + +import org.jclouds.domain.Credentials; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.inject.Inject; + +/** + * @author Adrian Cole + */ +@Singleton +public class ProxyForURI implements Function { + private final ProxyConfig config; + + @VisibleForTesting + @Inject + ProxyForURI(ProxyConfig config) { + this.config = checkNotNull(config, "config"); + } + + /** + * @param endpoint + *

    + *
  • http URI for http connections
  • + *
  • https URI for https connections
  • + *
  • ftp URI for ftp connections
  • + *
  • socket://host:port for tcp client sockets connections
  • + *
+ */ + @Override + public Proxy apply(URI endpoint) { + if (config.useSystem()) { + System.setProperty("java.net.useSystemProxies", "true"); + Iterable proxies = ProxySelector.getDefault().select(endpoint); + return getLast(proxies); + } else if (config.getProxy().isPresent()) { + SocketAddress addr = new InetSocketAddress(config.getProxy().get().getHostText(), config.getProxy().get() + .getPort()); + Proxy proxy = new Proxy(config.getType(), addr); + + final Optional creds = config.getCredentials(); + if (creds.isPresent()) { + Authenticator authenticator = new Authenticator() { + public PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(creds.get().identity, creds.get().credential.toCharArray()); + } + }; + Authenticator.setDefault(authenticator); + } + return proxy; + } else { + return Proxy.NO_PROXY; + } + } + +} diff --git a/core/src/main/java/org/jclouds/proxy/internal/GuiceProxyConfig.java b/core/src/main/java/org/jclouds/proxy/internal/GuiceProxyConfig.java new file mode 100644 index 0000000000..5013ad275c --- /dev/null +++ b/core/src/main/java/org/jclouds/proxy/internal/GuiceProxyConfig.java @@ -0,0 +1,123 @@ +/** + * 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.internal; + +import static com.google.common.base.Preconditions.checkArgument; +import static org.jclouds.Constants.PROPERTY_PROXY_HOST; +import static org.jclouds.Constants.PROPERTY_PROXY_PASSWORD; +import static org.jclouds.Constants.PROPERTY_PROXY_PORT; +import static org.jclouds.Constants.PROPERTY_PROXY_SYSTEM; +import static org.jclouds.Constants.PROPERTY_PROXY_TYPE; +import static org.jclouds.Constants.PROPERTY_PROXY_USER; + +import java.net.Proxy; +import java.net.Proxy.Type; + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.domain.Credentials; +import org.jclouds.proxy.ProxyConfig; + +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.base.Strings; +import com.google.common.net.HostAndPort; +import com.google.inject.Inject; + +/** + * Configuration derived from Guice properties. + * + * @author Adrian Cole + */ +@Singleton +public class GuiceProxyConfig implements ProxyConfig { + + @Inject(optional = true) + @Named(PROPERTY_PROXY_SYSTEM) + private boolean systemProxies = Boolean.parseBoolean(System.getProperty("java.net.useSystemProxies", "false")); + @Inject(optional = true) + @Named(PROPERTY_PROXY_HOST) + private String host; + @Inject(optional = true) + @Named(PROPERTY_PROXY_PORT) + private Integer port; + @Inject(optional = true) + @Named(PROPERTY_PROXY_USER) + private String user; + @Inject(optional = true) + @Named(PROPERTY_PROXY_PASSWORD) + private String password; + @Inject(optional = true) + @Named(PROPERTY_PROXY_TYPE) + private Proxy.Type type = Proxy.Type.HTTP; + + @Override + public Optional getProxy() { + if (host == null) + return Optional.absent(); + Integer port = this.port; + if (port == null) { + switch (type) { + case HTTP: + port = 80; + break; + case SOCKS: + port = 1080; + break; + default: + throw new IllegalArgumentException(type + " not supported"); + } + } + return Optional.of(HostAndPort.fromParts(host, port)); + } + + @Override + public Optional getCredentials() { + if (user == null) + return Optional.absent(); + return Optional.of(new Credentials(user, checkNotEmpty(password, "set property %s for user %s", + PROPERTY_PROXY_PASSWORD, user))); + } + + private static String checkNotEmpty(String nullableString, String message, Object... args) { + checkArgument(Strings.emptyToNull(nullableString) != null, message, args); + return nullableString; + } + + @Override + public Type getType() { + return type; + } + + @Override + public boolean useSystem() { + return systemProxies; + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return Objects.toStringHelper(this).omitNullValues().add("systemProxies", systemProxies ? "true" : null) + .add("proxy", getProxy().orNull()).add("user", user).add("type", host != null ? type : null).toString(); + } + +} diff --git a/core/src/main/java/org/jclouds/rest/config/RestModule.java b/core/src/main/java/org/jclouds/rest/config/RestModule.java index 315f152bde..5112d57891 100644 --- a/core/src/main/java/org/jclouds/rest/config/RestModule.java +++ b/core/src/main/java/org/jclouds/rest/config/RestModule.java @@ -33,6 +33,7 @@ import static org.jclouds.util.Maps2.transformKeys; import static org.jclouds.util.Predicates2.startsWith; import java.lang.reflect.Method; +import java.net.Proxy; import java.net.URI; import java.util.Map; import java.util.Set; @@ -46,6 +47,8 @@ import org.jclouds.http.functions.config.SaxParserModule; import org.jclouds.internal.FilterStringsBoundToInjectorByName; import org.jclouds.json.config.GsonModule; import org.jclouds.location.config.LocationModule; +import com.google.common.reflect.Invokable; +import org.jclouds.proxy.ProxyForURI; import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.HttpAsyncClient; import org.jclouds.rest.HttpClient; @@ -59,7 +62,6 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import com.google.common.reflect.Invokable; import com.google.common.reflect.Parameter; import com.google.inject.AbstractModule; import com.google.inject.Provides; @@ -147,8 +149,8 @@ public class RestModule extends AbstractModule { }).toInstance(authException); bind(new TypeLiteral, Map>>() { }).to(FilterStringsBoundToInjectorByName.class); - bind(new TypeLiteral, Map>>() { - }).to(FilterStringsBoundToInjectorByName.class); + bind(new TypeLiteral>() { + }).to(ProxyForURI.class); installLocations(); } diff --git a/core/src/test/java/org/jclouds/http/internal/TrackingJavaUrlHttpCommandExecutorService.java b/core/src/test/java/org/jclouds/http/internal/TrackingJavaUrlHttpCommandExecutorService.java index 0719883ef7..c4c1db4bb2 100644 --- a/core/src/test/java/org/jclouds/http/internal/TrackingJavaUrlHttpCommandExecutorService.java +++ b/core/src/test/java/org/jclouds/http/internal/TrackingJavaUrlHttpCommandExecutorService.java @@ -18,6 +18,8 @@ */ package org.jclouds.http.internal; +import java.net.Proxy; +import java.net.URI; import java.util.Collection; import java.util.List; @@ -37,6 +39,7 @@ import org.jclouds.http.handlers.DelegatingRetryHandler; import org.jclouds.io.ContentMetadataCodec; import org.jclouds.rest.internal.GeneratedHttpRequest; +import com.google.common.base.Function; import com.google.common.base.Supplier; import com.google.common.collect.Iterables; import com.google.common.reflect.Invokable; @@ -91,10 +94,10 @@ public class TrackingJavaUrlHttpCommandExecutorService extends JavaUrlHttpComman @Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor, DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler, DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier, - @Named("untrusted") Supplier untrustedSSLContextProvider, List commandsInvoked) - throws SecurityException, NoSuchFieldException { + @Named("untrusted") Supplier untrustedSSLContextProvider, Function proxyForURI, + List commandsInvoked) throws SecurityException, NoSuchFieldException { super(utils, contentMetadataCodec, ioExecutor, retryHandler, ioRetryHandler, errorHandler, wire, verifier, - untrustedSSLContextProvider); + untrustedSSLContextProvider, proxyForURI); this.commandsInvoked = commandsInvoked; } diff --git a/drivers/apachehc/src/main/java/org/jclouds/http/apachehc/config/ApacheHCHttpCommandExecutorServiceModule.java b/drivers/apachehc/src/main/java/org/jclouds/http/apachehc/config/ApacheHCHttpCommandExecutorServiceModule.java index 1fe98a9fd1..7733debcdc 100644 --- a/drivers/apachehc/src/main/java/org/jclouds/http/apachehc/config/ApacheHCHttpCommandExecutorServiceModule.java +++ b/drivers/apachehc/src/main/java/org/jclouds/http/apachehc/config/ApacheHCHttpCommandExecutorServiceModule.java @@ -53,6 +53,7 @@ import org.jclouds.http.apachehc.ApacheHCHttpCommandExecutorService; import org.jclouds.http.config.ConfiguresHttpCommandExecutorService; import org.jclouds.http.config.SSLModule; import org.jclouds.lifecycle.Closer; +import org.jclouds.proxy.ProxyConfig; import com.google.common.base.Supplier; import com.google.inject.AbstractModule; @@ -155,9 +156,9 @@ public class ApacheHCHttpCommandExecutorServiceModule extends AbstractModule { @Provides @Singleton - HttpClient newDefaultHttpClient(HttpUtils utils, BasicHttpParams params, ClientConnectionManager cm) { + HttpClient newDefaultHttpClient(ProxyConfig config, BasicHttpParams params, ClientConnectionManager cm) { DefaultHttpClient client = new DefaultHttpClient(cm, params); - if (utils.useSystemProxies()) { + if (config.useSystem()) { ProxySelectorRoutePlanner routePlanner = new ProxySelectorRoutePlanner(client.getConnectionManager() .getSchemeRegistry(), ProxySelector.getDefault()); client.setRoutePlanner(routePlanner); From 3afdc3550e7c98e5a2da18b7fb6eb83a5ac84a47 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Sat, 8 Dec 2012 14:34:37 -0800 Subject: [PATCH 3/3] add support for jsch proxy --- .../org/jclouds/ssh/jsch/JschSshClient.java | 10 +- .../jclouds/ssh/jsch/SessionConnection.java | 98 +++++++++++++++---- .../ssh/jsch/config/JschSshClientModule.java | 13 ++- 3 files changed, 93 insertions(+), 28 deletions(-) diff --git a/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/JschSshClient.java b/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/JschSshClient.java index 16e5ba912e..5b2565822d 100644 --- a/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/JschSshClient.java +++ b/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/JschSshClient.java @@ -50,6 +50,7 @@ import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.jclouds.io.Payload; import org.jclouds.io.Payloads; import org.jclouds.logging.Logger; +import org.jclouds.proxy.ProxyConfig; import org.jclouds.rest.AuthorizationException; import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshException; @@ -123,7 +124,8 @@ public class JschSshClient implements SshClient { final String user; final String host; - public JschSshClient(BackoffLimitedRetryHandler backoffLimitedRetryHandler, HostAndPort socket, + + public JschSshClient(ProxyConfig proxyConfig, BackoffLimitedRetryHandler backoffLimitedRetryHandler, HostAndPort socket, LoginCredentials loginCredentials, int timeout) { this.user = checkNotNull(loginCredentials, "loginCredentials").getUser(); this.host = checkNotNull(socket, "socket").getHostText(); @@ -142,7 +144,7 @@ public class JschSshClient implements SshClient { fingerPrint, sha1, host, socket.getPort()); } sessionConnection = SessionConnection.builder().hostAndPort(HostAndPort.fromParts(host, socket.getPort())).loginCredentials( - loginCredentials).connectTimeout(timeout).sessionTimeout(timeout).build(); + loginCredentials).proxy(checkNotNull(proxyConfig, "proxyConfig")).connectTimeout(timeout).sessionTimeout(timeout).build(); } @Override @@ -467,8 +469,8 @@ public class JschSshClient implements SshClient { @Override public ExecChannel create() throws Exception { - this.sessionConnection = acquire(SessionConnection.builder().fromSessionConnection( - JschSshClient.this.sessionConnection).sessionTimeout(0).build()); + this.sessionConnection = acquire(SessionConnection.builder().from(JschSshClient.this.sessionConnection) + .sessionTimeout(0).build()); String channel = "exec"; executor = (ChannelExec) sessionConnection.openChannel(channel); executor.setCommand(command); diff --git a/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/SessionConnection.java b/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/SessionConnection.java index d95d53d3dc..49f03252dc 100644 --- a/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/SessionConnection.java +++ b/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/SessionConnection.java @@ -20,26 +20,35 @@ package org.jclouds.ssh.jsch; import static com.google.common.base.Objects.equal; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import org.jclouds.domain.Credentials; import org.jclouds.domain.LoginCredentials; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.proxy.ProxyConfig; import org.jclouds.ssh.jsch.JschSshClient.Connection; import com.google.common.base.Objects; +import com.google.common.base.Optional; import com.google.common.net.HostAndPort; import com.jcraft.jsch.JSch; +import com.jcraft.jsch.Proxy; +import com.jcraft.jsch.ProxyHTTP; +import com.jcraft.jsch.ProxySOCKS5; import com.jcraft.jsch.Session; -public class SessionConnection implements Connection { +public final class SessionConnection implements Connection { public static Builder builder() { return new Builder(); } - public static class Builder { + public final static class Builder { - protected HostAndPort hostAndPort; - protected LoginCredentials loginCredentials; - protected int connectTimeout; - protected int sessionTimeout; + private HostAndPort hostAndPort; + private LoginCredentials loginCredentials; + private Optional proxy = Optional.absent(); + private int connectTimeout; + private int sessionTimeout; /** * @see SessionConnection#getHostAndPort() @@ -57,6 +66,39 @@ public class SessionConnection implements Connection { return this; } + /** + * @see SessionConnection#getProxy() + */ + public Builder proxy(Proxy proxy) { + this.proxy = Optional.fromNullable(proxy); + return this; + } + + /** + * @see #proxy(Proxy) + */ + public Builder proxy(ProxyConfig proxyConfig) { + Optional proxyEndpoint = proxyConfig.getProxy(); + if (!proxyEndpoint.isPresent()) + return proxy((Proxy) null); + + Optional creds = proxyConfig.getCredentials(); + switch (proxyConfig.getType()) { + case HTTP: + ProxyHTTP httpProxy = new ProxyHTTP(proxyEndpoint.get().getHostText(), proxyEndpoint.get().getPort()); + if (creds.isPresent()) + httpProxy.setUserPasswd(creds.get().identity, creds.get().credential); + return proxy(httpProxy); + case SOCKS: + ProxySOCKS5 socksProxy = new ProxySOCKS5(proxyEndpoint.get().getHostText(), proxyEndpoint.get().getPort()); + if (creds.isPresent()) + socksProxy.setUserPasswd(creds.get().identity, creds.get().credential); + return proxy(socksProxy); + default: + throw new IllegalArgumentException(proxyConfig.getType() + " not supported"); + } + } + /** * @see SessionConnection#getConnectTimeout() */ @@ -74,27 +116,30 @@ public class SessionConnection implements Connection { } public SessionConnection build() { - return new SessionConnection(hostAndPort, loginCredentials, connectTimeout, sessionTimeout); + return new SessionConnection(hostAndPort, loginCredentials, proxy, connectTimeout, sessionTimeout); } - protected Builder fromSessionConnection(SessionConnection in) { - return hostAndPort(in.getHostAndPort()).connectTimeout(in.getConnectTimeout()).loginCredentials( - in.getLoginCredentials()); + public Builder from(SessionConnection in) { + return hostAndPort(in.hostAndPort).loginCredentials(in.loginCredentials).proxy(in.proxy.orNull()) + .connectTimeout(in.connectTimeout).sessionTimeout(in.sessionTimeout); } + } - private SessionConnection(HostAndPort hostAndPort, LoginCredentials loginCredentials, int connectTimeout, - int sessionTimeout) { - this.hostAndPort = hostAndPort; - this.loginCredentials = loginCredentials; + private SessionConnection(HostAndPort hostAndPort, LoginCredentials loginCredentials, Optional proxy, + int connectTimeout, int sessionTimeout) { + this.hostAndPort = checkNotNull(hostAndPort, "hostAndPort"); + this.loginCredentials = checkNotNull(loginCredentials, "loginCredentials for %", hostAndPort); this.connectTimeout = connectTimeout; this.sessionTimeout = sessionTimeout; + this.proxy = checkNotNull(proxy, "proxy for %", hostAndPort); } private static final byte[] emptyPassPhrase = new byte[0]; private final HostAndPort hostAndPort; private final LoginCredentials loginCredentials; + private final Optional proxy; private final int connectTimeout; private final int sessionTimeout; @@ -112,7 +157,7 @@ public class SessionConnection implements Connection { public Session create() throws Exception { JSch jsch = new JSch(); session = jsch - .getSession(loginCredentials.getUser(), hostAndPort.getHostText(), hostAndPort.getPortOrDefault(22)); + .getSession(loginCredentials.getUser(), hostAndPort.getHostText(), hostAndPort.getPortOrDefault(22)); if (sessionTimeout != 0) session.setTimeout(sessionTimeout); if (loginCredentials.getPrivateKey() == null) { @@ -126,6 +171,8 @@ public class SessionConnection implements Connection { java.util.Properties config = new java.util.Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config); + if (proxy.isPresent()) + session.setProxy(proxy.get()); session.connect(connectTimeout); return session; } @@ -145,6 +192,14 @@ public class SessionConnection implements Connection { return loginCredentials; } + /** + * + * @return proxy used for this connection + */ + public Optional getProxy() { + return proxy; + } + /** * * @return how long to wait for the initial connection to be made @@ -165,6 +220,7 @@ public class SessionConnection implements Connection { * * @return the current session or {@code null} if not connected */ + @Nullable public Session getSession() { return session; } @@ -177,7 +233,7 @@ public class SessionConnection implements Connection { return false; SessionConnection that = SessionConnection.class.cast(o); return equal(this.hostAndPort, that.hostAndPort) && equal(this.loginCredentials, that.loginCredentials) - && equal(this.session, that.session); + && equal(this.session, that.session); } @Override @@ -187,10 +243,12 @@ public class SessionConnection implements Connection { @Override public String toString() { - return Objects.toStringHelper("").add("hostAndPort", hostAndPort).add("loginUser", loginCredentials.getUser()) - .add("session", session != null ? session.hashCode() : null).add("connectTimeout", connectTimeout).add( - "sessionTimeout", sessionTimeout).toString(); + return Objects.toStringHelper("").omitNullValues() + .add("hostAndPort", hostAndPort).add("loginUser", loginCredentials.getUser()) + .add("session", session != null ? session.hashCode() : null) + .add("connectTimeout", connectTimeout) + .add("proxy", proxy.orNull()) + .add("sessionTimeout", sessionTimeout).toString(); } - } diff --git a/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/config/JschSshClientModule.java b/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/config/JschSshClientModule.java index 58ca3b1f0f..7330fc7dd4 100644 --- a/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/config/JschSshClientModule.java +++ b/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/config/JschSshClientModule.java @@ -18,11 +18,14 @@ */ package org.jclouds.ssh.jsch.config; +import static com.google.common.base.Preconditions.checkNotNull; + import javax.inject.Named; import org.jclouds.Constants; import org.jclouds.domain.LoginCredentials; import org.jclouds.http.handlers.BackoffLimitedRetryHandler; +import org.jclouds.proxy.ProxyConfig; import org.jclouds.ssh.SshClient; import org.jclouds.ssh.config.ConfiguresSshClient; import org.jclouds.ssh.jsch.JschSshClient; @@ -49,18 +52,20 @@ public class JschSshClientModule extends AbstractModule { @Inject(optional = true) int timeout = 60000; + private final ProxyConfig proxyConfig; private final BackoffLimitedRetryHandler backoffLimitedRetryHandler; private final Injector injector; @Inject - public Factory(BackoffLimitedRetryHandler backoffLimitedRetryHandler, Injector injector) { - this.backoffLimitedRetryHandler = backoffLimitedRetryHandler; - this.injector = injector; + public Factory(ProxyConfig proxyConfig, BackoffLimitedRetryHandler backoffLimitedRetryHandler, Injector injector) { + this.proxyConfig = checkNotNull(proxyConfig, "proxyConfig"); + this.backoffLimitedRetryHandler = checkNotNull(backoffLimitedRetryHandler, "backoffLimitedRetryHandler"); + this.injector = checkNotNull(injector, "injector"); } @Override public SshClient create(HostAndPort socket, LoginCredentials credentials) { - SshClient client = new JschSshClient(backoffLimitedRetryHandler, socket, credentials, timeout); + SshClient client = new JschSshClient(proxyConfig, backoffLimitedRetryHandler, socket, credentials, timeout); injector.injectMembers(client);// add logger return client; }