michael@0: /* Licensed to the Apache Software Foundation (ASF) under one or more michael@0: * contributor license agreements. See the NOTICE file distributed with michael@0: * this work for additional information regarding copyright ownership. michael@0: * The ASF licenses this file to You under the Apache License, Version 2.0 michael@0: * (the "License"); you may not use this file except in compliance with michael@0: * the License. You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, software michael@0: * distributed under the License is distributed on an "AS IS" BASIS, michael@0: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: * See the License for the specific language governing permissions and michael@0: * limitations under the License. michael@0: */ michael@0: michael@0: // This code is based on AOSP /libcore/luni/src/main/java/java/net/ProxySelectorImpl.java michael@0: michael@0: package org.mozilla.gecko.util; michael@0: michael@0: import android.text.TextUtils; michael@0: michael@0: import java.io.IOException; michael@0: import java.net.InetSocketAddress; michael@0: import java.net.Proxy; michael@0: michael@0: public class ProxySelector { michael@0: public ProxySelector() { michael@0: } michael@0: michael@0: public Proxy select(String scheme, String host) { michael@0: int port = -1; michael@0: Proxy proxy = null; michael@0: String nonProxyHostsKey = null; michael@0: boolean httpProxyOkay = true; michael@0: if ("http".equalsIgnoreCase(scheme)) { michael@0: port = 80; michael@0: nonProxyHostsKey = "http.nonProxyHosts"; michael@0: proxy = lookupProxy("http.proxyHost", "http.proxyPort", Proxy.Type.HTTP, port); michael@0: } else if ("https".equalsIgnoreCase(scheme)) { michael@0: port = 443; michael@0: nonProxyHostsKey = "https.nonProxyHosts"; // RI doesn't support this michael@0: proxy = lookupProxy("https.proxyHost", "https.proxyPort", Proxy.Type.HTTP, port); michael@0: } else if ("ftp".equalsIgnoreCase(scheme)) { michael@0: port = 80; // not 21 as you might guess michael@0: nonProxyHostsKey = "ftp.nonProxyHosts"; michael@0: proxy = lookupProxy("ftp.proxyHost", "ftp.proxyPort", Proxy.Type.HTTP, port); michael@0: } else if ("socket".equalsIgnoreCase(scheme)) { michael@0: httpProxyOkay = false; michael@0: } else { michael@0: return Proxy.NO_PROXY; michael@0: } michael@0: michael@0: if (nonProxyHostsKey != null michael@0: && isNonProxyHost(host, System.getProperty(nonProxyHostsKey))) { michael@0: return Proxy.NO_PROXY; michael@0: } michael@0: michael@0: if (proxy != null) { michael@0: return proxy; michael@0: } michael@0: michael@0: if (httpProxyOkay) { michael@0: proxy = lookupProxy("proxyHost", "proxyPort", Proxy.Type.HTTP, port); michael@0: if (proxy != null) { michael@0: return proxy; michael@0: } michael@0: } michael@0: michael@0: proxy = lookupProxy("socksProxyHost", "socksProxyPort", Proxy.Type.SOCKS, 1080); michael@0: if (proxy != null) { michael@0: return proxy; michael@0: } michael@0: michael@0: return Proxy.NO_PROXY; michael@0: } michael@0: michael@0: /** michael@0: * Returns the proxy identified by the {@code hostKey} system property, or michael@0: * null. michael@0: */ michael@0: private Proxy lookupProxy(String hostKey, String portKey, Proxy.Type type, int defaultPort) { michael@0: String host = System.getProperty(hostKey); michael@0: if (TextUtils.isEmpty(host)) { michael@0: return null; michael@0: } michael@0: michael@0: int port = getSystemPropertyInt(portKey, defaultPort); michael@0: return new Proxy(type, InetSocketAddress.createUnresolved(host, port)); michael@0: } michael@0: michael@0: private int getSystemPropertyInt(String key, int defaultValue) { michael@0: String string = System.getProperty(key); michael@0: if (string != null) { michael@0: try { michael@0: return Integer.parseInt(string); michael@0: } catch (NumberFormatException ignored) { michael@0: } michael@0: } michael@0: return defaultValue; michael@0: } michael@0: michael@0: /** michael@0: * Returns true if the {@code nonProxyHosts} system property pattern exists michael@0: * and matches {@code host}. michael@0: */ michael@0: private boolean isNonProxyHost(String host, String nonProxyHosts) { michael@0: if (host == null || nonProxyHosts == null) { michael@0: return false; michael@0: } michael@0: michael@0: // construct pattern michael@0: StringBuilder patternBuilder = new StringBuilder(); michael@0: for (int i = 0; i < nonProxyHosts.length(); i++) { michael@0: char c = nonProxyHosts.charAt(i); michael@0: switch (c) { michael@0: case '.': michael@0: patternBuilder.append("\\."); michael@0: break; michael@0: case '*': michael@0: patternBuilder.append(".*"); michael@0: break; michael@0: default: michael@0: patternBuilder.append(c); michael@0: } michael@0: } michael@0: // check whether the host is the nonProxyHosts. michael@0: String pattern = patternBuilder.toString(); michael@0: return host.matches(pattern); michael@0: } michael@0: } michael@0: