blob: 955f6eb1a9cef2a4fb75fb1818858bfc39f14a43 [file] [log] [blame]
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.net;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.harmony.luni.internal.nls.Messages;
import org.apache.harmony.luni.util.PriviAction;
/**
* Default implementation for {@code ProxySelector}.
*/
@SuppressWarnings("unchecked")
class ProxySelectorImpl extends ProxySelector {
private static final int HTTP_PROXY_PORT = 80;
private static final int HTTPS_PROXY_PORT = 443;
private static final int FTP_PROXY_PORT = 80;
private static final int SOCKS_PROXY_PORT = 1080;
// Net properties read from net.properties file.
private static Properties netProps = null;
// read net.properties file
static {
AccessController.doPrivileged(new java.security.PrivilegedAction() {
public Object run() {
File f = new File(System.getProperty("java.home") //$NON-NLS-1$
+ File.separator + "lib" + File.separator //$NON-NLS-1$
+ "net.properties"); //$NON-NLS-1$
if (f.exists()) {
try {
FileInputStream fis = new FileInputStream(f);
InputStream is = new BufferedInputStream(fis);
netProps = new Properties();
netProps.load(is);
is.close();
} catch (IOException e) {
}
}
return null;
}
});
}
public ProxySelectorImpl() {
super();
}
@Override
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
if (null == uri || null == sa || null == ioe) {
// luni.4D=Argument must not be null"
throw new IllegalArgumentException(Messages.getString("luni.4D")); //$NON-NLS-1$
}
}
@Override
public List<Proxy> select(URI uri) {
// argument check
if (null == uri) {
// luni.4D=Argument must not be null
throw new IllegalArgumentException(Messages.getString("luni.4D")); //$NON-NLS-1$
}
// check scheme
String scheme = uri.getScheme();
if (null == scheme) {
throw new IllegalArgumentException();
}
String host = uri.getHost();
Proxy proxy = Proxy.NO_PROXY;
if ("http".equals(scheme)) { //$NON-NLS-1$
proxy = selectHttpProxy(host);
} else if ("https".equals(scheme)) { //$NON-NLS-1$
proxy = selectHttpsProxy();
} else if ("ftp".equals(scheme)) { //$NON-NLS-1$
proxy = selectFtpProxy(host);
} else if ("socket".equals(scheme)) { //$NON-NLS-1$
proxy = selectSocksProxy();
}
List<Proxy> proxyList = new ArrayList<Proxy>(1);
proxyList.add(proxy);
return proxyList;
}
/*
* Gets proxy for http request. 1. gets from "http.proxyHost", then gets
* port from "http.proxyPort", or from "proxyPort" if "http.proxyPort" is
* unavailable. 2. gets from "proxyHost" if 1 is unavailable,then get port
* from "proxyPort", or from "http.proxyPort" if "proxyPort" is unavailable.
* 3. gets from "socksProxyHost" if 2 is unavailable.
*/
private Proxy selectHttpProxy(String uriHost) {
String host;
String port = null;
Proxy.Type type = Proxy.Type.DIRECT;
String nonProxyHosts = getSystemProperty("http.nonProxyHosts"); //$NON-NLS-1$
// if host is in non proxy host list, returns Proxy.NO_PROXY
if (isNonProxyHost(uriHost, nonProxyHosts)) {
return Proxy.NO_PROXY;
}
host = getSystemProperty("http.proxyHost"); //$NON-NLS-1$
if (null != host) {
// case 1: http.proxyHost is set, use exact http proxy
type = Proxy.Type.HTTP;
port = getSystemPropertyOrAlternative("http.proxyPort", //$NON-NLS-1$
"proxyPort", String.valueOf(HTTP_PROXY_PORT)); //$NON-NLS-1$
} else if ((host = getSystemProperty("proxyHost", null)) != null) { //$NON-NLS-1$
// case 2: proxyHost is set, use exact http proxy
type = Proxy.Type.HTTP;
port = getSystemPropertyOrAlternative("proxyPort", //$NON-NLS-1$
"http.proxyPort", String.valueOf(HTTP_PROXY_PORT)); //$NON-NLS-1$
} else if ((host = getSystemProperty("socksProxyHost")) != null) { //$NON-NLS-1$
// case 3: use socks proxy instead
type = Proxy.Type.SOCKS;
port = getSystemProperty(
"socksProxyPort", String.valueOf(SOCKS_PROXY_PORT)); //$NON-NLS-1$
}
int defaultPort = (type == Proxy.Type.SOCKS) ? SOCKS_PROXY_PORT
: HTTP_PROXY_PORT;
return createProxy(type, host, port, defaultPort);
}
/*
* Gets proxy for https request.
*/
private Proxy selectHttpsProxy() {
String host;
String port = null;
Proxy.Type type = Proxy.Type.DIRECT;
host = getSystemProperty("https.proxyHost"); //$NON-NLS-1$
if (null != host) {
// case 1: use exact https proxy
type = Proxy.Type.HTTP;
port = getSystemProperty(
"https.proxyPort", String.valueOf(HTTPS_PROXY_PORT)); //$NON-NLS-1$
} else {
host = getSystemProperty("socksProxyHost"); //$NON-NLS-1$
if (null != host) {
// case 2: use socks proxy instead
type = Proxy.Type.SOCKS;
port = getSystemProperty(
"socksProxyPort", String.valueOf(SOCKS_PROXY_PORT)); //$NON-NLS-1$
}
}
int defaultPort = (type == Proxy.Type.SOCKS) ? SOCKS_PROXY_PORT
: HTTPS_PROXY_PORT;
return createProxy(type, host, port, defaultPort);
}
/*
* Gets proxy for ftp request.
*/
private Proxy selectFtpProxy(String uriHost) {
String host;
String port = null;
Proxy.Type type = Proxy.Type.DIRECT;
String nonProxyHosts = getSystemProperty("ftp.nonProxyHosts"); //$NON-NLS-1$
// if host is in non proxy host list, returns Proxy.NO_PROXY
if (isNonProxyHost(uriHost, nonProxyHosts)) {
return Proxy.NO_PROXY;
}
host = getSystemProperty("ftp.proxyHost"); //$NON-NLS-1$
if (null != host) {
// case 1: use exact ftp proxy
type = Proxy.Type.HTTP;
port = getSystemProperty(
"ftp.proxyPort", String.valueOf(FTP_PROXY_PORT)); //$NON-NLS-1$
} else {
host = getSystemProperty("socksProxyHost"); //$NON-NLS-1$
if (null != host) {
// case 2: use socks proxy instead
type = Proxy.Type.SOCKS;
port = getSystemProperty(
"socksProxyPort", String.valueOf(SOCKS_PROXY_PORT)); //$NON-NLS-1$
}
}
int defaultPort = (type == Proxy.Type.SOCKS) ? SOCKS_PROXY_PORT
: FTP_PROXY_PORT;
return createProxy(type, host, port, defaultPort);
}
/*
* Gets proxy for socks request.
*/
private Proxy selectSocksProxy() {
String host;
String port = null;
Proxy.Type type = Proxy.Type.DIRECT;
host = getSystemProperty("socksProxyHost"); //$NON-NLS-1$
if (null != host) {
type = Proxy.Type.SOCKS;
port = getSystemProperty(
"socksProxyPort", String.valueOf(SOCKS_PROXY_PORT)); //$NON-NLS-1$
}
return createProxy(type, host, port, SOCKS_PROXY_PORT);
}
/*
* checks whether the host needs proxy. return true if it doesn't need a
* proxy.
*/
private boolean isNonProxyHost(String host, String nonProxyHosts) {
// nonProxyHosts is not set
if (null == host || null == nonProxyHosts) {
return false;
}
// Construct regex expression of nonProxyHosts
int length = nonProxyHosts.length();
char ch;
StringBuilder buf = new StringBuilder(length);
for (int i = 0; i < nonProxyHosts.length(); i++) {
ch = nonProxyHosts.charAt(i);
switch (ch) {
case '.':
buf.append("\\."); //$NON-NLS-1$
break;
case '*':
buf.append(".*"); //$NON-NLS-1$
break;
default:
buf.append(ch);
}
}
String nonProxyHostsReg = buf.toString();
// check whether the host is the nonProxyHosts.
return host.matches(nonProxyHostsReg);
}
/*
* Create Proxy by "type","host" and "port".
*/
private Proxy createProxy(Proxy.Type type, String host, String port,
int defaultPort) {
Proxy proxy;
if (type == Proxy.Type.DIRECT) {
proxy = Proxy.NO_PROXY;
} else {
int iPort;
try {
iPort = Integer.valueOf(port).intValue();
} catch (NumberFormatException e) {
iPort = defaultPort;
}
proxy = new Proxy(type, InetSocketAddress.createUnresolved(host,
iPort));
}
return proxy;
}
/*
* gets system property, privileged operation. If the value of the property
* is null or empty String, it returns defaultValue.
*/
private String getSystemProperty(final String property) {
return getSystemProperty(property, null);
}
/*
* gets system property, privileged operation. If the value of the property
* is null or empty String, it returns defaultValue.
*/
private String getSystemProperty(final String property,
final String defaultValue) {
String value = AccessController.doPrivileged(new PriviAction<String>(
property));
if (null == value || "".equals(value)) { //$NON-NLS-1$
value = (netProps != null)
? netProps.getProperty(property, defaultValue)
: defaultValue;
}
return value;
}
/*
* gets system property, privileged operation. If the value of "key"
* property is null, then retrieve value from "alternative" property.
* Finally, if the value is null or empty String, it returns defaultValue.
*/
private String getSystemPropertyOrAlternative(final String key,
final String alternativeKey, final String defaultValue) {
String value = getSystemProperty(key);
if (value == null) {
value = getSystemProperty(alternativeKey);
if (null == value) {
value = defaultValue;
}
}
return value;
}
}