6893702: Overhaul of Ftp Client internal code
Major reorg of internal FTP client code Reviewed-by: chegar
This commit is contained in:
parent
48792ee40c
commit
196a0c5cf8
@ -45,8 +45,14 @@ FILES_java = \
|
||||
sun/net/dns/ResolverConfiguration.java \
|
||||
sun/net/dns/ResolverConfigurationImpl.java \
|
||||
sun/net/ftp/FtpClient.java \
|
||||
sun/net/ftp/FtpClientProvider.java \
|
||||
sun/net/ftp/FtpDirEntry.java \
|
||||
sun/net/ftp/FtpReplyCode.java \
|
||||
sun/net/ftp/FtpDirParser.java \
|
||||
sun/net/ftp/FtpLoginException.java \
|
||||
sun/net/ftp/FtpProtocolException.java \
|
||||
sun/net/ftp/impl/FtpClient.java \
|
||||
sun/net/ftp/impl/DefaultFtpClientProvider.java \
|
||||
sun/net/spi/DefaultProxySelector.java \
|
||||
sun/net/spi/nameservice/NameServiceDescriptor.java \
|
||||
sun/net/spi/nameservice/NameService.java \
|
||||
|
File diff suppressed because it is too large
Load Diff
158
jdk/src/share/classes/sun/net/ftp/FtpClientProvider.java
Normal file
158
jdk/src/share/classes/sun/net/ftp/FtpClientProvider.java
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
package sun.net.ftp;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ServiceConfigurationError;
|
||||
//import sun.misc.Service;
|
||||
|
||||
/**
|
||||
* Service provider class for FtpClient.
|
||||
* Sub-classes of FtpClientProvider provide an implementation of {@link FtpClient}
|
||||
* and associated classes. Applications do not normally use this class directly.
|
||||
* See {@link #provider() } for how providers are found and loaded.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public abstract class FtpClientProvider {
|
||||
|
||||
/**
|
||||
* Creates a FtpClient from this provider.
|
||||
*
|
||||
* @return The created {@link FtpClient}.
|
||||
*/
|
||||
public abstract FtpClient createFtpClient();
|
||||
private static final Object lock = new Object();
|
||||
private static FtpClientProvider provider = null;
|
||||
|
||||
/**
|
||||
* Initializes a new instance of this class.
|
||||
*
|
||||
* @throws SecurityException if a security manager is installed and it denies
|
||||
* {@link RuntimePermission}<tt>("ftpClientProvider")</tt>
|
||||
*/
|
||||
protected FtpClientProvider() {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new RuntimePermission("ftpClientProvider"));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean loadProviderFromProperty() {
|
||||
String cm = System.getProperty("sun.net.ftpClientProvider");
|
||||
if (cm == null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
Class c = Class.forName(cm, true, null);
|
||||
provider = (FtpClientProvider) c.newInstance();
|
||||
return true;
|
||||
} catch (ClassNotFoundException x) {
|
||||
throw new ServiceConfigurationError(x.toString());
|
||||
} catch (IllegalAccessException x) {
|
||||
throw new ServiceConfigurationError(x.toString());
|
||||
} catch (InstantiationException x) {
|
||||
throw new ServiceConfigurationError(x.toString());
|
||||
} catch (SecurityException x) {
|
||||
throw new ServiceConfigurationError(x.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean loadProviderAsService() {
|
||||
// Iterator i = Service.providers(FtpClientProvider.class,
|
||||
// ClassLoader.getSystemClassLoader());
|
||||
// while (i.hasNext()) {
|
||||
// try {
|
||||
// provider = (FtpClientProvider) i.next();
|
||||
// return true;
|
||||
// } catch (ServiceConfigurationError sce) {
|
||||
// if (sce.getCause() instanceof SecurityException) {
|
||||
// // Ignore, try next provider, if any
|
||||
// continue;
|
||||
// }
|
||||
// throw sce;
|
||||
// }
|
||||
// }
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the system wide default FtpClientProvider for this invocation of
|
||||
* the Java virtual machine.
|
||||
*
|
||||
* <p> The first invocation of this method locates the default provider
|
||||
* object as follows: </p>
|
||||
*
|
||||
* <ol>
|
||||
*
|
||||
* <li><p> If the system property
|
||||
* <tt>java.net.FtpClientProvider</tt> is defined then it is
|
||||
* taken to be the fully-qualified name of a concrete provider class.
|
||||
* The class is loaded and instantiated; if this process fails then an
|
||||
* unspecified unchecked error or exception is thrown. </p></li>
|
||||
*
|
||||
* <li><p> If a provider class has been installed in a jar file that is
|
||||
* visible to the system class loader, and that jar file contains a
|
||||
* provider-configuration file named
|
||||
* <tt>java.net.FtpClientProvider</tt> in the resource
|
||||
* directory <tt>META-INF/services</tt>, then the first class name
|
||||
* specified in that file is taken. The class is loaded and
|
||||
* instantiated; if this process fails then an unspecified unchecked error or exception is
|
||||
* thrown. </p></li>
|
||||
*
|
||||
* <li><p> Finally, if no provider has been specified by any of the above
|
||||
* means then the system-default provider class is instantiated and the
|
||||
* result is returned. </p></li>
|
||||
*
|
||||
* </ol>
|
||||
*
|
||||
* <p> Subsequent invocations of this method return the provider that was
|
||||
* returned by the first invocation. </p>
|
||||
*
|
||||
* @return The system-wide default FtpClientProvider
|
||||
*/
|
||||
public static FtpClientProvider provider() {
|
||||
synchronized (lock) {
|
||||
if (provider != null) {
|
||||
return provider;
|
||||
}
|
||||
return (FtpClientProvider) AccessController.doPrivileged(
|
||||
new PrivilegedAction<Object>() {
|
||||
|
||||
public Object run() {
|
||||
if (loadProviderFromProperty()) {
|
||||
return provider;
|
||||
}
|
||||
if (loadProviderAsService()) {
|
||||
return provider;
|
||||
}
|
||||
provider = new sun.net.ftp.impl.DefaultFtpClientProvider();
|
||||
return provider;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
331
jdk/src/share/classes/sun/net/ftp/FtpDirEntry.java
Normal file
331
jdk/src/share/classes/sun/net/ftp/FtpDirEntry.java
Normal file
@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
package sun.net.ftp;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* A {@code FtpDirEntry} is a class agregating all the information that the FTP client
|
||||
* can gather from the server by doing a {@code LST} (or {@code NLST}) command and
|
||||
* parsing the output. It will typically contain the name, type, size, last modification
|
||||
* time, owner and group of the file, although some of these could be unavailable
|
||||
* due to specific FTP server limitations.
|
||||
*
|
||||
* @see sun.net.ftp.FtpDirParser
|
||||
* @since 1.7
|
||||
*/
|
||||
public class FtpDirEntry {
|
||||
|
||||
public enum Type {
|
||||
|
||||
FILE, DIR, PDIR, CDIR, LINK
|
||||
};
|
||||
|
||||
public enum Permission {
|
||||
|
||||
USER(0), GROUP(1), OTHERS(2);
|
||||
int value;
|
||||
|
||||
Permission(int v) {
|
||||
value = v;
|
||||
}
|
||||
};
|
||||
private final String name;
|
||||
private String user = null;
|
||||
private String group = null;
|
||||
private long size = -1;
|
||||
private java.util.Date created = null;
|
||||
private java.util.Date lastModified = null;
|
||||
private Type type = Type.FILE;
|
||||
private boolean[][] permissions = null;
|
||||
private HashMap<String, String> facts = new HashMap<String, String>();
|
||||
|
||||
private FtpDirEntry() {
|
||||
name = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an FtpDirEntry instance with only the name being set.
|
||||
*
|
||||
* @param name The name of the file
|
||||
*/
|
||||
public FtpDirEntry(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the remote file.
|
||||
*
|
||||
* @return a {@code String} containing the name of the remote file.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user name of the owner of the file as returned by the FTP
|
||||
* server, if provided. This could be a name or a user id (number).
|
||||
*
|
||||
* @return a {@code String} containing the user name or
|
||||
* {@code null} if that information is not available.
|
||||
*/
|
||||
public String getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the user name of the owner of the file. Intended mostly to be
|
||||
* used from inside a {@link java.net.FtpDirParser} implementation.
|
||||
*
|
||||
* @param user The user name of the owner of the file, or {@code null}
|
||||
* if that information is not available.
|
||||
* @return this FtpDirEntry
|
||||
*/
|
||||
public FtpDirEntry setUser(String user) {
|
||||
this.user = user;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the group name of the file as returned by the FTP
|
||||
* server, if provided. This could be a name or a group id (number).
|
||||
*
|
||||
* @return a {@code String} containing the group name or
|
||||
* {@code null} if that information is not available.
|
||||
*/
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the group to which the file belong. Intended mostly to be
|
||||
* used from inside a {@link java.net.FtpDirParser} implementation.
|
||||
*
|
||||
* @param group The name of the group to which the file belong, or {@code null}
|
||||
* if that information is not available.
|
||||
* @return this FtpDirEntry
|
||||
*/
|
||||
public FtpDirEntry setGroup(String group) {
|
||||
this.group = group;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the remote file as it was returned by the FTP
|
||||
* server, if provided.
|
||||
*
|
||||
* @return the size of the file or -1 if that information is not available.
|
||||
*/
|
||||
public long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of that file. Intended mostly to be used from inside an
|
||||
* {@link java.net.FtpDirParser} implementation.
|
||||
*
|
||||
* @param size The size, in bytes, of that file. or -1 if unknown.
|
||||
* @return this FtpDirEntry
|
||||
*/
|
||||
public FtpDirEntry setSize(long size) {
|
||||
this.size = size;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of the remote file as it was returned by the FTP
|
||||
* server, if provided.
|
||||
* It returns a FtpDirEntry.Type enum and the values can be:
|
||||
* - FtpDirEntry.Type.FILE for a normal file
|
||||
* - FtpDirEntry.Type.DIR for a directory
|
||||
* - FtpDirEntry.Type.LINK for a symbolic link
|
||||
*
|
||||
* @return a {@code FtpDirEntry.Type} describing the type of the file
|
||||
* or {@code null} if that information is not available.
|
||||
*/
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of the file. Intended mostly to be used from inside an
|
||||
* {@link java.net.FtpDirParser} implementation.
|
||||
*
|
||||
* @param type the type of this file or {@code null} if that information
|
||||
* is not available.
|
||||
* @return this FtpDirEntry
|
||||
*/
|
||||
public FtpDirEntry setType(Type type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last modification time of the remote file as it was returned
|
||||
* by the FTP server, if provided, {@code null} otherwise.
|
||||
*
|
||||
* @return a <code>Date</code> representing the last time the file was
|
||||
* modified on the server, or {@code null} if that
|
||||
* information is not available.
|
||||
*/
|
||||
public java.util.Date getLastModified() {
|
||||
return this.lastModified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the last modification time of the file. Intended mostly to be used
|
||||
* from inside an {@link java.net.FtpDirParser} implementation.
|
||||
*
|
||||
* @param lastModified The Date representing the last modification time, or
|
||||
* {@code null} if that information is not available.
|
||||
* @return this FtpDirEntry
|
||||
*/
|
||||
public FtpDirEntry setLastModified(Date lastModified) {
|
||||
this.lastModified = lastModified;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether read access is granted for a specific permission.
|
||||
*
|
||||
* @param p the Permission (user, group, others) to check.
|
||||
* @return {@code true} if read access is granted.
|
||||
*/
|
||||
public boolean canRead(Permission p) {
|
||||
if (permissions != null) {
|
||||
return permissions[p.value][0];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether write access is granted for a specific permission.
|
||||
*
|
||||
* @param p the Permission (user, group, others) to check.
|
||||
* @return {@code true} if write access is granted.
|
||||
*/
|
||||
public boolean canWrite(Permission p) {
|
||||
if (permissions != null) {
|
||||
return permissions[p.value][1];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether execute access is granted for a specific permission.
|
||||
*
|
||||
* @param p the Permission (user, group, others) to check.
|
||||
* @return {@code true} if execute access is granted.
|
||||
*/
|
||||
public boolean canExexcute(Permission p) {
|
||||
if (permissions != null) {
|
||||
return permissions[p.value][2];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the permissions for that file. Intended mostly to be used
|
||||
* from inside an {@link java.net.FtpDirParser} implementation.
|
||||
* The permissions array is a 3x3 {@code boolean} array, the first index being
|
||||
* the User, group or owner (0, 1 and 2 respectively) while the second
|
||||
* index is read, write or execute (0, 1 and 2 respectively again).
|
||||
* <p>E.G.: {@code permissions[1][2]} is the group/execute permission.</p>
|
||||
*
|
||||
* @param permissions a 3x3 {@code boolean} array
|
||||
* @return this {@code FtpDirEntry}
|
||||
*/
|
||||
public FtpDirEntry setPermissions(boolean[][] permissions) {
|
||||
this.permissions = permissions;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a 'fact', as defined in RFC 3659, to the list of facts of this file.
|
||||
* Intended mostly to be used from inside a {@link java.net.FtpDirParser}
|
||||
* implementation.
|
||||
*
|
||||
* @param fact the name of the fact (e.g. "Media-Type"). It is not case-sensitive.
|
||||
* @param value the value associated with this fact.
|
||||
* @return this {@code FtpDirEntry}
|
||||
*/
|
||||
public FtpDirEntry addFact(String fact, String value) {
|
||||
facts.put(fact.toLowerCase(), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the requested 'fact', as defined in RFC 3659, if available.
|
||||
*
|
||||
* @param fact The name of the fact *e.g. "Media-Type"). It is not case sensitive.
|
||||
* @return The value of the fact or, {@code null} if that fact wasn't
|
||||
* provided by the server.
|
||||
*/
|
||||
public String getFact(String fact) {
|
||||
return facts.get(fact.toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the creation time of the file, when provided by the server.
|
||||
*
|
||||
* @return The Date representing the creation time, or {@code null}
|
||||
* if the server didn't provide that information.
|
||||
*/
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the creation time for that file. Intended mostly to be used from
|
||||
* inside a {@link java.net.FtpDirParser} implementation.
|
||||
*
|
||||
* @param created the Date representing the creation time for that file, or
|
||||
* {@code null} if that information is not available.
|
||||
* @return this FtpDirEntry
|
||||
*/
|
||||
public FtpDirEntry setCreated(Date created) {
|
||||
this.created = created;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the object.
|
||||
* The {@code toString} method for class {@code FtpDirEntry}
|
||||
* returns a string consisting of the name of the file, followed by its
|
||||
* type between brackets, followed by the user and group between
|
||||
* parenthesis, then size between '{', and, finally, the lastModified of last
|
||||
* modification if it's available.
|
||||
*
|
||||
* @return a string representation of the object.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
if (lastModified == null) {
|
||||
return name + " [" + type + "] (" + user + " / " + group + ") " + size;
|
||||
}
|
||||
return name + " [" + type + "] (" + user + " / " + group + ") {" + size + "} " + java.text.DateFormat.getDateInstance().format(lastModified);
|
||||
}
|
||||
}
|
49
jdk/src/share/classes/sun/net/ftp/FtpDirParser.java
Normal file
49
jdk/src/share/classes/sun/net/ftp/FtpDirParser.java
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package sun.net.ftp;
|
||||
|
||||
/**
|
||||
* This interface describes a parser for the FtpClient class. Such a parser is
|
||||
* used when listing a remote directory to transform text lines like:
|
||||
* drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog
|
||||
* into FtpDirEntry instances.
|
||||
*
|
||||
* @see java.net.FtpClient#setFileParser(FtpDirParser)
|
||||
* @since 1.7
|
||||
*/
|
||||
public interface FtpDirParser {
|
||||
|
||||
/**
|
||||
* Takes one line from a directory listing and returns an FtpDirEntry instance
|
||||
* based on the information contained.
|
||||
*
|
||||
* @param line a <code>String</code>, a line sent by the FTP server as a
|
||||
* result of the LST command.
|
||||
* @return an <code>FtpDirEntry</code> instance.
|
||||
* @see java.net.FtpDirEntry
|
||||
*/
|
||||
public FtpDirEntry parseLine(String line);
|
||||
}
|
@ -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
|
||||
@ -25,7 +25,7 @@
|
||||
|
||||
package sun.net.ftp;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This exception is thrown when an error is encountered during an
|
||||
@ -33,10 +33,10 @@ import java.io.*;
|
||||
*
|
||||
* @author Jonathan Payne
|
||||
*/
|
||||
public class FtpLoginException extends FtpProtocolException {
|
||||
public class FtpLoginException extends IOException {
|
||||
private static final long serialVersionUID = 2218162403237941536L;
|
||||
|
||||
FtpLoginException(String s) {
|
||||
public FtpLoginException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
@ -22,21 +22,49 @@
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package sun.net.ftp;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* This exeception is thrown when unexpected results are returned during
|
||||
* an FTP session.
|
||||
*
|
||||
* Thrown to indicate that the FTP server reported an error.
|
||||
* For instance that the requested file doesn't exist or
|
||||
* that a command isn't supported.
|
||||
* <p>The specific error code can be retreived with {@link #getReplyCode() }.</p>
|
||||
* @author Jonathan Payne
|
||||
*/
|
||||
public class FtpProtocolException extends IOException {
|
||||
public class FtpProtocolException extends Exception {
|
||||
private static final long serialVersionUID = 5978077070276545054L;
|
||||
private final FtpReplyCode code;
|
||||
|
||||
FtpProtocolException(String s) {
|
||||
super(s);
|
||||
/**
|
||||
* Constructs a new {@code FtpProtocolException} from the
|
||||
* specified detail message. The reply code is set to unknow error.
|
||||
*
|
||||
* @param detail the detail message.
|
||||
*/
|
||||
public FtpProtocolException(String detail) {
|
||||
super(detail);
|
||||
code = FtpReplyCode.UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FtpProtocolException} from the
|
||||
* specified response code and exception detail message
|
||||
*
|
||||
* @param detail the detail message.
|
||||
* @param code The {@code FtpRelyCode} received from server.
|
||||
*/
|
||||
public FtpProtocolException(String detail, FtpReplyCode code) {
|
||||
super(detail);
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the reply code sent by the server that led to this exception
|
||||
* being thrown.
|
||||
*
|
||||
* @return The {@link FtpReplyCode} associated with that exception.
|
||||
*/
|
||||
public FtpReplyCode getReplyCode() {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
248
jdk/src/share/classes/sun/net/ftp/FtpReplyCode.java
Normal file
248
jdk/src/share/classes/sun/net/ftp/FtpReplyCode.java
Normal file
@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
package sun.net.ftp;
|
||||
|
||||
/**
|
||||
* This class describes a FTP protocol reply code and associates a meaning
|
||||
* to the numerical value according to the various RFCs (RFC 959 in
|
||||
* particular).
|
||||
*
|
||||
*/
|
||||
public enum FtpReplyCode {
|
||||
|
||||
RESTART_MARKER(110),
|
||||
SERVICE_READY_IN(120),
|
||||
DATA_CONNECTION_ALREADY_OPEN(125),
|
||||
FILE_STATUS_OK(150),
|
||||
COMMAND_OK(200),
|
||||
NOT_IMPLEMENTED(202),
|
||||
SYSTEM_STATUS(211),
|
||||
DIRECTORY_STATUS(212),
|
||||
FILE_STATUS(213),
|
||||
HELP_MESSAGE(214),
|
||||
NAME_SYSTEM_TYPE(215),
|
||||
SERVICE_READY(220),
|
||||
SERVICE_CLOSING(221),
|
||||
DATA_CONNECTION_OPEN(225),
|
||||
CLOSING_DATA_CONNECTION(226),
|
||||
ENTERING_PASSIVE_MODE(227),
|
||||
ENTERING_EXT_PASSIVE_MODE(229),
|
||||
LOGGED_IN(230),
|
||||
SECURELY_LOGGED_IN(232),
|
||||
SECURITY_EXCHANGE_OK(234),
|
||||
SECURITY_EXCHANGE_COMPLETE(235),
|
||||
FILE_ACTION_OK(250),
|
||||
PATHNAME_CREATED(257),
|
||||
NEED_PASSWORD(331),
|
||||
NEED_ACCOUNT(332),
|
||||
NEED_ADAT(334),
|
||||
NEED_MORE_ADAT(335),
|
||||
FILE_ACTION_PENDING(350),
|
||||
SERVICE_NOT_AVAILABLE(421),
|
||||
CANT_OPEN_DATA_CONNECTION(425),
|
||||
CONNECTION_CLOSED(426),
|
||||
NEED_SECURITY_RESOURCE(431),
|
||||
FILE_ACTION_NOT_TAKEN(450),
|
||||
ACTION_ABORTED(451),
|
||||
INSUFFICIENT_STORAGE(452),
|
||||
COMMAND_UNRECOGNIZED(500),
|
||||
INVALID_PARAMETER(501),
|
||||
BAD_SEQUENCE(503),
|
||||
NOT_IMPLEMENTED_FOR_PARAMETER(504),
|
||||
NOT_LOGGED_IN(530),
|
||||
NEED_ACCOUNT_FOR_STORING(532),
|
||||
PROT_LEVEL_DENIED(533),
|
||||
REQUEST_DENIED(534),
|
||||
FAILED_SECURITY_CHECK(535),
|
||||
UNSUPPORTED_PROT_LEVEL(536),
|
||||
PROT_LEVEL_NOT_SUPPORTED_BY_SECURITY(537),
|
||||
FILE_UNAVAILABLE(550),
|
||||
PAGE_TYPE_UNKNOWN(551),
|
||||
EXCEEDED_STORAGE(552),
|
||||
FILE_NAME_NOT_ALLOWED(553),
|
||||
PROTECTED_REPLY(631),
|
||||
UNKNOWN_ERROR(999);
|
||||
private final int value;
|
||||
|
||||
FtpReplyCode(int val) {
|
||||
this.value = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the numerical value of the code.
|
||||
*
|
||||
* @return the numerical value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the code is a Positive Preliminary response.
|
||||
* This means beginning with a 1 (which means a value between 100 and 199)
|
||||
*
|
||||
* @return <code>true</code> if the reply code is a positive preliminary
|
||||
* response.
|
||||
*/
|
||||
public boolean isPositivePreliminary() {
|
||||
return value >= 100 && value < 200;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the code is a Positive Completion response.
|
||||
* This means beginning with a 2 (which means a value between 200 and 299)
|
||||
*
|
||||
* @return <code>true</code> if the reply code is a positive completion
|
||||
* response.
|
||||
*/
|
||||
public boolean isPositiveCompletion() {
|
||||
return value >= 200 && value < 300;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the code is a positive internediate response.
|
||||
* This means beginning with a 3 (which means a value between 300 and 399)
|
||||
*
|
||||
* @return <code>true</code> if the reply code is a positive intermediate
|
||||
* response.
|
||||
*/
|
||||
public boolean isPositiveIntermediate() {
|
||||
return value >= 300 && value < 400;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the code is a transient negative response.
|
||||
* This means beginning with a 4 (which means a value between 400 and 499)
|
||||
*
|
||||
* @return <code>true</code> if the reply code is a transient negative
|
||||
* response.
|
||||
*/
|
||||
public boolean isTransientNegative() {
|
||||
return value >= 400 && value < 500;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the code is a permanent negative response.
|
||||
* This means beginning with a 5 (which means a value between 500 and 599)
|
||||
*
|
||||
* @return <code>true</code> if the reply code is a permanent negative
|
||||
* response.
|
||||
*/
|
||||
public boolean isPermanentNegative() {
|
||||
return value >= 500 && value < 600;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the code is a protected reply response.
|
||||
* This means beginning with a 6 (which means a value between 600 and 699)
|
||||
*
|
||||
* @return <code>true</code> if the reply code is a protected reply
|
||||
* response.
|
||||
*/
|
||||
public boolean isProtectedReply() {
|
||||
return value >= 600 && value < 700;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the code is a syntax related response.
|
||||
* This means the second digit is a 0.
|
||||
*
|
||||
* @return <code>true</code> if the reply code is a syntax related
|
||||
* response.
|
||||
*/
|
||||
public boolean isSyntax() {
|
||||
return ((value / 10) - ((value / 100) * 10)) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the code is an information related response.
|
||||
* This means the second digit is a 1.
|
||||
*
|
||||
* @return <code>true</code> if the reply code is an information related
|
||||
* response.
|
||||
*/
|
||||
public boolean isInformation() {
|
||||
return ((value / 10) - ((value / 100) * 10)) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the code is a connection related response.
|
||||
* This means the second digit is a 2.
|
||||
*
|
||||
* @return <code>true</code> if the reply code is a connection related
|
||||
* response.
|
||||
*/
|
||||
public boolean isConnection() {
|
||||
return ((value / 10) - ((value / 100) * 10)) == 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the code is an authentication related response.
|
||||
* This means the second digit is a 3.
|
||||
*
|
||||
* @return <code>true</code> if the reply code is an authentication related
|
||||
* response.
|
||||
*/
|
||||
public boolean isAuthentication() {
|
||||
return ((value / 10) - ((value / 100) * 10)) == 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the code is an unspecified type of response.
|
||||
* This means the second digit is a 4.
|
||||
*
|
||||
* @return <code>true</code> if the reply code is an unspecified type of
|
||||
* response.
|
||||
*/
|
||||
public boolean isUnspecified() {
|
||||
return ((value / 10) - ((value / 100) * 10)) == 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the code is a file system related response.
|
||||
* This means the second digit is a 5.
|
||||
*
|
||||
* @return <code>true</code> if the reply code is a file system related
|
||||
* response.
|
||||
*/
|
||||
public boolean isFileSystem() {
|
||||
return ((value / 10) - ((value / 100) * 10)) == 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static utility method to convert a value into a FtpReplyCode.
|
||||
*
|
||||
* @param v the value to convert
|
||||
* @return the <code>FtpReplyCode</code> associated with the value.
|
||||
*/
|
||||
public static FtpReplyCode find(int v) {
|
||||
for (FtpReplyCode code : FtpReplyCode.values()) {
|
||||
if (code.getValue() == v) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
package sun.net.ftp.impl;
|
||||
|
||||
/**
|
||||
* Default FtpClientProvider.
|
||||
* Uses sun.net.ftp.FtpCLient.
|
||||
*/
|
||||
public class DefaultFtpClientProvider extends sun.net.ftp.FtpClientProvider {
|
||||
|
||||
@Override
|
||||
public sun.net.ftp.FtpClient createFtpClient() {
|
||||
return sun.net.ftp.impl.FtpClient.create();
|
||||
}
|
||||
|
||||
}
|
2191
jdk/src/share/classes/sun/net/ftp/impl/FtpClient.java
Normal file
2191
jdk/src/share/classes/sun/net/ftp/impl/FtpClient.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -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.FilterInputStream;
|
||||
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 @@ public class FtpURLConnection extends URLConnection {
|
||||
// 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 @@ public class FtpURLConnection extends URLConnection {
|
||||
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 @@ public class FtpURLConnection extends URLConnection {
|
||||
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 @@ public class FtpURLConnection extends URLConnection {
|
||||
|
||||
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 @@ public class FtpURLConnection extends URLConnection {
|
||||
* 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 @@ public class FtpURLConnection extends URLConnection {
|
||||
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 @@ public class FtpURLConnection extends URLConnection {
|
||||
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 @@ public class FtpURLConnection extends URLConnection {
|
||||
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 @@ public class FtpURLConnection extends URLConnection {
|
||||
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 @@ public class FtpURLConnection extends URLConnection {
|
||||
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 @@ public class FtpURLConnection extends URLConnection {
|
||||
* 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 @@ public class FtpURLConnection extends URLConnection {
|
||||
* @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 @@ public class FtpURLConnection extends URLConnection {
|
||||
|
||||
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) {
|
||||
// Check if URL should be metered
|
||||
boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, "GET");
|
||||
ProgressSource pi = null;
|
||||
|
||||
// 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;
|
||||
|
||||
if (meteredInput) {
|
||||
pi = new ProgressSource(url, "GET", l);
|
||||
pi.beginTracking();
|
||||
}
|
||||
|
||||
is = new MeteredStream(is, pi, l);
|
||||
if (meteredInput) {
|
||||
pi = new ProgressSource(url, "GET", l);
|
||||
pi.beginTracking();
|
||||
}
|
||||
|
||||
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 @@ public class FtpURLConnection extends URLConnection {
|
||||
* 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 @@ public class FtpURLConnection extends URLConnection {
|
||||
*
|
||||
* @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 @@ public class FtpURLConnection extends URLConnection {
|
||||
* @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 @@ public class FtpURLConnection extends URLConnection {
|
||||
* @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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user