1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* Licensed to the Apache Software Foundation (ASF) under one or more 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 7f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 163b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.net; 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 203b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilsonimport java.util.Collections; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.List; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 233b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilsonfinal class ProxySelectorImpl extends ProxySelector { 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 253b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson @Override public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { 26b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes if (uri == null || sa == null || ioe == null) { 27b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IllegalArgumentException(); 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 313b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson @Override public List<Proxy> select(URI uri) { 323b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson return Collections.singletonList(selectOneProxy(uri)); 333b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson } 343b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson 353b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson private Proxy selectOneProxy(URI uri) { 36b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes if (uri == null) { 37b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IllegalArgumentException("uri == null"); 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String scheme = uri.getScheme(); 403b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson if (scheme == null) { 413b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson throw new IllegalArgumentException("scheme == null"); 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 443b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson int port = -1; 453b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson Proxy proxy = null; 463b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson String nonProxyHostsKey = null; 473b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson boolean httpProxyOkay = true; 483b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson if ("http".equalsIgnoreCase(scheme)) { 493b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson port = 80; 503b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson nonProxyHostsKey = "http.nonProxyHosts"; 513b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson proxy = lookupProxy("http.proxyHost", "http.proxyPort", Proxy.Type.HTTP, port); 523b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson } else if ("https".equalsIgnoreCase(scheme)) { 533b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson port = 443; 543b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson nonProxyHostsKey = "https.nonProxyHosts"; // RI doesn't support this 553b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson proxy = lookupProxy("https.proxyHost", "https.proxyPort", Proxy.Type.HTTP, port); 563b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson } else if ("ftp".equalsIgnoreCase(scheme)) { 573b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson port = 80; // not 21 as you might guess 583b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson nonProxyHostsKey = "ftp.nonProxyHosts"; 593b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson proxy = lookupProxy("ftp.proxyHost", "ftp.proxyPort", Proxy.Type.HTTP, port); 603b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson } else if ("socket".equalsIgnoreCase(scheme)) { 613b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson httpProxyOkay = false; 623b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson } else { 633b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson return Proxy.NO_PROXY; 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 663b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson if (nonProxyHostsKey != null 673b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson && isNonProxyHost(uri.getHost(), System.getProperty(nonProxyHostsKey))) { 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Proxy.NO_PROXY; 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 713b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson if (proxy != null) { 723b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson return proxy; 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 753b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson if (httpProxyOkay) { 763b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson proxy = lookupProxy("proxyHost", "proxyPort", Proxy.Type.HTTP, port); 773b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson if (proxy != null) { 783b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson return proxy; 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 823b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson proxy = lookupProxy("socksProxyHost", "socksProxyPort", Proxy.Type.SOCKS, 1080); 833b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson if (proxy != null) { 843b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson return proxy; 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 873b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson return Proxy.NO_PROXY; 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 903b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson /** 913b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson * Returns the proxy identified by the {@code hostKey} system property, or 923b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson * null. 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 943b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson private Proxy lookupProxy(String hostKey, String portKey, Proxy.Type type, int defaultPort) { 953b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson String host = System.getProperty(hostKey); 963b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson if (host == null || host.isEmpty()) { 973b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson return null; 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1003b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson int port = getSystemPropertyInt(portKey, defaultPort); 1013b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson return new Proxy(type, InetSocketAddress.createUnresolved(host, port)); 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1043b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson private int getSystemPropertyInt(String key, int defaultValue) { 1053b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson String string = System.getProperty(key); 1063b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson if (string != null) { 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 1083b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson return Integer.parseInt(string); 1093b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson } catch (NumberFormatException ignored) { 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1123b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson return defaultValue; 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1153b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson /** 1163b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson * Returns true if the {@code nonProxyHosts} system property pattern exists 1173b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson * and matches {@code host}. 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1193b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson private boolean isNonProxyHost(String host, String nonProxyHosts) { 1203b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson if (host == null || nonProxyHosts == null) { 1213b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson return false; 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1243b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson // construct pattern 1253b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson StringBuilder patternBuilder = new StringBuilder(); 1263b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson for (int i = 0; i < nonProxyHosts.length(); i++) { 1273b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson char c = nonProxyHosts.charAt(i); 1283b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson switch (c) { 1293b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson case '.': 1303b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson patternBuilder.append("\\."); 1313b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson break; 1323b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson case '*': 1333b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson patternBuilder.append(".*"); 1343b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson break; 1353b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson default: 1363b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson patternBuilder.append(c); 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1393b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson // check whether the host is the nonProxyHosts. 1403b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson String pattern = patternBuilder.toString(); 1413b0348d1081a4645aa38da97ee299fadc040c1b4Jesse Wilson return host.matches(pattern); 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 144