jdk/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java
changeset 4155 460e37d40f12
parent 715 f16baef3a20e
child 5506 202f599c92aa
--- a/jdk/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java	Wed Oct 21 13:42:39 2009 +0200
+++ b/jdk/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java	Wed Oct 21 16:28:57 2009 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1994-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1994-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,10 +37,8 @@
 import java.io.FilterOutputStream;
 import java.io.FileNotFoundException;
 import java.net.URL;
-import java.net.URLStreamHandler;
 import java.net.SocketPermission;
 import java.net.UnknownHostException;
-import java.net.MalformedURLException;
 import java.net.InetSocketAddress;
 import java.net.URI;
 import java.net.Proxy;
@@ -84,7 +82,6 @@
     // In case we have to use proxies, we use HttpURLConnection
     HttpURLConnection http = null;
     private Proxy instProxy;
-    Proxy proxy = null;
 
     InputStream is = null;
     OutputStream os = null;
@@ -125,12 +122,11 @@
             ftp = cl;
         }
 
+        @Override
         public void close() throws IOException {
             super.close();
-            try {
-                if (ftp != null)
-                    ftp.closeServer();
-            } catch (IOException ex) {
+            if (ftp != null) {
+                ftp.close();
             }
         }
     }
@@ -149,12 +145,11 @@
             ftp = cl;
         }
 
+        @Override
         public void close() throws IOException {
             super.close();
-            try {
-                if (ftp != null)
-                    ftp.closeServer();
-            } catch (IOException ex) {
+            if (ftp != null) {
+                ftp.close();
             }
         }
     }
@@ -192,10 +187,12 @@
 
     private void setTimeouts() {
         if (ftp != null) {
-            if (connectTimeout >= 0)
+            if (connectTimeout >= 0) {
                 ftp.setConnectTimeout(connectTimeout);
-            if (readTimeout >= 0)
+            }
+            if (readTimeout >= 0) {
                 ftp.setReadTimeout(readTimeout);
+            }
         }
     }
 
@@ -218,21 +215,22 @@
              * Do we have to use a proxy?
              */
             ProxySelector sel = java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedAction<ProxySelector>() {
-                    public ProxySelector run() {
-                                return ProxySelector.getDefault();
-                            }
-                            });
+                    new java.security.PrivilegedAction<ProxySelector>() {
+                        public ProxySelector run() {
+                            return ProxySelector.getDefault();
+                        }
+                    });
             if (sel != null) {
                 URI uri = sun.net.www.ParseUtil.toURI(url);
                 Iterator<Proxy> it = sel.select(uri).iterator();
                 while (it.hasNext()) {
                     p = it.next();
                     if (p == null || p == Proxy.NO_PROXY ||
-                        p.type() == Proxy.Type.SOCKS)
+                        p.type() == Proxy.Type.SOCKS) {
                         break;
+                    }
                     if (p.type() != Proxy.Type.HTTP ||
-                        !(p.address() instanceof InetSocketAddress)) {
+                            !(p.address() instanceof InetSocketAddress)) {
                         sel.connectFailed(uri, p.address(), new IOException("Wrong proxy type"));
                         continue;
                     }
@@ -240,10 +238,14 @@
                     InetSocketAddress paddr = (InetSocketAddress) p.address();
                     try {
                         http = new HttpURLConnection(url, p);
-                        if (connectTimeout >= 0)
+                        http.setDoInput(getDoInput());
+                        http.setDoOutput(getDoOutput());
+                        if (connectTimeout >= 0) {
                             http.setConnectTimeout(connectTimeout);
-                        if (readTimeout >= 0)
+                        }
+                        if (readTimeout >= 0) {
                             http.setReadTimeout(readTimeout);
+                        }
                         http.connect();
                         connected = true;
                         return;
@@ -257,10 +259,14 @@
             p = instProxy;
             if (p.type() == Proxy.Type.HTTP) {
                 http = new HttpURLConnection(url, instProxy);
-                if (connectTimeout >= 0)
+                http.setDoInput(getDoInput());
+                http.setDoOutput(getDoOutput());
+                if (connectTimeout >= 0) {
                     http.setConnectTimeout(connectTimeout);
-                if (readTimeout >= 0)
+                }
+                if (readTimeout >= 0) {
                     http.setReadTimeout(readTimeout);
+                }
                 http.connect();
                 connected = true;
                 return;
@@ -270,31 +276,35 @@
         if (user == null) {
             user = "anonymous";
             String vers = java.security.AccessController.doPrivileged(
-                new GetPropertyAction("java.version"));
+                    new GetPropertyAction("java.version"));
             password = java.security.AccessController.doPrivileged(
-                new GetPropertyAction("ftp.protocol.user",
-                                      "Java" + vers +"@"));
+                    new GetPropertyAction("ftp.protocol.user",
+                                          "Java" + vers + "@"));
         }
         try {
-            if (p != null)
-                ftp = new FtpClient(p);
-            else
-                ftp = new FtpClient();
+            ftp = FtpClient.create();
+            if (p != null) {
+                ftp.setProxy(p);
+            }
             setTimeouts();
-            if (port != -1)
-                ftp.openServer(host, port);
-            else
-                ftp.openServer(host);
+            if (port != -1) {
+                ftp.connect(new InetSocketAddress(host, port));
+            } else {
+                ftp.connect(new InetSocketAddress(host, FtpClient.defaultPort()));
+            }
         } catch (UnknownHostException e) {
             // Maybe do something smart here, like use a proxy like iftp.
             // Just keep throwing for now.
             throw e;
+        } catch (FtpProtocolException fe) {
+            throw new IOException(fe);
         }
         try {
-            ftp.login(user, password);
-        } catch (sun.net.ftp.FtpLoginException e) {
-            ftp.closeServer();
-            throw e;
+            ftp.login(user, password.toCharArray());
+        } catch (sun.net.ftp.FtpProtocolException e) {
+            ftp.close();
+            // Backward compatibility
+            throw new sun.net.ftp.FtpLoginException("Invalid username/password");
         }
         connected = true;
     }
@@ -306,24 +316,29 @@
     private void decodePath(String path) {
         int i = path.indexOf(";type=");
         if (i >= 0) {
-            String s1 = path.substring(i+6, path.length());
-            if ("i".equalsIgnoreCase(s1))
+            String s1 = path.substring(i + 6, path.length());
+            if ("i".equalsIgnoreCase(s1)) {
                 type = BIN;
-            if ("a".equalsIgnoreCase(s1))
+            }
+            if ("a".equalsIgnoreCase(s1)) {
                 type = ASCII;
-            if ("d".equalsIgnoreCase(s1))
+            }
+            if ("d".equalsIgnoreCase(s1)) {
                 type = DIR;
+            }
             path = path.substring(0, i);
         }
         if (path != null && path.length() > 1 &&
-            path.charAt(0) == '/')
+                path.charAt(0) == '/') {
             path = path.substring(1);
-        if (path == null || path.length() == 0)
+        }
+        if (path == null || path.length() == 0) {
             path = "./";
+        }
         if (!path.endsWith("/")) {
             i = path.lastIndexOf('/');
             if (i > 0) {
-                filename = path.substring(i+1, path.length());
+                filename = path.substring(i + 1, path.length());
                 filename = ParseUtil.decode(filename);
                 pathname = path.substring(0, i);
             } else {
@@ -334,10 +349,11 @@
             pathname = path.substring(0, path.length() - 1);
             filename = null;
         }
-        if (pathname != null)
+        if (pathname != null) {
             fullpath = pathname + "/" + (filename != null ? filename : "");
-        else
+        } else {
             fullpath = filename;
+        }
     }
 
     /*
@@ -346,18 +362,19 @@
      * This is because, '/' is not necessarly the directory delimiter
      * on every systems.
      */
-
-    private void cd(String path) throws IOException {
-        if (path == null || "".equals(path))
+    private void cd(String path) throws FtpProtocolException, IOException {
+        if (path == null || path.isEmpty()) {
             return;
+        }
         if (path.indexOf('/') == -1) {
-            ftp.cd(ParseUtil.decode(path));
+            ftp.changeDirectory(ParseUtil.decode(path));
             return;
         }
 
-        StringTokenizer token = new StringTokenizer(path,"/");
-        while (token.hasMoreTokens())
-            ftp.cd(ParseUtil.decode(token.nextToken()));
+        StringTokenizer token = new StringTokenizer(path, "/");
+        while (token.hasMoreTokens()) {
+            ftp.changeDirectory(ParseUtil.decode(token.nextToken()));
+        }
     }
 
     /**
@@ -369,16 +386,19 @@
      * @throws  IOException if already opened for output
      * @throws  FtpProtocolException if errors occur during the transfert.
      */
+    @Override
     public InputStream getInputStream() throws IOException {
         if (!connected) {
             connect();
         }
 
-        if (http != null)
+        if (http != null) {
             return http.getInputStream();
+        }
 
-        if (os != null)
+        if (os != null) {
             throw new IOException("Already opened for output");
+        }
 
         if (is != null) {
             return is;
@@ -386,82 +406,85 @@
 
         MessageHeader msgh = new MessageHeader();
 
+        boolean isAdir = false;
         try {
             decodePath(url.getPath());
             if (filename == null || type == DIR) {
-                ftp.ascii();
+                ftp.setAsciiType();
                 cd(pathname);
-                if (filename == null)
-                    is = new FtpInputStream(ftp, ftp.list());
-                else
+                if (filename == null) {
+                    is = new FtpInputStream(ftp, ftp.list(null));
+                } else {
                     is = new FtpInputStream(ftp, ftp.nameList(filename));
+                }
             } else {
-                if (type == ASCII)
-                    ftp.ascii();
-                else
-                    ftp.binary();
+                if (type == ASCII) {
+                    ftp.setAsciiType();
+                } else {
+                    ftp.setBinaryType();
+                }
                 cd(pathname);
-                is = new FtpInputStream(ftp, ftp.get(filename));
+                is = new FtpInputStream(ftp, ftp.getFileStream(filename));
             }
 
             /* Try to get the size of the file in bytes.  If that is
-               successful, then create a MeteredStream. */
+            successful, then create a MeteredStream. */
             try {
-                String response = ftp.getResponseString();
-                int offset;
+                long l = ftp.getLastTransferSize();
+                msgh.add("content-length", Long.toString(l));
+                if (l > 0) {
 
-                if ((offset = response.indexOf(" bytes)")) != -1) {
-                    int i = offset;
-                    int c;
+                    // Wrap input stream with MeteredStream to ensure read() will always return -1
+                    // at expected length.
 
-                    while (--i >= 0 && ((c = response.charAt(i)) >= '0'
-                                        && c <= '9'))
-                        ;
-                    long l = Long.parseLong(response.substring(i + 1, offset));
-                    msgh.add("content-length", Long.toString(l));
-                    if (l > 0) {
-
-                        // Wrap input stream with MeteredStream to ensure read() will always return -1
-                        // at expected length.
+                    // Check if URL should be metered
+                    boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, "GET");
+                    ProgressSource pi = null;
 
-                        // Check if URL should be metered
-                        boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, "GET");
-                        ProgressSource pi = null;
+                    if (meteredInput) {
+                        pi = new ProgressSource(url, "GET", l);
+                        pi.beginTracking();
+                    }
 
-                        if (meteredInput)   {
-                            pi = new ProgressSource(url, "GET", l);
-                            pi.beginTracking();
-                        }
-
-                        is = new MeteredStream(is, pi, l);
-                    }
+                    is = new MeteredStream(is, pi, l);
                 }
             } catch (Exception e) {
                 e.printStackTrace();
-                /* do nothing, since all we were doing was trying to
-                   get the size in bytes of the file */
+            /* do nothing, since all we were doing was trying to
+            get the size in bytes of the file */
             }
 
-            String type = guessContentTypeFromName(fullpath);
-            if (type == null && is.markSupported()) {
-                type = guessContentTypeFromStream(is);
-            }
-            if (type != null) {
-                msgh.add("content-type", type);
+            if (isAdir) {
+                msgh.add("content-type", "text/plain");
+                msgh.add("access-type", "directory");
+            } else {
+                msgh.add("access-type", "file");
+                String ftype = guessContentTypeFromName(fullpath);
+                if (ftype == null && is.markSupported()) {
+                    ftype = guessContentTypeFromStream(is);
+                }
+                if (ftype != null) {
+                    msgh.add("content-type", ftype);
+                }
             }
         } catch (FileNotFoundException e) {
             try {
                 cd(fullpath);
                 /* if that worked, then make a directory listing
-                   and build an html stream with all the files in
-                   the directory */
-                ftp.ascii();
+                and build an html stream with all the files in
+                the directory */
+                ftp.setAsciiType();
 
-                is = new FtpInputStream(ftp, ftp.list());
+                is = new FtpInputStream(ftp, ftp.list(null));
                 msgh.add("content-type", "text/plain");
+                msgh.add("access-type", "directory");
             } catch (IOException ex) {
                 throw new FileNotFoundException(fullpath);
+            } catch (FtpProtocolException ex2) {
+                throw new FileNotFoundException(fullpath);
             }
+        } catch (FtpProtocolException ftpe) {
+            throw new IOException(ftpe);
         }
         setProperties(msgh);
         return is;
@@ -477,31 +500,45 @@
      *          points to a directory
      * @throws  FtpProtocolException if errors occur during the transfert.
      */
+    @Override
     public OutputStream getOutputStream() throws IOException {
         if (!connected) {
             connect();
         }
 
-        if (http != null)
-            return http.getOutputStream();
+        if (http != null) {
+            OutputStream out = http.getOutputStream();
+            // getInputStream() is neccessary to force a writeRequests()
+            // on the http client.
+            http.getInputStream();
+            return out;
+        }
 
-        if (is != null)
+        if (is != null) {
             throw new IOException("Already opened for input");
+        }
 
         if (os != null) {
             return os;
         }
 
         decodePath(url.getPath());
-        if (filename == null || filename.length() == 0)
+        if (filename == null || filename.length() == 0) {
             throw new IOException("illegal filename for a PUT");
-        if (pathname != null)
-            cd(pathname);
-        if (type == ASCII)
-            ftp.ascii();
-        else
-            ftp.binary();
-        os = new FtpOutputStream(ftp, ftp.put(filename));
+        }
+        try {
+            if (pathname != null) {
+                cd(pathname);
+            }
+            if (type == ASCII) {
+                ftp.setAsciiType();
+            } else {
+                ftp.setBinaryType();
+            }
+            os = new FtpOutputStream(ftp, ftp.putFileStream(filename, false));
+        } catch (FtpProtocolException e) {
+            throw new IOException(e);
+        }
         return os;
     }
 
@@ -514,12 +551,13 @@
      *
      * @return  The <code>Permission</code> object.
      */
+    @Override
     public Permission getPermission() {
         if (permission == null) {
-            int port = url.getPort();
-            port = port < 0 ? FtpClient.FTP_PORT : port;
-            String host = this.host + ":" + port;
-            permission = new SocketPermission(host, "connect");
+            int urlport = url.getPort();
+            urlport = urlport < 0 ? FtpClient.defaultPort() : urlport;
+            String urlhost = this.host + ":" + urlport;
+            permission = new SocketPermission(urlhost, "connect");
         }
         return permission;
     }
@@ -534,21 +572,22 @@
      * @throws IllegalStateException if already connected
      * @see #getRequestProperty(java.lang.String)
      */
+    @Override
     public void setRequestProperty(String key, String value) {
-        super.setRequestProperty (key, value);
-        if ("type".equals (key)) {
-            if ("i".equalsIgnoreCase(value))
+        super.setRequestProperty(key, value);
+        if ("type".equals(key)) {
+            if ("i".equalsIgnoreCase(value)) {
                 type = BIN;
-            else if ("a".equalsIgnoreCase(value))
+            } else if ("a".equalsIgnoreCase(value)) {
                 type = ASCII;
-            else
-                if ("d".equalsIgnoreCase(value))
-                    type = DIR;
-            else
+            } else if ("d".equalsIgnoreCase(value)) {
+                type = DIR;
+            } else {
                 throw new IllegalArgumentException(
-                    "Value of '" + key +
-                    "' request property was '" + value +
-                    "' when it must be either 'i', 'a' or 'd'");
+                        "Value of '" + key +
+                        "' request property was '" + value +
+                        "' when it must be either 'i', 'a' or 'd'");
+            }
         }
     }
 
@@ -562,33 +601,41 @@
      * @throws IllegalStateException if already connected
      * @see #setRequestProperty(java.lang.String, java.lang.String)
      */
+    @Override
     public String getRequestProperty(String key) {
-        String value = super.getRequestProperty (key);
+        String value = super.getRequestProperty(key);
 
         if (value == null) {
-            if ("type".equals (key))
+            if ("type".equals(key)) {
                 value = (type == ASCII ? "a" : type == DIR ? "d" : "i");
+            }
         }
 
         return value;
     }
 
+    @Override
     public void setConnectTimeout(int timeout) {
-        if (timeout < 0)
+        if (timeout < 0) {
             throw new IllegalArgumentException("timeouts can't be negative");
+        }
         connectTimeout = timeout;
     }
 
+    @Override
     public int getConnectTimeout() {
         return (connectTimeout < 0 ? 0 : connectTimeout);
     }
 
+    @Override
     public void setReadTimeout(int timeout) {
-        if (timeout < 0)
+        if (timeout < 0) {
             throw new IllegalArgumentException("timeouts can't be negative");
+        }
         readTimeout = timeout;
     }
 
+    @Override
     public int getReadTimeout() {
         return readTimeout < 0 ? 0 : readTimeout;
     }