Initial revision
From-SVN: r102074
This commit is contained in:
parent
6f4434b39b
commit
f911ba985a
4557 changed files with 1000262 additions and 0 deletions
319
libjava/classpath/gnu/java/net/protocol/file/Connection.java
Normal file
319
libjava/classpath/gnu/java/net/protocol/file/Connection.java
Normal file
|
@ -0,0 +1,319 @@
|
|||
/* FileURLConnection.java -- URLConnection class for "file" protocol
|
||||
Copyright (C) 1998, 1999, 2003 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.file;
|
||||
|
||||
import gnu.classpath.SystemProperties;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FilePermission;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.security.Permission;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* This subclass of java.net.URLConnection models a URLConnection via
|
||||
* the "file" protocol.
|
||||
*
|
||||
* @author Aaron M. Renn (arenn@urbanophile.com)
|
||||
* @author Nic Ferrier (nferrier@tapsellferrier.co.uk)
|
||||
* @author Warren Levy (warrenl@cygnus.com)
|
||||
*/
|
||||
public class Connection extends URLConnection
|
||||
{
|
||||
/**
|
||||
* Default permission for a file
|
||||
*/
|
||||
private static final String DEFAULT_PERMISSION = "read";
|
||||
|
||||
private static class StaticData
|
||||
{
|
||||
/**
|
||||
* HTTP-style DateFormat, used to format the last-modified header.
|
||||
*/
|
||||
static SimpleDateFormat dateFormat
|
||||
= new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss 'GMT'",
|
||||
new Locale ("En", "Us", "Unix"));
|
||||
|
||||
static String lineSeparator =
|
||||
SystemProperties.getProperty("line.separator");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is a File object for this connection
|
||||
*/
|
||||
private File file;
|
||||
|
||||
/**
|
||||
* If a directory, contains a list of files in the directory.
|
||||
*/
|
||||
private byte[] directoryListing;
|
||||
|
||||
/**
|
||||
* InputStream if we are reading from the file
|
||||
*/
|
||||
private InputStream inputStream;
|
||||
|
||||
/**
|
||||
* OutputStream if we are writing to the file
|
||||
*/
|
||||
private OutputStream outputStream;
|
||||
|
||||
/**
|
||||
* FilePermission to read the file
|
||||
*/
|
||||
private FilePermission permission;
|
||||
|
||||
/**
|
||||
* Calls superclass constructor to initialize.
|
||||
*/
|
||||
public Connection(URL url)
|
||||
{
|
||||
super (url);
|
||||
|
||||
permission = new FilePermission(getURL().getFile(), DEFAULT_PERMISSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* "Connects" to the file by opening it.
|
||||
*/
|
||||
public void connect() throws IOException
|
||||
{
|
||||
// Call is ignored if already connected.
|
||||
if (connected)
|
||||
return;
|
||||
|
||||
// If not connected, then file needs to be openned.
|
||||
file = new File (getURL().getFile());
|
||||
|
||||
if (! file.isDirectory())
|
||||
{
|
||||
if (doInput)
|
||||
inputStream = new BufferedInputStream(new FileInputStream(file));
|
||||
|
||||
if (doOutput)
|
||||
outputStream = new BufferedOutputStream(new FileOutputStream(file));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (doInput)
|
||||
{
|
||||
inputStream = new ByteArrayInputStream(getDirectoryListing());
|
||||
}
|
||||
|
||||
if (doOutput)
|
||||
throw new ProtocolException
|
||||
("file: protocol does not support output on directories");
|
||||
}
|
||||
|
||||
connected = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the <code>directoryListing</code> field with a byte array
|
||||
* containing a representation of the directory listing.
|
||||
*/
|
||||
byte[] getDirectoryListing()
|
||||
throws IOException
|
||||
{
|
||||
if (directoryListing == null)
|
||||
{
|
||||
ByteArrayOutputStream sink = new ByteArrayOutputStream();
|
||||
// NB uses default character encoding for this system
|
||||
Writer writer = new OutputStreamWriter(sink);
|
||||
|
||||
String[] files = file.list();
|
||||
|
||||
for (int i = 0; i < files.length; i++)
|
||||
{
|
||||
writer.write(files[i]);
|
||||
writer.write(StaticData.lineSeparator);
|
||||
}
|
||||
|
||||
directoryListing = sink.toByteArray();
|
||||
}
|
||||
return directoryListing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the file for reading and returns a stream for it.
|
||||
*
|
||||
* @return An InputStream for this connection.
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
public InputStream getInputStream()
|
||||
throws IOException
|
||||
{
|
||||
if (!doInput)
|
||||
throw new ProtocolException("Can't open InputStream if doInput is false");
|
||||
|
||||
if (!connected)
|
||||
connect();
|
||||
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the file for writing and returns a stream for it.
|
||||
*
|
||||
* @return An OutputStream for this connection.
|
||||
*
|
||||
* @exception IOException If an error occurs.
|
||||
*/
|
||||
public OutputStream getOutputStream()
|
||||
throws IOException
|
||||
{
|
||||
if (!doOutput)
|
||||
throw new
|
||||
ProtocolException("Can't open OutputStream if doOutput is false");
|
||||
|
||||
if (!connected)
|
||||
connect();
|
||||
|
||||
return outputStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last modified time of the resource.
|
||||
*
|
||||
* @return the time since epoch that the resource was modified.
|
||||
*/
|
||||
public long getLastModified()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!connected)
|
||||
connect();
|
||||
|
||||
return file.lastModified();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an http-style header field. Just handle a few common ones.
|
||||
*/
|
||||
public String getHeaderField(String field)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!connected)
|
||||
connect();
|
||||
|
||||
if (field.equals("content-type"))
|
||||
return guessContentTypeFromName(file.getName());
|
||||
else if (field.equals("content-length"))
|
||||
{
|
||||
if (file.isDirectory())
|
||||
{
|
||||
return Integer.toString(getContentLength());
|
||||
}
|
||||
return Long.toString(file.length());
|
||||
}
|
||||
else if (field.equals("last-modified"))
|
||||
{
|
||||
synchronized (StaticData.dateFormat)
|
||||
{
|
||||
return StaticData.dateFormat.format(
|
||||
new Date(file.lastModified()));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// Fall through.
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the length of content.
|
||||
*
|
||||
* @return the length of the content.
|
||||
*/
|
||||
public int getContentLength()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!connected)
|
||||
connect();
|
||||
|
||||
if (file.isDirectory())
|
||||
{
|
||||
return getDirectoryListing().length;
|
||||
}
|
||||
return (int) file.length();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a <code>Permission</code> object representing the
|
||||
* permissions required to access this URL. This method returns a
|
||||
* <code>java.io.FilePermission</code> for the file's path with a read
|
||||
* permission.
|
||||
*
|
||||
* @return A Permission object
|
||||
*/
|
||||
public Permission getPermission() throws IOException
|
||||
{
|
||||
return permission;
|
||||
}
|
||||
}
|
91
libjava/classpath/gnu/java/net/protocol/file/Handler.java
Normal file
91
libjava/classpath/gnu/java/net/protocol/file/Handler.java
Normal file
|
@ -0,0 +1,91 @@
|
|||
/* Handler.java -- "file" protocol handler for java.net
|
||||
Copyright (C) 1998, 1999, 2000, 2002, 2003, 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.file;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLStreamHandler;
|
||||
|
||||
/**
|
||||
* This is the protocol handler for the "file" protocol.
|
||||
* It implements the abstract openConnection() method from
|
||||
* URLStreamHandler by returning a new FileURLConnection object (from
|
||||
* this package). All other methods are inherited
|
||||
*
|
||||
* @author Aaron M. Renn (arenn@urbanophile.com)
|
||||
* @author Warren Levy (warrenl@cygnus.com)
|
||||
*/
|
||||
public class Handler extends URLStreamHandler
|
||||
{
|
||||
/**
|
||||
* A do nothing constructor
|
||||
*/
|
||||
public Handler()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returs a new FileURLConnection for the specified URL
|
||||
*
|
||||
* @param url The URL to return a connection for
|
||||
*
|
||||
* @return The URLConnection
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected URLConnection openConnection(URL url) throws IOException
|
||||
{
|
||||
// If a hostname is set, then we need to switch protocols to ftp
|
||||
// in order to transfer this from the remote host.
|
||||
String host = url.getHost();
|
||||
if ((host != null) && (! host.equals("")))
|
||||
{
|
||||
// Reset the protocol (and implicitly the handler) for this URL.
|
||||
// Then have the URL attempt the connection again, as it will
|
||||
// get the changed handler the next time around.
|
||||
// If the ftp protocol handler is not installed, an
|
||||
// exception will be thrown from the new openConnection() call.
|
||||
setURL (url, "ftp", url.getHost(), url.getPort(), url.getFile(),
|
||||
url.getRef());
|
||||
return url.openConnection();
|
||||
}
|
||||
|
||||
return new Connection(url);
|
||||
}
|
||||
} // class Handler
|
46
libjava/classpath/gnu/java/net/protocol/file/package.html
Normal file
46
libjava/classpath/gnu/java/net/protocol/file/package.html
Normal file
|
@ -0,0 +1,46 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<!-- package.html - describes classes in gnu.java.net.protocol.file 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.file</title></head>
|
||||
|
||||
<body>
|
||||
<p></p>
|
||||
|
||||
</body>
|
||||
</html>
|
251
libjava/classpath/gnu/java/net/protocol/ftp/ActiveModeDTP.java
Normal file
251
libjava/classpath/gnu/java/net/protocol/ftp/ActiveModeDTP.java
Normal file
|
@ -0,0 +1,251 @@
|
|||
/* ActiveModeDTP.java --
|
||||
Copyright (C) 2003, 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.ftp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
* An active mode FTP data transfer process.
|
||||
* This starts a server on the specified port listening for a data
|
||||
* connection. It converts the socket input into a file stream for reading.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
final class ActiveModeDTP
|
||||
implements DTP, Runnable
|
||||
{
|
||||
|
||||
ServerSocket server;
|
||||
Socket socket;
|
||||
DTPInputStream in;
|
||||
DTPOutputStream out;
|
||||
boolean completed;
|
||||
boolean inProgress;
|
||||
int transferMode;
|
||||
IOException exception;
|
||||
Thread acceptThread;
|
||||
int connectionTimeout;
|
||||
|
||||
ActiveModeDTP(InetAddress localhost, int port,
|
||||
int connectionTimeout, int timeout)
|
||||
throws IOException
|
||||
{
|
||||
completed = false;
|
||||
inProgress = false;
|
||||
server = new ServerSocket(port, 1, localhost);
|
||||
if (timeout > 0)
|
||||
{
|
||||
server.setSoTimeout(timeout);
|
||||
}
|
||||
if (connectionTimeout <= 0)
|
||||
{
|
||||
connectionTimeout = 20000;
|
||||
}
|
||||
this.connectionTimeout = connectionTimeout;
|
||||
acceptThread = new Thread(this, "ActiveModeDTP");
|
||||
acceptThread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start listening.
|
||||
*/
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
socket = server.accept();
|
||||
//System.err.println("Accepted connection from "+socket.getInetAddress()+":"+socket.getPort());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
exception = e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits until a client has connected.
|
||||
*/
|
||||
public void waitFor()
|
||||
throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
acceptThread.join(connectionTimeout);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
}
|
||||
if (exception != null)
|
||||
{
|
||||
throw exception;
|
||||
}
|
||||
if (socket == null)
|
||||
{
|
||||
server.close();
|
||||
throw new IOException("client did not connect before timeout");
|
||||
}
|
||||
acceptThread = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an input stream from which a remote file can be read.
|
||||
*/
|
||||
public InputStream getInputStream()
|
||||
throws IOException
|
||||
{
|
||||
if (inProgress)
|
||||
{
|
||||
throw new IOException("Transfer in progress");
|
||||
}
|
||||
if (acceptThread != null)
|
||||
{
|
||||
waitFor();
|
||||
}
|
||||
switch (transferMode)
|
||||
{
|
||||
case FTPConnection.MODE_STREAM:
|
||||
in = new StreamInputStream(this, socket.getInputStream());
|
||||
break;
|
||||
case FTPConnection.MODE_BLOCK:
|
||||
in = new BlockInputStream(this, socket.getInputStream());
|
||||
break;
|
||||
case FTPConnection.MODE_COMPRESSED:
|
||||
in = new CompressedInputStream(this, socket.getInputStream());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("invalid transfer mode");
|
||||
}
|
||||
in.setTransferComplete(false);
|
||||
return in;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an output stream to which a local file can be written for
|
||||
* upload.
|
||||
*/
|
||||
public OutputStream getOutputStream() throws IOException
|
||||
{
|
||||
if (inProgress)
|
||||
{
|
||||
throw new IOException("Transfer in progress");
|
||||
}
|
||||
if (acceptThread != null)
|
||||
{
|
||||
waitFor();
|
||||
}
|
||||
switch (transferMode)
|
||||
{
|
||||
case FTPConnection.MODE_STREAM:
|
||||
out = new StreamOutputStream(this, socket.getOutputStream());
|
||||
break;
|
||||
case FTPConnection.MODE_BLOCK:
|
||||
out = new BlockOutputStream(this, socket.getOutputStream());
|
||||
break;
|
||||
case FTPConnection.MODE_COMPRESSED:
|
||||
out = new CompressedOutputStream(this, socket.getOutputStream());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("invalid transfer mode");
|
||||
}
|
||||
out.setTransferComplete(false);
|
||||
return out;
|
||||
}
|
||||
|
||||
public void setTransferMode(int mode)
|
||||
{
|
||||
transferMode = mode;
|
||||
}
|
||||
|
||||
public void complete()
|
||||
{
|
||||
completed = true;
|
||||
if (!inProgress)
|
||||
{
|
||||
transferComplete();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean abort()
|
||||
{
|
||||
completed = true;
|
||||
transferComplete();
|
||||
return inProgress;
|
||||
}
|
||||
|
||||
public void transferComplete()
|
||||
{
|
||||
if (socket == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (in != null)
|
||||
{
|
||||
in.setTransferComplete(true);
|
||||
}
|
||||
if (out != null)
|
||||
{
|
||||
out.setTransferComplete(true);
|
||||
}
|
||||
completed = completed || (transferMode == FTPConnection.MODE_STREAM);
|
||||
if (completed && socket != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
socket.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
}
|
||||
try
|
||||
{
|
||||
server.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
/* BlockInputStream.java --
|
||||
Copyright (C) 2003, 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.ftp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* A DTP input stream that implements the FTP block transfer mode.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
class BlockInputStream
|
||||
extends DTPInputStream
|
||||
{
|
||||
|
||||
static final int EOF = 64;
|
||||
|
||||
int descriptor;
|
||||
int max = -1;
|
||||
int count = -1;
|
||||
|
||||
BlockInputStream(DTP dtp, InputStream in)
|
||||
{
|
||||
super(dtp, in);
|
||||
}
|
||||
|
||||
public int read()
|
||||
throws IOException
|
||||
{
|
||||
if (transferComplete)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (count == -1)
|
||||
{
|
||||
readHeader();
|
||||
}
|
||||
if (max < 1)
|
||||
{
|
||||
close();
|
||||
return -1;
|
||||
}
|
||||
int c = in.read();
|
||||
if (c == -1)
|
||||
{
|
||||
dtp.transferComplete();
|
||||
}
|
||||
count++;
|
||||
if (count >= max)
|
||||
{
|
||||
count = -1;
|
||||
if (descriptor == EOF)
|
||||
{
|
||||
close();
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
public int read(byte[] buf)
|
||||
throws IOException
|
||||
{
|
||||
return read(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
public int read(byte[] buf, int off, int len)
|
||||
throws IOException
|
||||
{
|
||||
if (transferComplete)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (count == -1)
|
||||
{
|
||||
readHeader();
|
||||
}
|
||||
if (max < 1)
|
||||
{
|
||||
close();
|
||||
return -1;
|
||||
}
|
||||
int l = in.read(buf, off, len);
|
||||
if (l == -1)
|
||||
{
|
||||
dtp.transferComplete();
|
||||
}
|
||||
count += l;
|
||||
if (count >= max)
|
||||
{
|
||||
count = -1;
|
||||
if (descriptor == EOF)
|
||||
{
|
||||
close();
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the block header.
|
||||
*/
|
||||
void readHeader()
|
||||
throws IOException
|
||||
{
|
||||
descriptor = in.read();
|
||||
int max_hi = in.read();
|
||||
int max_lo = in.read();
|
||||
max = (max_hi << 8) | max_lo;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/* BlockOutputStream.java --
|
||||
Copyright (C) 2003, 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.ftp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* A DTP output stream that implements the FTP block transfer mode.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
class BlockOutputStream
|
||||
extends DTPOutputStream
|
||||
{
|
||||
|
||||
static final byte RECORD = -128; // 0x80
|
||||
static final byte EOF = 64; // 0x40
|
||||
|
||||
BlockOutputStream(DTP dtp, OutputStream out)
|
||||
{
|
||||
super(dtp, out);
|
||||
}
|
||||
|
||||
public void write(int c)
|
||||
throws IOException
|
||||
{
|
||||
if (transferComplete)
|
||||
{
|
||||
return;
|
||||
}
|
||||
byte[] buf = new byte[]
|
||||
{
|
||||
RECORD, /* record descriptor */
|
||||
0x00, 0x01, /* one byte */
|
||||
(byte) c /* the byte */
|
||||
};
|
||||
out.write(buf, 0, 4);
|
||||
}
|
||||
|
||||
public void write(byte[] b)
|
||||
throws IOException
|
||||
{
|
||||
write(b, 0, b.length);
|
||||
}
|
||||
|
||||
public void write(byte[] b, int off, int len)
|
||||
throws IOException
|
||||
{
|
||||
if (transferComplete)
|
||||
{
|
||||
return;
|
||||
}
|
||||
byte[] buf = new byte[len + 3];
|
||||
buf[0] = RECORD; /* record descriptor */
|
||||
buf[1] = (byte) ((len & 0x00ff) >> 8); /* high byte of bytecount */
|
||||
buf[2] = (byte) (len & 0xff00); /* low byte of bytecount */
|
||||
System.arraycopy(b, off, buf, 3, len);
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
|
||||
public void close()
|
||||
throws IOException
|
||||
{
|
||||
byte[] buf = new byte[]
|
||||
{
|
||||
EOF, /* eof descriptor */
|
||||
0x00, 0x00 /* no bytes */
|
||||
};
|
||||
out.write(buf, 0, 3);
|
||||
super.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
/* CompressedInputStream.java --
|
||||
Copyright (C) 2003, 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.ftp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.ProtocolException;
|
||||
|
||||
/**
|
||||
* A DTP input stream that implements the FTP compressed transfer mode.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
class CompressedInputStream
|
||||
extends DTPInputStream
|
||||
{
|
||||
|
||||
static final int EOF = 64;
|
||||
|
||||
static final int RAW = 0x00;
|
||||
static final int COMPRESSED = 0x80;
|
||||
static final int FILLER = 0xc0;
|
||||
|
||||
int descriptor;
|
||||
int max = -1;
|
||||
int count = -1;
|
||||
|
||||
int state = RAW; // RAW | STATE | FILLER
|
||||
int rep; // the compressed byte
|
||||
int n = 0; // the number of compressed or raw bytes
|
||||
|
||||
CompressedInputStream(DTP dtp, InputStream in)
|
||||
{
|
||||
super(dtp, in);
|
||||
}
|
||||
|
||||
public int read()
|
||||
throws IOException
|
||||
{
|
||||
if (transferComplete)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (count == -1)
|
||||
{
|
||||
readHeader();
|
||||
}
|
||||
if (max < 1)
|
||||
{
|
||||
close();
|
||||
return -1;
|
||||
}
|
||||
if (n > 0 && (state == COMPRESSED || state == FILLER))
|
||||
{
|
||||
n--;
|
||||
return rep;
|
||||
}
|
||||
int c = in.read();
|
||||
if (c == -1)
|
||||
{
|
||||
close();
|
||||
}
|
||||
count++;
|
||||
if (count >= max)
|
||||
{
|
||||
count = -1;
|
||||
if (descriptor == EOF)
|
||||
{
|
||||
close();
|
||||
}
|
||||
}
|
||||
if (c == -1)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
while (n == 0) // read code header
|
||||
{
|
||||
state = (c & 0xc0);
|
||||
n = (c & 0x3f);
|
||||
c = in.read();
|
||||
if (c == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
switch (state)
|
||||
{
|
||||
case RAW:
|
||||
break;
|
||||
case COMPRESSED:
|
||||
case FILLER:
|
||||
rep = c;
|
||||
break;
|
||||
default:
|
||||
throw new ProtocolException("Illegal state: " + state);
|
||||
}
|
||||
n--;
|
||||
return c;
|
||||
}
|
||||
|
||||
public int read(byte[] buf)
|
||||
throws IOException
|
||||
{
|
||||
return read(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
public int read(byte[] buf, int off, int len)
|
||||
throws IOException
|
||||
{
|
||||
if (transferComplete)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (count == -1)
|
||||
{
|
||||
readHeader();
|
||||
}
|
||||
if (max < 1)
|
||||
{
|
||||
close();
|
||||
return -1;
|
||||
}
|
||||
// TODO improve performance
|
||||
for (int i = off; i < len; i++)
|
||||
{
|
||||
int c = read();
|
||||
if (c == -1)
|
||||
{
|
||||
close();
|
||||
return i;
|
||||
}
|
||||
buf[i] = (byte) c;
|
||||
}
|
||||
return len;
|
||||
/*
|
||||
int l = in.read (buf, off, len);
|
||||
if (l==-1)
|
||||
{
|
||||
close ();
|
||||
}
|
||||
count += l;
|
||||
if (count>=max)
|
||||
{
|
||||
count = -1;
|
||||
if (descriptor==EOF)
|
||||
{
|
||||
close ();
|
||||
}
|
||||
}
|
||||
return l;
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the block header.
|
||||
*/
|
||||
void readHeader()
|
||||
throws IOException
|
||||
{
|
||||
descriptor = in.read();
|
||||
int max_hi = in.read();
|
||||
int max_lo = in.read();
|
||||
max = (max_hi << 8) | max_lo;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the code header.
|
||||
*/
|
||||
void readCodeHeader()
|
||||
throws IOException
|
||||
{
|
||||
int code = in.read();
|
||||
state = (code & 0xc0);
|
||||
n = (code & 0x3f);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,228 @@
|
|||
/* CompressedOutputStream.java --
|
||||
Copyright (C) 2003, 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.ftp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* A DTP output stream that implements the FTP compressed transfer mode.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
class CompressedOutputStream
|
||||
extends DTPOutputStream
|
||||
{
|
||||
|
||||
static final byte RECORD = -128; // 0x80
|
||||
static final byte EOF = 64; // 0x40
|
||||
|
||||
CompressedOutputStream(DTP dtp, OutputStream out)
|
||||
{
|
||||
super(dtp, out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Just one byte cannot be compressed.
|
||||
* It takes 5 bytes to transmit - hardly very compressed!
|
||||
*/
|
||||
public void write(int c)
|
||||
throws IOException
|
||||
{
|
||||
if (transferComplete)
|
||||
{
|
||||
return;
|
||||
}
|
||||
byte[] buf = new byte[]
|
||||
{
|
||||
RECORD, /* record descriptor */
|
||||
0x00, 0x01, /* one byte */
|
||||
0x01, /* one uncompressed byte */
|
||||
(byte) c /* the byte */
|
||||
};
|
||||
out.write(buf, 0, 5);
|
||||
}
|
||||
|
||||
public void write(byte[] b)
|
||||
throws IOException
|
||||
{
|
||||
write(b, 0, b.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* The larger len is, the better.
|
||||
*/
|
||||
public void write(byte[] b, int off, int len)
|
||||
throws IOException
|
||||
{
|
||||
if (transferComplete)
|
||||
{
|
||||
return;
|
||||
}
|
||||
byte[] buf = compress(b, off, len);
|
||||
len = buf.length;
|
||||
buf[0] = RECORD; /* record descriptor */
|
||||
buf[1] = (byte) ((len & 0x00ff) >> 8); /* high byte of bytecount */
|
||||
buf[2] = (byte) (len & 0xff00); /* low byte of bytecount */
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the compressed form of the given byte array.
|
||||
* The first 3 bytes are left free for header information.
|
||||
*/
|
||||
byte[] compress(byte[] b, int off, int len)
|
||||
{
|
||||
byte[] buf = new byte[len];
|
||||
byte last = 0;
|
||||
int pos = 0, raw_count = 0, rep_count = 1;
|
||||
for (int i = off; i < len; i++)
|
||||
{
|
||||
byte c = b[i];
|
||||
if (i > off && c == last) // compress
|
||||
{
|
||||
if (raw_count > 0) // flush raw bytes to buf
|
||||
{
|
||||
// need to add raw_count+1 bytes
|
||||
if (pos + (raw_count + 1) > buf.length)
|
||||
{
|
||||
buf = realloc(buf, len);
|
||||
}
|
||||
pos = flush_raw(buf, pos, b, (i - raw_count) - 1,
|
||||
raw_count);
|
||||
raw_count = 0;
|
||||
}
|
||||
rep_count++; // keep looking for same byte
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rep_count > 1) // flush compressed bytes to buf
|
||||
{
|
||||
// need to add 2 bytes
|
||||
if (pos + 2 > buf.length)
|
||||
{
|
||||
buf = realloc(buf, len);
|
||||
}
|
||||
pos = flush_compressed(buf, pos, rep_count, last);
|
||||
rep_count = 1;
|
||||
}
|
||||
raw_count++; // keep looking for raw bytes
|
||||
}
|
||||
if (rep_count == 127) // flush compressed bytes
|
||||
{
|
||||
// need to add 2 bytes
|
||||
if (pos + 2 > buf.length)
|
||||
{
|
||||
buf = realloc(buf, len);
|
||||
}
|
||||
pos = flush_compressed(buf, pos, rep_count, last);
|
||||
rep_count = 1;
|
||||
}
|
||||
if (raw_count == 127) // flush raw bytes
|
||||
{
|
||||
// need to add raw_count+1 bytes
|
||||
if (pos + (raw_count + 1) > buf.length)
|
||||
{
|
||||
buf = realloc(buf, len);
|
||||
}
|
||||
pos = flush_raw(buf, pos, b, (i - raw_count), raw_count);
|
||||
raw_count = 0;
|
||||
}
|
||||
last = c;
|
||||
}
|
||||
if (rep_count > 1) // flush compressed bytes
|
||||
{
|
||||
// need to add 2 bytes
|
||||
if (pos + 2 > buf.length)
|
||||
{
|
||||
buf = realloc(buf, len);
|
||||
}
|
||||
pos = flush_compressed(buf, pos, rep_count, last);
|
||||
rep_count = 1;
|
||||
}
|
||||
if (raw_count > 0) // flush raw bytes
|
||||
{
|
||||
// need to add raw_count+1 bytes
|
||||
if (pos + (raw_count + 1) > buf.length)
|
||||
{
|
||||
buf = realloc(buf, len);
|
||||
}
|
||||
pos = flush_raw(buf, pos, b, (len - raw_count), raw_count);
|
||||
raw_count = 0;
|
||||
}
|
||||
byte[] ret = new byte[pos + 3];
|
||||
System.arraycopy(buf, 0, ret, 3, pos);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int flush_compressed(byte[] buf, int pos, int count, byte c)
|
||||
{
|
||||
buf[pos++] = (byte) (0x80 | count);
|
||||
buf[pos++] = c;
|
||||
return pos;
|
||||
}
|
||||
|
||||
int flush_raw(byte[] buf, int pos, byte[] src, int off, int len)
|
||||
{
|
||||
buf[pos++] = (byte) len;
|
||||
System.arraycopy(src, off, buf, pos, len);
|
||||
return pos + len;
|
||||
}
|
||||
|
||||
byte[] realloc(byte[] buf, int len)
|
||||
{
|
||||
byte[] ret = new byte[buf.length + len];
|
||||
System.arraycopy(buf, 0, ret, 0, buf.length);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void close()
|
||||
throws IOException
|
||||
{
|
||||
byte[] buf = new byte[]
|
||||
{
|
||||
EOF, /* eof descriptor */
|
||||
0x00, 0x00 /* no bytes */
|
||||
};
|
||||
out.write(buf, 0, 3);
|
||||
out.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
92
libjava/classpath/gnu/java/net/protocol/ftp/DTP.java
Normal file
92
libjava/classpath/gnu/java/net/protocol/ftp/DTP.java
Normal file
|
@ -0,0 +1,92 @@
|
|||
/* DTP.java --
|
||||
Copyright (C) 2003, 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.ftp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* An FTP data transfer process.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
interface DTP
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns an input stream from which a remote file can be read.
|
||||
*/
|
||||
InputStream getInputStream()
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Returns an output stream to which a local file can be written for
|
||||
* upload.
|
||||
*/
|
||||
OutputStream getOutputStream()
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Sets the transfer mode to be used with this DTP.
|
||||
*/
|
||||
void setTransferMode(int mode);
|
||||
|
||||
/**
|
||||
* Marks this DTP completed.
|
||||
* When the current transfer has finished, any resources will be released.
|
||||
*/
|
||||
void complete();
|
||||
|
||||
/**
|
||||
* Aborts any current transfer and releases all resources held by this
|
||||
* DTP.
|
||||
* @return true if a transfer was interrupted, false otherwise
|
||||
*/
|
||||
boolean abort();
|
||||
|
||||
/**
|
||||
* Used to notify the DTP that its current transfer is complete.
|
||||
* This occurs either when end-of-stream is reached or a 226 response is
|
||||
* received.
|
||||
*/
|
||||
void transferComplete();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/* DTPInputStream.java --
|
||||
Copyright (C) 2003, 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.ftp;
|
||||
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* An input stream that notifies a DTP on completion.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
abstract class DTPInputStream
|
||||
extends FilterInputStream
|
||||
{
|
||||
|
||||
DTP dtp;
|
||||
boolean transferComplete;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param dtp the controlling data transfer process
|
||||
* @param in the underlying socket stream
|
||||
*/
|
||||
DTPInputStream (DTP dtp, InputStream in)
|
||||
{
|
||||
super(in);
|
||||
this.dtp = dtp;
|
||||
transferComplete = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks this input stream complete.
|
||||
* This is called by the DTP.
|
||||
*/
|
||||
void setTransferComplete(boolean flag)
|
||||
{
|
||||
transferComplete = flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the controlling DTP that this stream has completed transfer.
|
||||
*/
|
||||
public void close()
|
||||
throws IOException
|
||||
{
|
||||
dtp.transferComplete();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/* DTPOutputStream.java --
|
||||
Copyright (C) 2003, 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.ftp;
|
||||
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* An output stream that notifies a DTP on end of stream.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
abstract class DTPOutputStream extends FilterOutputStream
|
||||
{
|
||||
|
||||
DTP dtp;
|
||||
boolean transferComplete;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param dtp the controlling data transfer process
|
||||
* @param out the socket output stream
|
||||
*/
|
||||
DTPOutputStream (DTP dtp, OutputStream out)
|
||||
{
|
||||
super (out);
|
||||
this.dtp = dtp;
|
||||
transferComplete = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells this stream whether transfer has completed or not.
|
||||
* @param flag true if the process has completed, false otherwise
|
||||
*/
|
||||
void setTransferComplete (boolean flag)
|
||||
{
|
||||
transferComplete = flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the controlling DTP that this stream has been terminated.
|
||||
*/
|
||||
public void close () throws IOException
|
||||
{
|
||||
dtp.transferComplete ();
|
||||
}
|
||||
|
||||
}
|
1348
libjava/classpath/gnu/java/net/protocol/ftp/FTPConnection.java
Normal file
1348
libjava/classpath/gnu/java/net/protocol/ftp/FTPConnection.java
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,76 @@
|
|||
/* FTPException.java --
|
||||
Copyright (C) 2003. 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.ftp;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An FTP control exception.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public class FTPException
|
||||
extends IOException
|
||||
{
|
||||
|
||||
/**
|
||||
* The response that provoked this exception.
|
||||
*/
|
||||
protected final FTPResponse response;
|
||||
|
||||
/**
|
||||
* Constructs a new FTP exception.
|
||||
* @param response the response that provoked this exception
|
||||
*/
|
||||
public FTPException(FTPResponse response)
|
||||
{
|
||||
super(response.getMessage());
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the response that provoked this exception.
|
||||
*/
|
||||
public FTPResponse getResponse()
|
||||
{
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
|
112
libjava/classpath/gnu/java/net/protocol/ftp/FTPResponse.java
Normal file
112
libjava/classpath/gnu/java/net/protocol/ftp/FTPResponse.java
Normal file
|
@ -0,0 +1,112 @@
|
|||
/* FTPResponse.java --
|
||||
Copyright (C) 2003, 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.ftp;
|
||||
|
||||
/**
|
||||
* An FTP control response.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public final class FTPResponse
|
||||
{
|
||||
|
||||
/**
|
||||
* The 3-digit status code.
|
||||
*/
|
||||
protected final int code;
|
||||
|
||||
/**
|
||||
* The human-readable message.
|
||||
*/
|
||||
protected final String message;
|
||||
|
||||
/**
|
||||
* Multiline data, if present.
|
||||
*/
|
||||
protected final String data;
|
||||
|
||||
/**
|
||||
* Constructs a new FTP response.
|
||||
* @param code the status code
|
||||
* @param message the message
|
||||
*/
|
||||
public FTPResponse(int code, String message)
|
||||
{
|
||||
this(code, message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new multiline FTP response.
|
||||
* @param code the status code
|
||||
* @param message the message
|
||||
* @param data multiline data
|
||||
*/
|
||||
public FTPResponse(int code, String message, String data)
|
||||
{
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the 3-digit status code.
|
||||
*/
|
||||
public int getCode()
|
||||
{
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the human-readable message.
|
||||
*/
|
||||
public String getMessage()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the multiline data, or null if there was no such data.
|
||||
*/
|
||||
public String getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,398 @@
|
|||
/* FTPURLConnection.java --
|
||||
Copyright (C) 2003, 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.ftp;
|
||||
|
||||
import gnu.java.net.GetLocalHostAction;
|
||||
import gnu.java.security.action.GetPropertyAction;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An FTP URL connection.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public class FTPURLConnection
|
||||
extends URLConnection
|
||||
{
|
||||
|
||||
/**
|
||||
* The connection managing the protocol exchange.
|
||||
*/
|
||||
protected FTPConnection connection;
|
||||
|
||||
protected boolean passive;
|
||||
protected int representationType;
|
||||
protected int fileStructure;
|
||||
protected int transferMode;
|
||||
|
||||
/**
|
||||
* Constructs an FTP connection to the specified URL.
|
||||
* @param url the URL
|
||||
*/
|
||||
public FTPURLConnection(URL url)
|
||||
{
|
||||
super(url);
|
||||
passive = true;
|
||||
representationType = FTPConnection.TYPE_BINARY;
|
||||
fileStructure = -1;
|
||||
transferMode = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the connection.
|
||||
*/
|
||||
public void connect()
|
||||
throws IOException
|
||||
{
|
||||
if (connected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
String host = url.getHost();
|
||||
int port = url.getPort();
|
||||
String username = url.getUserInfo();
|
||||
String password = null;
|
||||
if (username != null)
|
||||
{
|
||||
int ci = username.indexOf(':');
|
||||
if (ci != -1)
|
||||
{
|
||||
password = username.substring(ci + 1);
|
||||
username = username.substring(0, ci);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
username = "anonymous";
|
||||
PrivilegedAction a = new GetPropertyAction("user.name");
|
||||
String systemUsername =(String) AccessController.doPrivileged(a);
|
||||
a = new GetLocalHostAction();
|
||||
InetAddress localhost =(InetAddress) AccessController.doPrivileged(a);
|
||||
password = systemUsername + "@" +
|
||||
((localhost == null) ? "localhost" : localhost.getHostName());
|
||||
}
|
||||
connection = new FTPConnection(host, port);
|
||||
if (!connection.authenticate(username, password))
|
||||
{
|
||||
throw new SecurityException("Authentication failed");
|
||||
}
|
||||
connection.setPassive(passive);
|
||||
if (representationType != -1)
|
||||
{
|
||||
connection.setRepresentationType(representationType);
|
||||
}
|
||||
if (fileStructure != -1)
|
||||
{
|
||||
connection.setFileStructure(fileStructure);
|
||||
}
|
||||
if (transferMode != -1)
|
||||
{
|
||||
connection.setTransferMode(transferMode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This connection supports doInput.
|
||||
*/
|
||||
public void setDoInput(boolean doinput)
|
||||
{
|
||||
doInput = doinput;
|
||||
}
|
||||
|
||||
/**
|
||||
* This connection supports doOutput.
|
||||
*/
|
||||
public void setDoOutput(boolean dooutput)
|
||||
{
|
||||
doOutput = dooutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an input stream that reads from this open connection.
|
||||
*/
|
||||
public InputStream getInputStream()
|
||||
throws IOException
|
||||
{
|
||||
if (!connected)
|
||||
{
|
||||
connect();
|
||||
}
|
||||
String path = url.getPath();
|
||||
String filename = null;
|
||||
int lsi = path.lastIndexOf('/');
|
||||
if (lsi != -1)
|
||||
{
|
||||
filename = path.substring(lsi + 1);
|
||||
path = path.substring(0, lsi);
|
||||
if (!connection.changeWorkingDirectory(path))
|
||||
{
|
||||
throw new FileNotFoundException(path);
|
||||
}
|
||||
}
|
||||
if (filename != null && filename.length() > 0)
|
||||
{
|
||||
return this.new ClosingInputStream(connection.retrieve(filename));
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.new ClosingInputStream(connection.list(null));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an output stream that writes to this connection.
|
||||
*/
|
||||
public OutputStream getOutputStream()
|
||||
throws IOException
|
||||
{
|
||||
if (!connected)
|
||||
{
|
||||
connect();
|
||||
}
|
||||
String dir = url.getPath();
|
||||
String filename = url.getFile();
|
||||
if (!connection.changeWorkingDirectory(dir))
|
||||
{
|
||||
throw new FileNotFoundException(dir);
|
||||
}
|
||||
if (filename != null)
|
||||
{
|
||||
return this.new ClosingOutputStream(connection.store(filename));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FileNotFoundException(filename);
|
||||
}
|
||||
}
|
||||
|
||||
public String getRequestProperty(String key)
|
||||
{
|
||||
if ("passive".equals(key))
|
||||
{
|
||||
return Boolean.toString(passive);
|
||||
}
|
||||
else if ("representationType".equals(key))
|
||||
{
|
||||
switch (representationType)
|
||||
{
|
||||
case FTPConnection.TYPE_ASCII:
|
||||
return "ASCII";
|
||||
case FTPConnection.TYPE_EBCDIC:
|
||||
return "EBCDIC";
|
||||
case FTPConnection.TYPE_BINARY:
|
||||
return "BINARY";
|
||||
}
|
||||
}
|
||||
else if ("fileStructure".equals(key))
|
||||
{
|
||||
switch (fileStructure)
|
||||
{
|
||||
case FTPConnection.STRUCTURE_FILE:
|
||||
return "FILE";
|
||||
case FTPConnection.STRUCTURE_RECORD:
|
||||
return "RECORD";
|
||||
case FTPConnection.STRUCTURE_PAGE:
|
||||
return "PAGE";
|
||||
}
|
||||
}
|
||||
else if ("transferMode".equals(key))
|
||||
{
|
||||
switch (transferMode)
|
||||
{
|
||||
case FTPConnection.MODE_STREAM:
|
||||
return "STREAM";
|
||||
case FTPConnection.MODE_BLOCK:
|
||||
return "BLOCK";
|
||||
case FTPConnection.MODE_COMPRESSED:
|
||||
return "COMPRESSED";
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map getRequestProperties()
|
||||
{
|
||||
Map map = new HashMap();
|
||||
addRequestPropertyValue(map, "passive");
|
||||
addRequestPropertyValue(map, "representationType");
|
||||
addRequestPropertyValue(map, "fileStructure");
|
||||
addRequestPropertyValue(map, "transferMode");
|
||||
return map;
|
||||
}
|
||||
|
||||
private void addRequestPropertyValue(Map map, String key)
|
||||
{
|
||||
String value = getRequestProperty(key);
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
public void setRequestProperty(String key, String value)
|
||||
{
|
||||
if (connected)
|
||||
{
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if ("passive".equals(key))
|
||||
{
|
||||
passive = Boolean.valueOf(value).booleanValue();
|
||||
}
|
||||
else if ("representationType".equals(key))
|
||||
{
|
||||
if ("A".equalsIgnoreCase(value) ||
|
||||
"ASCII".equalsIgnoreCase(value))
|
||||
{
|
||||
representationType = FTPConnection.TYPE_ASCII;
|
||||
}
|
||||
else if ("E".equalsIgnoreCase(value) ||
|
||||
"EBCDIC".equalsIgnoreCase(value))
|
||||
{
|
||||
representationType = FTPConnection.TYPE_EBCDIC;
|
||||
}
|
||||
else if ("I".equalsIgnoreCase(value) ||
|
||||
"BINARY".equalsIgnoreCase(value))
|
||||
{
|
||||
representationType = FTPConnection.TYPE_BINARY;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException(value);
|
||||
}
|
||||
}
|
||||
else if ("fileStructure".equals(key))
|
||||
{
|
||||
if ("F".equalsIgnoreCase(value) ||
|
||||
"FILE".equalsIgnoreCase(value))
|
||||
{
|
||||
fileStructure = FTPConnection.STRUCTURE_FILE;
|
||||
}
|
||||
else if ("R".equalsIgnoreCase(value) ||
|
||||
"RECORD".equalsIgnoreCase(value))
|
||||
{
|
||||
fileStructure = FTPConnection.STRUCTURE_RECORD;
|
||||
}
|
||||
else if ("P".equalsIgnoreCase(value) ||
|
||||
"PAGE".equalsIgnoreCase(value))
|
||||
{
|
||||
fileStructure = FTPConnection.STRUCTURE_PAGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException(value);
|
||||
}
|
||||
}
|
||||
else if ("transferMode".equals(key))
|
||||
{
|
||||
if ("S".equalsIgnoreCase(value) ||
|
||||
"STREAM".equalsIgnoreCase(value))
|
||||
{
|
||||
transferMode = FTPConnection.MODE_STREAM;
|
||||
}
|
||||
else if ("B".equalsIgnoreCase(value) ||
|
||||
"BLOCK".equalsIgnoreCase(value))
|
||||
{
|
||||
transferMode = FTPConnection.MODE_BLOCK;
|
||||
}
|
||||
else if ("C".equalsIgnoreCase(value) ||
|
||||
"COMPRESSED".equalsIgnoreCase(value))
|
||||
{
|
||||
transferMode = FTPConnection.MODE_COMPRESSED;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addRequestProperty(String key, String value)
|
||||
{
|
||||
setRequestProperty(key, value);
|
||||
}
|
||||
|
||||
class ClosingInputStream
|
||||
extends FilterInputStream
|
||||
{
|
||||
|
||||
ClosingInputStream(InputStream in)
|
||||
{
|
||||
super(in);
|
||||
}
|
||||
|
||||
public void close()
|
||||
throws IOException
|
||||
{
|
||||
super.close();
|
||||
connection.logout();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ClosingOutputStream
|
||||
extends FilterOutputStream
|
||||
{
|
||||
|
||||
ClosingOutputStream(OutputStream out)
|
||||
{
|
||||
super(out);
|
||||
}
|
||||
|
||||
public void close()
|
||||
throws IOException
|
||||
{
|
||||
super.close();
|
||||
connection.logout();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
70
libjava/classpath/gnu/java/net/protocol/ftp/Handler.java
Normal file
70
libjava/classpath/gnu/java/net/protocol/ftp/Handler.java
Normal file
|
@ -0,0 +1,70 @@
|
|||
/* Handler.java --
|
||||
Copyright (C) 2003, 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.ftp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLStreamHandler;
|
||||
|
||||
/**
|
||||
* An FTP URL stream handler.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public class Handler
|
||||
extends URLStreamHandler
|
||||
{
|
||||
|
||||
protected int getDefaultPort()
|
||||
{
|
||||
return FTPConnection.FTP_PORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an FTPURLConnection for the given URL.
|
||||
*/
|
||||
public URLConnection openConnection(URL url)
|
||||
throws IOException
|
||||
{
|
||||
return new FTPURLConnection(url);
|
||||
}
|
||||
|
||||
}
|
||||
|
201
libjava/classpath/gnu/java/net/protocol/ftp/PassiveModeDTP.java
Normal file
201
libjava/classpath/gnu/java/net/protocol/ftp/PassiveModeDTP.java
Normal file
|
@ -0,0 +1,201 @@
|
|||
/* PassiveModeDTP.java --
|
||||
Copyright (C) 2003, 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.ftp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
* A passive mode FTP data transfer process.
|
||||
* This connects to the host specified and proxies the resulting socket's
|
||||
* input and output streams.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
final class PassiveModeDTP
|
||||
implements DTP
|
||||
{
|
||||
|
||||
final String address;
|
||||
final int port;
|
||||
Socket socket;
|
||||
DTPInputStream in;
|
||||
DTPOutputStream out;
|
||||
boolean completed;
|
||||
boolean inProgress;
|
||||
int transferMode;
|
||||
|
||||
PassiveModeDTP(String address, int port, InetAddress localhost,
|
||||
int connectionTimeout, int timeout)
|
||||
throws IOException
|
||||
{
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
completed = false;
|
||||
inProgress = false;
|
||||
socket = new Socket();
|
||||
InetSocketAddress remote = new InetSocketAddress(address, port);
|
||||
InetSocketAddress local = new InetSocketAddress(localhost, port + 1);
|
||||
socket.bind(local);
|
||||
if (connectionTimeout > 0)
|
||||
{
|
||||
socket.connect(remote, connectionTimeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
socket.connect(remote);
|
||||
}
|
||||
if (timeout > 0)
|
||||
{
|
||||
socket.setSoTimeout(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an input stream from which a remote file can be read.
|
||||
*/
|
||||
public InputStream getInputStream()
|
||||
throws IOException
|
||||
{
|
||||
if (inProgress)
|
||||
{
|
||||
throw new IOException("Transfer in progress");
|
||||
}
|
||||
switch (transferMode)
|
||||
{
|
||||
case FTPConnection.MODE_STREAM:
|
||||
in = new StreamInputStream(this, socket.getInputStream());
|
||||
break;
|
||||
case FTPConnection.MODE_BLOCK:
|
||||
in = new BlockInputStream(this, socket.getInputStream());
|
||||
break;
|
||||
case FTPConnection.MODE_COMPRESSED:
|
||||
in = new CompressedInputStream(this, socket.getInputStream());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Invalid transfer mode");
|
||||
}
|
||||
in.setTransferComplete(false);
|
||||
return in;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an output stream to which a local file can be written for
|
||||
* upload.
|
||||
*/
|
||||
public OutputStream getOutputStream()
|
||||
throws IOException
|
||||
{
|
||||
if (inProgress)
|
||||
{
|
||||
throw new IOException("Transfer in progress");
|
||||
}
|
||||
switch (transferMode)
|
||||
{
|
||||
case FTPConnection.MODE_STREAM:
|
||||
out = new StreamOutputStream(this, socket.getOutputStream());
|
||||
break;
|
||||
case FTPConnection.MODE_BLOCK:
|
||||
out = new BlockOutputStream(this, socket.getOutputStream());
|
||||
break;
|
||||
case FTPConnection.MODE_COMPRESSED:
|
||||
out = new CompressedOutputStream(this, socket.getOutputStream());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Invalid transfer mode");
|
||||
}
|
||||
out.setTransferComplete(false);
|
||||
return out;
|
||||
}
|
||||
|
||||
public void setTransferMode(int mode)
|
||||
{
|
||||
transferMode = mode;
|
||||
}
|
||||
|
||||
public void complete()
|
||||
{
|
||||
completed = true;
|
||||
if (!inProgress)
|
||||
{
|
||||
transferComplete();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean abort()
|
||||
{
|
||||
completed = true;
|
||||
transferComplete();
|
||||
return inProgress;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by DTPInputStream or DTPOutputStream when end of
|
||||
* stream is reached.
|
||||
*/
|
||||
public void transferComplete()
|
||||
{
|
||||
if (in != null)
|
||||
{
|
||||
in.setTransferComplete(true);
|
||||
}
|
||||
if (out != null)
|
||||
{
|
||||
out.setTransferComplete(true);
|
||||
}
|
||||
inProgress = false;
|
||||
completed = completed ||(transferMode == FTPConnection.MODE_STREAM);
|
||||
if (completed && socket != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
socket.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/* StreamInputStream.java --
|
||||
Copyright (C) 2003, 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.ftp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* A DTP input stream that implements the FTP stream data transfer mode.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
class StreamInputStream
|
||||
extends DTPInputStream
|
||||
{
|
||||
|
||||
StreamInputStream(DTP dtp, InputStream in)
|
||||
{
|
||||
super(dtp, in);
|
||||
}
|
||||
|
||||
public int read()
|
||||
throws IOException
|
||||
{
|
||||
if (transferComplete)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
int c = in.read();
|
||||
if (c == -1)
|
||||
{
|
||||
close();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
public int read(byte[] buf)
|
||||
throws IOException
|
||||
{
|
||||
return read(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
public int read(byte[] buf, int off, int len)
|
||||
throws IOException
|
||||
{
|
||||
if (transferComplete)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
int l = in.read(buf, off, len);
|
||||
if (l == -1)
|
||||
{
|
||||
close();
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/* StreamOutputStream.java --
|
||||
Copyright (C) 2003, 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.ftp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* A DTP output stream that implements the FTP stream transfer mode.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
class StreamOutputStream
|
||||
extends DTPOutputStream
|
||||
{
|
||||
|
||||
StreamOutputStream(DTP dtp, OutputStream out)
|
||||
{
|
||||
super(dtp, out);
|
||||
}
|
||||
|
||||
public void write(int c)
|
||||
throws IOException
|
||||
{
|
||||
if (transferComplete)
|
||||
{
|
||||
return;
|
||||
}
|
||||
out.write(c);
|
||||
}
|
||||
|
||||
public void write(byte[] b)
|
||||
throws IOException
|
||||
{
|
||||
write(b, 0, b.length);
|
||||
}
|
||||
|
||||
public void write(byte[] b, int off, int len)
|
||||
throws IOException
|
||||
{
|
||||
if (transferComplete)
|
||||
{
|
||||
return;
|
||||
}
|
||||
out.write(b, off, len);
|
||||
}
|
||||
|
||||
}
|
||||
|
60
libjava/classpath/gnu/java/net/protocol/ftp/package.html
Normal file
60
libjava/classpath/gnu/java/net/protocol/ftp/package.html
Normal file
|
@ -0,0 +1,60 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<!-- package.html - describes classes in gnu.java.net.protocol.ftp package.
|
||||
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. -->
|
||||
|
||||
<html>
|
||||
<head><title>GNU Classpath - gnu.java.net.protocol.ftp</title></head>
|
||||
|
||||
<body>
|
||||
|
||||
<p>
|
||||
This package contains an FTP client. It can handle both active and passive
|
||||
mode connections and the various transfer modes and representation types.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Interaction with the server is via a simple stream interface. Only one
|
||||
concurrent stream (input or output) is supported.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The control connection to the server can be protected using TLS
|
||||
(the starttls method).
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,59 @@
|
|||
/* Authenticator.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 managing authentication.
|
||||
* @see Request#setAuthenticator
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public interface Authenticator
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the credentials to supply for the given realm.
|
||||
* @param realm the authentication realm
|
||||
* @param attempt zero on first authentication attempt, increments on each
|
||||
* unsuccessful attempt
|
||||
*/
|
||||
Credentials getCredentials(String realm, int attempt);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/* ByteArrayRequestBodyWriter.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;
|
||||
|
||||
/**
|
||||
* A simple request body writer using a byte array.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public class ByteArrayRequestBodyWriter
|
||||
implements RequestBodyWriter
|
||||
{
|
||||
|
||||
/**
|
||||
* The content.
|
||||
*/
|
||||
protected byte[] content;
|
||||
|
||||
/**
|
||||
* The position within the content at which the next read will occur.
|
||||
*/
|
||||
protected int pos;
|
||||
|
||||
/**
|
||||
* Constructs a new byte array request body writer with the specified
|
||||
* content.
|
||||
* @param content the content buffer
|
||||
*/
|
||||
public ByteArrayRequestBodyWriter(byte[] content)
|
||||
{
|
||||
this.content = content;
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total number of bytes that will be written in a single pass
|
||||
* by this writer.
|
||||
*/
|
||||
public int getContentLength()
|
||||
{
|
||||
return content.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises the writer.
|
||||
* This will be called before each pass.
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes body content to the supplied buffer.
|
||||
* @param buffer the content buffer
|
||||
* @return the number of bytes written
|
||||
*/
|
||||
public int write(byte[] buffer)
|
||||
{
|
||||
int len = content.length - pos;
|
||||
len = (buffer.length < len) ? buffer.length : len;
|
||||
if (len > -1)
|
||||
{
|
||||
System.arraycopy(content, pos, buffer, 0, len);
|
||||
pos += len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
/* 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
/* ChunkedInputStream.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;
|
||||
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.ProtocolException;
|
||||
|
||||
/**
|
||||
* Input stream wrapper for the "chunked" transfer-coding.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public class ChunkedInputStream
|
||||
extends FilterInputStream
|
||||
{
|
||||
|
||||
private static final byte CR = 0x0d;
|
||||
private static final byte LF = 0x0a;
|
||||
|
||||
int size;
|
||||
int count;
|
||||
boolean meta;
|
||||
boolean eof;
|
||||
Headers headers;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param in the response socket input stream
|
||||
* @param headers the headers to receive additional header lines
|
||||
*/
|
||||
public ChunkedInputStream(InputStream in, Headers headers)
|
||||
{
|
||||
super(in);
|
||||
this.headers = headers;
|
||||
size = -1;
|
||||
count = 0;
|
||||
meta = true;
|
||||
}
|
||||
|
||||
public int read()
|
||||
throws IOException
|
||||
{
|
||||
byte[] buf = new byte[1];
|
||||
int len = read(buf, 0, 1);
|
||||
if (len == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
int ret = (int) buf[0];
|
||||
if (ret < 0)
|
||||
{
|
||||
ret += 0x100;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int read(byte[] buffer)
|
||||
throws IOException
|
||||
{
|
||||
return read(buffer, 0, buffer.length);
|
||||
}
|
||||
|
||||
public int read(byte[] buffer, int offset, int length)
|
||||
throws IOException
|
||||
{
|
||||
if (eof)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (meta)
|
||||
{
|
||||
// Read chunk header
|
||||
int c, last = 0;
|
||||
boolean seenSemi = false;
|
||||
StringBuffer buf = new StringBuffer();
|
||||
do
|
||||
{
|
||||
c = in.read();
|
||||
if (c == 0x3b) // ;
|
||||
{
|
||||
seenSemi = true;
|
||||
}
|
||||
else if (c == 0x0a && last == 0x0d) // CRLF
|
||||
{
|
||||
size = Integer.parseInt(buf.toString(), 16);
|
||||
break;
|
||||
}
|
||||
else if (!seenSemi && c >= 0x30)
|
||||
{
|
||||
buf.append ((char) c);
|
||||
}
|
||||
last = c;
|
||||
}
|
||||
while(c != -1);
|
||||
count = 0;
|
||||
meta = false;
|
||||
}
|
||||
if (size == 0)
|
||||
{
|
||||
// Read trailer
|
||||
headers.parse(in);
|
||||
eof = true;
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int diff = length - offset;
|
||||
int max = size - count;
|
||||
max = (diff < max) ? diff : max;
|
||||
int len = (max > 0) ? in.read(buffer, offset, max) : 0;
|
||||
count += len;
|
||||
if (count == size)
|
||||
{
|
||||
// Read CRLF
|
||||
int c1 = in.read();
|
||||
int c2 = in.read();
|
||||
if (c1 == -1 && c2 == -1)
|
||||
{
|
||||
// EOF before CRLF: bad, but ignore
|
||||
eof = true;
|
||||
return -1;
|
||||
}
|
||||
if (c1 != 0x0d || c2 != 0x0a)
|
||||
{
|
||||
throw new ProtocolException("expecting CRLF: " + c1 + "," + c2);
|
||||
}
|
||||
meta = true;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
160
libjava/classpath/gnu/java/net/protocol/http/Cookie.java
Normal file
160
libjava/classpath/gnu/java/net/protocol/http/Cookie.java
Normal file
|
@ -0,0 +1,160 @@
|
|||
/* Cookie.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;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* An HTTP cookie, as specified in RFC 2109.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public class Cookie
|
||||
{
|
||||
|
||||
/**
|
||||
* The name of the cookie.
|
||||
*/
|
||||
protected final String name;
|
||||
|
||||
/**
|
||||
* The value of the cookie.
|
||||
*/
|
||||
protected final String value;
|
||||
|
||||
/**
|
||||
* Optional documentation of the intended use of the cookie.
|
||||
*/
|
||||
protected final String comment;
|
||||
|
||||
/**
|
||||
* The domain for which the cookie is valid.
|
||||
*/
|
||||
protected final String domain;
|
||||
|
||||
/**
|
||||
* Optional subset of URL paths within the domain for which the cookie is
|
||||
* valid.
|
||||
*/
|
||||
protected final String path;
|
||||
|
||||
/**
|
||||
* Indicates that the user-agent should only use secure means to transmit
|
||||
* this cookie to the server.
|
||||
*/
|
||||
protected final boolean secure;
|
||||
|
||||
/**
|
||||
* The date at which this cookie expires.
|
||||
*/
|
||||
protected final Date expires;
|
||||
|
||||
public Cookie(String name, String value, String comment, String domain,
|
||||
String path, boolean secure, Date expires)
|
||||
{
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.comment = comment;
|
||||
this.domain = domain;
|
||||
this.path = path;
|
||||
this.secure = secure;
|
||||
this.expires = expires;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getComment()
|
||||
{
|
||||
return comment;
|
||||
}
|
||||
|
||||
public String getDomain()
|
||||
{
|
||||
return domain;
|
||||
}
|
||||
|
||||
public String getPath()
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
public boolean isSecure()
|
||||
{
|
||||
return secure;
|
||||
}
|
||||
|
||||
public Date getExpiryDate()
|
||||
{
|
||||
return expires;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return toString(true, true);
|
||||
}
|
||||
|
||||
public String toString(boolean showPath, boolean showDomain)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(name);
|
||||
buf.append('=');
|
||||
buf.append(value);
|
||||
if (showPath)
|
||||
{
|
||||
buf.append("; $Path=");
|
||||
buf.append(path);
|
||||
}
|
||||
if (showDomain)
|
||||
{
|
||||
buf.append("; $Domain=");
|
||||
buf.append(domain);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/* CookieManager.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;
|
||||
|
||||
/**
|
||||
* Cookie manager interface.
|
||||
* If an application wants to handle cookies, they should implement this
|
||||
* interface and register the instance with each HTTPConnection they use.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public interface CookieManager
|
||||
{
|
||||
|
||||
/**
|
||||
* Stores a cookie in the cookie manager.
|
||||
* @param cookie the cookie to store
|
||||
*/
|
||||
void setCookie(Cookie cookie);
|
||||
|
||||
/**
|
||||
* Retrieves the cookies matching the specified criteria.
|
||||
* @param host the host name
|
||||
* @param secure whether the connection is secure
|
||||
* @param path the path to access
|
||||
*/
|
||||
Cookie[] getCookies(String host, boolean secure, String path);
|
||||
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/* Credentials.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;
|
||||
|
||||
/**
|
||||
* Represents a username/password combination that can be used to
|
||||
* authenticate to an HTTP server.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public class Credentials
|
||||
{
|
||||
|
||||
/**
|
||||
* The username.
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* The password.
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param username the username
|
||||
* @param password the password
|
||||
*/
|
||||
public Credentials(String username, String password)
|
||||
{
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the username.
|
||||
*/
|
||||
public String getUsername()
|
||||
{
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the password.
|
||||
*/
|
||||
public String getPassword()
|
||||
{
|
||||
return password;
|
||||
}
|
||||
|
||||
}
|
||||
|
681
libjava/classpath/gnu/java/net/protocol/http/HTTPConnection.java
Normal file
681
libjava/classpath/gnu/java/net/protocol/http/HTTPConnection.java
Normal file
|
@ -0,0 +1,681 @@
|
|||
/* HTTPConnection.java --
|
||||
Copyright (C) 2004, 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 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;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.net.ssl.HandshakeCompletedListener;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
|
||||
/**
|
||||
* A connection to an HTTP server.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public class HTTPConnection
|
||||
{
|
||||
|
||||
/**
|
||||
* The default HTTP port.
|
||||
*/
|
||||
public static final int HTTP_PORT = 80;
|
||||
|
||||
/**
|
||||
* The default HTTPS port.
|
||||
*/
|
||||
public static final int HTTPS_PORT = 443;
|
||||
|
||||
private static final String userAgent = SystemProperties.getProperty("http.agent");
|
||||
|
||||
/**
|
||||
* The host name of the server to connect to.
|
||||
*/
|
||||
protected final String hostname;
|
||||
|
||||
/**
|
||||
* The port to connect to.
|
||||
*/
|
||||
protected final int port;
|
||||
|
||||
/**
|
||||
* Whether the connection should use transport level security (HTTPS).
|
||||
*/
|
||||
protected final boolean secure;
|
||||
|
||||
/**
|
||||
* The connection timeout for connecting the underlying socket.
|
||||
*/
|
||||
protected final int connectionTimeout;
|
||||
|
||||
/**
|
||||
* The read timeout for reads on the underlying socket.
|
||||
*/
|
||||
protected final int timeout;
|
||||
|
||||
/**
|
||||
* The host name of the proxy to connect to.
|
||||
*/
|
||||
protected String proxyHostname;
|
||||
|
||||
/**
|
||||
* The port on the proxy to connect to.
|
||||
*/
|
||||
protected int proxyPort;
|
||||
|
||||
/**
|
||||
* The major version of HTTP supported by this client.
|
||||
*/
|
||||
protected int majorVersion;
|
||||
|
||||
/**
|
||||
* The minor version of HTTP supported by this client.
|
||||
*/
|
||||
protected int minorVersion;
|
||||
|
||||
private final List connectionListeners;
|
||||
private final List requestListeners;
|
||||
private final List handshakeCompletedListeners;
|
||||
|
||||
/**
|
||||
* The socket this connection communicates on.
|
||||
*/
|
||||
protected Socket socket;
|
||||
|
||||
/**
|
||||
* The SSL socket factory to use.
|
||||
*/
|
||||
private SSLSocketFactory sslSocketFactory;
|
||||
|
||||
/**
|
||||
* The socket input stream.
|
||||
*/
|
||||
protected InputStream in;
|
||||
|
||||
/**
|
||||
* The socket output stream.
|
||||
*/
|
||||
protected OutputStream out;
|
||||
|
||||
/**
|
||||
* Nonce values seen by this connection.
|
||||
*/
|
||||
private Map nonceCounts;
|
||||
|
||||
/**
|
||||
* The cookie manager for this connection.
|
||||
*/
|
||||
protected CookieManager cookieManager;
|
||||
|
||||
/**
|
||||
* Creates a new HTTP connection.
|
||||
* @param hostname the name of the host to connect to
|
||||
*/
|
||||
public HTTPConnection(String hostname)
|
||||
{
|
||||
this(hostname, HTTP_PORT, false, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new HTTP or HTTPS connection.
|
||||
* @param hostname the name of the host to connect to
|
||||
* @param secure whether to use a secure connection
|
||||
*/
|
||||
public HTTPConnection(String hostname, boolean secure)
|
||||
{
|
||||
this(hostname, secure ? HTTPS_PORT : HTTP_PORT, secure, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new HTTP or HTTPS connection on the specified port.
|
||||
* @param hostname the name of the host to connect to
|
||||
* @param secure whether to use a secure connection
|
||||
* @param connectionTimeout the connection timeout
|
||||
* @param timeout the socket read timeout
|
||||
*/
|
||||
public HTTPConnection(String hostname, boolean secure,
|
||||
int connectionTimeout, int timeout)
|
||||
{
|
||||
this(hostname, secure ? HTTPS_PORT : HTTP_PORT, secure,
|
||||
connectionTimeout, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new HTTP connection on the specified port.
|
||||
* @param hostname the name of the host to connect to
|
||||
* @param port the port on the host to connect to
|
||||
*/
|
||||
public HTTPConnection(String hostname, int port)
|
||||
{
|
||||
this(hostname, port, false, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new HTTP or HTTPS connection on the specified port.
|
||||
* @param hostname the name of the host to connect to
|
||||
* @param port the port on the host to connect to
|
||||
* @param secure whether to use a secure connection
|
||||
*/
|
||||
public HTTPConnection(String hostname, int port, boolean secure)
|
||||
{
|
||||
this(hostname, port, secure, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new HTTP or HTTPS connection on the specified port.
|
||||
* @param hostname the name of the host to connect to
|
||||
* @param port the port on the host to connect to
|
||||
* @param secure whether to use a secure connection
|
||||
* @param connectionTimeout the connection timeout
|
||||
* @param timeout the socket read timeout
|
||||
*/
|
||||
public HTTPConnection(String hostname, int port, boolean secure,
|
||||
int connectionTimeout, int timeout)
|
||||
{
|
||||
this.hostname = hostname;
|
||||
this.port = port;
|
||||
this.secure = secure;
|
||||
this.connectionTimeout = connectionTimeout;
|
||||
this.timeout = timeout;
|
||||
majorVersion = minorVersion = 1;
|
||||
connectionListeners = new ArrayList(4);
|
||||
requestListeners = new ArrayList(4);
|
||||
handshakeCompletedListeners = new ArrayList(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the host to connect to.
|
||||
*/
|
||||
public String getHostName()
|
||||
{
|
||||
return hostname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the port on the host to connect to.
|
||||
*/
|
||||
public int getPort()
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether to use a secure connection or not.
|
||||
*/
|
||||
public boolean isSecure()
|
||||
{
|
||||
return secure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTTP version string supported by this connection.
|
||||
* @see #version
|
||||
*/
|
||||
public String getVersion()
|
||||
{
|
||||
return "HTTP/" + majorVersion + '.' + minorVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the HTTP version supported by this connection.
|
||||
* @param majorVersion the major version
|
||||
* @param minorVersion the minor version
|
||||
*/
|
||||
public void setVersion(int majorVersion, int minorVersion)
|
||||
{
|
||||
if (majorVersion != 1)
|
||||
{
|
||||
throw new IllegalArgumentException("major version not supported: " +
|
||||
majorVersion);
|
||||
}
|
||||
if (minorVersion < 0 || minorVersion > 1)
|
||||
{
|
||||
throw new IllegalArgumentException("minor version not supported: " +
|
||||
minorVersion);
|
||||
}
|
||||
this.majorVersion = majorVersion;
|
||||
this.minorVersion = minorVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Directs this connection to use the specified proxy.
|
||||
* @param hostname the proxy host name
|
||||
* @param port the port on the proxy to connect to
|
||||
*/
|
||||
public void setProxy(String hostname, int port)
|
||||
{
|
||||
proxyHostname = hostname;
|
||||
proxyPort = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this connection is using an HTTP proxy.
|
||||
*/
|
||||
public boolean isUsingProxy()
|
||||
{
|
||||
return (proxyHostname != null && proxyPort > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cookie manager to use for this connection.
|
||||
* @param cookieManager the cookie manager
|
||||
*/
|
||||
public void setCookieManager(CookieManager cookieManager)
|
||||
{
|
||||
this.cookieManager = cookieManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cookie manager in use for this connection.
|
||||
*/
|
||||
public CookieManager getCookieManager()
|
||||
{
|
||||
return cookieManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new request using this connection.
|
||||
* @param method the HTTP method to invoke
|
||||
* @param path the URI-escaped RFC2396 <code>abs_path</code> with
|
||||
* optional query part
|
||||
*/
|
||||
public Request newRequest(String method, String path)
|
||||
{
|
||||
if (method == null || method.length() == 0)
|
||||
{
|
||||
throw new IllegalArgumentException("method must have non-zero length");
|
||||
}
|
||||
if (path == null || path.length() == 0)
|
||||
{
|
||||
path = "/";
|
||||
}
|
||||
Request ret = new Request(this, method, path);
|
||||
if ((secure && port != HTTPS_PORT) ||
|
||||
(!secure && port != HTTP_PORT))
|
||||
{
|
||||
ret.setHeader("Host", hostname + ":" + port);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.setHeader("Host", hostname);
|
||||
}
|
||||
ret.setHeader("User-Agent", userAgent);
|
||||
ret.setHeader("Connection", "keep-alive");
|
||||
ret.setHeader("Accept-Encoding",
|
||||
"chunked;q=1.0, gzip;q=0.9, deflate;q=0.8, " +
|
||||
"identity;q=0.6, *;q=0");
|
||||
if (cookieManager != null)
|
||||
{
|
||||
Cookie[] cookies = cookieManager.getCookies(hostname, secure, path);
|
||||
if (cookies != null && cookies.length > 0)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append("$Version=1");
|
||||
for (int i = 0; i < cookies.length; i++)
|
||||
{
|
||||
buf.append(',');
|
||||
buf.append(' ');
|
||||
buf.append(cookies[i].toString());
|
||||
}
|
||||
ret.setHeader("Cookie", buf.toString());
|
||||
}
|
||||
}
|
||||
fireRequestEvent(RequestEvent.REQUEST_CREATED, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes this connection.
|
||||
*/
|
||||
public void close()
|
||||
throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
closeConnection();
|
||||
}
|
||||
finally
|
||||
{
|
||||
fireConnectionEvent(ConnectionEvent.CONNECTION_CLOSED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the socket associated with this connection.
|
||||
* This creates the socket if necessary.
|
||||
*/
|
||||
protected synchronized Socket getSocket()
|
||||
throws IOException
|
||||
{
|
||||
if (socket == null)
|
||||
{
|
||||
String connectHostname = hostname;
|
||||
int connectPort = port;
|
||||
if (isUsingProxy())
|
||||
{
|
||||
connectHostname = proxyHostname;
|
||||
connectPort = proxyPort;
|
||||
}
|
||||
socket = new Socket();
|
||||
InetSocketAddress address =
|
||||
new InetSocketAddress(connectHostname, connectPort);
|
||||
if (connectionTimeout > 0)
|
||||
{
|
||||
socket.connect(address, connectionTimeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
socket.connect(address);
|
||||
}
|
||||
if (timeout > 0)
|
||||
{
|
||||
socket.setSoTimeout(timeout);
|
||||
}
|
||||
if (secure)
|
||||
{
|
||||
try
|
||||
{
|
||||
SSLSocketFactory factory = getSSLSocketFactory();
|
||||
SSLSocket ss =
|
||||
(SSLSocket) factory.createSocket(socket, connectHostname,
|
||||
connectPort, true);
|
||||
String[] protocols = { "TLSv1", "SSLv3" };
|
||||
ss.setEnabledProtocols(protocols);
|
||||
ss.setUseClientMode(true);
|
||||
synchronized (handshakeCompletedListeners)
|
||||
{
|
||||
if (!handshakeCompletedListeners.isEmpty())
|
||||
{
|
||||
for (Iterator i =
|
||||
handshakeCompletedListeners.iterator();
|
||||
i.hasNext(); )
|
||||
{
|
||||
HandshakeCompletedListener l =
|
||||
(HandshakeCompletedListener) i.next();
|
||||
ss.addHandshakeCompletedListener(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
ss.startHandshake();
|
||||
socket = ss;
|
||||
}
|
||||
catch (GeneralSecurityException e)
|
||||
{
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
}
|
||||
in = socket.getInputStream();
|
||||
in = new BufferedInputStream(in);
|
||||
out = socket.getOutputStream();
|
||||
out = new BufferedOutputStream(out);
|
||||
}
|
||||
return socket;
|
||||
}
|
||||
|
||||
SSLSocketFactory getSSLSocketFactory()
|
||||
throws GeneralSecurityException
|
||||
{
|
||||
if (sslSocketFactory == null)
|
||||
{
|
||||
TrustManager tm = new EmptyX509TrustManager();
|
||||
SSLContext context = SSLContext.getInstance("SSL");
|
||||
TrustManager[] trust = new TrustManager[] { tm };
|
||||
context.init(null, trust, null);
|
||||
sslSocketFactory = context.getSocketFactory();
|
||||
}
|
||||
return sslSocketFactory;
|
||||
}
|
||||
|
||||
void setSSLSocketFactory(SSLSocketFactory factory)
|
||||
{
|
||||
sslSocketFactory = factory;
|
||||
}
|
||||
|
||||
protected synchronized InputStream getInputStream()
|
||||
throws IOException
|
||||
{
|
||||
if (socket == null)
|
||||
{
|
||||
getSocket();
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
protected synchronized OutputStream getOutputStream()
|
||||
throws IOException
|
||||
{
|
||||
if (socket == null)
|
||||
{
|
||||
getSocket();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the underlying socket, if any.
|
||||
*/
|
||||
protected synchronized void closeConnection()
|
||||
throws IOException
|
||||
{
|
||||
if (socket != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
socket.close();
|
||||
}
|
||||
finally
|
||||
{
|
||||
socket = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a URI representing the connection.
|
||||
* This does not include any request path component.
|
||||
*/
|
||||
protected String getURI()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(secure ? "https://" : "http://");
|
||||
buf.append(hostname);
|
||||
if (secure)
|
||||
{
|
||||
if (port != HTTPConnection.HTTPS_PORT)
|
||||
{
|
||||
buf.append(':');
|
||||
buf.append(port);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (port != HTTPConnection.HTTP_PORT)
|
||||
{
|
||||
buf.append(':');
|
||||
buf.append(port);
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of times the specified nonce has been seen by this
|
||||
* connection.
|
||||
*/
|
||||
int getNonceCount(String nonce)
|
||||
{
|
||||
if (nonceCounts == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return((Integer) nonceCounts.get(nonce)).intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the number of times the specified nonce has been seen.
|
||||
*/
|
||||
void incrementNonce(String nonce)
|
||||
{
|
||||
int current = getNonceCount(nonce);
|
||||
if (nonceCounts == null)
|
||||
{
|
||||
nonceCounts = new HashMap();
|
||||
}
|
||||
nonceCounts.put(nonce, new Integer(current + 1));
|
||||
}
|
||||
|
||||
// -- 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)
|
||||
{
|
||||
handshakeCompletedListeners.add(l);
|
||||
}
|
||||
}
|
||||
void removeHandshakeCompletedListener(HandshakeCompletedListener l)
|
||||
{
|
||||
synchronized (handshakeCompletedListeners)
|
||||
{
|
||||
handshakeCompletedListeners.remove(l);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
441
libjava/classpath/gnu/java/net/protocol/http/HTTPDateFormat.java
Normal file
441
libjava/classpath/gnu/java/net/protocol/http/HTTPDateFormat.java
Normal file
|
@ -0,0 +1,441 @@
|
|||
/* HTTPDateFormat.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;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.FieldPosition;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParsePosition;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* HTTP date formatter and parser.
|
||||
* Formats dates according to RFC 822 (updated by RFC 1123).
|
||||
* Parses dates according to the above, <i>or</i> RFC 1036, <i>or</i> the
|
||||
* ANSI C <code>asctime()</code> format.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public class HTTPDateFormat
|
||||
extends DateFormat
|
||||
{
|
||||
|
||||
static final String[] DAYS_OF_WEEK = {
|
||||
null, "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||
};
|
||||
|
||||
static final String[] MONTHS = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
public HTTPDateFormat()
|
||||
{
|
||||
calendar = new GregorianCalendar(TimeZone.getTimeZone ("GMT"));
|
||||
numberFormat = new DecimalFormat();
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the textual value for the specified field to the given string
|
||||
* buffer. This method should be avoided, use <code>format(Date)</code>
|
||||
* instead.
|
||||
* @param date the Date object
|
||||
* @param buf the buffer to append to
|
||||
* @param field the current field position
|
||||
* @return the modified buffer
|
||||
*/
|
||||
public StringBuffer format(Date date, StringBuffer buf,
|
||||
FieldPosition field)
|
||||
{
|
||||
calendar.clear();
|
||||
calendar.setTime(date);
|
||||
buf.setLength(0);
|
||||
|
||||
// Day of week
|
||||
buf.append(DAYS_OF_WEEK[calendar.get(Calendar.DAY_OF_WEEK)]);
|
||||
buf.append(',');
|
||||
buf.append(' ');
|
||||
|
||||
// Day of month
|
||||
int day = calendar.get(Calendar.DAY_OF_MONTH);
|
||||
buf.append(Character.forDigit(day / 10, 10));
|
||||
buf.append(Character.forDigit(day % 10, 10));
|
||||
buf.append(' ');
|
||||
|
||||
// Month
|
||||
buf.append(MONTHS[calendar.get(Calendar.MONTH)]);
|
||||
buf.append(' ');
|
||||
|
||||
// Year
|
||||
int year = calendar.get(Calendar.YEAR);
|
||||
if (year < 1000)
|
||||
{
|
||||
buf.append('0');
|
||||
if (year < 100)
|
||||
{
|
||||
buf.append('0');
|
||||
if (year < 10)
|
||||
{
|
||||
buf.append('0');
|
||||
}
|
||||
}
|
||||
}
|
||||
buf.append(Integer.toString(year));
|
||||
buf.append(' ');
|
||||
|
||||
// Hour
|
||||
int hour = calendar.get(Calendar.HOUR_OF_DAY);
|
||||
buf.append(Character.forDigit(hour / 10, 10));
|
||||
buf.append(Character.forDigit(hour % 10, 10));
|
||||
buf.append(':');
|
||||
|
||||
// Minute
|
||||
int minute = calendar.get(Calendar.MINUTE);
|
||||
buf.append(Character.forDigit(minute / 10, 10));
|
||||
buf.append(Character.forDigit(minute % 10, 10));
|
||||
buf.append(':');
|
||||
|
||||
// Second
|
||||
int second = calendar.get(Calendar.SECOND);
|
||||
buf.append(Character.forDigit(second / 10, 10));
|
||||
buf.append(Character.forDigit(second % 10, 10));
|
||||
buf.append(' ');
|
||||
|
||||
// Timezone
|
||||
// Get time offset in minutes
|
||||
int zoneOffset =(calendar.get(Calendar.ZONE_OFFSET) +
|
||||
calendar.get(Calendar.DST_OFFSET)) / 60000;
|
||||
|
||||
// Apply + or - appropriately
|
||||
if (zoneOffset < 0)
|
||||
{
|
||||
zoneOffset = -zoneOffset;
|
||||
buf.append('-');
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.append('+');
|
||||
}
|
||||
|
||||
// Set the 2 2-char fields as specified above
|
||||
int tzhours = zoneOffset / 60;
|
||||
buf.append(Character.forDigit(tzhours / 10, 10));
|
||||
buf.append(Character.forDigit(tzhours % 10, 10));
|
||||
int tzminutes = zoneOffset % 60;
|
||||
buf.append(Character.forDigit(tzminutes / 10, 10));
|
||||
buf.append(Character.forDigit(tzminutes % 10, 10));
|
||||
|
||||
field.setBeginIndex(0);
|
||||
field.setEndIndex(buf.length());
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given date in the current TimeZone.
|
||||
* @param text the formatted date to be parsed
|
||||
* @param pos the current parse position
|
||||
*/
|
||||
public Date parse(String text, ParsePosition pos)
|
||||
{
|
||||
int date, month, year, hour, minute, second;
|
||||
String monthText;
|
||||
int start = 0, end = -1;
|
||||
int len = text.length();
|
||||
calendar.clear();
|
||||
pos.setIndex(start);
|
||||
try
|
||||
{
|
||||
// Advance to date
|
||||
if (Character.isLetter(text.charAt(start)))
|
||||
{
|
||||
start = skipNonWhitespace(text, start);
|
||||
}
|
||||
// Determine mode
|
||||
switch(start)
|
||||
{
|
||||
case 3:
|
||||
// asctime
|
||||
start = skipWhitespace(text, start);
|
||||
pos.setIndex(start);
|
||||
end = skipNonWhitespace(text, start + 1);
|
||||
monthText = text.substring(start, end);
|
||||
month = -1;
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
if (MONTHS[i].equals(monthText))
|
||||
{
|
||||
month = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (month == -1)
|
||||
{
|
||||
pos.setErrorIndex(end);
|
||||
return null;
|
||||
}
|
||||
// Advance to date
|
||||
start = skipWhitespace(text, end + 1);
|
||||
pos.setIndex(start);
|
||||
end = skipNonWhitespace(text, start + 1);
|
||||
date = Integer.parseInt(text.substring(start, end));
|
||||
// Advance to hour
|
||||
start = skipWhitespace(text, end + 1);
|
||||
pos.setIndex(start);
|
||||
end = skipTo(text, start + 1, ':');
|
||||
hour = Integer.parseInt(text.substring(start, end));
|
||||
// Advance to minute
|
||||
start = end + 1;
|
||||
pos.setIndex(start);
|
||||
end = skipTo(text, start + 1, ':');
|
||||
minute = Integer.parseInt(text.substring(start, end));
|
||||
// Advance to second
|
||||
start = end + 1;
|
||||
pos.setIndex(start);
|
||||
end = skipNonWhitespace(text, start + 1);
|
||||
second = Integer.parseInt(text.substring(start, end));
|
||||
// Advance to year
|
||||
start = skipWhitespace(text, end + 1);
|
||||
pos.setIndex(start);
|
||||
end = skipNonWhitespace(text, start + 1);
|
||||
year = Integer.parseInt(text.substring(start, end));
|
||||
break;
|
||||
case 0:
|
||||
case 4:
|
||||
// rfc822
|
||||
start = skipWhitespace(text, start);
|
||||
pos.setIndex(start);
|
||||
end = skipNonWhitespace(text, start + 1);
|
||||
date = Integer.parseInt(text.substring(start, end));
|
||||
// Advance to month
|
||||
start = skipWhitespace(text, end + 1);
|
||||
pos.setIndex(start);
|
||||
end = skipNonWhitespace(text, start + 1);
|
||||
monthText = text.substring(start, end);
|
||||
month = -1;
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
if (MONTHS[i].equals(monthText))
|
||||
{
|
||||
month = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (month == -1)
|
||||
{
|
||||
pos.setErrorIndex(end);
|
||||
return null;
|
||||
}
|
||||
// Advance to year
|
||||
start = skipWhitespace(text, end + 1);
|
||||
pos.setIndex(start);
|
||||
end = skipNonWhitespace(text, start + 1);
|
||||
year = Integer.parseInt(text.substring(start, end));
|
||||
// Advance to hour
|
||||
start = skipWhitespace(text, end + 1);
|
||||
pos.setIndex(start);
|
||||
end = skipTo(text, start + 1, ':');
|
||||
hour = Integer.parseInt(text.substring(start, end));
|
||||
// Advance to minute
|
||||
start = end + 1;
|
||||
pos.setIndex(start);
|
||||
end = skipTo(text, start + 1, ':');
|
||||
minute = Integer.parseInt(text.substring(start, end));
|
||||
// Advance to second
|
||||
start = end + 1;
|
||||
pos.setIndex(start);
|
||||
end = start + 1;
|
||||
while (end < len && !Character.isWhitespace(text.charAt(end)))
|
||||
{
|
||||
end++;
|
||||
}
|
||||
second = Integer.parseInt(text.substring(start, end));
|
||||
break;
|
||||
default:
|
||||
// rfc850(obsolete)
|
||||
start = skipWhitespace(text, start);
|
||||
pos.setIndex(start);
|
||||
end = skipTo(text, start + 1, '-');
|
||||
date = Integer.parseInt(text.substring(start, end));
|
||||
// Advance to month
|
||||
start = end + 1;
|
||||
pos.setIndex(start);
|
||||
end = skipTo(text, start + 1, '-');
|
||||
monthText = text.substring(start, end);
|
||||
month = -1;
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
if (MONTHS[i].equals(monthText))
|
||||
{
|
||||
month = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (month == -1)
|
||||
{
|
||||
pos.setErrorIndex(end);
|
||||
return null;
|
||||
}
|
||||
// Advance to year
|
||||
start = end + 1;
|
||||
pos.setIndex(start);
|
||||
end = skipNonWhitespace(text, start + 1);
|
||||
year = 1900 + Integer.parseInt(text.substring(start, end));
|
||||
// Advance to hour
|
||||
start = skipWhitespace(text, end + 1);
|
||||
pos.setIndex(start);
|
||||
end = skipTo(text, start + 1, ':');
|
||||
hour = Integer.parseInt(text.substring(start, end));
|
||||
// Advance to minute
|
||||
start = end + 1;
|
||||
pos.setIndex(start);
|
||||
end = skipTo(text, start + 1, ':');
|
||||
minute = Integer.parseInt(text.substring(start, end));
|
||||
// Advance to second
|
||||
start = end + 1;
|
||||
pos.setIndex(start);
|
||||
end = start + 1;
|
||||
while (end < len && !Character.isWhitespace(text.charAt(end)))
|
||||
{
|
||||
end++;
|
||||
}
|
||||
second = Integer.parseInt(text.substring(start, end));
|
||||
}
|
||||
|
||||
calendar.set(Calendar.YEAR, year);
|
||||
calendar.set(Calendar.MONTH, month);
|
||||
calendar.set(Calendar.DAY_OF_MONTH, date);
|
||||
calendar.set(Calendar.HOUR, hour);
|
||||
calendar.set(Calendar.MINUTE, minute);
|
||||
calendar.set(Calendar.SECOND, second);
|
||||
|
||||
if (end != len)
|
||||
{
|
||||
// Timezone
|
||||
start = skipWhitespace(text, end + 1);
|
||||
end = start + 1;
|
||||
while (end < len && !Character.isWhitespace(text.charAt(end)))
|
||||
{
|
||||
end++;
|
||||
}
|
||||
char pm = text.charAt(start);
|
||||
if (Character.isLetter(pm))
|
||||
{
|
||||
TimeZone tz =
|
||||
TimeZone.getTimeZone(text.substring(start, end));
|
||||
calendar.set(Calendar.ZONE_OFFSET, tz.getRawOffset());
|
||||
}
|
||||
else
|
||||
{
|
||||
int zoneOffset = 0;
|
||||
zoneOffset += 600 * Character.digit(text.charAt(++start), 10);
|
||||
zoneOffset += 60 * Character.digit(text.charAt(++start), 10);
|
||||
zoneOffset += 10 * Character.digit(text.charAt(++start), 10);
|
||||
zoneOffset += Character.digit(text.charAt(++start), 10);
|
||||
zoneOffset *= 60000; // minutes -> ms
|
||||
if ('-' == pm)
|
||||
{
|
||||
zoneOffset = -zoneOffset;
|
||||
}
|
||||
calendar.set(Calendar.ZONE_OFFSET, zoneOffset);
|
||||
}
|
||||
}
|
||||
pos.setIndex(end);
|
||||
|
||||
return calendar.getTime();
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
pos.setErrorIndex(Math.max(start, end));
|
||||
}
|
||||
catch (StringIndexOutOfBoundsException e)
|
||||
{
|
||||
pos.setErrorIndex(Math.max(start, end));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private int skipWhitespace(String text, int pos)
|
||||
{
|
||||
while(Character.isWhitespace(text.charAt(pos)))
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
private int skipNonWhitespace(String text, int pos)
|
||||
{
|
||||
while(!Character.isWhitespace(text.charAt(pos)))
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
private int skipTo(String text, int pos, char c)
|
||||
{
|
||||
while(text.charAt(pos) != c)
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't allow setting the calendar.
|
||||
*/
|
||||
public void setCalendar(Calendar newCalendar)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't allow setting the NumberFormat.
|
||||
*/
|
||||
public void setNumberFormat(NumberFormat newNumberFormat)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,688 @@
|
|||
/* HTTPURLConnection.java --
|
||||
Copyright (C) 2004, 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.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.URL;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.net.ssl.HandshakeCompletedEvent;
|
||||
import javax.net.ssl.HandshakeCompletedListener;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
/**
|
||||
* A URLConnection that uses the HTTPConnection class.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public class HTTPURLConnection
|
||||
extends HttpsURLConnection
|
||||
implements HandshakeCompletedListener
|
||||
{
|
||||
|
||||
/**
|
||||
* Pool of reusable connections, used if keepAlive is true.
|
||||
*/
|
||||
private static final Map connectionPool = new LinkedHashMap();
|
||||
|
||||
/*
|
||||
* The underlying connection.
|
||||
*/
|
||||
private HTTPConnection connection;
|
||||
|
||||
// These are package private for use in anonymous inner classes.
|
||||
String proxyHostname;
|
||||
int proxyPort;
|
||||
String agent;
|
||||
boolean keepAlive;
|
||||
int maxConnections;
|
||||
|
||||
private Request request;
|
||||
private Headers requestHeaders;
|
||||
private ByteArrayOutputStream requestSink;
|
||||
private boolean requestMethodSetExplicitly;
|
||||
|
||||
private Response response;
|
||||
private ByteArrayInputStream responseSink;
|
||||
private ByteArrayInputStream errorSink;
|
||||
|
||||
private HandshakeCompletedEvent handshakeEvent;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param url the URL
|
||||
*/
|
||||
public HTTPURLConnection(URL url)
|
||||
throws IOException
|
||||
{
|
||||
super(url);
|
||||
requestHeaders = new Headers();
|
||||
AccessController.doPrivileged(this.new GetHTTPPropertiesAction());
|
||||
}
|
||||
|
||||
class GetHTTPPropertiesAction
|
||||
implements PrivilegedAction
|
||||
{
|
||||
|
||||
public Object run()
|
||||
{
|
||||
proxyHostname = System.getProperty("http.proxyHost");
|
||||
if (proxyHostname != null && proxyHostname.length() > 0)
|
||||
{
|
||||
String port = System.getProperty("http.proxyPort");
|
||||
if (port != null && port.length() > 0)
|
||||
{
|
||||
proxyPort = Integer.parseInt(port);
|
||||
}
|
||||
else
|
||||
{
|
||||
proxyHostname = null;
|
||||
proxyPort = -1;
|
||||
}
|
||||
}
|
||||
agent = System.getProperty("http.agent");
|
||||
String ka = System.getProperty("http.keepAlive");
|
||||
keepAlive = !(ka != null && "false".equals(ka));
|
||||
String mc = System.getProperty("http.maxConnections");
|
||||
maxConnections = (mc != null && mc.length() > 0) ?
|
||||
Math.max(Integer.parseInt(mc), 1) : 5;
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void connect()
|
||||
throws IOException
|
||||
{
|
||||
if (connected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
String protocol = url.getProtocol();
|
||||
boolean secure = "https".equals(protocol);
|
||||
String host = url.getHost();
|
||||
int port = url.getPort();
|
||||
if (port < 0)
|
||||
{
|
||||
port = secure ? HTTPConnection.HTTPS_PORT :
|
||||
HTTPConnection.HTTP_PORT;
|
||||
}
|
||||
String file = url.getFile();
|
||||
String username = url.getUserInfo();
|
||||
String password = null;
|
||||
if (username != null)
|
||||
{
|
||||
int ci = username.indexOf(':');
|
||||
if (ci != -1)
|
||||
{
|
||||
password = username.substring(ci + 1);
|
||||
username = username.substring(0, ci);
|
||||
}
|
||||
}
|
||||
final Credentials creds = (username == null) ? null :
|
||||
new Credentials (username, password);
|
||||
|
||||
boolean retry;
|
||||
do
|
||||
{
|
||||
retry = false;
|
||||
if (connection == null)
|
||||
{
|
||||
connection = getConnection(host, port, secure);
|
||||
if (secure)
|
||||
{
|
||||
SSLSocketFactory factory = getSSLSocketFactory();
|
||||
HostnameVerifier verifier = getHostnameVerifier();
|
||||
if (factory != null)
|
||||
{
|
||||
connection.setSSLSocketFactory(factory);
|
||||
}
|
||||
connection.addHandshakeCompletedListener(this);
|
||||
// TODO verifier
|
||||
}
|
||||
}
|
||||
if (proxyHostname != null)
|
||||
{
|
||||
if (proxyPort < 0)
|
||||
{
|
||||
proxyPort = secure ? HTTPConnection.HTTPS_PORT :
|
||||
HTTPConnection.HTTP_PORT;
|
||||
}
|
||||
connection.setProxy(proxyHostname, proxyPort);
|
||||
}
|
||||
request = connection.newRequest(method, file);
|
||||
if (!keepAlive)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return (attempts < 2) ? creds : null;
|
||||
}
|
||||
});
|
||||
}
|
||||
response = request.dispatch();
|
||||
if (response.getCodeClass() == 3 && getInstanceFollowRedirects())
|
||||
{
|
||||
// Follow redirect
|
||||
String location = response.getHeader("Location");
|
||||
if (location != null)
|
||||
{
|
||||
String connectionUri = connection.getURI();
|
||||
int start = connectionUri.length();
|
||||
if (location.startsWith(connectionUri) &&
|
||||
location.charAt(start) == '/')
|
||||
{
|
||||
file = location.substring(start);
|
||||
retry = true;
|
||||
}
|
||||
else if (location.startsWith("http:"))
|
||||
{
|
||||
connection.close();
|
||||
connection = null;
|
||||
secure = false;
|
||||
start = 7;
|
||||
int end = location.indexOf('/', start);
|
||||
host = location.substring(start, end);
|
||||
int ci = host.lastIndexOf(':');
|
||||
if (ci != -1)
|
||||
{
|
||||
port = Integer.parseInt(host.substring (ci + 1));
|
||||
host = host.substring(0, ci);
|
||||
}
|
||||
else
|
||||
{
|
||||
port = HTTPConnection.HTTP_PORT;
|
||||
}
|
||||
file = location.substring(end);
|
||||
retry = true;
|
||||
}
|
||||
else if (location.startsWith("https:"))
|
||||
{
|
||||
connection.close();
|
||||
connection = null;
|
||||
secure = true;
|
||||
start = 8;
|
||||
int end = location.indexOf('/', start);
|
||||
host = location.substring(start, end);
|
||||
int ci = host.lastIndexOf(':');
|
||||
if (ci != -1)
|
||||
{
|
||||
port = Integer.parseInt(host.substring (ci + 1));
|
||||
host = host.substring(0, ci);
|
||||
}
|
||||
else
|
||||
{
|
||||
port = HTTPConnection.HTTPS_PORT;
|
||||
}
|
||||
file = location.substring(end);
|
||||
retry = true;
|
||||
}
|
||||
else if (location.length() > 0)
|
||||
{
|
||||
// Malformed absolute URI, treat as file part of URI
|
||||
if (location.charAt(0) == '/')
|
||||
{
|
||||
// Absolute path
|
||||
file = location;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Relative path
|
||||
int lsi = file.lastIndexOf('/');
|
||||
file = (lsi == -1) ? "/" : file.substring(0, lsi + 1);
|
||||
file += location;
|
||||
}
|
||||
retry = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
responseSink = new ByteArrayInputStream(reader.toByteArray ());
|
||||
if (response.getCode() == 404)
|
||||
{
|
||||
errorSink = responseSink;
|
||||
throw new FileNotFoundException(url.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
while (retry);
|
||||
connected = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a connection, from the pool if necessary.
|
||||
*/
|
||||
HTTPConnection getConnection(String host, int port, boolean secure)
|
||||
throws IOException
|
||||
{
|
||||
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();
|
||||
synchronized (connectionPool)
|
||||
{
|
||||
connection = (HTTPConnection) connectionPool.get(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
connection = new HTTPConnection(host, port, secure);
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
public void disconnect()
|
||||
{
|
||||
if (connection != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
connection.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean usingProxy()
|
||||
{
|
||||
return (proxyHostname != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the corresponding method in HttpURLConnection to permit
|
||||
* arbitrary methods, as long as they're valid ASCII alphabetic
|
||||
* characters. This is to permit WebDAV and other HTTP extensions to
|
||||
* function.
|
||||
* @param method the method
|
||||
*/
|
||||
public void setRequestMethod(String method)
|
||||
throws ProtocolException
|
||||
{
|
||||
if (connected)
|
||||
{
|
||||
throw new ProtocolException("Already connected");
|
||||
}
|
||||
// Validate
|
||||
method = method.toUpperCase();
|
||||
int len = method.length();
|
||||
if (len == 0)
|
||||
{
|
||||
throw new ProtocolException("Empty method name");
|
||||
}
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
char c = method.charAt(i);
|
||||
if (c < 0x41 || c > 0x5a)
|
||||
{
|
||||
throw new ProtocolException("Illegal character '" + c +
|
||||
"' at index " + i);
|
||||
}
|
||||
}
|
||||
// OK
|
||||
this.method = method;
|
||||
requestMethodSetExplicitly = true;
|
||||
}
|
||||
|
||||
public String getRequestProperty(String key)
|
||||
{
|
||||
return requestHeaders.getValue(key);
|
||||
}
|
||||
|
||||
public Map getRequestProperties()
|
||||
{
|
||||
return requestHeaders;
|
||||
}
|
||||
|
||||
public void setRequestProperty(String key, String value)
|
||||
{
|
||||
requestHeaders.put(key, value);
|
||||
}
|
||||
|
||||
public void addRequestProperty(String key, String value)
|
||||
{
|
||||
String old = requestHeaders.getValue(key);
|
||||
if (old == null)
|
||||
{
|
||||
requestHeaders.put(key, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
requestHeaders.put(key, old + "," + value);
|
||||
}
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream()
|
||||
throws IOException
|
||||
{
|
||||
if (connected)
|
||||
{
|
||||
throw new ProtocolException("Already connected");
|
||||
}
|
||||
if (!doOutput)
|
||||
{
|
||||
throw new ProtocolException("doOutput is false");
|
||||
}
|
||||
else if (!requestMethodSetExplicitly)
|
||||
{
|
||||
/*
|
||||
* Silently change the method to POST if no method was set
|
||||
* explicitly. This is due to broken applications depending on this
|
||||
* behaviour (Apache XMLRPC for one).
|
||||
*/
|
||||
method = "POST";
|
||||
}
|
||||
if (requestSink == null)
|
||||
{
|
||||
requestSink = new ByteArrayOutputStream();
|
||||
}
|
||||
return requestSink;
|
||||
}
|
||||
|
||||
// -- Response --
|
||||
|
||||
public InputStream getInputStream()
|
||||
throws IOException
|
||||
{
|
||||
if (!connected)
|
||||
{
|
||||
connect();
|
||||
}
|
||||
if (!doInput)
|
||||
{
|
||||
throw new ProtocolException("doInput is false");
|
||||
}
|
||||
return responseSink;
|
||||
}
|
||||
|
||||
public InputStream getErrorStream()
|
||||
{
|
||||
return errorSink;
|
||||
}
|
||||
|
||||
public Map getHeaderFields()
|
||||
{
|
||||
if (!connected)
|
||||
{
|
||||
try
|
||||
{
|
||||
connect();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Map headers = response.getHeaders();
|
||||
Map ret = new LinkedHashMap();
|
||||
ret.put("", Collections.singletonList(getStatusLine(response)));
|
||||
for (Iterator i = headers.entrySet().iterator(); i.hasNext(); )
|
||||
{
|
||||
Map.Entry entry = (Map.Entry) i.next();
|
||||
String key = (String) entry.getKey();
|
||||
String value = (String) entry.getValue();
|
||||
ret.put(key, Collections.singletonList(value));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
String getStatusLine(Response response)
|
||||
{
|
||||
return "HTTP/" + response.getMajorVersion() +
|
||||
"." + response.getMinorVersion() +
|
||||
" " + response.getCode() +
|
||||
" " + response.getMessage();
|
||||
}
|
||||
|
||||
public String getHeaderField(int index)
|
||||
{
|
||||
if (!connected)
|
||||
{
|
||||
try
|
||||
{
|
||||
connect();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (index == 0)
|
||||
{
|
||||
return getStatusLine(response);
|
||||
}
|
||||
Iterator i = response.getHeaders().entrySet().iterator();
|
||||
Map.Entry entry;
|
||||
int count = 1;
|
||||
do
|
||||
{
|
||||
if (!i.hasNext())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
entry = (Map.Entry) i.next();
|
||||
count++;
|
||||
}
|
||||
while (count <= index);
|
||||
return (String) entry.getValue();
|
||||
}
|
||||
|
||||
public String getHeaderFieldKey(int index)
|
||||
{
|
||||
if (!connected)
|
||||
{
|
||||
try
|
||||
{
|
||||
connect();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (index == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Iterator i = response.getHeaders().entrySet().iterator();
|
||||
Map.Entry entry;
|
||||
int count = 1;
|
||||
do
|
||||
{
|
||||
if (!i.hasNext())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
entry = (Map.Entry) i.next();
|
||||
count++;
|
||||
}
|
||||
while (count <= index);
|
||||
return (String) entry.getKey();
|
||||
}
|
||||
|
||||
public String getHeaderField(String name)
|
||||
{
|
||||
if (!connected)
|
||||
{
|
||||
try
|
||||
{
|
||||
connect();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return (String) response.getHeader(name);
|
||||
}
|
||||
|
||||
public long getHeaderFieldDate(String name, long def)
|
||||
{
|
||||
if (!connected)
|
||||
{
|
||||
try
|
||||
{
|
||||
connect();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
return def;
|
||||
}
|
||||
}
|
||||
Date date = response.getDateHeader(name);
|
||||
return (date == null) ? def : date.getTime();
|
||||
}
|
||||
|
||||
public String getContentType()
|
||||
{
|
||||
return getHeaderField("Content-Type");
|
||||
}
|
||||
|
||||
public int getResponseCode()
|
||||
throws IOException
|
||||
{
|
||||
if (!connected)
|
||||
{
|
||||
connect();
|
||||
}
|
||||
return response.getCode();
|
||||
}
|
||||
|
||||
public String getResponseMessage()
|
||||
throws IOException
|
||||
{
|
||||
if (!connected)
|
||||
{
|
||||
connect();
|
||||
}
|
||||
return response.getMessage();
|
||||
}
|
||||
|
||||
// -- HTTPS specific --
|
||||
|
||||
public String getCipherSuite()
|
||||
{
|
||||
if (!connected)
|
||||
{
|
||||
throw new IllegalStateException("not connected");
|
||||
}
|
||||
return handshakeEvent.getCipherSuite();
|
||||
}
|
||||
|
||||
public Certificate[] getLocalCertificates()
|
||||
{
|
||||
if (!connected)
|
||||
{
|
||||
throw new IllegalStateException("not connected");
|
||||
}
|
||||
return handshakeEvent.getLocalCertificates();
|
||||
}
|
||||
|
||||
public Certificate[] getServerCertificates()
|
||||
throws SSLPeerUnverifiedException
|
||||
{
|
||||
if (!connected)
|
||||
{
|
||||
throw new IllegalStateException("not connected");
|
||||
}
|
||||
return handshakeEvent.getPeerCertificates();
|
||||
}
|
||||
|
||||
// HandshakeCompletedListener
|
||||
|
||||
public void handshakeCompleted(HandshakeCompletedEvent event)
|
||||
{
|
||||
handshakeEvent = event;
|
||||
}
|
||||
|
||||
}
|
||||
|
73
libjava/classpath/gnu/java/net/protocol/http/Handler.java
Normal file
73
libjava/classpath/gnu/java/net/protocol/http/Handler.java
Normal file
|
@ -0,0 +1,73 @@
|
|||
/* Handler.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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLStreamHandler;
|
||||
|
||||
/**
|
||||
* An HTTP URL stream handler.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public class Handler
|
||||
extends URLStreamHandler
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the default HTTP port (80).
|
||||
*/
|
||||
protected int getDefaultPort()
|
||||
{
|
||||
return HTTPConnection.HTTP_PORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an HTTPURLConnection for the given URL.
|
||||
*/
|
||||
public URLConnection openConnection(URL url)
|
||||
throws IOException
|
||||
{
|
||||
return new HTTPURLConnection(url);
|
||||
}
|
||||
|
||||
}
|
||||
|
369
libjava/classpath/gnu/java/net/protocol/http/Headers.java
Normal file
369
libjava/classpath/gnu/java/net/protocol/http/Headers.java
Normal file
|
@ -0,0 +1,369 @@
|
|||
/* Headers.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;
|
||||
|
||||
import gnu.java.net.LineInputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A collection of HTTP header names and associated values.
|
||||
* Retrieval of values is case insensitive. An iteration over the keys
|
||||
* returns the header names in the order they were received.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public class Headers
|
||||
implements Map
|
||||
{
|
||||
|
||||
static final DateFormat dateFormat = new HTTPDateFormat();
|
||||
|
||||
static class Header
|
||||
{
|
||||
|
||||
final String name;
|
||||
|
||||
Header(String name)
|
||||
{
|
||||
if (name == null || name.length() == 0)
|
||||
{
|
||||
throw new IllegalArgumentException(name);
|
||||
}
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
return name.toLowerCase().hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object other)
|
||||
{
|
||||
if (other instanceof Header)
|
||||
{
|
||||
return ((Header) other).name.equalsIgnoreCase(name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class HeaderEntry
|
||||
implements Map.Entry
|
||||
{
|
||||
|
||||
final Map.Entry entry;
|
||||
|
||||
HeaderEntry(Map.Entry entry)
|
||||
{
|
||||
this.entry = entry;
|
||||
}
|
||||
|
||||
public Object getKey()
|
||||
{
|
||||
return ((Header) entry.getKey()).name;
|
||||
}
|
||||
|
||||
public Object getValue()
|
||||
{
|
||||
return entry.getValue();
|
||||
}
|
||||
|
||||
public Object setValue(Object value)
|
||||
{
|
||||
return entry.setValue(value);
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
return entry.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object other)
|
||||
{
|
||||
return entry.equals(other);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return getKey().toString() + "=" + getValue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public Object get(Object key)
|
||||
{
|
||||
return headers.get(new Header((String) key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the specified header as a string.
|
||||
*/
|
||||
public String getValue(String header)
|
||||
{
|
||||
return (String) headers.get(new Header(header));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the specified header as an integer,
|
||||
* or -1 if the header is not present or not an integer.
|
||||
*/
|
||||
public int getIntValue(String header)
|
||||
{
|
||||
String val = getValue(header);
|
||||
if (val == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
try
|
||||
{
|
||||
return Integer.parseInt(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.
|
||||
*/
|
||||
public Date getDateValue(String header)
|
||||
{
|
||||
String val = getValue(header);
|
||||
if (val == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
try
|
||||
{
|
||||
return dateFormat.parse(val);
|
||||
}
|
||||
catch (ParseException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Object put(Object key, Object value)
|
||||
{
|
||||
return headers.put(new Header((String) key), value);
|
||||
}
|
||||
|
||||
public Object remove(Object key)
|
||||
{
|
||||
return headers.remove(new Header((String) key));
|
||||
}
|
||||
|
||||
public void putAll(Map t)
|
||||
{
|
||||
for (Iterator i = t.keySet().iterator(); i.hasNext(); )
|
||||
{
|
||||
String key = (String) i.next();
|
||||
String value = (String) t.get(key);
|
||||
headers.put(new Header(key), value);
|
||||
}
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
headers.clear();
|
||||
}
|
||||
|
||||
public Set keySet()
|
||||
{
|
||||
Set keys = headers.keySet();
|
||||
Set ret = new LinkedHashSet();
|
||||
for (Iterator i = keys.iterator(); i.hasNext(); )
|
||||
{
|
||||
ret.add(((Header) i.next()).name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Collection values()
|
||||
{
|
||||
return headers.values();
|
||||
}
|
||||
|
||||
public Set entrySet()
|
||||
{
|
||||
Set entries = headers.entrySet();
|
||||
Set ret = new LinkedHashSet();
|
||||
for (Iterator i = entries.iterator(); i.hasNext(); )
|
||||
{
|
||||
Map.Entry entry = (Map.Entry) i.next();
|
||||
ret.add(new HeaderEntry(entry));
|
||||
}
|
||||
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.
|
||||
*/
|
||||
public void parse(InputStream in)
|
||||
throws IOException
|
||||
{
|
||||
LineInputStream lin = (in instanceof LineInputStream) ?
|
||||
(LineInputStream) in : new LineInputStream(in);
|
||||
|
||||
String name = null;
|
||||
StringBuffer value = new StringBuffer();
|
||||
while (true)
|
||||
{
|
||||
String line = lin.readLine();
|
||||
if (line == null)
|
||||
{
|
||||
if (name != null)
|
||||
{
|
||||
addValue(name, value.toString());
|
||||
}
|
||||
break;
|
||||
}
|
||||
int len = line.length();
|
||||
if (len < 2)
|
||||
{
|
||||
if (name != null)
|
||||
{
|
||||
addValue(name, value.toString());
|
||||
}
|
||||
break;
|
||||
}
|
||||
char c1 = line.charAt(0);
|
||||
if (c1 == ' ' || c1 == '\t')
|
||||
{
|
||||
// Continuation
|
||||
int last = len - 1;
|
||||
if (line.charAt(last) != '\r')
|
||||
++last;
|
||||
value.append(line.substring(0, last));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (name != null)
|
||||
{
|
||||
addValue(name, value.toString());
|
||||
}
|
||||
|
||||
int di = line.indexOf(':');
|
||||
name = line.substring(0, di);
|
||||
value.setLength(0);
|
||||
do
|
||||
{
|
||||
di++;
|
||||
}
|
||||
while (di < len && line.charAt(di) == ' ');
|
||||
int last = len - 1;
|
||||
if (line.charAt(last) != '\r')
|
||||
++last;
|
||||
value.append(line.substring(di, last));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addValue(String name, String value)
|
||||
{
|
||||
Header key = new Header(name);
|
||||
String old = (String) headers.get(key);
|
||||
if (old == null)
|
||||
{
|
||||
headers.put(key, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
headers.put(key, old + ", " + value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
915
libjava/classpath/gnu/java/net/protocol/http/Request.java
Normal file
915
libjava/classpath/gnu/java/net/protocol/http/Request.java
Normal file
|
@ -0,0 +1,915 @@
|
|||
/* Request.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;
|
||||
|
||||
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;
|
||||
import java.io.OutputStream;
|
||||
import java.net.ProtocolException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
/**
|
||||
* A single HTTP request.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public class Request
|
||||
{
|
||||
|
||||
/**
|
||||
* The connection context in which this request is invoked.
|
||||
*/
|
||||
protected final HTTPConnection connection;
|
||||
|
||||
/**
|
||||
* The HTTP method to invoke.
|
||||
*/
|
||||
protected final String method;
|
||||
|
||||
/**
|
||||
* The path identifying the resource.
|
||||
* This string must conform to the abs_path definition given in RFC2396,
|
||||
* with an optional "?query" part, and must be URI-escaped by the caller.
|
||||
*/
|
||||
protected final String path;
|
||||
|
||||
/**
|
||||
* The headers in this request.
|
||||
*/
|
||||
protected final Headers requestHeaders;
|
||||
|
||||
/**
|
||||
* The request body provider.
|
||||
*/
|
||||
protected RequestBodyWriter requestBodyWriter;
|
||||
|
||||
/**
|
||||
* Request body negotiation threshold for 100-continue expectations.
|
||||
*/
|
||||
protected int requestBodyNegotiationThreshold;
|
||||
|
||||
/**
|
||||
* The response body reader.
|
||||
*/
|
||||
protected ResponseBodyReader responseBodyReader;
|
||||
|
||||
/**
|
||||
* Map of response header handlers.
|
||||
*/
|
||||
protected Map responseHeaderHandlers;
|
||||
|
||||
/**
|
||||
* The authenticator.
|
||||
*/
|
||||
protected Authenticator authenticator;
|
||||
|
||||
/**
|
||||
* Whether this request has been dispatched yet.
|
||||
*/
|
||||
private boolean dispatched;
|
||||
|
||||
/**
|
||||
* Constructor for a new request.
|
||||
* @param connection the connection context
|
||||
* @param method the HTTP method
|
||||
* @param path the resource path including query part
|
||||
*/
|
||||
protected Request(HTTPConnection connection, String method,
|
||||
String path)
|
||||
{
|
||||
this.connection = connection;
|
||||
this.method = method;
|
||||
this.path = path;
|
||||
requestHeaders = new Headers();
|
||||
responseHeaderHandlers = new HashMap();
|
||||
requestBodyNegotiationThreshold = 4096;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the connection associated with this request.
|
||||
* @see #connection
|
||||
*/
|
||||
public HTTPConnection getConnection()
|
||||
{
|
||||
return connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTTP method to invoke.
|
||||
* @see #method
|
||||
*/
|
||||
public String getMethod()
|
||||
{
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resource path.
|
||||
* @see #path
|
||||
*/
|
||||
public String getPath()
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full request-URI represented by this request, as specified
|
||||
* by HTTP/1.1.
|
||||
*/
|
||||
public String getRequestURI()
|
||||
{
|
||||
return connection.getURI() + path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the headers in this request.
|
||||
*/
|
||||
public Headers getHeaders()
|
||||
{
|
||||
return requestHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the specified header in this request.
|
||||
* @param name the header name
|
||||
*/
|
||||
public String getHeader(String name)
|
||||
{
|
||||
return requestHeaders.getValue(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the specified header in this request as an integer.
|
||||
* @param name the header name
|
||||
*/
|
||||
public int getIntHeader(String name)
|
||||
{
|
||||
return requestHeaders.getIntValue(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the specified header in this request as a date.
|
||||
* @param name the header name
|
||||
*/
|
||||
public Date getDateHeader(String name)
|
||||
{
|
||||
return requestHeaders.getDateValue(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified header in this request.
|
||||
* @param name the header name
|
||||
* @param value the header value
|
||||
*/
|
||||
public void setHeader(String name, String value)
|
||||
{
|
||||
requestHeaders.put(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to set the entire request body.
|
||||
* @param requestBody the request body content
|
||||
*/
|
||||
public void setRequestBody(byte[] requestBody)
|
||||
{
|
||||
setRequestBodyWriter(new ByteArrayRequestBodyWriter(requestBody));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the request body provider.
|
||||
* @param requestBodyWriter the handler used to obtain the request body
|
||||
*/
|
||||
public void setRequestBodyWriter(RequestBodyWriter requestBodyWriter)
|
||||
{
|
||||
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
|
||||
* @param handler the handler to receive the value for the header
|
||||
*/
|
||||
public void setResponseHeaderHandler(String name,
|
||||
ResponseHeaderHandler handler)
|
||||
{
|
||||
responseHeaderHandlers.put(name, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an authenticator that can be used to handle authentication
|
||||
* automatically.
|
||||
* @param authenticator the authenticator
|
||||
*/
|
||||
public void setAuthenticator(Authenticator authenticator)
|
||||
{
|
||||
this.authenticator = authenticator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the request body negotiation threshold.
|
||||
* If this is set, it determines the maximum size that the request body
|
||||
* may be before body negotiation occurs(via the
|
||||
* <code>100-continue</code> expectation). This ensures that a large
|
||||
* request body is not sent when the server wouldn't have accepted it
|
||||
* anyway.
|
||||
* @param threshold the body negotiation threshold, or <=0 to disable
|
||||
* request body negotation entirely
|
||||
*/
|
||||
public void setRequestBodyNegotiationThreshold(int threshold)
|
||||
{
|
||||
requestBodyNegotiationThreshold = threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches this request.
|
||||
* A request can only be dispatched once; calling this method a second
|
||||
* time results in a protocol exception.
|
||||
* @exception IOException if an I/O error occurred
|
||||
* @return an HTTP response object representing the result of the operation
|
||||
*/
|
||||
public Response dispatch()
|
||||
throws IOException
|
||||
{
|
||||
if (dispatched)
|
||||
{
|
||||
throw new ProtocolException("request already dispatched");
|
||||
}
|
||||
final String CRLF = "\r\n";
|
||||
final String HEADER_SEP = ": ";
|
||||
final String US_ASCII = "US-ASCII";
|
||||
final String version = connection.getVersion();
|
||||
Response response;
|
||||
int contentLength = -1;
|
||||
boolean retry = false;
|
||||
int attempts = 0;
|
||||
boolean expectingContinue = false;
|
||||
if (requestBodyWriter != null)
|
||||
{
|
||||
contentLength = requestBodyWriter.getContentLength();
|
||||
if (contentLength > requestBodyNegotiationThreshold)
|
||||
{
|
||||
expectingContinue = true;
|
||||
setHeader("Expect", "100-continue");
|
||||
}
|
||||
else
|
||||
{
|
||||
setHeader("Content-Length", Integer.toString(contentLength));
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Loop while authentication fails or continue
|
||||
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() &&
|
||||
!"*".equals(requestUri) &&
|
||||
!"CONNECT".equals(method))
|
||||
{
|
||||
requestUri = getRequestURI();
|
||||
}
|
||||
String line = method + ' ' + requestUri + ' ' + version + CRLF;
|
||||
out.write(line.getBytes(US_ASCII));
|
||||
// Request headers
|
||||
for (Iterator i = requestHeaders.keySet().iterator();
|
||||
i.hasNext(); )
|
||||
{
|
||||
String name =(String) i.next();
|
||||
String value =(String) requestHeaders.get(name);
|
||||
line = name + HEADER_SEP + value + CRLF;
|
||||
out.write(line.getBytes(US_ASCII));
|
||||
}
|
||||
out.write(CRLF.getBytes(US_ASCII));
|
||||
// Request body
|
||||
if (requestBodyWriter != null && !expectingContinue)
|
||||
{
|
||||
byte[] buffer = new byte[4096];
|
||||
int len;
|
||||
int count = 0;
|
||||
|
||||
requestBodyWriter.reset();
|
||||
do
|
||||
{
|
||||
len = requestBodyWriter.write(buffer);
|
||||
if (len > 0)
|
||||
{
|
||||
out.write(buffer, 0, len);
|
||||
}
|
||||
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 (retry);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
connection.close();
|
||||
throw e;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
Response readResponse(LineInputStream in)
|
||||
throws IOException
|
||||
{
|
||||
String line;
|
||||
int len;
|
||||
|
||||
// Read response status line
|
||||
line = in.readLine();
|
||||
if (line == null)
|
||||
{
|
||||
throw new ProtocolException("Peer closed connection");
|
||||
}
|
||||
if (!line.startsWith("HTTP/"))
|
||||
{
|
||||
throw new ProtocolException(line);
|
||||
}
|
||||
len = line.length();
|
||||
int start = 5, end = 6;
|
||||
while (line.charAt(end) != '.')
|
||||
{
|
||||
end++;
|
||||
}
|
||||
int majorVersion = Integer.parseInt(line.substring(start, end));
|
||||
start = end + 1;
|
||||
end = start + 1;
|
||||
while (line.charAt(end) != ' ')
|
||||
{
|
||||
end++;
|
||||
}
|
||||
int minorVersion = Integer.parseInt(line.substring(start, end));
|
||||
start = end + 1;
|
||||
end = start + 3;
|
||||
int code = Integer.parseInt(line.substring(start, end));
|
||||
String message = line.substring(end + 1, len - 1);
|
||||
// Read response headers
|
||||
Headers responseHeaders = new Headers();
|
||||
responseHeaders.parse(in);
|
||||
notifyHeaderHandlers(responseHeaders);
|
||||
// Construct response
|
||||
int codeClass = code / 100;
|
||||
Response ret = new Response(majorVersion, minorVersion, code,
|
||||
codeClass, message, responseHeaders);
|
||||
switch (code)
|
||||
{
|
||||
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);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void notifyHeaderHandlers(Headers headers)
|
||||
{
|
||||
for (Iterator i = headers.entrySet().iterator(); i.hasNext(); )
|
||||
{
|
||||
Map.Entry entry = (Map.Entry) i.next();
|
||||
String name =(String) entry.getKey();
|
||||
// Handle Set-Cookie
|
||||
if ("Set-Cookie".equalsIgnoreCase(name))
|
||||
{
|
||||
String value = (String) entry.getValue();
|
||||
handleSetCookie(value);
|
||||
}
|
||||
ResponseHeaderHandler handler =
|
||||
(ResponseHeaderHandler) responseHeaderHandlers.get(name);
|
||||
if (handler != null)
|
||||
{
|
||||
String value = (String) entry.getValue();
|
||||
handler.setValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void readResponseBody(Response response, InputStream in,
|
||||
boolean notify)
|
||||
throws IOException
|
||||
{
|
||||
byte[] buffer = new byte[4096];
|
||||
int contentLength = -1;
|
||||
Headers trailer = null;
|
||||
|
||||
String transferCoding = response.getHeader("Transfer-Encoding");
|
||||
if ("chunked".equalsIgnoreCase(transferCoding))
|
||||
{
|
||||
trailer = new Headers();
|
||||
in = new ChunkedInputStream(in, trailer);
|
||||
}
|
||||
else
|
||||
{
|
||||
contentLength = response.getIntHeader("Content-Length");
|
||||
}
|
||||
String contentCoding = response.getHeader("Content-Encoding");
|
||||
if (contentCoding != null && !"identity".equals(contentCoding))
|
||||
{
|
||||
if ("gzip".equals(contentCoding))
|
||||
{
|
||||
in = new GZIPInputStream(in);
|
||||
}
|
||||
else if ("deflate".equals(contentCoding))
|
||||
{
|
||||
in = new InflaterInputStream(in);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ProtocolException("Unsupported Content-Encoding: " +
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
boolean authenticate(Response response, int attempts)
|
||||
throws IOException
|
||||
{
|
||||
String challenge = response.getHeader("WWW-Authenticate");
|
||||
if (challenge == null)
|
||||
{
|
||||
challenge = response.getHeader("Proxy-Authenticate");
|
||||
}
|
||||
int si = challenge.indexOf(' ');
|
||||
String scheme = (si == -1) ? challenge : challenge.substring(0, si);
|
||||
if ("Basic".equalsIgnoreCase(scheme))
|
||||
{
|
||||
Properties params = parseAuthParams(challenge.substring(si + 1));
|
||||
String realm = params.getProperty("realm");
|
||||
Credentials creds = authenticator.getCredentials(realm, attempts);
|
||||
String userPass = creds.getUsername() + ':' + creds.getPassword();
|
||||
byte[] b_userPass = userPass.getBytes("US-ASCII");
|
||||
byte[] b_encoded = BASE64.encode(b_userPass);
|
||||
String authorization =
|
||||
scheme + " " + new String(b_encoded, "US-ASCII");
|
||||
setHeader("Authorization", authorization);
|
||||
return true;
|
||||
}
|
||||
else if ("Digest".equalsIgnoreCase(scheme))
|
||||
{
|
||||
Properties params = parseAuthParams(challenge.substring(si + 1));
|
||||
String realm = params.getProperty("realm");
|
||||
String nonce = params.getProperty("nonce");
|
||||
String qop = params.getProperty("qop");
|
||||
String algorithm = params.getProperty("algorithm");
|
||||
String digestUri = getRequestURI();
|
||||
Credentials creds = authenticator.getCredentials(realm, attempts);
|
||||
String username = creds.getUsername();
|
||||
String password = creds.getPassword();
|
||||
connection.incrementNonce(nonce);
|
||||
try
|
||||
{
|
||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||
final byte[] COLON = { 0x3a };
|
||||
|
||||
// Calculate H(A1)
|
||||
md5.reset();
|
||||
md5.update(username.getBytes("US-ASCII"));
|
||||
md5.update(COLON);
|
||||
md5.update(realm.getBytes("US-ASCII"));
|
||||
md5.update(COLON);
|
||||
md5.update(password.getBytes("US-ASCII"));
|
||||
byte[] ha1 = md5.digest();
|
||||
if ("md5-sess".equals(algorithm))
|
||||
{
|
||||
byte[] cnonce = generateNonce();
|
||||
md5.reset();
|
||||
md5.update(ha1);
|
||||
md5.update(COLON);
|
||||
md5.update(nonce.getBytes("US-ASCII"));
|
||||
md5.update(COLON);
|
||||
md5.update(cnonce);
|
||||
ha1 = md5.digest();
|
||||
}
|
||||
String ha1Hex = toHexString(ha1);
|
||||
|
||||
// Calculate H(A2)
|
||||
md5.reset();
|
||||
md5.update(method.getBytes("US-ASCII"));
|
||||
md5.update(COLON);
|
||||
md5.update(digestUri.getBytes("US-ASCII"));
|
||||
if ("auth-int".equals(qop))
|
||||
{
|
||||
byte[] hEntity = null; // TODO hash of entity body
|
||||
md5.update(COLON);
|
||||
md5.update(hEntity);
|
||||
}
|
||||
byte[] ha2 = md5.digest();
|
||||
String ha2Hex = toHexString(ha2);
|
||||
|
||||
// Calculate response
|
||||
md5.reset();
|
||||
md5.update(ha1Hex.getBytes("US-ASCII"));
|
||||
md5.update(COLON);
|
||||
md5.update(nonce.getBytes("US-ASCII"));
|
||||
if ("auth".equals(qop) || "auth-int".equals(qop))
|
||||
{
|
||||
String nc = getNonceCount(nonce);
|
||||
byte[] cnonce = generateNonce();
|
||||
md5.update(COLON);
|
||||
md5.update(nc.getBytes("US-ASCII"));
|
||||
md5.update(COLON);
|
||||
md5.update(cnonce);
|
||||
md5.update(COLON);
|
||||
md5.update(qop.getBytes("US-ASCII"));
|
||||
}
|
||||
md5.update(COLON);
|
||||
md5.update(ha2Hex.getBytes("US-ASCII"));
|
||||
String digestResponse = toHexString(md5.digest());
|
||||
|
||||
String authorization = scheme +
|
||||
" username=\"" + username + "\"" +
|
||||
" realm=\"" + realm + "\"" +
|
||||
" nonce=\"" + nonce + "\"" +
|
||||
" uri=\"" + digestUri + "\"" +
|
||||
" response=\"" + digestResponse + "\"";
|
||||
setHeader("Authorization", authorization);
|
||||
return true;
|
||||
}
|
||||
catch (NoSuchAlgorithmException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Scheme not recognised
|
||||
return false;
|
||||
}
|
||||
|
||||
Properties parseAuthParams(String text)
|
||||
{
|
||||
int len = text.length();
|
||||
String key = null;
|
||||
StringBuffer buf = new StringBuffer();
|
||||
Properties ret = new Properties();
|
||||
boolean inQuote = false;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
char c = text.charAt(i);
|
||||
if (c == '"')
|
||||
{
|
||||
inQuote = !inQuote;
|
||||
}
|
||||
else if (c == '=' && key == null)
|
||||
{
|
||||
key = buf.toString().trim();
|
||||
buf.setLength(0);
|
||||
}
|
||||
else if (c == ' ' && !inQuote)
|
||||
{
|
||||
String value = unquote(buf.toString().trim());
|
||||
ret.put(key, value);
|
||||
key = null;
|
||||
buf.setLength(0);
|
||||
}
|
||||
else if (c != ',' || (i <(len - 1) && text.charAt(i + 1) != ' '))
|
||||
{
|
||||
buf.append(c);
|
||||
}
|
||||
}
|
||||
if (key != null)
|
||||
{
|
||||
String value = unquote(buf.toString().trim());
|
||||
ret.put(key, value);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
String unquote(String text)
|
||||
{
|
||||
int len = text.length();
|
||||
if (len > 0 && text.charAt(0) == '"' && text.charAt(len - 1) == '"')
|
||||
{
|
||||
return text.substring(1, len - 1);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of times the specified nonce value has been seen.
|
||||
* This always returns an 8-byte 0-padded hexadecimal string.
|
||||
*/
|
||||
String getNonceCount(String nonce)
|
||||
{
|
||||
int nc = connection.getNonceCount(nonce);
|
||||
String hex = Integer.toHexString(nc);
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (int i = 8 - hex.length(); i > 0; i--)
|
||||
{
|
||||
buf.append('0');
|
||||
}
|
||||
buf.append(hex);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Client nonce value.
|
||||
*/
|
||||
byte[] nonce;
|
||||
|
||||
/**
|
||||
* Generates a new client nonce value.
|
||||
*/
|
||||
byte[] generateNonce()
|
||||
throws IOException, NoSuchAlgorithmException
|
||||
{
|
||||
if (nonce == null)
|
||||
{
|
||||
long time = System.currentTimeMillis();
|
||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||
md5.update(Long.toString(time).getBytes("US-ASCII"));
|
||||
nonce = md5.digest();
|
||||
}
|
||||
return nonce;
|
||||
}
|
||||
|
||||
String toHexString(byte[] bytes)
|
||||
{
|
||||
char[] ret = new char[bytes.length * 2];
|
||||
for (int i = 0, j = 0; i < bytes.length; i++)
|
||||
{
|
||||
int c =(int) bytes[i];
|
||||
if (c < 0)
|
||||
{
|
||||
c += 0x100;
|
||||
}
|
||||
ret[j++] = Character.forDigit(c / 0x10, 0x10);
|
||||
ret[j++] = Character.forDigit(c % 0x10, 0x10);
|
||||
}
|
||||
return new String(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the specified cookie list and notify the cookie manager.
|
||||
*/
|
||||
void handleSetCookie(String text)
|
||||
{
|
||||
CookieManager cookieManager = connection.getCookieManager();
|
||||
if (cookieManager == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
String name = null;
|
||||
String value = null;
|
||||
String comment = null;
|
||||
String domain = connection.getHostName();
|
||||
String path = this.path;
|
||||
int lsi = path.lastIndexOf('/');
|
||||
if (lsi != -1)
|
||||
{
|
||||
path = path.substring(0, lsi);
|
||||
}
|
||||
boolean secure = false;
|
||||
Date expires = null;
|
||||
|
||||
int len = text.length();
|
||||
String attr = null;
|
||||
StringBuffer buf = new StringBuffer();
|
||||
boolean inQuote = false;
|
||||
for (int i = 0; i <= len; i++)
|
||||
{
|
||||
char c =(i == len) ? '\u0000' : text.charAt(i);
|
||||
if (c == '"')
|
||||
{
|
||||
inQuote = !inQuote;
|
||||
}
|
||||
else if (!inQuote)
|
||||
{
|
||||
if (c == '=' && attr == null)
|
||||
{
|
||||
attr = buf.toString().trim();
|
||||
buf.setLength(0);
|
||||
}
|
||||
else if (c == ';' || i == len || c == ',')
|
||||
{
|
||||
String val = unquote(buf.toString().trim());
|
||||
if (name == null)
|
||||
{
|
||||
name = attr;
|
||||
value = val;
|
||||
}
|
||||
else if ("Comment".equalsIgnoreCase(attr))
|
||||
{
|
||||
comment = val;
|
||||
}
|
||||
else if ("Domain".equalsIgnoreCase(attr))
|
||||
{
|
||||
domain = val;
|
||||
}
|
||||
else if ("Path".equalsIgnoreCase(attr))
|
||||
{
|
||||
path = val;
|
||||
}
|
||||
else if ("Secure".equalsIgnoreCase(val))
|
||||
{
|
||||
secure = true;
|
||||
}
|
||||
else if ("Max-Age".equalsIgnoreCase(attr))
|
||||
{
|
||||
int delta = Integer.parseInt(val);
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTimeInMillis(System.currentTimeMillis());
|
||||
cal.add(Calendar.SECOND, delta);
|
||||
expires = cal.getTime();
|
||||
}
|
||||
else if ("Expires".equalsIgnoreCase(attr))
|
||||
{
|
||||
DateFormat dateFormat = new HTTPDateFormat();
|
||||
try
|
||||
{
|
||||
expires = dateFormat.parse(val);
|
||||
}
|
||||
catch (ParseException e)
|
||||
{
|
||||
// if this isn't a valid date, it may be that
|
||||
// the value was returned unquoted; in that case, we
|
||||
// want to continue buffering the value
|
||||
buf.append(c);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
attr = null;
|
||||
buf.setLength(0);
|
||||
// case EOL
|
||||
if (i == len || c == ',')
|
||||
{
|
||||
Cookie cookie = new Cookie(name, value, comment, domain,
|
||||
path, secure, expires);
|
||||
cookieManager.setCookie(cookie);
|
||||
}
|
||||
if (c == ',')
|
||||
{
|
||||
// Reset cookie fields
|
||||
name = null;
|
||||
value = null;
|
||||
comment = null;
|
||||
domain = connection.getHostName();
|
||||
path = this.path;
|
||||
if (lsi != -1)
|
||||
{
|
||||
path = path.substring(0, lsi);
|
||||
}
|
||||
secure = false;
|
||||
expires = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.append(c);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/* RequestBodyWriter.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 writing request body content.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public interface RequestBodyWriter
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the total number of bytes that will be written in a single pass
|
||||
* by this writer.
|
||||
*/
|
||||
int getContentLength();
|
||||
|
||||
/**
|
||||
* Initialises the writer.
|
||||
* This will be called before each pass.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* Writes body content to the supplied buffer.
|
||||
* @param buffer the content buffer
|
||||
* @return the number of bytes written
|
||||
*/
|
||||
int write(byte[] buffer);
|
||||
|
||||
}
|
||||
|
185
libjava/classpath/gnu/java/net/protocol/http/Response.java
Normal file
185
libjava/classpath/gnu/java/net/protocol/http/Response.java
Normal file
|
@ -0,0 +1,185 @@
|
|||
/* Response.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;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* An HTTP response.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public class Response
|
||||
{
|
||||
|
||||
/**
|
||||
* The HTTP major version of the server issuing the response.
|
||||
*/
|
||||
protected final int majorVersion;
|
||||
|
||||
/**
|
||||
* The HTTP minor version of the server issuing the response.
|
||||
*/
|
||||
protected final int minorVersion;
|
||||
|
||||
/**
|
||||
* The HTTP status code of the 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.
|
||||
*/
|
||||
protected final String message;
|
||||
|
||||
/**
|
||||
* The response headers.
|
||||
*/
|
||||
protected final Headers headers;
|
||||
|
||||
/**
|
||||
* Constructs a new response with the specified parameters.
|
||||
*/
|
||||
protected Response(int majorVersion, int minorVersion, int code,
|
||||
int codeClass, String message,
|
||||
Headers headers)
|
||||
{
|
||||
this.majorVersion = majorVersion;
|
||||
this.minorVersion = minorVersion;
|
||||
this.code = code;
|
||||
this.codeClass = codeClass;
|
||||
this.message = message;
|
||||
this.headers = headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTTP major version of the server issuing the response.
|
||||
* @see #majorVersion
|
||||
*/
|
||||
public int getMajorVersion()
|
||||
{
|
||||
return majorVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTTP minor version of the server issuing the response.
|
||||
* @see #minorVersion
|
||||
*/
|
||||
public int getMinorVersion()
|
||||
{
|
||||
return minorVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTTP status code of the response.
|
||||
* @see #code
|
||||
*/
|
||||
public int getCode()
|
||||
{
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class of the response.
|
||||
* @see #codeClass
|
||||
*/
|
||||
public int getCodeClass()
|
||||
{
|
||||
return codeClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the human-readable text of the response.
|
||||
* @see #message
|
||||
*/
|
||||
public String getMessage()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the headers in the response.
|
||||
*/
|
||||
public Headers getHeaders()
|
||||
{
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the header value for the specified name.
|
||||
* @param name the header name
|
||||
*/
|
||||
public String getHeader(String name)
|
||||
{
|
||||
return headers.getValue(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the header value for the specified name as an integer.
|
||||
* @param name the header name
|
||||
*/
|
||||
public int getIntHeader(String name)
|
||||
{
|
||||
return headers.getIntValue(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the header value for the specified name as a date.
|
||||
* @param name the header name
|
||||
*/
|
||||
public Date getDateHeader(String name)
|
||||
{
|
||||
return headers.getDateValue(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/* 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();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/* ResponseHeaderHandler.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 objects that wish to be notified of response
|
||||
* header values.
|
||||
* @see Request#setHeaderHandler(String)
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public interface ResponseHeaderHandler
|
||||
{
|
||||
|
||||
/**
|
||||
* Sets the value for the header associated with this handler.
|
||||
*/
|
||||
void setValue(String value);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
/* CookieManager.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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A simple non-persistent cookie manager. This class can be extended to
|
||||
* provide cookie persistence.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public class SimpleCookieManager
|
||||
implements CookieManager
|
||||
{
|
||||
|
||||
/**
|
||||
* The cookie cache.
|
||||
* This is a dictionary mapping domains to maps of cookies by name.
|
||||
*/
|
||||
protected Map cookies;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public SimpleCookieManager()
|
||||
{
|
||||
cookies = new HashMap();
|
||||
}
|
||||
|
||||
public void setCookie(Cookie cookie)
|
||||
{
|
||||
String domain = cookie.getDomain();
|
||||
Map map =(Map) cookies.get(domain);
|
||||
if (map == null)
|
||||
{
|
||||
map = new HashMap();
|
||||
cookies.put(domain, map);
|
||||
}
|
||||
String name = cookie.getName();
|
||||
map.put(name, cookie); // will replace a cookie of the same name
|
||||
}
|
||||
|
||||
public Cookie[] getCookies(String host, boolean secure, String path)
|
||||
{
|
||||
List matches = new ArrayList();
|
||||
Date now = new Date();
|
||||
if (Character.isLetter(host.charAt(0)))
|
||||
{
|
||||
int di = host.indexOf('.');
|
||||
while (di != -1)
|
||||
{
|
||||
addCookies(matches, host, secure, path, now);
|
||||
host = host.substring(di);
|
||||
di = host.indexOf('.', 1);
|
||||
}
|
||||
}
|
||||
addCookies(matches, host, secure, path, now);
|
||||
Cookie[] ret = new Cookie[matches.size()];
|
||||
matches.toArray(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void addCookies(List matches, String domain, boolean secure,
|
||||
String path, Date now)
|
||||
{
|
||||
Map map = (Map) cookies.get(domain);
|
||||
if (map != null)
|
||||
{
|
||||
List expired = new ArrayList();
|
||||
for (Iterator i = map.entrySet().iterator(); i.hasNext(); )
|
||||
{
|
||||
Map.Entry entry = (Map.Entry) i.next();
|
||||
Cookie cookie = (Cookie) entry.getValue();
|
||||
Date expires = cookie.getExpiryDate();
|
||||
if (expires != null && expires.before(now))
|
||||
{
|
||||
expired.add(entry.getKey());
|
||||
continue;
|
||||
}
|
||||
if (secure && !cookie.isSecure())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (path.startsWith(cookie.getPath()))
|
||||
{
|
||||
matches.add(cookie);
|
||||
}
|
||||
}
|
||||
// Good housekeeping
|
||||
for (Iterator i = expired.iterator(); i.hasNext(); )
|
||||
{
|
||||
map.remove(i.next());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/* 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/* 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);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/* 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/* 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);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<!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>
|
76
libjava/classpath/gnu/java/net/protocol/http/package.html
Normal file
76
libjava/classpath/gnu/java/net/protocol/http/package.html
Normal file
|
@ -0,0 +1,76 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<!-- package.html - describes classes in gnu.java.net.protocol.http package.
|
||||
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. -->
|
||||
|
||||
<html>
|
||||
<head><title>GNU Classpath - gnu.java.net.protocol.http</title></head>
|
||||
|
||||
<body>
|
||||
|
||||
<p>
|
||||
This package contains an HTTP/1.1 client, as described in RFC 2616.
|
||||
It supports the following features:
|
||||
<ul>
|
||||
<li>Persistent connections</li>
|
||||
<li>Basic and Digest authentication (RFC 2617)</li>
|
||||
<li>HTTPS</li>
|
||||
<li>HTTP proxies</li>
|
||||
<li>HTTP/1.0 compatibility</li>
|
||||
<li>Support for WebDAV methods and other HTTP extensions</li>
|
||||
<li>Automatic decoding of the chunked transfer-coding</li>
|
||||
<li>Parsing of HTTP date headers</li>
|
||||
<li>Support for the 100-continue expectation</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The API is similar to the <a href='http://www.webdav.org/neon/'>neon</a>
|
||||
WebDAV/HTTP library. A logical connection to the server is instantiated,
|
||||
and multiple requests can be issued for this connection. Each request
|
||||
has an atomic <code>dispatch</code> method which returns the response.
|
||||
All I/O, authentication, etc is handled by registering callback objects
|
||||
with the request prior to dispatch, which are notified during the dispatch
|
||||
procedure as necessary. Simple byte-array content callbacks are supplied
|
||||
which can manage any request/response content that fits in available memory.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
An URL stream handler is provided, supporting the full HttpURLConnection
|
||||
specification.
|
||||
</p>
|
||||
|
||||
</body>
|
76
libjava/classpath/gnu/java/net/protocol/https/Handler.java
Normal file
76
libjava/classpath/gnu/java/net/protocol/https/Handler.java
Normal file
|
@ -0,0 +1,76 @@
|
|||
/* Handler.java --
|
||||
Copyright (C) 2004, 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.https;
|
||||
|
||||
import gnu.java.net.protocol.http.HTTPConnection;
|
||||
import gnu.java.net.protocol.http.HTTPURLConnection;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLStreamHandler;
|
||||
|
||||
/**
|
||||
* An HTTPS URL stream handler.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public class Handler
|
||||
extends URLStreamHandler
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the default HTTPS port (443).
|
||||
*/
|
||||
protected int getDefaultPort()
|
||||
{
|
||||
return HTTPConnection.HTTPS_PORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an HTTPURLConnection for the given URL.
|
||||
*/
|
||||
public URLConnection openConnection(URL url)
|
||||
throws IOException
|
||||
{
|
||||
return new HTTPURLConnection(url);
|
||||
}
|
||||
|
||||
}
|
||||
|
170
libjava/classpath/gnu/java/net/protocol/jar/Connection.java
Normal file
170
libjava/classpath/gnu/java/net/protocol/jar/Connection.java
Normal file
|
@ -0,0 +1,170 @@
|
|||
/* Connection - jar url connection for java.net
|
||||
Copyright (C) 1999, 2002, 2003, 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.jar;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Hashtable;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
/**
|
||||
* This subclass of java.net.JarURLConnection models a URLConnection via
|
||||
* the "jar" protocol.
|
||||
*
|
||||
* @author Kresten Krab Thorup (krab@gnu.org)
|
||||
*/
|
||||
public final class Connection extends JarURLConnection
|
||||
{
|
||||
private JarFile jar_file;
|
||||
private JarEntry jar_entry;
|
||||
private URL jar_url;
|
||||
|
||||
public static class JarFileCache
|
||||
{
|
||||
private static Hashtable cache = new Hashtable();
|
||||
private static final int READBUFSIZE = 4*1024;
|
||||
|
||||
public static synchronized JarFile get (URL url) throws IOException
|
||||
{
|
||||
JarFile jf = (JarFile) cache.get (url);
|
||||
|
||||
if (jf != null)
|
||||
return jf;
|
||||
|
||||
if ("file".equals (url.getProtocol()))
|
||||
{
|
||||
File f = new File (url.getFile());
|
||||
jf = new JarFile (f, true, ZipFile.OPEN_READ);
|
||||
}
|
||||
else
|
||||
{
|
||||
URLConnection urlconn = url.openConnection();
|
||||
InputStream is = urlconn.getInputStream();
|
||||
byte[] buf = new byte [READBUFSIZE];
|
||||
File f = File.createTempFile ("cache", "jar");
|
||||
FileOutputStream fos = new FileOutputStream (f);
|
||||
int len = 0;
|
||||
|
||||
while ((len = is.read (buf)) != -1)
|
||||
{
|
||||
fos.write (buf, 0, len);
|
||||
}
|
||||
|
||||
fos.close();
|
||||
// Always verify the Manifest, open read only and delete when done.
|
||||
jf = new JarFile (f, true,
|
||||
ZipFile.OPEN_READ | ZipFile.OPEN_DELETE);
|
||||
}
|
||||
|
||||
cache.put (url, jf);
|
||||
|
||||
return jf;
|
||||
}
|
||||
}
|
||||
|
||||
protected Connection(URL url)
|
||||
throws MalformedURLException
|
||||
{
|
||||
super(url);
|
||||
}
|
||||
|
||||
public synchronized void connect() throws IOException
|
||||
{
|
||||
// Call is ignored if already connected.
|
||||
if (connected)
|
||||
return;
|
||||
|
||||
jar_url = getJarFileURL();
|
||||
jar_file = JarFileCache.get (jar_url);
|
||||
String entry_name = getEntryName();
|
||||
|
||||
if (entry_name != null
|
||||
&& !entry_name.equals (""))
|
||||
{
|
||||
jar_entry = (JarEntry) jar_file.getEntry (entry_name);
|
||||
|
||||
if(jar_entry == null)
|
||||
throw new IOException ("No entry for " + entry_name + " exists.");
|
||||
}
|
||||
|
||||
connected = true;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException
|
||||
{
|
||||
if (!connected)
|
||||
connect();
|
||||
|
||||
if (! doInput)
|
||||
throw new ProtocolException("Can't open InputStream if doInput is false");
|
||||
|
||||
if (jar_entry == null)
|
||||
throw new IOException (jar_url + " couldn't be found.");
|
||||
|
||||
return jar_file.getInputStream (jar_entry);
|
||||
}
|
||||
|
||||
public synchronized JarFile getJarFile() throws IOException
|
||||
{
|
||||
if (!connected)
|
||||
connect();
|
||||
|
||||
if (! doInput)
|
||||
throw new ProtocolException("Can't open JarFile if doInput is false");
|
||||
|
||||
return jar_file;
|
||||
}
|
||||
|
||||
public int getContentLength()
|
||||
{
|
||||
if (!connected)
|
||||
return -1;
|
||||
|
||||
return (int) jar_entry.getSize();
|
||||
}
|
||||
}
|
173
libjava/classpath/gnu/java/net/protocol/jar/Handler.java
Normal file
173
libjava/classpath/gnu/java/net/protocol/jar/Handler.java
Normal file
|
@ -0,0 +1,173 @@
|
|||
/* gnu.java.net.protocol.jar.Handler - jar protocol handler for java.net
|
||||
Copyright (C) 1999, 2002, 2003, 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.jar;
|
||||
|
||||
import gnu.java.net.URLParseError;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLStreamHandler;
|
||||
|
||||
/**
|
||||
* @author Kresten Krab Thorup (krab@gnu.org)
|
||||
*/
|
||||
public class Handler extends URLStreamHandler
|
||||
{
|
||||
/**
|
||||
* A do nothing constructor
|
||||
*/
|
||||
public Handler()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returs a new JarURLConnection for the specified URL
|
||||
*
|
||||
* @param url The URL to return a connection for
|
||||
*
|
||||
* @return The URLConnection
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected URLConnection openConnection(URL url) throws IOException
|
||||
{
|
||||
return new Connection(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method overrides URLStreamHandler's for parsing url of protocol "jar"
|
||||
*
|
||||
* @param url The URL object in which to store the results
|
||||
* @param url_string The String-ized URL to parse
|
||||
* @param start The position in the string to start scanning from
|
||||
* @param end The position in the string to stop scanning
|
||||
*/
|
||||
protected void parseURL (URL url, String url_string, int start, int end)
|
||||
{
|
||||
// This method does not throw an exception or return a value. Thus our
|
||||
// strategy when we encounter an error in parsing is to return without
|
||||
// doing anything.
|
||||
String file = url.getFile();
|
||||
|
||||
if (!file.equals(""))
|
||||
{ //has context url
|
||||
url_string = url_string.substring (start, end);
|
||||
if (url_string.startsWith("/"))
|
||||
{ //url string is an absolute path
|
||||
int idx = file.lastIndexOf ("!/");
|
||||
|
||||
if (idx < 0)
|
||||
throw new URLParseError("no !/ in spec");
|
||||
|
||||
file = file.substring (0, idx + 1) + url_string;
|
||||
}
|
||||
else if (url_string.length() > 0)
|
||||
{
|
||||
int idx = file.lastIndexOf ("/");
|
||||
if (idx == -1) //context path is weird
|
||||
file = "/" + url_string;
|
||||
else if (idx == (file.length() - 1))
|
||||
//just concatenate two parts
|
||||
file = file + url_string;
|
||||
else
|
||||
// according to Java API Documentation, here is a little different
|
||||
// with URLStreamHandler.parseURL
|
||||
// but JDK seems doesn't handle it well
|
||||
file = file.substring(0, idx + 1) + url_string;
|
||||
}
|
||||
|
||||
setURL (url, "jar", url.getHost(), url.getPort(), file, null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Bunches of things should be true. Make sure.
|
||||
if (end < start)
|
||||
return;
|
||||
if (end - start < 2)
|
||||
return;
|
||||
if (start > url_string.length())
|
||||
return;
|
||||
|
||||
// Skip remains of protocol
|
||||
url_string = url_string.substring (start, end);
|
||||
|
||||
int jar_stop;
|
||||
if ((jar_stop = url_string.indexOf("!/")) < 0)
|
||||
throw new URLParseError("no !/ in spec");
|
||||
|
||||
try
|
||||
{
|
||||
new URL(url_string.substring (0, jar_stop));
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
throw new URLParseError("invalid inner URL: " + e.getMessage());
|
||||
}
|
||||
|
||||
if (!url.getProtocol().equals ("jar") )
|
||||
throw new URLParseError("unexpected protocol " + url.getProtocol());
|
||||
|
||||
setURL (url, "jar", url.getHost(), url.getPort(), url_string, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method converts a Jar URL object into a String.
|
||||
*
|
||||
* @param url The URL object to convert
|
||||
*/
|
||||
protected String toExternalForm (URL url)
|
||||
{
|
||||
String file = url.getFile();
|
||||
String ref = url.getRef();
|
||||
|
||||
// return "jar:" + file;
|
||||
// Performance!!:
|
||||
// Do the concatenation manually to avoid resize StringBuffer's
|
||||
// internal buffer. The length of ref is not taken into consideration
|
||||
// as it's a rare path.
|
||||
StringBuffer sb = new StringBuffer (file.length() + 5);
|
||||
sb.append ("jar:");
|
||||
sb.append (file);
|
||||
if (ref != null)
|
||||
sb.append('#').append(ref);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
46
libjava/classpath/gnu/java/net/protocol/jar/package.html
Normal file
46
libjava/classpath/gnu/java/net/protocol/jar/package.html
Normal file
|
@ -0,0 +1,46 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<!-- package.html - describes classes in gnu.java.net.protocol.jar 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.jar</title></head>
|
||||
|
||||
<body>
|
||||
<p></p>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue