diff -r afd948aaf965 -r 460e37d40f12 jdk/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java --- 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() { - public ProxySelector run() { - return ProxySelector.getDefault(); - } - }); + new java.security.PrivilegedAction() { + public ProxySelector run() { + return ProxySelector.getDefault(); + } + }); if (sel != null) { URI uri = sun.net.www.ParseUtil.toURI(url); Iterator 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 Permission 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; }