Index: modules/luni/src/test/java/org/apache/harmony/tests/internal/net/www/protocol/http/HttpURLConnectionTest.java
===================================================================
--- modules/luni/src/test/java/org/apache/harmony/tests/internal/net/www/protocol/http/HttpURLConnectionTest.java (revision 412668)
+++ modules/luni/src/test/java/org/apache/harmony/tests/internal/net/www/protocol/http/HttpURLConnectionTest.java (working copy)
@@ -18,51 +18,99 @@
import java.io.IOException;
import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
import java.net.ServerSocket;
+import java.net.SocketAddress;
import java.net.SocketTimeoutException;
+import java.net.URI;
import java.net.URL;
+import java.util.ArrayList;
import junit.framework.TestCase;
/**
* Tests for HTTPURLConnection class constructors and methods.
- *
+ *
*/
public class HttpURLConnectionTest extends TestCase {
-
- private final Object bound = new Object();
- //TODO: replace with connection to a mock server
- Thread httpServer = new Thread(new Runnable() {
+ private static int port = 34567;
+
+ private final static Object bound = new Object();
+
+ static class MockServer extends Thread {
+ ServerSocket serverSocket;
+ boolean accepted = false;
+
+ public MockServer(String name) throws IOException {
+ super(name);
+ serverSocket = new ServerSocket(0);
+ serverSocket.setSoTimeout(1000);
+ }
+
+ public int port() {
+ return serverSocket.getLocalPort();
+ }
+
public void run() {
try {
- ServerSocket ss = new ServerSocket(port);
- synchronized(bound) {
+ synchronized (bound) {
bound.notify();
}
- ss.setSoTimeout(1000);
try {
- ss.accept().close();
+ serverSocket.accept().close();
+ accepted = true;
} catch (SocketTimeoutException ignore) {
}
- ss.close();
+ serverSocket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
- }, "ServerSocket for HttpURLConnectionTest");
-
- private int port = 34567;
-
- public void setUp() throws Exception {
- super.setUp();
- httpServer.start();
}
- public void tearDown() throws Exception {
- super.tearDown();
- httpServer.join();
+ /**
+ * ProxySelector implementation used in the test.
+ */
+ static class TestProxySelector extends ProxySelector {
+
+ // this uri request will go through proxy
+ private URI uri;
+ // proxy port
+ private int proxy_port;
+ // server port
+ private int server_port;
+
+ /**
+ * Creates proxy selector instance.
+ * Selector will return the proxy, only if the connection
+ * is made to localhost:server_port. Otherwise it will
+ * return NO_PROXY.
+ * Address of the returned proxy will be localhost:proxy_port.
+ */
+ public TestProxySelector(int server_port, int proxy_port) {
+ this.server_port = server_port;
+ this.proxy_port = proxy_port;
+ }
+
+ public java.util.List select(URI uri) {
+ Proxy proxy = Proxy.NO_PROXY;
+ if (("localhost".equals(uri.getHost()))
+ && (server_port == uri.getPort())) {
+ proxy = new Proxy(Proxy.Type.HTTP,
+ new InetSocketAddress("localhost", proxy_port));
+ }
+ ArrayList result = new ArrayList();
+ result.add(proxy);
+ return result;
+ }
+
+ public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
+ // do nothing
+ }
}
/**
@@ -70,15 +118,103 @@
*/
public void testGetOutputStream() throws Exception {
// Regression for HARMONY-482
+ MockServer httpServer =
+ new MockServer("ServerSocket for HttpURLConnectionTest");
+ httpServer.start();
synchronized(bound) {
bound.wait(5000);
}
- HttpURLConnection c = (HttpURLConnection) new URL("http://127.0.0.1:"
- + port).openConnection();
+ HttpURLConnection c = (HttpURLConnection)
+ new URL("http://127.0.0.1:" + httpServer.port()).openConnection();
c.setDoOutput(true);
- //use new String("POST") instead of simple "POST" to obtain other
- //object instances then those that are in HttpURLConnection classes
+ //use new String("POST") instead of simple "POST" to obtain other
+ //object instances then those that are in HttpURLConnection classes
c.setRequestMethod(new String("POST"));
c.getOutputStream();
+ httpServer.join();
}
+
+
+ /**
+ * Test checks if the proxy specified in openConnection
+ * method will be used for connection to the server
+ */
+ public void testUsingProxy() throws Exception {
+ // Regression for HARMONY-570
+ MockServer server = new MockServer("server");
+ MockServer proxy = new MockServer("proxy");
+
+ URL url = new URL("http://localhost:" + server.port());
+
+ HttpURLConnection connection = (HttpURLConnection) url
+ .openConnection(new Proxy(Proxy.Type.HTTP,
+ new InetSocketAddress("localhost",
+ proxy.port())));
+ connection.setConnectTimeout(2000);
+ connection.setReadTimeout(2000);
+
+ server.start();
+ synchronized(bound) {
+ bound.wait(5000);
+ }
+ proxy.start();
+ synchronized(bound) {
+ bound.wait(5000);
+ }
+
+ connection.connect();
+
+ // wait while server and proxy run
+ server.join();
+ proxy.join();
+
+ assertTrue("Connection does not use proxy", connection.usingProxy());
+ assertTrue("Proxy server was not used", proxy.accepted);
+ }
+
+ /**
+ * Test checks if the proxy provided by proxy selector
+ * will be used for connection to the server
+ */
+ public void testUsingProxySelector() throws Exception {
+ // Regression for HARMONY-570
+ MockServer server = new MockServer("server");
+ MockServer proxy = new MockServer("proxy");
+
+ URL url = new URL("http://localhost:" + server.port());
+
+ // keep default proxy selector
+ ProxySelector defPS = ProxySelector.getDefault();
+ // replace selector
+ ProxySelector.setDefault(
+ new TestProxySelector(server.port(), proxy.port()));
+
+ try {
+ HttpURLConnection connection =
+ (HttpURLConnection) url.openConnection();
+ connection.setConnectTimeout(2000);
+ connection.setReadTimeout(2000);
+
+ server.start();
+ synchronized(bound) {
+ bound.wait(5000);
+ }
+ proxy.start();
+ synchronized(bound) {
+ bound.wait(5000);
+ }
+ connection.connect();
+
+ // wait while server and proxy run
+ server.join();
+ proxy.join();
+
+ assertTrue("Connection does not use proxy",
+ connection.usingProxy());
+ assertTrue("Proxy server was not used", proxy.accepted);
+ } finally {
+ // restore default proxy selector
+ ProxySelector.setDefault(defPS);
+ }
+ }
}
Index: modules/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java
===================================================================
--- modules/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java (revision 412668)
+++ modules/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java (working copy)
@@ -92,6 +92,8 @@
private boolean hasTriedCache = false;
+ private boolean usingProxy = false;
+
private HttpOutputStream os;
private boolean sentRequest = false;
@@ -523,23 +525,80 @@
if (getFromCache()) {
return;
}
- Socket socket;
- int connectTimeout = getConnectTimeout();
- InetAddress host = getHostAddress();
- int port = getHostPort();
- SocketAddress sa = new InetSocketAddress(host, port);
- if (null == currentProxy || Proxy.Type.HTTP == currentProxy.type()) {
- socket = new Socket();
+ // socket to be used for connection
+ Socket socket = null;
+ // try to determine: to use the proxy or not
+ if (proxy != null) {
+ // try to make the connection to the proxy
+ // specified in constructor.
+ // IOException will be thrown in the case of failure
+ socket = getHTTPConnection(proxy.address());
} else {
- socket = new Socket(currentProxy);
+ // Use system-wide ProxySelect to select proxy list,
+ // then try to connect via elements in the proxy list.
+ ProxySelector selector = ProxySelector.getDefault();
+ List proxyList = selector.select(uri);
+ if (proxyList != null) {
+ for (Proxy selectedProxy: proxyList) {
+ if (selectedProxy.type() == Proxy.Type.DIRECT) {
+ // the same as NO_PROXY
+ continue;
+ }
+ try {
+ socket = getHTTPConnection(selectedProxy);
+ proxy = selectedProxy;
+ break; // connected
+ } catch (IOException e) {
+ socket = null;
+ // failed to connect, tell it to the selector
+ selector.connectFailed(
+ uri, selectedProxy.address(), e);
+ }
+ }
+ }
}
- socket.connect(sa, connectTimeout);
+ if (socket != null) {
+ // connection was made through the proxy
+ usingProxy = true;
+ } else {
+ // make direct connection
+ socket = getHTTPConnection(
+ new InetSocketAddress(url.getHost(), url.getPort()));
+ }
socket.setSoTimeout(getReadTimeout());
connected = true;
socketOut = socket.getOutputStream();
is = new BufferedInputStream(socket.getInputStream());
}
+
+ /**
+ * Returns connected socket to be used for this HTTP connection.
+ * TODO: implement persistent connections.
+ */
+ protected Socket getHTTPConnection(SocketAddress address) throws IOException {
+ Socket socket = new Socket();
+ socket.connect(address, getConnectTimeout());
+ return socket;
+ }
+ /**
+ * Returns connected socket to be used for this HTTP connection.
+ * TODO: implement persistent connections.
+ */
+ protected Socket getHTTPConnection(Proxy proxy) throws IOException {
+ Socket socket;
+ if (proxy.type() == Proxy.Type.HTTP) {
+ socket = getHTTPConnection(proxy.address());
+ } else {
+ // using DIRECT or SOCKS proxy
+ socket = new Socket(proxy);
+ socket.connect(
+ new InetSocketAddress(url.getHost(), url.getPort()),
+ getConnectTimeout());
+ }
+ return socket;
+ }
+
// Tries to get head and body from cache, return true if has got this time or
// already got before
private boolean getFromCache() throws IOException {
@@ -1194,20 +1253,9 @@
* if a proxy port has been set.
*/
private int getHostPort() {
- if (usingProxy()) {
- if (null == currentProxy) {
- // get from system property
- String portString = getSystemPropertyOrAlternative(
- "http.proxyPort", "proxyPort");
- if (portString != null) {
- hostPort = Integer.parseInt(portString);
- }
- } else {
- // get from proxy
- InetSocketAddress addr = (InetSocketAddress) currentProxy
- .address();
- hostPort = addr.getPort();
- }
+ int hostPort;
+ if (proxy != null) {
+ hostPort = ((InetSocketAddress) proxy.address()).getPort();
} else {
hostPort = url.getPort();
}
@@ -1222,7 +1270,11 @@
* given in the URL or the address of the proxy server.
*/
private InetAddress getHostAddress() throws IOException {
- return InetAddress.getByName(getHostName());
+ if (proxy != null) {
+ return ((InetSocketAddress) proxy.address()).getAddress();
+ } else {
+ return InetAddress.getByName(url.getHost());
+ }
}
/**
@@ -1230,21 +1282,11 @@
* in the URL or the name of the proxy server.
*/
private String getHostName() {
- if (proxyName != null) {
- return proxyName;
+ if (proxy != null) {
+ return ((InetSocketAddress) proxy.address()).getHostName();
+ } else {
+ return url.getHost();
}
- if (usingProxy()) {
- if (null == currentProxy) {
- proxyName = getSystemPropertyOrAlternative("http.proxyHost",
- "proxyHost");
- } else {
- InetSocketAddress addr = (InetSocketAddress) currentProxy
- .address();
- proxyName = addr.getHostName();
- }
- return proxyName;
- }
- return url.getHost();
}
private String getSystemPropertyOrAlternative(final String key,
@@ -1268,27 +1310,7 @@
* 1.0 and JDK 1.1
*/
public boolean usingProxy() {
- if (Proxy.NO_PROXY == currentProxy) {
- return false;
- }
- // using proxy if http proxy is set by caller.
- if (null != currentProxy && Proxy.Type.HTTP == currentProxy.type()) {
- return true;
- }
- // First check whether the user explicitly set whether to use a proxy.
- String proxySet = getSystemProperty("http.proxySet");
- if (proxySet != null)
- return proxySet.toLowerCase().equals("true");
-
- proxySet = getSystemProperty("proxySet");
- if (proxySet != null)
- return proxySet.toLowerCase().equals("true");
-
- // The user didn't explicitly set whether to use a proxy. Answer true if
- // the user specified a proxyHost.
- if (getSystemProperty("http.proxyHost") != null)
- return true;
- return getSystemProperty("proxyHost") != null;
+ return usingProxy;
}
/**
@@ -1306,41 +1328,7 @@
}
return;
}
- // Use system-wide ProxySelect to select proxy list,
- // then try to connect via elements in the proxy list.
- if (null != proxy) {
- proxyList = new ArrayList(1);
- proxyList.add(proxy);
- } else {
- proxyList = NetUtil.getProxyList(uri);
- }
- if (null == proxyList) {
- currentProxy = null;
- doRequestInternal();
- } else {
- // try the proxy list until one of them establish
- // the connection successfully.
- ProxySelector selector = ProxySelector.getDefault();
- Iterator iter = proxyList.iterator();
- boolean doRequestOK = false;
- while (iter.hasNext() && !doRequestOK) {
- currentProxy = (Proxy) iter.next();
- try {
- doRequestInternal();
- doRequestOK = true;
- } catch (IOException ioe) {
- // if connect failed, callback method "connectFailed"
- // should be invoked.
- if (null != selector && Proxy.NO_PROXY != currentProxy) {
- selector
- .connectFailed(uri, currentProxy.address(), ioe);
- }
- }
- }
- if (!doRequestOK) {
- throw new IOException(Msg.getString("K0097"));
- }
- }
+ doRequestInternal();
}
void doRequestInternal() throws IOException {