Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
michael@0 | 1 | /* Licensed to the Apache Software Foundation (ASF) under one or more |
michael@0 | 2 | * contributor license agreements. See the NOTICE file distributed with |
michael@0 | 3 | * this work for additional information regarding copyright ownership. |
michael@0 | 4 | * The ASF licenses this file to You under the Apache License, Version 2.0 |
michael@0 | 5 | * (the "License"); you may not use this file except in compliance with |
michael@0 | 6 | * the License. You may obtain a copy of the License at |
michael@0 | 7 | * |
michael@0 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
michael@0 | 9 | * |
michael@0 | 10 | * Unless required by applicable law or agreed to in writing, software |
michael@0 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
michael@0 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
michael@0 | 13 | * See the License for the specific language governing permissions and |
michael@0 | 14 | * limitations under the License. |
michael@0 | 15 | */ |
michael@0 | 16 | |
michael@0 | 17 | // This code is based on AOSP /libcore/luni/src/main/java/java/net/ProxySelectorImpl.java |
michael@0 | 18 | |
michael@0 | 19 | package org.mozilla.gecko.util; |
michael@0 | 20 | |
michael@0 | 21 | import android.text.TextUtils; |
michael@0 | 22 | |
michael@0 | 23 | import java.io.IOException; |
michael@0 | 24 | import java.net.InetSocketAddress; |
michael@0 | 25 | import java.net.Proxy; |
michael@0 | 26 | |
michael@0 | 27 | public class ProxySelector { |
michael@0 | 28 | public ProxySelector() { |
michael@0 | 29 | } |
michael@0 | 30 | |
michael@0 | 31 | public Proxy select(String scheme, String host) { |
michael@0 | 32 | int port = -1; |
michael@0 | 33 | Proxy proxy = null; |
michael@0 | 34 | String nonProxyHostsKey = null; |
michael@0 | 35 | boolean httpProxyOkay = true; |
michael@0 | 36 | if ("http".equalsIgnoreCase(scheme)) { |
michael@0 | 37 | port = 80; |
michael@0 | 38 | nonProxyHostsKey = "http.nonProxyHosts"; |
michael@0 | 39 | proxy = lookupProxy("http.proxyHost", "http.proxyPort", Proxy.Type.HTTP, port); |
michael@0 | 40 | } else if ("https".equalsIgnoreCase(scheme)) { |
michael@0 | 41 | port = 443; |
michael@0 | 42 | nonProxyHostsKey = "https.nonProxyHosts"; // RI doesn't support this |
michael@0 | 43 | proxy = lookupProxy("https.proxyHost", "https.proxyPort", Proxy.Type.HTTP, port); |
michael@0 | 44 | } else if ("ftp".equalsIgnoreCase(scheme)) { |
michael@0 | 45 | port = 80; // not 21 as you might guess |
michael@0 | 46 | nonProxyHostsKey = "ftp.nonProxyHosts"; |
michael@0 | 47 | proxy = lookupProxy("ftp.proxyHost", "ftp.proxyPort", Proxy.Type.HTTP, port); |
michael@0 | 48 | } else if ("socket".equalsIgnoreCase(scheme)) { |
michael@0 | 49 | httpProxyOkay = false; |
michael@0 | 50 | } else { |
michael@0 | 51 | return Proxy.NO_PROXY; |
michael@0 | 52 | } |
michael@0 | 53 | |
michael@0 | 54 | if (nonProxyHostsKey != null |
michael@0 | 55 | && isNonProxyHost(host, System.getProperty(nonProxyHostsKey))) { |
michael@0 | 56 | return Proxy.NO_PROXY; |
michael@0 | 57 | } |
michael@0 | 58 | |
michael@0 | 59 | if (proxy != null) { |
michael@0 | 60 | return proxy; |
michael@0 | 61 | } |
michael@0 | 62 | |
michael@0 | 63 | if (httpProxyOkay) { |
michael@0 | 64 | proxy = lookupProxy("proxyHost", "proxyPort", Proxy.Type.HTTP, port); |
michael@0 | 65 | if (proxy != null) { |
michael@0 | 66 | return proxy; |
michael@0 | 67 | } |
michael@0 | 68 | } |
michael@0 | 69 | |
michael@0 | 70 | proxy = lookupProxy("socksProxyHost", "socksProxyPort", Proxy.Type.SOCKS, 1080); |
michael@0 | 71 | if (proxy != null) { |
michael@0 | 72 | return proxy; |
michael@0 | 73 | } |
michael@0 | 74 | |
michael@0 | 75 | return Proxy.NO_PROXY; |
michael@0 | 76 | } |
michael@0 | 77 | |
michael@0 | 78 | /** |
michael@0 | 79 | * Returns the proxy identified by the {@code hostKey} system property, or |
michael@0 | 80 | * null. |
michael@0 | 81 | */ |
michael@0 | 82 | private Proxy lookupProxy(String hostKey, String portKey, Proxy.Type type, int defaultPort) { |
michael@0 | 83 | String host = System.getProperty(hostKey); |
michael@0 | 84 | if (TextUtils.isEmpty(host)) { |
michael@0 | 85 | return null; |
michael@0 | 86 | } |
michael@0 | 87 | |
michael@0 | 88 | int port = getSystemPropertyInt(portKey, defaultPort); |
michael@0 | 89 | return new Proxy(type, InetSocketAddress.createUnresolved(host, port)); |
michael@0 | 90 | } |
michael@0 | 91 | |
michael@0 | 92 | private int getSystemPropertyInt(String key, int defaultValue) { |
michael@0 | 93 | String string = System.getProperty(key); |
michael@0 | 94 | if (string != null) { |
michael@0 | 95 | try { |
michael@0 | 96 | return Integer.parseInt(string); |
michael@0 | 97 | } catch (NumberFormatException ignored) { |
michael@0 | 98 | } |
michael@0 | 99 | } |
michael@0 | 100 | return defaultValue; |
michael@0 | 101 | } |
michael@0 | 102 | |
michael@0 | 103 | /** |
michael@0 | 104 | * Returns true if the {@code nonProxyHosts} system property pattern exists |
michael@0 | 105 | * and matches {@code host}. |
michael@0 | 106 | */ |
michael@0 | 107 | private boolean isNonProxyHost(String host, String nonProxyHosts) { |
michael@0 | 108 | if (host == null || nonProxyHosts == null) { |
michael@0 | 109 | return false; |
michael@0 | 110 | } |
michael@0 | 111 | |
michael@0 | 112 | // construct pattern |
michael@0 | 113 | StringBuilder patternBuilder = new StringBuilder(); |
michael@0 | 114 | for (int i = 0; i < nonProxyHosts.length(); i++) { |
michael@0 | 115 | char c = nonProxyHosts.charAt(i); |
michael@0 | 116 | switch (c) { |
michael@0 | 117 | case '.': |
michael@0 | 118 | patternBuilder.append("\\."); |
michael@0 | 119 | break; |
michael@0 | 120 | case '*': |
michael@0 | 121 | patternBuilder.append(".*"); |
michael@0 | 122 | break; |
michael@0 | 123 | default: |
michael@0 | 124 | patternBuilder.append(c); |
michael@0 | 125 | } |
michael@0 | 126 | } |
michael@0 | 127 | // check whether the host is the nonProxyHosts. |
michael@0 | 128 | String pattern = patternBuilder.toString(); |
michael@0 | 129 | return host.matches(pattern); |
michael@0 | 130 | } |
michael@0 | 131 | } |
michael@0 | 132 |