Name: tb29552 Date: 09/07/99
1) Run the test program to reproduce the problem.
2) Error msg:
java.net.UnknownServiceException: protocol doesn't support output
at java.net.URLConnection.getOutputStream(URLConnection.java:618)
at FtpTest.main(Compiled Code)
3) none
4) java version "1.2.1"
Classic VM (build JDK-1.2.1-A, native threads)
5) This has bearing on part of the problem. A computer (Win98)
with multiple ethernet interfaces (one netword card and one PPP
via modem).
In the process of providing an output stream via an ftp URL I
have fixed three bugs and written eight distinct enhancements.
All of the code overlaps in the same files so separating them
into multiple reports is impractical (I'd have to assume that
you processed each in precise order for the context diffs to
make any sense). I have, therefore, included all of the changes
in one context diff. However, each change is discussed
individually below.
The changes are as follows:
1) BUG: The input stream processed the
URL: ftp://ftp.sun.com/pub/showrev.dat as a request for the
file '/pub/showrev.dat' on the host 'ftp.sun.com'. Please note
that this does not conform with the description of a URL in
RFC1738:
url-path
The rest of the locator consists of data specific to the
scheme, and is known as the "url-path". It supplies the
details of how the specified resource can be accessed.
Note that the "/" between the host (or port) and the
url-path is NOT part of the url-path.
The first character returned by getURL() [the '/' at the
beginning of '/pub/showrev.dat'] is now discarded.
2) BUG: Hosts with multiple IP addresses were not properly
supported. The problem was that FtpClient relied on
InetAddress.getLocalHost().getAddress() to get the IP address
sent via the PORT command to the ftp server. However, this
IP address has only a 1 in N (where N is the number of
network/modem/other IP interfaces present on the computer) of
succeeding. The modified code now tries to use the local IP
address of the existing command channel (the inherited telnet
socket). If that fails, which it may since getLocalAddress
is permitted to return '0.0.0.0', the code attempts to open a
data channel using every IP address returned by
InetAddress.getAllByName (The successful address is cached so
subsequent PORT commands require no iteration).
3) BUG: The reply processing did not allow for the (obscure)
case of two pending replies being sent consequtively by the
server. The old code cleared replyPending AFTER reading the
second reply rather than BEFORE reading it.
4) ENHANCEMENT: Added an inner class, DataSocket, to perform the
functionality of FtpInputStream. The new class eliminated the
need to create FtpOutputStream and actually eliminated all use
of FtpInputStream.
The new DataSocket offers two new capabilities:
a) It's instance counted so that code with access to the
FtpClient instance can't close the command channel BEFORE
closing the data channels. This usually forces the data channels
to terminate.
b) It can support multiple, simultaneous data channels (provided
the ftp server supports them). This capability is indicated by
the ftp server issuing a completed reply prior to the data
channel closing.
5)ENHANCEMENT: Thrown exceptions, if at all possible, now
include the ftp server's reply in their message [This is why I
started working on this code. The original exception message
printed "POST" when I really needed to see "POST 10.0.0.2"!].
6) ENHANCEMENT: FtpClient now supports the pwd() method. This
method was added as FtpURLConnection objects may now "share" a
single FtpClient. The second FtpURLConnection needs to reset
the FtpClient to its original directory (hence pwd()) so that
a relative url-path will work.
7) ENHANCEMENT: FtpClient's cd method now accepts either null
or "" as a request to return the ftp server to the same working
directory as it had when the FtpClient first opened the command
connection. This would not be necessary if I knew that all
servers supported "~" as the "home directory".
8) ENHANCEMENT: FtpClient now supports the noop() method. This
can be used to test whether the ftp server has closed
(timed-out) the command channel.
9) ENHANCEMENT: FtpClient now supports the isBusy() method.
Many, if not all, ftp servers are highly serialized. As a
result, any command sent after FtpClient recieves a pending
reply and before FtpClient recieves the completed reply will
block this thread (It's an I/O wait, not something that I did).
The isBusy() method simply indicates that FtpClient is still
expecting a completed reply from the ftp server.
10) ENHANCEMENT: FtpURLConnection now supports opening either
(but not both) an input stream or an output stream.
11) ENHANCEMENT: FtpURLConnection is no longer tightly coupled
to a single FtpClient. Multiple, sequential file transfers can
now be performed using a single FtpClient. Parallel transfers,
or transfers to distinct hosts, are still handled using
individual FtpClient objects. This particular change was not
required to make ftp output streams work. The original author
of FtpURLConnection left a comment in the code indicating
that this change would be desireable.
TEST CASE:
class FtpTest {
public static void main(String[] args) {
int i;
try {
java.net.URL inURL = new java.net.URL
("ftp://ftp.sun.com/pub/showrev.dat");
java.net.URL outURL = new java.net.URL
("ftp://localhost/tmp/showrev.out");
java.net.URLConnection inConnection = inURL.openConnection ();
java.net.URLConnection outConnection = outURL.openConnection ();
java.io.InputStream is = inConnection.getInputStream ();
java.io.OutputStream os = outConnection.getOutputStream ();
byte[] buffer = new byte [1024];
boolean once = true;
while ((i = is.read (buffer)) >= 0) {
os.write (buffer, 0, i);
}
is.close ();
os.close ();
} catch (Throwable e) {
e.printStackTrace ();
}
}
}
(Review ID: 94414)
======================================================================
krystyna.polomski@Eng 2001-03-22
updated FtpTest class to work within
Sun. Attached as xxFtpTest.java
- duplicates
-
JDK-4066202 Add an FtpURLConnection class and/or an FTPClient class. Exi
- Closed