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