Index: src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java
===================================================================
--- src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java (revision 504056)
+++ src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java (working copy)
@@ -17,7 +17,6 @@
package org.apache.harmony.luni.internal.net.www.protocol.http;
-import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -33,8 +32,6 @@
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.ResponseCache;
-import java.net.Socket;
-import java.net.SocketAddress;
import java.net.SocketPermission;
import java.net.URI;
import java.net.URISyntaxException;
@@ -73,6 +70,8 @@
private final int defaultPort;
private int httpVersion = 1; // Assume HTTP/1.1
+
+ protected HttpConnection connection;
private InputStream is;
@@ -78,8 +77,6 @@
private InputStream uis;
- protected Socket socket;
-
private OutputStream socketOut;
private OutputStream cacheOut;
@@ -130,8 +127,12 @@
@Override
public void close() throws IOException {
- bytesRemaining = 0;
- closeSocket();
+ if(bytesRemaining > 0) {
+ bytesRemaining = 0;
+ disconnect(true); // Should close the socket if client hasn't read all the data
+ } else {
+ disconnect(false);
+ }
/*
* if user has set useCache to true and cache exists, aborts it when
* closing
@@ -153,6 +154,7 @@
@Override
public int read() throws IOException {
if (bytesRemaining <= 0) {
+ disconnect(false);
return -1;
}
int result = is.read();
@@ -176,6 +178,7 @@
throw new ArrayIndexOutOfBoundsException();
}
if (bytesRemaining <= 0) {
+ disconnect(false);
return -1;
}
if (length > bytesRemaining) {
@@ -195,6 +198,7 @@
public long skip(int amount) throws IOException {
if (bytesRemaining <= 0) {
+ disconnect(false);
return -1;
}
if (amount > bytesRemaining) {
@@ -219,8 +223,12 @@
@Override
public void close() throws IOException {
+ if(!atEnd && available() > 0) {
+ disconnect(true);
+ } else {
+ disconnect(false);
+ }
atEnd = true;
- closeSocket();
// if user has set useCache to true and cache exists, abort
if (useCaches && null != cacheRequest) {
cacheRequest.abort();
@@ -261,6 +269,7 @@
readChunkSize();
}
if (atEnd) {
+ disconnect(false);
return -1;
}
bytesRemaining--;
@@ -286,6 +295,7 @@
readChunkSize();
}
if (atEnd) {
+ disconnect(false);
return -1;
}
if (length > bytesRemaining) {
@@ -305,6 +315,7 @@
public long skip(int amount) throws IOException {
if (atEnd) {
+ disconnect(false);
return -1;
}
if (bytesRemaining <= 0) {
@@ -428,6 +439,7 @@
}
sendCache(closed);
}
+ disconnect(false);
}
@Override
@@ -585,7 +597,7 @@
return;
}
// socket to be used for connection
- Socket socket = null;
+ connection = null;
// try to determine: to use the proxy or not
if (proxy != null) {
// try to make the connection to the proxy
@@ -591,7 +603,7 @@
// try to make the connection to the proxy
// specified in constructor.
// IOException will be thrown in the case of failure
- socket = getHTTPConnection(proxy);
+ connection = getHTTPConnection(proxy);
} else {
// Use system-wide ProxySelect to select proxy list,
// then try to connect via elements in the proxy list.
@@ -604,7 +616,7 @@
continue;
}
try {
- socket = getHTTPConnection(selectedProxy);
+ connection = getHTTPConnection(selectedProxy);
proxy = selectedProxy;
break; // connected
} catch (IOException e) {
@@ -614,12 +626,12 @@
}
}
}
- if (socket == null) {
+ if (connection == null) {
// make direct connection
- socket = getHTTPConnection(null);
+ connection = getHTTPConnection(null);
}
- socket.setSoTimeout(getReadTimeout());
- setUpTransportIO(socket);
+ connection.setSoTimeout(getReadTimeout());
+ setUpTransportIO(connection);
connected = true;
}
@@ -624,42 +636,22 @@
}
/**
- * Returns connected socket to be used for this HTTP connection. TODO:
- * implement persistent connections.
+ * Returns connected socket to be used for this HTTP connection.
*/
- protected Socket getHTTPConnection(Proxy proxy) throws IOException {
- Socket socket;
+ protected HttpConnection getHTTPConnection(Proxy proxy) throws IOException {
+ HttpConnection connection;
if (proxy == null || proxy.type() == Proxy.Type.DIRECT) {
- this.proxy = null; // not using proxy
- socket = new Socket();
- socket.connect(new InetSocketAddress(getHostName(), getHostPort()),
+ this.proxy = null; // not using proxy
+ connection = HttpConnectionManager.getDefault().getConnection(getHostName(), getHostPort(),
getConnectTimeout());
} else if (proxy.type() == Proxy.Type.HTTP) {
- socket = new Socket();
-
- SocketAddress proxyAddr = proxy.address();
-
- if (!(proxyAddr instanceof InetSocketAddress)) {
- throw new IllegalArgumentException(Msg.getString(
- "K0316", proxyAddr.getClass())); //$NON-NLS-1$
- }
-
- InetSocketAddress iProxyAddr = (InetSocketAddress) proxyAddr;
-
- if( iProxyAddr.getAddress() == null ) {
- // Resolve proxy, see HARMONY-3113
- socket.connect(new InetSocketAddress((iProxyAddr.getHostName()),
- iProxyAddr.getPort()), getConnectTimeout());
- } else {
- socket.connect(iProxyAddr, getConnectTimeout());
- }
+ connection = HttpConnectionManager.getDefault().getConnection(proxy, getConnectTimeout());
} else {
// using SOCKS proxy
- socket = new Socket(proxy);
- socket.connect(new InetSocketAddress(getHostName(), getHostPort()),
- getConnectTimeout());
+ connection = HttpConnectionManager.getDefault().getConnection(proxy, getHostName(), getHostPort(),
+ getConnectTimeout());
}
- return socket;
+ return connection;
}
/**
@@ -665,13 +657,12 @@
/**
* Sets up the data streams used to send request[s] and read response[s].
*
- * @param socket
- * socket to be used for connection
+ * @param connection
+ * HttpConnection to be used
*/
- protected void setUpTransportIO(Socket socket) throws IOException {
- this.socket = socket;
- socketOut = socket.getOutputStream();
- is = new BufferedInputStream(socket.getInputStream());
+ protected void setUpTransportIO(HttpConnection connection) throws IOException {
+ socketOut = connection.getOutputStream();
+ is = connection.getInputStream();
}
// Tries to get head and body from cache, return true if has got this time
@@ -721,16 +712,17 @@
*/
@Override
public void disconnect() {
- try {
- closeSocket();
- } catch (IOException e) {
- }
+ disconnect(true);
}
-
- void closeSocket() throws IOException {
- if (is != null) {
- is.close();
+
+ private void disconnect(boolean closeSocket) {
+ if(closeSocket) {
+ connection.closeSocketAndStreams();
+ } else if (connection != null) {
+ HttpConnectionManager.getDefault().returnConnectionToPool(connection);
+ connection = null;
}
+ connection = null;
}
protected void endRequest() throws IOException {
@@ -1067,7 +1059,7 @@
if (method == HEAD || (responseCode >= 100 && responseCode < 200)
|| responseCode == HTTP_NO_CONTENT
|| responseCode == HTTP_NOT_MODIFIED) {
- closeSocket();
+ disconnect();
uis = new LimitedInputStream(0);
}
putToCache();
@@ -1378,7 +1370,7 @@
// drop everything and reconnect, might not be required for
// HTTP/1.1
endRequest();
- closeSocket();
+ disconnect();
connected = false;
String credentials = getAuthorizationCredentials(challenge);
if (credentials == null) {
@@ -1401,7 +1393,7 @@
// drop everything and reconnect, might not be required for
// HTTP/1.1
endRequest();
- closeSocket();
+ disconnect();
connected = false;
String credentials = getAuthorizationCredentials(challenge);
if (credentials == null) {
@@ -1447,7 +1439,7 @@
hostPort = -1;
}
endRequest();
- closeSocket();
+ disconnect();
connected = false;
continue;
}
@@ -1464,7 +1456,7 @@
* authorization challenge
*
* @param challenge
- * @return
+ * @return authorization credentials
* @throws IOException
*/
private String getAuthorizationCredentials(String challenge)
Index: src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConfiguration.java
===================================================================
--- src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConfiguration.java
+++ src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConfiguration.java
@@ -0,0 +1,100 @@
+/*
+ * 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 org.apache.harmony.luni.internal.net.www.protocol.http;
+
+import java.net.Proxy;
+
+/**
+ * An HttpConfiguration contains all the details needed to create an http connection
+ * and to compare whether or not two connections are the same. An HttpConfiguration
+ * will either consist of a Proxy or a port number (int)
+ * and host name (String) or all three, depending on whether or not a
+ * Proxy is used and the type of Proxy it is.
+ *
+ * HttpConfiguration is used as a key by HttpConnectionManager
+ * to retrieve HttpConnections from its connection pool.
+ */
+public class HttpConfiguration {
+
+ private Proxy proxy;
+ private int hostPort;
+ private String hostName;
+
+ public HttpConfiguration(String hostName, int hostPort) {
+ this.hostName = hostName;
+ this.hostPort = hostPort;
+ }
+
+ public HttpConfiguration(Proxy proxy) {
+ this.proxy = proxy;
+ }
+
+ public HttpConfiguration(Proxy proxy, String hostName, int hostPort) {
+ this.proxy = proxy;
+ this.hostName = hostName;
+ this.hostPort = hostPort;
+ }
+
+ /**
+ * Returns true if this configuration uses a Proxy
+ */
+ public boolean usesProxy() {
+ return proxy != null;
+ }
+
+ /**
+ * Returns the Proxy for this configuration, or null if a proxy
+ * is not used
+ */
+ public Proxy getProxy() {
+ return proxy;
+ }
+
+ /**
+ * Returns the host name for this configuration, or null if an http Proxy is used
+ */
+ public String getHostName() {
+ return hostName;
+ }
+
+ /**
+ * Returns the port for this configuration, or 0 if an http Proxy is used
+ */
+ public int getHostPort() {
+ return hostPort;
+ }
+
+ @Override
+ public boolean equals(Object arg0) {
+ if(!(arg0 instanceof HttpConfiguration)) {
+ return false;
+ } else {
+ HttpConfiguration config = (HttpConfiguration)arg0;
+ return config.proxy == null ? proxy == null : config.proxy.equals(proxy)
+ && config.hostPort == hostPort
+ && config.hostName == null ? hostName == null : config.hostName.equals(hostName);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return (((hostName != null) ? hostName.hashCode() : 0) * 37
+ + hostPort) * 37
+ + ((proxy != null) ? proxy.hashCode() : 0);
+ }
+
+}
\ No newline at end of file
Index: src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnection.java
===================================================================
--- src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnection.java
+++ src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnection.java
@@ -0,0 +1,201 @@
+/*
+ * 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 org.apache.harmony.luni.internal.net.www.protocol.http;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+
+import org.apache.harmony.luni.internal.nls.Messages;
+import org.apache.harmony.luni.util.Msg;
+
+/**
+ * An HttpConnection represents a persistent http or https connection and contains
+ * various utility methods to access that connection.
+ */
+public class HttpConnection {
+
+ private boolean usingSecureSocket = false;
+
+ private Socket socket;
+ private SSLSocket sslSocket;
+
+ private InputStream inputStream;
+ private OutputStream outputStream;
+ private InputStream sslInputStream;
+ private OutputStream sslOutputStream;
+
+ private HttpConfiguration config;
+
+ public HttpConnection(HttpConfiguration config, int connectTimeout) throws IOException {
+ this.config = config;
+ String hostName = config.getHostName();
+ int hostPort = config.getHostPort();
+ if(config.usesProxy()) {
+ Proxy proxy = config.getProxy();
+ if(hostName == null) {
+ socket = new Socket();
+ SocketAddress proxyAddr = proxy.address();
+ if (!(proxyAddr instanceof InetSocketAddress)) {
+ throw new IllegalArgumentException(Msg.getString(
+ "K0316", proxyAddr.getClass())); //$NON-NLS-1$
+ }
+ InetSocketAddress iProxyAddr = (InetSocketAddress) proxyAddr;
+
+ if( iProxyAddr.getAddress() == null ) {
+ // Resolve proxy, see HARMONY-3113
+ socket.connect(new InetSocketAddress((iProxyAddr.getHostName()),
+ iProxyAddr.getPort()), connectTimeout);
+ } else {
+ socket.connect(iProxyAddr, connectTimeout);
+ }
+ } else {
+ socket = new Socket(proxy);
+ socket.connect(new InetSocketAddress(hostName, hostPort), connectTimeout);
+ }
+ } else {
+ socket = new Socket();
+ socket.connect(new InetSocketAddress(hostName, hostPort), connectTimeout);
+ }
+ }
+
+ public void closeSocketAndStreams() {
+ if(usingSecureSocket) {
+ if (null != sslOutputStream) {
+ OutputStream temp = sslOutputStream;
+ sslOutputStream = null;
+ try {
+ temp.close();
+ } catch (Exception ex) {
+ // ignored
+ }
+ }
+
+ if (null != sslInputStream) {
+ InputStream temp = sslInputStream;
+ sslInputStream = null;
+ try {
+ temp.close();
+ } catch (Exception ex) {
+ // ignored
+ }
+ }
+
+ if (null != sslSocket) {
+ Socket temp = sslSocket;
+ sslSocket = null;
+ try {
+ temp.close();
+ } catch (Exception ex) {
+ // ignored
+ }
+ }
+ }
+ if (null != outputStream) {
+ OutputStream temp = outputStream;
+ outputStream = null;
+ try {
+ temp.close();
+ } catch (Exception ex) {
+ // ignored
+ }
+ }
+
+ if (null != inputStream) {
+ InputStream temp = inputStream;
+ inputStream = null;
+ try {
+ temp.close();
+ } catch (Exception ex) {
+ // ignored
+ }
+ }
+
+ if (null != socket) {
+ Socket temp = socket;
+ socket = null;
+ try {
+ temp.close();
+ } catch (Exception ex) {
+ // ignored
+ }
+ }
+ }
+
+ public void setSoTimeout(int readTimeout) throws SocketException {
+ socket.setSoTimeout(readTimeout);
+ }
+
+ public OutputStream getOutputStream() throws IOException {
+ if(usingSecureSocket) {
+ if (sslOutputStream == null) {
+ sslOutputStream = sslSocket.getOutputStream();
+ }
+ return sslOutputStream;
+ } else if(outputStream == null) {
+ outputStream = socket.getOutputStream();
+ }
+ return outputStream;
+ }
+
+ public InputStream getInputStream() throws IOException {
+ if(usingSecureSocket) {
+ if (sslInputStream == null) {
+ sslInputStream = sslSocket.getInputStream();
+ }
+ return sslInputStream;
+ } else if(inputStream == null) {
+ inputStream = socket.getInputStream();
+ }
+ return inputStream;
+ }
+
+ public HttpConfiguration getHttpConfiguration() {
+ return config;
+ }
+
+ public SSLSocket getSecureSocket(SSLSocketFactory sslSocketFactory, HostnameVerifier hostnameVerifier) throws IOException {
+ if(!usingSecureSocket) {
+ String hostName = config.getHostName();
+ int port = config.getHostPort();
+ // create the wrapper over connected socket
+ sslSocket = (SSLSocket) sslSocketFactory.createSocket(socket,
+ hostName, port, true);
+ sslSocket.setUseClientMode(true);
+ sslSocket.startHandshake();
+ if (!hostnameVerifier.verify(hostName, sslSocket.getSession())) {
+ throw new IOException(Messages.getString("luni.02", hostName)); //$NON-NLS-1$
+ }
+ usingSecureSocket = true;
+ }
+ return sslSocket;
+ }
+
+ Socket getSocket() {
+ return socket;
+ }
+
+}
Index: src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnectionManager.java
===================================================================
--- src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnectionManager.java
+++ src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnectionManager.java
@@ -0,0 +1,170 @@
+/*
+ * 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 org.apache.harmony.luni.internal.net.www.protocol.http;
+
+import java.io.IOException;
+import java.net.Proxy;
+import java.security.AccessController;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.harmony.luni.util.PriviAction;
+
+/**
+ * HttpConnectionManager manages a pool of HttpConnections
+ * that are not currently in use and is used to get hold of persistent HttpConnections.
+ * Clients should return an HttpConnection to the pool after use by calling
+ * returnConnectionToPool
+ *
+ * Two system properties affect the behaviour of this class - http.maxConnections
+ * and http.keepAlive. http.keepAlive determines whether
+ * or not connections should be persisted and http.maxConnections
+ * determines the maximum number of connections to each individual host that
+ * should be kept in the pool.
+ */
+public class HttpConnectionManager {
+
+ // The maximum number of connections to any location
+ private static int maxConnections = 5;
+
+ // Keeps connections alive if true
+ private static boolean keepAlive = true;
+
+ private static HttpConnectionManager defaultConnectionManager;
+ private ConnectionPool pool = new ConnectionPool();
+
+ /**
+ * Returns the default connection manager
+ */
+ public static HttpConnectionManager getDefault() {
+ if(defaultConnectionManager == null) {
+ defaultConnectionManager = new HttpConnectionManager();
+ }
+ return defaultConnectionManager;
+ }
+
+ public HttpConnection getConnection(String hostName, int hostPort, int connectTimeout) throws IOException {
+ checkSystemProperties();
+ HttpConfiguration config = new HttpConfiguration(hostName, hostPort);
+ return pool.getHttpConnection(config, connectTimeout);
+ }
+
+ public HttpConnection getConnection(Proxy proxy, int connectTimeout) throws IOException {
+ checkSystemProperties();
+ HttpConfiguration config = new HttpConfiguration(proxy);
+ return pool.getHttpConnection(config, connectTimeout);
+ }
+
+ public HttpConnection getConnection(Proxy proxy, String hostName, int hostPort, int connectTimeout) throws IOException {
+ checkSystemProperties();
+ HttpConfiguration config = new HttpConfiguration(proxy, hostName, hostPort);
+ return pool.getHttpConnection(config, connectTimeout);
+ }
+
+ public void returnConnectionToPool(HttpConnection connection) {
+ checkSystemProperties();
+ pool.returnConnection(connection);
+ }
+
+ public int numFreeConnections() {
+ return pool.numFreeConnections();
+ }
+
+ private void checkSystemProperties() {
+ String httpMaxConnections = AccessController.doPrivileged(new PriviAction("http.maxConnections"));
+ String httpKeepAlive = AccessController.doPrivileged(new PriviAction("http.keepAlive"));
+ if(httpMaxConnections != null) {
+ maxConnections = Integer.parseInt(httpMaxConnections);
+ }
+ if(httpKeepAlive != null) {
+ keepAlive = Boolean.parseBoolean(httpKeepAlive);
+ if(!keepAlive) {
+ pool.shutdown();
+ }
+ }
+ }
+
+ private static class ConnectionPool {
+
+ private Map> freeConnectionMap = new HashMap>(); // Map of free Sockets
+
+ public synchronized void shutdown() {
+ for (Iterator> iter = freeConnectionMap.values().iterator(); iter.hasNext();) {
+ List connections = iter.next();
+ for (Iterator iterator = connections.iterator(); iterator.hasNext();) {
+ HttpConnection connection = iterator.next();
+ connection.closeSocketAndStreams();
+ }
+ }
+ freeConnectionMap.clear();
+ }
+
+ public synchronized void returnConnection(HttpConnection connection) {
+ if(!connection.getSocket().isClosed() && keepAlive) {
+ HttpConfiguration config = connection.getHttpConfiguration();
+ List connections = freeConnectionMap.get(config);
+ if(connections == null) {
+ connections = new ArrayList();
+ freeConnectionMap.put(config, connections);
+ }
+ if(connections.size() < HttpConnectionManager.maxConnections) {
+ if(!connections.contains(connection)) {
+ connections.add(connection);
+ }
+ } else {
+ connection.closeSocketAndStreams();
+ }
+ } else {
+ // Make sure all streams are closed etc.
+ connection.closeSocketAndStreams();
+ }
+ }
+
+ public synchronized HttpConnection getHttpConnection(HttpConfiguration config, int connectTimeout) throws IOException {
+ List connections = freeConnectionMap.get(config);
+ if(keepAlive && connections == null) {
+ connections = new ArrayList();
+ freeConnectionMap.put(config, connections);
+ }
+ if(!keepAlive || connections.isEmpty()) {
+ HttpConnection connection = new HttpConnection(config, connectTimeout);
+ return connection;
+ } else {
+ HttpConnection connection = connections.get(0);
+ connections.remove(0);
+ if(!connection.getSocket().isClosed()) {
+ return connection;
+ } else {
+ return getHttpConnection(config, connectTimeout);
+ }
+ }
+ }
+
+ public int numFreeConnections() {
+ int numFree = 0;
+ for (Iterator> iter = freeConnectionMap.values().iterator(); iter.hasNext();) {
+ List connections = iter.next();
+ numFree += connections.size();
+ }
+ return numFree;
+ }
+ }
+
+}
\ No newline at end of file
Index: src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java
===================================================================
--- src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java (revision 494409)
+++ src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java (working copy)
@@ -22,7 +22,6 @@
import java.io.OutputStream;
import java.net.ProtocolException;
import java.net.Proxy;
-import java.net.Socket;
import java.net.URL;
import java.security.Permission;
import java.security.Principal;
@@ -363,8 +362,8 @@
@Override
public void connect() throws IOException {
- if (connected) {
- return;
+ if (connected) {
+ return;
}
if (usingProxy() && !makingSSLTunnel) {
// SSL Tunnel through the proxy was not established yet, do so
@@ -387,7 +386,7 @@
responseMessage, responseCode));
}
// if there are some remaining data in the stream - read it out
- InputStream is = socket.getInputStream();
+ InputStream is = connection.getInputStream();
while (is.available() != 0) {
is.read();
}
@@ -397,7 +396,8 @@
super.connect();
}
if (!makingSSLTunnel) {
- setUpTransportIO(wrapConnection(socket));
+ sslSocket = connection.getSecureSocket(getSSLSocketFactory(), getHostnameVerifier());
+ setUpTransportIO(connection);
}
}
@@ -420,21 +420,5 @@
return super.requestString();
}
- /**
- * Create the secure socket over the connected socket and verify remote
- * hostname.
- */
- private Socket wrapConnection(Socket socket) throws IOException {
- String hostname = url.getHost();
- // create the wrapper over connected socket
- sslSocket = (SSLSocket) getSSLSocketFactory().createSocket(socket,
- hostname, url.getPort(), true);
- sslSocket.setUseClientMode(true);
- sslSocket.startHandshake();
- if (!getHostnameVerifier().verify(hostname, sslSocket.getSession())) {
- throw new IOException(Messages.getString("luni.02", hostname)); //$NON-NLS-1$
- }
- return sslSocket;
- }
}
}
Index: src/test/java/org/apache/harmony/tests/internal/net/www/protocol/http/HttpURLConnectionTest.java
===================================================================
--- src/test/java/org/apache/harmony/tests/internal/net/www/protocol/http/HttpURLConnectionTest.java (revision 494409)
+++ src/test/java/org/apache/harmony/tests/internal/net/www/protocol/http/HttpURLConnectionTest.java (working copy)
@@ -18,9 +18,13 @@
package org.apache.harmony.tests.internal.net.www.protocol.http;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.InvocationTargetException;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.ProxySelector;
@@ -34,9 +38,12 @@
import junit.framework.TestCase;
+import org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection;
+import org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnectionManager;
+
/**
- * Tests for HTTPURLConnection class constructors and methods.
+ * Tests for HttpURLConnection class constructors and methods.
*
*/
public class HttpURLConnectionTest extends TestCase {
@@ -76,6 +83,49 @@
}
}
}
+
+ static class MockHTTPServer extends MockServer {
+ int persUses;
+
+ public MockHTTPServer(String name, int persUses) throws IOException {
+ super(name);
+ this.persUses = persUses;
+ }
+
+ public int port() {
+ return serverSocket.getLocalPort();
+ }
+
+ @Override
+ public void run() {
+ try {
+ synchronized (bound) {
+ started = true;
+ bound.notify();
+ }
+ try {
+ Socket client = serverSocket.accept();
+ accepted = true;
+ for (int i=0; i