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