Imported GNU Classpath 0.19 + gcj-import-20051115.

* sources.am: Regenerated.
       * Makefile.in: Likewise.
       * scripts/makemake.tcl: Use glob -nocomplain.

From-SVN: r107049
This commit is contained in:
Mark Wielaard 2005-11-15 23:20:01 +00:00
parent 02e549bfaa
commit 8f523f3a10
1241 changed files with 97711 additions and 25284 deletions

View file

@ -1,123 +0,0 @@
/* Authenticator.java --ByteArrayResponseBodyReader.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.net.protocol.http;
/**
* Simple response body reader that stores content in a byte array.
*
* @author Chris Burdess (dog@gnu.org)
*/
public class ByteArrayResponseBodyReader
implements ResponseBodyReader
{
/**
* The content.
*/
protected byte[] content;
/**
* The position in the content at which the next write will occur.
*/
protected int pos;
/**
* The length of the buffer.
*/
protected int len;
/**
* Constructs a new byte array response body reader.
*/
public ByteArrayResponseBodyReader()
{
this(4096);
}
/**
* Constructs a new byte array response body reader with the specified
* initial buffer size.
* @param size the initial buffer size
*/
public ByteArrayResponseBodyReader(int size)
{
content = new byte[size];
pos = len = 0;
}
/**
* This reader accepts all responses.
*/
public boolean accept(Request request, Response response)
{
return true;
}
public void read(byte[] buffer, int offset, int length)
{
int l = length - offset;
if (pos + l > content.length)
{
byte[] tmp = new byte[content.length * 2];
System.arraycopy(content, 0, tmp, 0, pos);
content = tmp;
}
System.arraycopy(buffer, offset, content, pos, l);
pos += l;
len = pos;
}
public void close()
{
pos = 0;
}
/**
* Retrieves the content of this reader as a byte array.
* The size of the returned array is the number of bytes read.
*/
public byte[] toByteArray()
{
byte[] ret = new byte[len];
System.arraycopy(content, 0, ret, 0, len);
return ret;
}
}

View file

@ -110,7 +110,7 @@ public class ChunkedInputStream
// Read chunk header
int c, last = 0;
boolean seenSemi = false;
StringBuffer buf = new StringBuffer();
StringBuilder buf = new StringBuilder();
do
{
c = in.read();

View file

@ -139,7 +139,7 @@ public class Cookie
public String toString(boolean showPath, boolean showDomain)
{
StringBuffer buf = new StringBuffer();
StringBuilder buf = new StringBuilder();
buf.append(name);
buf.append('=');
buf.append(value);

View file

@ -41,10 +41,6 @@ package gnu.java.net.protocol.http;
import gnu.classpath.Configuration;
import gnu.classpath.SystemProperties;
import gnu.java.net.EmptyX509TrustManager;
import gnu.java.net.protocol.http.event.ConnectionEvent;
import gnu.java.net.protocol.http.event.ConnectionListener;
import gnu.java.net.protocol.http.event.RequestEvent;
import gnu.java.net.protocol.http.event.RequestListener;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@ -57,6 +53,7 @@ import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -131,8 +128,6 @@ public class HTTPConnection
*/
protected int minorVersion;
private final List connectionListeners;
private final List requestListeners;
private final List handshakeCompletedListeners;
/**
@ -165,6 +160,12 @@ public class HTTPConnection
*/
protected CookieManager cookieManager;
/**
* The pool that this connection is a member of (if any).
*/
private LinkedHashMap pool;
/**
* Creates a new HTTP connection.
* @param hostname the name of the host to connect to
@ -236,8 +237,6 @@ public class HTTPConnection
this.connectionTimeout = connectionTimeout;
this.timeout = timeout;
majorVersion = minorVersion = 1;
connectionListeners = new ArrayList(4);
requestListeners = new ArrayList(4);
handshakeCompletedListeners = new ArrayList(2);
}
@ -331,6 +330,73 @@ public class HTTPConnection
return cookieManager;
}
/**
* The number of times this HTTPConnection has be used via keep-alive.
*/
int useCount;
/**
* Generates a key for connections in the connection pool.
*
* @param h the host name.
* @param p the port.
* @param sec true if using https.
*
* @return the key.
*/
static Object getPoolKey(String h, int p, boolean sec)
{
StringBuilder buf = new StringBuilder(sec ? "https://" : "http://");
buf.append(h);
buf.append(':');
buf.append(p);
return buf.toString();
}
/**
* Set the connection pool that this HTTPConnection is a member of.
* If left unset or set to null, it will not be a member of any pool
* and will not be a candidate for reuse.
*
* @param p the pool.
*/
void setPool(LinkedHashMap p)
{
pool = p;
}
/**
* Signal that this HTTPConnection is no longer needed and can be
* returned to the connection pool.
*
*/
void release()
{
if (pool != null)
{
synchronized (pool)
{
useCount++;
Object key = HTTPConnection.getPoolKey(hostname, port, secure);
pool.put(key, this);
while (pool.size() >= HTTPURLConnection.maxConnections)
{
// maxConnections must always be >= 1
Object lru = pool.keySet().iterator().next();
HTTPConnection c = (HTTPConnection)pool.remove(lru);
try
{
c.closeConnection();
}
catch (IOException ioe)
{
// Ignore it. We are just cleaning up.
}
}
}
}
}
/**
* Creates a new request using this connection.
* @param method the HTTP method to invoke
@ -367,7 +433,7 @@ public class HTTPConnection
Cookie[] cookies = cookieManager.getCookies(hostname, secure, path);
if (cookies != null && cookies.length > 0)
{
StringBuffer buf = new StringBuffer();
StringBuilder buf = new StringBuilder();
buf.append("$Version=1");
for (int i = 0; i < cookies.length; i++)
{
@ -378,7 +444,6 @@ public class HTTPConnection
ret.setHeader("Cookie", buf.toString());
}
}
fireRequestEvent(RequestEvent.REQUEST_CREATED, ret);
return ret;
}
@ -388,14 +453,7 @@ public class HTTPConnection
public void close()
throws IOException
{
try
{
closeConnection();
}
finally
{
fireConnectionEvent(ConnectionEvent.CONNECTION_CLOSED);
}
closeConnection();
}
/**
@ -534,7 +592,7 @@ public class HTTPConnection
*/
protected String getURI()
{
StringBuffer buf = new StringBuffer();
StringBuilder buf = new StringBuilder();
buf.append(secure ? "https://" : "http://");
buf.append(hostname);
if (secure)
@ -584,84 +642,6 @@ public class HTTPConnection
// -- Events --
public void addConnectionListener(ConnectionListener l)
{
synchronized (connectionListeners)
{
connectionListeners.add(l);
}
}
public void removeConnectionListener(ConnectionListener l)
{
synchronized (connectionListeners)
{
connectionListeners.remove(l);
}
}
protected void fireConnectionEvent(int type)
{
ConnectionEvent event = new ConnectionEvent(this, type);
ConnectionListener[] l = null;
synchronized (connectionListeners)
{
l = new ConnectionListener[connectionListeners.size()];
connectionListeners.toArray(l);
}
for (int i = 0; i < l.length; i++)
{
switch (type)
{
case ConnectionEvent.CONNECTION_CLOSED:
l[i].connectionClosed(event);
break;
}
}
}
public void addRequestListener(RequestListener l)
{
synchronized (requestListeners)
{
requestListeners.add(l);
}
}
public void removeRequestListener(RequestListener l)
{
synchronized (requestListeners)
{
requestListeners.remove(l);
}
}
protected void fireRequestEvent(int type, Request request)
{
RequestEvent event = new RequestEvent(this, type, request);
RequestListener[] l = null;
synchronized (requestListeners)
{
l = new RequestListener[requestListeners.size()];
requestListeners.toArray(l);
}
for (int i = 0; i < l.length; i++)
{
switch (type)
{
case RequestEvent.REQUEST_CREATED:
l[i].requestCreated(event);
break;
case RequestEvent.REQUEST_SENDING:
l[i].requestSent(event);
break;
case RequestEvent.REQUEST_SENT:
l[i].requestSent(event);
break;
}
}
}
void addHandshakeCompletedListener(HandshakeCompletedListener l)
{
synchronized (handshakeCompletedListeners)

View file

@ -38,7 +38,6 @@ exception statement from your version. */
package gnu.java.net.protocol.http;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
@ -75,7 +74,8 @@ public class HTTPURLConnection
/**
* Pool of reusable connections, used if keepAlive is true.
*/
private static final Map connectionPool = new LinkedHashMap();
private static final LinkedHashMap connectionPool = new LinkedHashMap();
static int maxConnections;
/*
* The underlying connection.
@ -87,7 +87,6 @@ public class HTTPURLConnection
int proxyPort;
String agent;
boolean keepAlive;
int maxConnections;
private Request request;
private Headers requestHeaders;
@ -95,8 +94,8 @@ public class HTTPURLConnection
private boolean requestMethodSetExplicitly;
private Response response;
private ByteArrayInputStream responseSink;
private ByteArrayInputStream errorSink;
private InputStream responseSink;
private InputStream errorSink;
private HandshakeCompletedEvent handshakeEvent;
@ -202,34 +201,59 @@ public class HTTPURLConnection
}
connection.setProxy(proxyHostname, proxyPort);
}
request = connection.newRequest(method, file);
if (!keepAlive)
try
{
request.setHeader("Connection", "close");
}
if (agent != null)
{
request.setHeader("User-Agent", agent);
}
request.getHeaders().putAll(requestHeaders);
if (requestSink != null)
{
byte[] content = requestSink.toByteArray();
RequestBodyWriter writer = new ByteArrayRequestBodyWriter(content);
request.setRequestBodyWriter(writer);
}
ByteArrayResponseBodyReader reader = new ByteArrayResponseBodyReader();
request.setResponseBodyReader(reader);
if (creds != null)
{
request.setAuthenticator(new Authenticator() {
public Credentials getCredentials(String realm, int attempts)
request = connection.newRequest(method, file);
if (!keepAlive)
{
return (attempts < 2) ? creds : null;
request.setHeader("Connection", "close");
}
});
if (agent != null)
{
request.setHeader("User-Agent", agent);
}
request.getHeaders().putAll(requestHeaders);
if (requestSink != null)
{
byte[] content = requestSink.toByteArray();
RequestBodyWriter writer = new ByteArrayRequestBodyWriter(content);
request.setRequestBodyWriter(writer);
}
if (creds != null)
{
request.setAuthenticator(new Authenticator() {
public Credentials getCredentials(String realm, int attempts)
{
return (attempts < 2) ? creds : null;
}
});
}
response = request.dispatch();
}
response = request.dispatch();
catch (IOException ioe)
{
if (connection.useCount > 0)
{
// Connection re-use failed: Try a new connection.
try
{
connection.close();
}
catch (IOException _)
{
// Ignore.
}
connection = null;
retry = true;
continue;
}
else
{
// First time the connection was used: Hard failure.
throw ioe;
}
}
if (response.getCodeClass() == 3 && getInstanceFollowRedirects())
{
// Follow redirect
@ -307,7 +331,8 @@ public class HTTPURLConnection
}
else
{
responseSink = new ByteArrayInputStream(reader.toByteArray ());
responseSink = response.getBody();
if (response.getCode() == 404)
{
errorSink = responseSink;
@ -328,27 +353,14 @@ public class HTTPURLConnection
HTTPConnection connection;
if (keepAlive)
{
StringBuffer buf = new StringBuffer(secure ? "https://" : "http://");
buf.append(Thread.currentThread().hashCode());
buf.append('@');
buf.append(host);
buf.append(':');
buf.append(port);
String key = buf.toString();
Object key = HTTPConnection.getPoolKey(host, port, secure);
synchronized (connectionPool)
{
connection = (HTTPConnection) connectionPool.get(key);
connection = (HTTPConnection) connectionPool.remove(key);
if (connection == null)
{
connection = new HTTPConnection(host, port, secure);
// Good housekeeping
if (connectionPool.size() == maxConnections)
{
// maxConnections must always be >= 1
Object lru = connectionPool.keySet().iterator().next();
connectionPool.remove(lru);
}
connectionPool.put(key, connection);
connection.setPool(connectionPool);
}
}
}
@ -502,9 +514,9 @@ public class HTTPURLConnection
return null;
}
}
Map headers = response.getHeaders();
Map ret = new LinkedHashMap();
ret.put("", Collections.singletonList(getStatusLine(response)));
Headers headers = response.getHeaders();
LinkedHashMap ret = new LinkedHashMap();
ret.put(null, Collections.singletonList(getStatusLine(response)));
for (Iterator i = headers.entrySet().iterator(); i.hasNext(); )
{
Map.Entry entry = (Map.Entry) i.next();
@ -512,7 +524,7 @@ public class HTTPURLConnection
String value = (String) entry.getValue();
ret.put(key, Collections.singletonList(value));
}
return ret;
return Collections.unmodifiableMap(ret);
}
String getStatusLine(Response response)

View file

@ -60,7 +60,7 @@ import java.util.Set;
* @author Chris Burdess (dog@gnu.org)
*/
public class Headers
implements Map
extends LinkedHashMap
{
static final DateFormat dateFormat = new HTTPDateFormat();
@ -143,36 +143,18 @@ public class Headers
}
private LinkedHashMap headers;
public Headers()
{
headers = new LinkedHashMap();
}
public int size()
{
return headers.size();
}
public boolean isEmpty()
{
return headers.isEmpty();
}
public boolean containsKey(Object key)
{
return headers.containsKey(new Header((String) key));
}
public boolean containsValue(Object value)
{
return headers.containsValue(value);
return super.containsKey(new Header((String) key));
}
public Object get(Object key)
{
return headers.get(new Header((String) key));
return super.get(new Header((String) key));
}
/**
@ -180,7 +162,7 @@ public class Headers
*/
public String getValue(String header)
{
return (String) headers.get(new Header(header));
return (String) super.get(new Header(header));
}
/**
@ -204,6 +186,27 @@ public class Headers
return -1;
}
/**
* Returns the value of the specified header as a long, or -1 if the
* header is not present or cannot be parsed as a long.
*/
public long getLongValue(String header)
{
String val = getValue(header);
if (val == null)
{
return -1;
}
try
{
return Long.parseLong(val);
}
catch (NumberFormatException e)
{
}
return -1;
}
/**
* Returns the value of the specified header as a date,
* or <code>null</code> if the header is not present or not a date.
@ -227,12 +230,12 @@ public class Headers
public Object put(Object key, Object value)
{
return headers.put(new Header((String) key), value);
return super.put(new Header((String) key), value);
}
public Object remove(Object key)
{
return headers.remove(new Header((String) key));
return super.remove(new Header((String) key));
}
public void putAll(Map t)
@ -241,18 +244,13 @@ public class Headers
{
String key = (String) i.next();
String value = (String) t.get(key);
headers.put(new Header(key), value);
put(key, value);
}
}
public void clear()
{
headers.clear();
}
public Set keySet()
{
Set keys = headers.keySet();
Set keys = super.keySet();
Set ret = new LinkedHashSet();
for (Iterator i = keys.iterator(); i.hasNext(); )
{
@ -261,14 +259,9 @@ public class Headers
return ret;
}
public Collection values()
{
return headers.values();
}
public Set entrySet()
{
Set entries = headers.entrySet();
Set entries = super.entrySet();
Set ret = new LinkedHashSet();
for (Iterator i = entries.iterator(); i.hasNext(); )
{
@ -278,16 +271,6 @@ public class Headers
return ret;
}
public boolean equals(Object other)
{
return headers.equals(other);
}
public int hashCode()
{
return headers.hashCode();
}
/**
* Parse the specified input stream, adding headers to this collection.
*/
@ -298,7 +281,7 @@ public class Headers
(LineInputStream) in : new LineInputStream(in);
String name = null;
StringBuffer value = new StringBuffer();
StringBuilder value = new StringBuilder();
while (true)
{
String line = lin.readLine();
@ -354,14 +337,14 @@ public class Headers
private void addValue(String name, String value)
{
Header key = new Header(name);
String old = (String) headers.get(key);
String old = (String) super.get(key);
if (old == null)
{
headers.put(key, value);
super.put(key, value);
}
else
{
headers.put(key, old + ", " + value);
super.put(key, old + ", " + value);
}
}

View file

@ -0,0 +1,220 @@
/* LimitedLengthInputStream.java --
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.net.protocol.http;
import java.io.IOException;
import java.io.InputStream;
/**
* InputStream that limits the total number of bytes that can be read
* from an underlying stream. In addition to limiting the number of
* bytes read, close() is not propagated to the underlying stream.
*
* @author David Daney (ddaney@avtrex.com)
*/
class LimitedLengthInputStream
extends InputStream
{
private long remainingLen;
private boolean restrictLen;
private HTTPConnection connection;
private boolean eof;
private InputStream in;
private boolean doClose;
private void handleClose()
throws IOException
{
eof = true;
if (doClose)
{
in.close();
}
else
{
connection.release();
}
in = null;
connection = null;
}
/**
* Constructor.
*
* @param in the underlying stream
*
* @param maxLen the maximum number of bytes to read
*
* @param restrictLen if true the number of bytes that can be read
* from this stream will be limited to maxLen, otherwise the number
* of bytes is not restricted.
*
* @param con the HTTPConnection associated with this stream
*
* @param doClose if true con will be closed when finished reading,
* else it will be placed back in the connection pool.
*
*/
LimitedLengthInputStream(InputStream in,
long maxLen,
boolean restrictLen,
HTTPConnection con,
boolean doClose)
throws IOException
{
this.in = in;
this.remainingLen = maxLen;
this.restrictLen = restrictLen;
this.connection = con;
this.doClose = doClose;
if (restrictLen)
{
if (maxLen < 0)
throw new IllegalArgumentException();
else if (maxLen == 0)
handleClose(); // Nothing to do, release the connection.
}
}
public synchronized int read()
throws IOException
{
if (eof)
return -1; // EOF
int r;
if (restrictLen)
{
r = in.read();
if (-1 != r)
remainingLen--;
if (0 == remainingLen)
handleClose();
}
else
{
r = in.read();
if (r == -1)
handleClose();
}
return r;
}
public int read(byte[] buffer)
throws IOException
{
return read(buffer, 0, buffer.length);
}
public synchronized int read(byte[] buffer, int offset, int length)
throws IOException
{
if (eof)
return -1; // EOF
if (restrictLen && length > remainingLen)
length = (int) remainingLen;
int r = in.read(buffer, offset, length);
if (-1 == r)
handleClose();
if (restrictLen && r > 0)
{
remainingLen -= r;
if (0 == remainingLen)
handleClose();
}
return r;
}
public synchronized long skip(long n)
throws IOException
{
if (eof)
return 0;
if (restrictLen && n > remainingLen)
n = remainingLen;
long r = in.skip(n);
if (restrictLen)
{
remainingLen -= r;
if (0 == remainingLen)
handleClose();
}
return r;
}
public synchronized int available()
throws IOException
{
if (eof)
return 0;
int a = in.available();
if (restrictLen && a > remainingLen)
a = (int)remainingLen;
return a;
}
public synchronized void close()
throws IOException
{
if (eof)
return;
// If we get to here, the stream was not fully read. Just throw
// it away.
doClose = true;
handleClose();
}
}

View file

@ -1,5 +1,5 @@
/* Request.java --
Copyright (C) 2004 Free Software Foundation, Inc.
Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@ -40,7 +40,6 @@ package gnu.java.net.protocol.http;
import gnu.java.net.BASE64;
import gnu.java.net.LineInputStream;
import gnu.java.net.protocol.http.event.RequestEvent;
import java.io.IOException;
import java.io.InputStream;
@ -99,11 +98,6 @@ public class Request
*/
protected int requestBodyNegotiationThreshold;
/**
* The response body reader.
*/
protected ResponseBodyReader responseBodyReader;
/**
* Map of response header handlers.
*/
@ -235,16 +229,6 @@ public class Request
this.requestBodyWriter = requestBodyWriter;
}
/**
* Sets the response body reader.
* @param responseBodyReader the handler to receive notifications of
* response body content
*/
public void setResponseBodyReader(ResponseBodyReader responseBodyReader)
{
this.responseBodyReader = responseBodyReader;
}
/**
* Sets a callback handler to be invoked for the specified header name.
* @param name the header name
@ -324,13 +308,10 @@ public class Request
do
{
retry = false;
// Send request
connection.fireRequestEvent(RequestEvent.REQUEST_SENDING, this);
// Get socket output and input streams
OutputStream out = connection.getOutputStream();
LineInputStream in =
new LineInputStream(connection.getInputStream());
// Request line
String requestUri = path;
if (connection.isUsingProxy() &&
@ -369,28 +350,42 @@ public class Request
count += len;
}
while (len > -1 && count < contentLength);
out.write(CRLF.getBytes(US_ASCII));
}
out.flush();
// Sent event
connection.fireRequestEvent(RequestEvent.REQUEST_SENT, this);
// Get response
response = readResponse(in);
int sc = response.getCode();
if (sc == 401 && authenticator != null)
{
if (authenticate(response, attempts++))
{
retry = true;
}
}
else if (sc == 100 && expectingContinue)
{
requestHeaders.remove("Expect");
setHeader("Content-Length", Integer.toString(contentLength));
expectingContinue = false;
retry = true;
}
while(true)
{
response = readResponse(connection.getInputStream());
int sc = response.getCode();
if (sc == 401 && authenticator != null)
{
if (authenticate(response, attempts++))
{
retry = true;
}
}
else if (sc == 100)
{
if (expectingContinue)
{
requestHeaders.remove("Expect");
setHeader("Content-Length",
Integer.toString(contentLength));
expectingContinue = false;
retry = true;
}
else
{
// A conforming server can send an unsoliceted
// Continue response but *should* not (RFC 2616
// sec 8.2.3). Ignore the bogus Continue
// response and get the real response that
// should follow
continue;
}
}
break;
}
}
while (retry);
}
@ -402,14 +397,16 @@ public class Request
return response;
}
Response readResponse(LineInputStream in)
Response readResponse(InputStream in)
throws IOException
{
String line;
int len;
// Read response status line
line = in.readLine();
LineInputStream lis = new LineInputStream(in);
line = lis.readLine();
if (line == null)
{
throw new ProtocolException("Peer closed connection");
@ -438,30 +435,25 @@ public class Request
String message = line.substring(end + 1, len - 1);
// Read response headers
Headers responseHeaders = new Headers();
responseHeaders.parse(in);
responseHeaders.parse(lis);
notifyHeaderHandlers(responseHeaders);
// Construct response
int codeClass = code / 100;
Response ret = new Response(majorVersion, minorVersion, code,
codeClass, message, responseHeaders);
InputStream body = null;
switch (code)
{
case 100:
case 204:
case 205:
case 304:
break;
default:
// Does response body reader want body?
boolean notify = (responseBodyReader != null);
if (notify)
{
if (!responseBodyReader.accept(this, ret))
{
notify = false;
}
}
readResponseBody(ret, in, notify);
body = createResponseBodyStream(responseHeaders, majorVersion,
minorVersion, in);
}
// Construct response
Response ret = new Response(majorVersion, minorVersion, code,
message, responseHeaders, body);
return ret;
}
@ -487,25 +479,40 @@ public class Request
}
}
void readResponseBody(Response response, InputStream in,
boolean notify)
private InputStream createResponseBodyStream(Headers responseHeaders,
int majorVersion,
int minorVersion,
InputStream in)
throws IOException
{
byte[] buffer = new byte[4096];
int contentLength = -1;
long contentLength = -1;
Headers trailer = null;
String transferCoding = response.getHeader("Transfer-Encoding");
// Persistent connections are the default in HTTP/1.1
boolean doClose = "close".equalsIgnoreCase(getHeader("Connection")) ||
"close".equalsIgnoreCase(responseHeaders.getValue("Connection")) ||
(connection.majorVersion == 1 && connection.minorVersion == 0) ||
(majorVersion == 1 && minorVersion == 0);
String transferCoding = responseHeaders.getValue("Transfer-Encoding");
if ("chunked".equalsIgnoreCase(transferCoding))
{
trailer = new Headers();
in = new ChunkedInputStream(in, trailer);
in = new LimitedLengthInputStream(in, -1, false, connection, doClose);
in = new ChunkedInputStream(in, responseHeaders);
}
else
{
contentLength = response.getIntHeader("Content-Length");
contentLength = responseHeaders.getLongValue("Content-Length");
if (contentLength < 0)
doClose = true; // No Content-Length, must close.
in = new LimitedLengthInputStream(in, contentLength,
contentLength >= 0,
connection, doClose);
}
String contentCoding = response.getHeader("Content-Encoding");
String contentCoding = responseHeaders.getValue("Content-Encoding");
if (contentCoding != null && !"identity".equals(contentCoding))
{
if ("gzip".equals(contentCoding))
@ -522,51 +529,7 @@ public class Request
contentCoding);
}
}
// Persistent connections are the default in HTTP/1.1
boolean doClose = "close".equalsIgnoreCase(getHeader("Connection")) ||
"close".equalsIgnoreCase(response.getHeader("Connection")) ||
(connection.majorVersion == 1 && connection.minorVersion == 0) ||
(response.majorVersion == 1 && response.minorVersion == 0);
int count = contentLength;
int len = (count > -1) ? count : buffer.length;
len = (len > buffer.length) ? buffer.length : len;
while (len > -1)
{
len = in.read(buffer, 0, len);
if (len < 0)
{
// EOF
connection.closeConnection();
break;
}
if (notify)
{
responseBodyReader.read(buffer, 0, len);
}
if (count > -1)
{
count -= len;
if (count < 1)
{
if (doClose)
{
connection.closeConnection();
}
break;
}
}
}
if (notify)
{
responseBodyReader.close();
}
if (trailer != null)
{
response.getHeaders().putAll(trailer);
notifyHeaderHandlers(trailer);
}
return in;
}
boolean authenticate(Response response, int attempts)
@ -686,7 +649,7 @@ public class Request
{
int len = text.length();
String key = null;
StringBuffer buf = new StringBuffer();
StringBuilder buf = new StringBuilder();
Properties ret = new Properties();
boolean inQuote = false;
for (int i = 0; i < len; i++)
@ -739,7 +702,7 @@ public class Request
{
int nc = connection.getNonceCount(nonce);
String hex = Integer.toHexString(nc);
StringBuffer buf = new StringBuffer();
StringBuilder buf = new StringBuilder();
for (int i = 8 - hex.length(); i > 0; i--)
{
buf.append('0');
@ -810,7 +773,7 @@ public class Request
int len = text.length();
String attr = null;
StringBuffer buf = new StringBuffer();
StringBuilder buf = new StringBuilder();
boolean inQuote = false;
for (int i = 0; i <= len; i++)
{

View file

@ -38,6 +38,7 @@ exception statement from your version. */
package gnu.java.net.protocol.http;
import java.io.InputStream;
import java.util.Date;
/**
@ -63,19 +64,6 @@ public class Response
*/
protected final int code;
/**
* The class of the response. This is the most significant digit of the
* status code.
* <dl>
* <dt><code>1xx</code></dt> <dd>Informational response</dd>
* <dt><code>2xx</code></dt> <dd>Success</dd>
* <dt><code>3xx</code></dt> <dd>Redirection</dd>
* <dt><code>4xx</code></dt> <dd>Client error</dd>
* <dt><code>5xx</code></dt> <dd>Server error</dd>
* </dl>
*/
protected final int codeClass;
/**
* Human-readable text of the response.
*/
@ -86,19 +74,23 @@ public class Response
*/
protected final Headers headers;
/**
* An InputStream that returns the body of the response.
*/
protected final InputStream body;
/**
* Constructs a new response with the specified parameters.
*/
protected Response(int majorVersion, int minorVersion, int code,
int codeClass, String message,
Headers headers)
String message, Headers headers, InputStream body)
{
this.majorVersion = majorVersion;
this.minorVersion = minorVersion;
this.code = code;
this.codeClass = codeClass;
this.message = message;
this.headers = headers;
this.body = body;
}
/**
@ -129,12 +121,19 @@ public class Response
}
/**
* Returns the class of the response.
* @see #codeClass
* Returns the class of the response. This is the most significant
* digit of the status code.
* <dl>
* <dt><code>1xx</code></dt> <dd>Informational response</dd>
* <dt><code>2xx</code></dt> <dd>Success</dd>
* <dt><code>3xx</code></dt> <dd>Redirection</dd>
* <dt><code>4xx</code></dt> <dd>Client error</dd>
* <dt><code>5xx</code></dt> <dd>Server error</dd>
* </dl>
*/
public int getCodeClass()
{
return codeClass;
return code / 100;
}
/**
@ -172,6 +171,15 @@ public class Response
return headers.getIntValue(name);
}
/**
* Returns the header value for the specified name as a long.
* @param name the header name
*/
public long getLongHeader(String name)
{
return headers.getLongValue(name);
}
/**
* Returns the header value for the specified name as a date.
* @param name the header name
@ -181,5 +189,14 @@ public class Response
return headers.getDateValue(name);
}
/**
* Returns an InputStream that returns the body of the response.
*
* @return the body of the response
*/
public InputStream getBody()
{
return body;
}
}

View file

@ -1,70 +0,0 @@
/* ResponseBodyReader.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.net.protocol.http;
/**
* Callback interface for receiving notification of response body content.
*
* @author Chris Burdess (dog@gnu.org)
*/
public interface ResponseBodyReader
{
/**
* Indicate whether this reader is interested in the specified response.
* If it returns false, it will not receive body content notifications for
* that response.
*/
boolean accept(Request request, Response response);
/**
* Receive notification of body content.
* @param buffer the content buffer
* @param offset the offset within the buffer that content starts
* @param length the length of the content
*/
void read(byte[] buffer, int offset, int length);
/**
* Notifies the reader that the end of the content was reached.
*/
void close();
}

View file

@ -1,81 +0,0 @@
/* ConnectionEvent.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.net.protocol.http.event;
import java.util.EventObject;
/**
* A connection event.
*
* @author Chris Burdess (dog@gnu.org)
*/
public class ConnectionEvent
extends EventObject
{
/**
* The connection closed event type.
*/
public static final int CONNECTION_CLOSED = 0;
/**
* The type of this event.
*/
protected int type;
/**
* Constructs a connection event with the specified source and type.
*/
public ConnectionEvent(Object source, int type)
{
super(source);
this.type = type;
}
/**
* Returns the type of this event.
* @see #type
*/
public int getType()
{
return type;
}
}

View file

@ -1,58 +0,0 @@
/* ConnectionListener.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.net.protocol.http.event;
import java.util.EventListener;
/**
* A connection listener.
*
* @author Chris Burdess (dog@gnu.org)
*/
public interface ConnectionListener
extends EventListener
{
/**
* Callback invoked when the associated connection is closed.
*/
void connectionClosed(ConnectionEvent event);
}

View file

@ -1,107 +0,0 @@
/* RequestEvent.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.net.protocol.http.event;
import gnu.java.net.protocol.http.Request;
import java.util.EventObject;
/**
* A request event.
*
* @author Chris Burdess (dog@gnu.org)
*/
public class RequestEvent
extends EventObject
{
/**
* The request created event type.
*/
public static final int REQUEST_CREATED = 0;
/**
* The request sending event type.
*/
public static final int REQUEST_SENDING = 1;
/**
* The request sent event type.
*/
public static final int REQUEST_SENT = 2;
/**
* The type of this event.
*/
protected int type;
/**
* The request associated with this event.
*/
protected Request request;
/**
* Constructs a request event with the specified source, type, and request.
*/
public RequestEvent(Object source, int type, Request request)
{
super(source);
this.type = type;
this.request = request;
}
/**
* Returns the type of this event.
* @see #type
*/
public int getType()
{
return type;
}
/**
* Returns the request associated with this event.
*/
public Request getRequest()
{
return request;
}
}

View file

@ -1,70 +0,0 @@
/* RequestListener.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.net.protocol.http.event;
import java.util.EventListener;
/**
* A request listener.
*
* @author Chris Burdess (dog@gnu.org)
*/
public interface RequestListener
extends EventListener
{
/**
* Callback invoked when a request is created from the associated
* connection.
*/
void requestCreated(RequestEvent event);
/**
* Callback invoked when the request has been initialised with all data
* and before sending this data to the server.
*/
void requestSending(RequestEvent event);
/**
* Callback invoked after all request data has been sent to the server.
*/
void requestSent(RequestEvent event);
}

View file

@ -1,46 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!-- package.html - describes classes in gnu.java.net.protocol.http.event package.
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. -->
<html>
<head><title>GNU Classpath - gnu.java.net.protocol.http.event</title></head>
<body>
<p></p>
</body>
</html>

View file

@ -69,13 +69,17 @@ public final class Connection extends JarURLConnection
private static Hashtable cache = new Hashtable();
private static final int READBUFSIZE = 4*1024;
public static synchronized JarFile get (URL url) throws IOException
public static synchronized JarFile get (URL url, boolean useCaches)
throws IOException
{
JarFile jf = (JarFile) cache.get (url);
JarFile jf;
if (useCaches)
{
jf = (JarFile) cache.get (url);
if (jf != null)
return jf;
}
if (jf != null)
return jf;
if ("file".equals (url.getProtocol()))
{
File f = new File (url.getFile());
@ -100,9 +104,10 @@ public final class Connection extends JarURLConnection
jf = new JarFile (f, true,
ZipFile.OPEN_READ | ZipFile.OPEN_DELETE);
}
cache.put (url, jf);
if (useCaches)
cache.put (url, jf);
return jf;
}
}
@ -120,7 +125,7 @@ public final class Connection extends JarURLConnection
return;
jar_url = getJarFileURL();
jar_file = JarFileCache.get (jar_url);
jar_file = JarFileCache.get (jar_url, useCaches);
String entry_name = getEntryName();
if (entry_name != null