ProxySelectorImpl.java revision fdb2704414a9ed92394ada0d1395e4db86889465
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 */
16package java.net;
17
18import java.io.BufferedInputStream;
19import java.io.File;
20import java.io.FileInputStream;
21import java.io.InputStream;
22import java.io.IOException;
23import java.security.AccessController;
24import java.util.ArrayList;
25import java.util.List;
26import java.util.Properties;
27
28import org.apache.harmony.luni.util.Msg;
29import org.apache.harmony.luni.util.PriviAction;
30
31/**
32 * Default implementation for ProxySelector
33 */
34class ProxySelectorImpl extends ProxySelector {
35
36    private static final int HTTP_PROXY_PORT = 80;
37
38    private static final int HTTPS_PROXY_PORT = 443;
39
40    private static final int FTP_PROXY_PORT = 80;
41
42    private static final int SOCKS_PROXY_PORT = 1080;
43
44    // Net properties read from net.properties file.
45    private static Properties netProps = null;
46
47    // read net.properties file
48    static {
49        AccessController.doPrivileged(new java.security.PrivilegedAction() {
50            public Object run() {
51                File f = new File(System.getProperty("java.home") //$NON-NLS-1$
52                        + File.separator + "lib" + File.separator //$NON-NLS-1$
53                        + "net.properties"); //$NON-NLS-1$
54
55                if (f.exists()) {
56                    try {
57                        FileInputStream fis = new FileInputStream(f);
58                        // BEGIN android-modified
59                        InputStream is = new BufferedInputStream(fis, 8192);
60                        // END android-modified
61                        netProps = new Properties();
62                        netProps.load(is);
63                        is.close();
64                    } catch (IOException e) {
65                    }
66                }
67                return null;
68            }
69        });
70    }
71
72    public ProxySelectorImpl() {
73        super();
74    }
75
76    @Override
77    public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
78        if (null == uri || null == sa || null == ioe) {
79            // "KA001=Argument must not be null"
80            throw new IllegalArgumentException(Msg.getString("KA001")); //$NON-NLS-1$
81        }
82    }
83
84    @Override
85    public List<Proxy> select(URI uri) {
86        // argument check
87        if (null == uri) {
88            // KA001=Argument must not be null
89            throw new IllegalArgumentException(Msg.getString("KA001")); //$NON-NLS-1$
90        }
91        // check scheme
92        String scheme = uri.getScheme();
93        if (null == scheme) {
94            throw new IllegalArgumentException();
95        }
96
97        String host = uri.getHost();
98        Proxy proxy = Proxy.NO_PROXY;
99
100        if ("http".equals(scheme)) { //$NON-NLS-1$
101            proxy = selectHttpProxy(host);
102        } else if ("https".equals(scheme)) { //$NON-NLS-1$
103            proxy = selectHttpsProxy();
104        } else if ("ftp".equals(scheme)) { //$NON-NLS-1$
105            proxy = selectFtpProxy(host);
106        } else if ("socket".equals(scheme)) { //$NON-NLS-1$
107            proxy = selectSocksProxy();
108        }
109        List<Proxy> proxyList = new ArrayList<Proxy>(1);
110        proxyList.add(proxy);
111        return proxyList;
112    }
113
114    /*
115     * Gets proxy for http request. 1. gets from "http.proxyHost", then gets
116     * port from "http.proxyPort", or from "proxyPort" if "http.proxyPort" is
117     * unavailable. 2. gets from "proxyHost" if 1 is unavailable,then get port
118     * from "proxyPort", or from "http.proxyPort" if "proxyPort" is unavailable.
119     * 3. gets from "socksProxyHost" if 2 is unavailable.
120     */
121
122    private Proxy selectHttpProxy(String uriHost) {
123        String host;
124        String port = null;
125        Proxy.Type type = Proxy.Type.DIRECT;
126
127        String nonProxyHosts = getSystemProperty("http.nonProxyHosts"); //$NON-NLS-1$
128        // if host is in non proxy host list, returns Proxy.NO_PROXY
129        if (isNonProxyHost(uriHost, nonProxyHosts)) {
130            return Proxy.NO_PROXY;
131        }
132
133        host = getSystemProperty("http.proxyHost"); //$NON-NLS-1$
134        if (null != host) {
135            // case 1: http.proxyHost is set, use exact http proxy
136            type = Proxy.Type.HTTP;
137            port = getSystemPropertyOrAlternative("http.proxyPort", //$NON-NLS-1$
138                    "proxyPort", String.valueOf(HTTP_PROXY_PORT)); //$NON-NLS-1$
139        } else if ((host = getSystemProperty("proxyHost", null)) != null) { //$NON-NLS-1$
140            // case 2: proxyHost is set, use exact http proxy
141            type = Proxy.Type.HTTP;
142            port = getSystemPropertyOrAlternative("proxyPort", //$NON-NLS-1$
143                    "http.proxyPort", String.valueOf(HTTP_PROXY_PORT)); //$NON-NLS-1$
144
145        } else if ((host = getSystemProperty("socksProxyHost")) != null) { //$NON-NLS-1$
146            // case 3: use socks proxy instead
147            type = Proxy.Type.SOCKS;
148            port = getSystemProperty(
149                    "socksProxyPort", String.valueOf(SOCKS_PROXY_PORT)); //$NON-NLS-1$
150        }
151        int defaultPort = (type == Proxy.Type.SOCKS) ? SOCKS_PROXY_PORT
152                : HTTP_PROXY_PORT;
153        return createProxy(type, host, port, defaultPort);
154    }
155
156    /*
157     * Gets proxy for https request.
158     */
159    private Proxy selectHttpsProxy() {
160        String host;
161        String port = null;
162        Proxy.Type type = Proxy.Type.DIRECT;
163
164        host = getSystemProperty("https.proxyHost"); //$NON-NLS-1$
165        if (null != host) {
166            // case 1: use exact https proxy
167            type = Proxy.Type.HTTP;
168            port = getSystemProperty(
169                    "https.proxyPort", String.valueOf(HTTPS_PROXY_PORT)); //$NON-NLS-1$
170        } else {
171            host = getSystemProperty("socksProxyHost"); //$NON-NLS-1$
172            if (null != host) {
173                // case 2: use socks proxy instead
174                type = Proxy.Type.SOCKS;
175                port = getSystemProperty(
176                        "socksProxyPort", String.valueOf(SOCKS_PROXY_PORT)); //$NON-NLS-1$
177            }
178        }
179        int defaultPort = (type == Proxy.Type.SOCKS) ? SOCKS_PROXY_PORT
180                : HTTPS_PROXY_PORT;
181        return createProxy(type, host, port, defaultPort);
182    }
183
184    /*
185     * Gets proxy for ftp request.
186     */
187    private Proxy selectFtpProxy(String uriHost) {
188        String host;
189        String port = null;
190        Proxy.Type type = Proxy.Type.DIRECT;
191        String nonProxyHosts = getSystemProperty("ftp.nonProxyHosts"); //$NON-NLS-1$
192        // if host is in non proxy host list, returns Proxy.NO_PROXY
193        if (isNonProxyHost(uriHost, nonProxyHosts)) {
194            return Proxy.NO_PROXY;
195        }
196
197        host = getSystemProperty("ftp.proxyHost"); //$NON-NLS-1$
198        if (null != host) {
199            // case 1: use exact ftp proxy
200            type = Proxy.Type.HTTP;
201            port = getSystemProperty(
202                    "ftp.proxyPort", String.valueOf(FTP_PROXY_PORT)); //$NON-NLS-1$
203        } else {
204            host = getSystemProperty("socksProxyHost"); //$NON-NLS-1$
205            if (null != host) {
206                // case 2: use socks proxy instead
207                type = Proxy.Type.SOCKS;
208                port = getSystemProperty(
209                        "socksProxyPort", String.valueOf(SOCKS_PROXY_PORT)); //$NON-NLS-1$
210            }
211        }
212        int defaultPort = (type == Proxy.Type.SOCKS) ? SOCKS_PROXY_PORT
213                : FTP_PROXY_PORT;
214        return createProxy(type, host, port, defaultPort);
215    }
216
217    /*
218     * Gets proxy for socks request.
219     */
220    private Proxy selectSocksProxy() {
221        String host;
222        String port = null;
223        Proxy.Type type = Proxy.Type.DIRECT;
224
225        host = getSystemProperty("socksProxyHost"); //$NON-NLS-1$
226        if (null != host) {
227            type = Proxy.Type.SOCKS;
228            port = getSystemProperty(
229                    "socksProxyPort", String.valueOf(SOCKS_PROXY_PORT)); //$NON-NLS-1$
230        }
231        return createProxy(type, host, port, SOCKS_PROXY_PORT);
232    }
233
234    /*
235     * checks whether the host needs proxy. return true if it doesn't need a
236     * proxy.
237     */
238    private boolean isNonProxyHost(String host, String nonProxyHosts) {
239        // nonProxyHosts is not set
240        if (null == nonProxyHosts) {
241            return false;
242        }
243        // Construct regex expression of nonProxyHosts
244        int length = nonProxyHosts.length();
245        char ch;
246        StringBuilder buf = new StringBuilder(length);
247        for (int i = 0; i < nonProxyHosts.length(); i++) {
248            ch = nonProxyHosts.charAt(i);
249            switch (ch) {
250                case '.':
251                    buf.append("\\."); //$NON-NLS-1$
252                    break;
253                case '*':
254                    buf.append(".*"); //$NON-NLS-1$
255                    break;
256                default:
257                    buf.append(ch);
258            }
259        }
260        String nonProxyHostsReg = buf.toString();
261        // check whether the host is the nonProxyHosts.
262        return host.matches(nonProxyHostsReg);
263    }
264
265    /*
266     * Create Proxy by "type","host" and "port".
267     */
268    private Proxy createProxy(Proxy.Type type, String host, String port,
269            int defaultPort) {
270        Proxy proxy;
271        if (type == Proxy.Type.DIRECT) {
272            proxy = Proxy.NO_PROXY;
273        } else {
274            int iPort;
275            try {
276// BEGIN android-changed
277                iPort = Integer.parseInt(port);
278// END android-changed
279            } catch (NumberFormatException e) {
280                iPort = defaultPort;
281            }
282            proxy = new Proxy(type, InetSocketAddress.createUnresolved(host,
283                    iPort));
284        }
285        return proxy;
286    }
287
288    /*
289     * gets system property, privileged operation. If the value of the property
290     * is null or empty String, it returns defaultValue.
291     */
292    private String getSystemProperty(final String property) {
293        return getSystemProperty(property, null);
294    }
295
296    /*
297     * gets system property, privileged operation. If the value of the property
298     * is null or empty String, it returns defaultValue.
299     */
300    private String getSystemProperty(final String property,
301            final String defaultValue) {
302        String value = AccessController.doPrivileged(new PriviAction<String>(
303                property));
304        if (null == value || "".equals(value)) { //$NON-NLS-1$
305            value = (netProps != null)
306                    ? netProps.getProperty(property, defaultValue)
307                    : defaultValue;
308        }
309        return value;
310    }
311
312    /*
313     * gets system property, privileged operation. If the value of "key"
314     * property is null, then retrieve value from "alternative" property.
315     * Finally, if the value is null or empty String, it returns defaultValue.
316     */
317    private String getSystemPropertyOrAlternative(final String key,
318            final String alternativeKey, final String defaultValue) {
319        String value = getSystemProperty(key);
320        if (value == null) {
321            value = getSystemProperty(alternativeKey);
322            if (null == value) {
323                value = defaultValue;
324            }
325        }
326        return value;
327    }
328}
329