package cyrille.net; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.ProxySelector; import java.net.SocketAddress; import java.net.URI; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.log4j.Logger; import org.springframework.beans.factory.InitializingBean; /** * @author <a href="mailto:cyrille.leclerc@pobox.com">Cyrille Le Clerc</a> */ public class ConfigurableProxySelector extends ProxySelector implements InitializingBean { private final Logger logger = Logger.getLogger(ConfigurableProxySelector.class); protected ProxySelector initialdefaultProxySelector; protected Map<String, Proxy> proxiesByHostName = new HashMap<String, Proxy>(); public void setProxiesByHostName(Map<String, Proxy> proxiesByHostName) { this.proxiesByHostName = proxiesByHostName; } /** * @param proxiesHostPortByHostName key: hostname that requires to be proxified, value=proxyHost:proxyPort */ public void setProxiesHostPortByHostName(Map<String, String> proxiesHostPortByHostName) { Map<String, Proxy> newProxiesByHostName = new HashMap<String, Proxy>(); for (Entry<String, String> entry : proxiesHostPortByHostName.entrySet()) { String hostName = entry.getKey(); String proxyHostPort = entry.getValue(); String[] proxyHostPortAsArray = proxyHostPort.split(":"); if (proxyHostPortAsArray.length != 2) { throw new IllegalArgumentException("Expected colon separated 'proxyHost:proxyPort' for host '" + hostName + "' ; not supported '" + proxyHostPort + "'"); } String proxyHost = proxyHostPortAsArray[0]; int proxyPort; try { proxyPort = Integer.valueOf(proxyHostPortAsArray[1]); } catch (NumberFormatException e) { throw new IllegalArgumentException("Unsupported port '" + proxyHostPortAsArray[1] + "' for host '" + hostName + "' and proxyHost '" + proxyHost + "'"); } newProxiesByHostName.put(hostName, new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort))); } this.proxiesByHostName = newProxiesByHostName; if (logger.isDebugEnabled()) { logger.debug("< setProxiesHostPortByHostName(proxiesHostPortByHostName=" + proxiesHostPortByHostName + ") : " + proxiesByHostName); } } @Override public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { if (logger.isDebugEnabled()) { logger.debug("connectFailed(uri=" + uri + "sa=" + sa + "ioe=" + ioe + ")"); } initialdefaultProxySelector.connectFailed(uri, sa, ioe); } @Override public List<Proxy> select(URI uri) { if (logger.isDebugEnabled()) { logger.debug("> select(uri=" + uri + ")"); } List<Proxy> result; Proxy proxy = proxiesByHostName.get(uri.getHost()); if (proxy == null) { result = initialdefaultProxySelector.select(uri); } else { result = Arrays.asList(proxy); } if (logger.isDebugEnabled()) { logger.debug("< select(uri=" + uri + ") : " + result); } return result; } public void afterPropertiesSet() throws Exception { initialdefaultProxySelector = ProxySelector.getDefault(); ProxySelector.setDefault(this); } }