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