/******************************************************************************* * Copyright (c) 2007, 2008 compeople AG and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * compeople AG (Stefan Liebig) - initial API and implementation *******************************************************************************/ package de.compeople.commons.net.proxy; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Scanner; import java.util.logging.Level; import java.util.logging.Logger; /** * Helper */ public final class ProxySelectorUtils { static private int PROXY_DEFAULT_PORT = 80; static private int HTTPPROXY_DEFAULT_PORT = PROXY_DEFAULT_PORT; static private int HTTPSPROXY_DEFAULT_PORT = 443; static private int SOCKSPROXY_DEFAULT_PORT = 1080; private static final List<Proxy> proxyListDirectAccessOnly = Collections.singletonList(Proxy.NO_PROXY); private static final List<Proxy> emptyProxyList = Collections.emptyList(); private static Logger LOGGER = Logger.getLogger(ProxySelectorUtils.class.getName()); private ProxySelectorUtils() { super(); } /** * Answer a list of proxies allowing direct access only * * @return <code>List<Proxy></code> an immutable list containing the * <code>Proxy.NO_PROXY</code> element only; */ public static List<Proxy> getProxyListDirectAccessOnly() { return proxyListDirectAccessOnly; } /** * Answer an empty immutable list of proxies * * @return an empty immutable <code>List<Proxy></code>. */ public static List<Proxy> getEmptyProxyList() { return emptyProxyList; } /** * Scan the proxy list string and fill this information in the correct list * or map. <br> * The proxy list contains one or more of the following strings separated by * semicolons:<br> * <code><pre> * ([<scheme>=][<scheme> "://" ]<server>[ ":" <port>]) * </pre></code> * * @param proxyList * @param universalProxies * @param protocolSpecificProxies */ public static void fillProxyLists(String proxyList, List<Proxy> universalProxies, Map<String, List<Proxy>> protocolSpecificProxies) { Scanner scanner = new Scanner(proxyList); scanner.useDelimiter(";"); while (scanner.hasNext()) { createProxy(scanner.next(), universalProxies, protocolSpecificProxies); } } private static void createProxy(final String proxyDefinition, List<Proxy> universalProxies, Map<String, List<Proxy>> protocolSpecificProxies) { String protocol = null; String host = null; int port = 0; int urlStart = 0; // if there is no '=' character within the proxy definition we have a // proxy // definition that serves all protocols. In this case we MUST ignore the // protocol, // otherwise the protocol MUST be used to determine the specific proxy // settings if (proxyDefinition.indexOf("=") != -1) { protocol = proxyDefinition.substring(0, proxyDefinition.indexOf("=")); urlStart = proxyDefinition.indexOf("=") + 1; } try { // The scheme of the uri is irrelevant. We add the http:// // scheme to enable class URI to parse the stuff String augmentedURI = proxyDefinition.substring(urlStart); if (augmentedURI.indexOf("://") == -1) { augmentedURI = "http://" + augmentedURI; } URI uri = new URI(augmentedURI); host = uri.getHost(); port = uri.getPort() > 0 ? uri.getPort() : getProxyDefaultPort(protocol); } catch (Exception ex) { LOGGER.log(Level.SEVERE, "not a valid proxy definition: '" + proxyDefinition + "'.", ex); return; } if (host == null) { LOGGER.log(Level.SEVERE, "not a valid proxy definition: '" + proxyDefinition + "'."); return; } if (protocol == null) { universalProxies.add(createProxy(Proxy.Type.HTTP, host, port)); } else { addProtocolSpecificProxy(protocolSpecificProxies, protocol, createProxy(resolveProxyType(protocol), host, port)); } } private static int getProxyDefaultPort(String protocol) { if (protocol == null) return PROXY_DEFAULT_PORT; if ("http".equalsIgnoreCase(protocol)) return HTTPPROXY_DEFAULT_PORT; if ("https".equalsIgnoreCase(protocol)) return HTTPSPROXY_DEFAULT_PORT; if ("socks".equalsIgnoreCase(protocol)) return SOCKSPROXY_DEFAULT_PORT; if ("socket".equalsIgnoreCase(protocol)) return SOCKSPROXY_DEFAULT_PORT; return PROXY_DEFAULT_PORT; } private static void addProtocolSpecificProxy(Map<String, List<Proxy>> protocolSpecificProxies, String protocol, Proxy proxy) { List<Proxy> list = protocolSpecificProxies.get(protocol); if (list == null) { list = new ArrayList<Proxy>(); protocolSpecificProxies.put(protocol, list); } list.add(proxy); } /** * @param type * @param host * @param port * @return */ private static Proxy createProxy(Proxy.Type type, String host, int port) { return new Proxy(type, InetSocketAddress.createUnresolved(host, port)); } /** * @param protocol * @return */ private static Proxy.Type resolveProxyType(String protocol) { // TODO: return HTTP proxy for well-known high level protocols only? if (protocol.equalsIgnoreCase("socks") || protocol.equalsIgnoreCase("socket")) { return Proxy.Type.SOCKS; } else { return Proxy.Type.HTTP; } } }