commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ima...@apache.org
Subject svn commit: r520100 - /jakarta/commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileObject.java
Date Mon, 19 Mar 2007 20:54:30 GMT
Author: imario
Date: Mon Mar 19 13:54:27 2007
New Revision: 520100

URL: http://svn.apache.org/viewvc?view=rev&rev=520100
Log:
VFS-114: avoid successive children refresh

Modified:
    jakarta/commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileObject.java

Modified: jakarta/commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileObject.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileObject.java?view=diff&rev=520100&r1=520099&r2=520100
==============================================================================
--- jakarta/commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileObject.java
(original)
+++ jakarta/commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileObject.java
Mon Mar 19 13:54:27 2007
@@ -48,150 +48,154 @@
  * @version $Revision$ $Date$
  */
 public class FtpFileObject
-    extends AbstractFileObject
+	extends AbstractFileObject
 {
-    private Log log = LogFactory.getLog(FtpFileObject.class);
+	private Log log = LogFactory.getLog(FtpFileObject.class);
 
-    private static final Map EMPTY_FTP_FILE_MAP = Collections.unmodifiableMap(new TreeMap());
+	private static final Map EMPTY_FTP_FILE_MAP = Collections.unmodifiableMap(new TreeMap());
 
-    private final FtpFileSystem ftpFs;
-    private final String relPath;
+	private final FtpFileSystem ftpFs;
+	private final String relPath;
 
-    // Cached info
-    private FTPFile fileInfo;
-    private Map children;
-    private FileObject linkDestination;
+	// Cached info
+	private FTPFile fileInfo;
+	private Map children;
+	private FileObject linkDestination;
 
-	private boolean inRefresh=false;
+	private boolean inRefresh = false;
 
 	protected FtpFileObject(final FileName name,
-                            final FtpFileSystem fileSystem,
-                            final FileName rootName)
-        throws FileSystemException
-    {
-        super(name, fileSystem);
-        ftpFs = fileSystem;
-        String relPath = UriParser.decode(rootName.getRelativeName(name));
-        if (".".equals(relPath))
-        {
-            // do not use the "." as path against the ftp-server
-            // e.g. the uu.net ftp-server do a recursive listing then
-            // this.relPath = UriParser.decode(rootName.getPath());
-            // this.relPath = ".";
-            this.relPath = null;
-        }
-        else
-        {
-            this.relPath = relPath;
-        }
-    }
-
-    /**
-     * Called by child file objects, to locate their ftp file info.
-     *
-     * @param name  the filename in its native form ie. without uri stuff (%nn)
-     * @param flush recreate children cache
-     */
-    private FTPFile getChildFile(final String name, final boolean flush) throws IOException
-    {
-        if (flush)
-        {
- 			children = null;
-        }
-
-        // List the children of this file
-        doGetChildren();
-
-        // Look for the requested child
-        FTPFile ftpFile = (FTPFile) children.get(name);
-        return ftpFile;
-    }
-
-    /**
-     * Fetches the children of this file, if not already cached.
-     */
-    private void doGetChildren() throws IOException
-    {
-        if (children != null)
-        {
-            return;
-        }
-
-        final FtpClient client = ftpFs.getClient();
-        try
-        {
-            final FTPFile[] tmpChildren = client.listFiles(relPath);
-            if (tmpChildren == null || tmpChildren.length == 0)
-            {
-                children = EMPTY_FTP_FILE_MAP;
-            }
-            else
-            {
-                children = new TreeMap();
-
-                // Remove '.' and '..' elements
-                for (int i = 0; i < tmpChildren.length; i++)
-                {
-                    final FTPFile child = tmpChildren[i];
-                    if (child == null)
-                    {
-                        if (log.isDebugEnabled())
-                        {
-                            log.debug(Messages.getString("vfs.provider.ftp/invalid-directory-entry.debug",
-                                new Object[]
-                                    {
-                                        new Integer(i), relPath
-                                    }));
-                        }
-                        continue;
-                    }
-                    if (!".".equals(child.getName())
-                        && !"..".equals(child.getName()))
-                    {
-                        children.put(child.getName(), child);
-                    }
-                }
-            }
-        }
-        finally
-        {
-            ftpFs.putClient(client);
-        }
-    }
-
-    /**
-     * Attaches this file object to its file resource.
-     */
-    protected void doAttach()
-        throws IOException
-    {
-        // Get the parent folder to find the info for this file
-        getInfo(false);
-    }
-
-    /**
-     * Fetches the info for this file.
-     */
-    private void getInfo(boolean flush) throws IOException
-    {
-        final FtpFileObject parent = (FtpFileObject) FileObjectUtils.getAbstractFileObject(getParent());
-        FTPFile newFileInfo;
-        if (parent != null)
-        {
-            newFileInfo = parent.getChildFile(UriParser.decode(getName().getBaseName()),
flush);
-        }
-        else
-        {
-            // Assume the root is a directory and exists
-            newFileInfo = new FTPFile();
-            newFileInfo.setType(FTPFile.DIRECTORY_TYPE);
-        }
-
-        this.fileInfo = newFileInfo;
-    }
+							final FtpFileSystem fileSystem,
+							final FileName rootName)
+		throws FileSystemException
+	{
+		super(name, fileSystem);
+		ftpFs = fileSystem;
+		String relPath = UriParser.decode(rootName.getRelativeName(name));
+		if (".".equals(relPath))
+		{
+			// do not use the "." as path against the ftp-server
+			// e.g. the uu.net ftp-server do a recursive listing then
+			// this.relPath = UriParser.decode(rootName.getPath());
+			// this.relPath = ".";
+			this.relPath = null;
+		}
+		else
+		{
+			this.relPath = relPath;
+		}
+	}
 
 	/**
+	 * Called by child file objects, to locate their ftp file info.
 	 *
+	 * @param name  the filename in its native form ie. without uri stuff (%nn)
+	 * @param flush recreate children cache
+	 */
+	private FTPFile getChildFile(final String name, final boolean flush) throws IOException
+	{
+		/* If we should flush cached children, clear our children map unless
+				 * we're in the middle of a refresh in which case we've just recently
+				 * refreshed our children. No need to do it again when our children are
+				 * refresh()ed, calling getChildFile() for themselves from within
+				 * getInfo(). See getChildren(). */
+		if (flush && !inRefresh)
+		{
+			children = null;
+		}
+
+		// List the children of this file
+		doGetChildren();
+
+		// Look for the requested child
+		FTPFile ftpFile = (FTPFile) children.get(name);
+		return ftpFile;
+	}
+
+	/**
+	 * Fetches the children of this file, if not already cached.
+	 */
+	private void doGetChildren() throws IOException
+	{
+		if (children != null)
+		{
+			return;
+		}
+
+		final FtpClient client = ftpFs.getClient();
+		try
+		{
+			final FTPFile[] tmpChildren = client.listFiles(relPath);
+			if (tmpChildren == null || tmpChildren.length == 0)
+			{
+				children = EMPTY_FTP_FILE_MAP;
+			}
+			else
+			{
+				children = new TreeMap();
+
+				// Remove '.' and '..' elements
+				for (int i = 0; i < tmpChildren.length; i++)
+				{
+					final FTPFile child = tmpChildren[i];
+					if (child == null)
+					{
+						if (log.isDebugEnabled())
+						{
+							log.debug(Messages.getString("vfs.provider.ftp/invalid-directory-entry.debug",
+								new Object[]
+									{
+										new Integer(i), relPath
+									}));
+						}
+						continue;
+					}
+					if (!".".equals(child.getName())
+						&& !"..".equals(child.getName()))
+					{
+						children.put(child.getName(), child);
+					}
+				}
+			}
+		}
+		finally
+		{
+			ftpFs.putClient(client);
+		}
+	}
+
+	/**
+	 * Attaches this file object to its file resource.
+	 */
+	protected void doAttach()
+		throws IOException
+	{
+		// Get the parent folder to find the info for this file
+		getInfo(false);
+	}
+
+	/**
+	 * Fetches the info for this file.
+	 */
+	private void getInfo(boolean flush) throws IOException
+	{
+		final FtpFileObject parent = (FtpFileObject) FileObjectUtils.getAbstractFileObject(getParent());
+		FTPFile newFileInfo;
+		if (parent != null)
+		{
+			newFileInfo = parent.getChildFile(UriParser.decode(getName().getBaseName()), flush);
+		}
+		else
+		{
+			// Assume the root is a directory and exists
+			newFileInfo = new FTPFile();
+			newFileInfo.setType(FTPFile.DIRECTORY_TYPE);
+		}
+
+		this.fileInfo = newFileInfo;
+	}
+
+	/**
 	 * @throws FileSystemException
 	 */
 	public void refresh() throws FileSystemException
@@ -220,391 +224,419 @@
 	}
 
 	/**
-     * Detaches this file object from its file resource.
-     */
-    protected void doDetach()
-    {
-        this.fileInfo = null;
-        children = null;
-    }
-
-    /**
-     * Called when the children of this file change.
-     */
-    protected void onChildrenChanged(FileName child, FileType newType)
-    {
-        if (children != null && newType.equals(FileType.IMAGINARY))
-        {
-            try
-            {
-                children.remove(UriParser.decode(child.getBaseName()));
-            }
-            catch (FileSystemException e)
-            {
-                throw new RuntimeException(e.getMessage());
-            }
-        }
-        else
-        {
-            // if child was added we have to rescan the children
-            // TODO - get rid of this
-            children = null;
-        }
-    }
-
-    /**
-     * Called when the type or content of this file changes.
-     */
-    protected void onChange() throws IOException
-    {
-        children = null;
-
-        if (getType().equals(FileType.IMAGINARY))
-        {
-            // file is deleted, avoid server lookup
-            this.fileInfo = null;
-            return;
-        }
-
-        getInfo(true);
-    }
-
-    /**
-     * Determines the type of the file, returns null if the file does not
-     * exist.
-     */
-    protected FileType doGetType()
-        throws Exception
-    {
-        if (this.fileInfo == null)
-        {
-            return FileType.IMAGINARY;
-        }
-        else if (this.fileInfo.isDirectory())
-        {
-            return FileType.FOLDER;
-        }
-        else if (this.fileInfo.isFile())
-        {
-            return FileType.FILE;
-        }
-        else if (this.fileInfo.isSymbolicLink())
-        {
-            return getLinkDestination().getType();
-        }
-
-        throw new FileSystemException("vfs.provider.ftp/get-type.error", getName());
-    }
-
-    private FileObject getLinkDestination() throws FileSystemException
-    {
-        if (linkDestination == null)
-        {
-            final String path = this.fileInfo.getLink();
-            FileName relativeTo = getName().getParent();
-            if (relativeTo == null)
-            {
-                relativeTo = getName();
-            }
-            FileName linkDestinationName = getFileSystem().getFileSystemManager().resolveName(relativeTo,
path);
-            linkDestination = getFileSystem().resolveFile(linkDestinationName);
-        }
-
-        return linkDestination;
-    }
-
-    protected FileObject[] doListChildrenResolved() throws Exception
-    {
-        if (this.fileInfo.isSymbolicLink())
-        {
-            return getLinkDestination().getChildren();
-        }
-
-        return null;
-    }
-
-    /**
-     * Lists the children of the file.
-     */
-    protected String[] doListChildren()
-        throws Exception
-    {
-        // List the children of this file
-        doGetChildren();
-
-        // TODO - get rid of this children stuff
-        final String[] childNames = new String[children.size()];
-        int childNum = -1;
-        Iterator iterChildren = children.values().iterator();
-        while (iterChildren.hasNext())
-        {
-            childNum++;
-            final FTPFile child = (FTPFile) iterChildren.next();
-            childNames[childNum] = child.getName();
-        }
-
-        return UriParser.encode(childNames);
-    }
-
-    /**
-     * Deletes the file.
-     */
-    protected void doDelete() throws Exception
-    {
-        final boolean ok;
-        final FtpClient ftpClient = ftpFs.getClient();
-        try
-        {
-            if (this.fileInfo.isDirectory())
-            {
-                ok = ftpClient.removeDirectory(relPath);
-            }
-            else
-            {
-                ok = ftpClient.deleteFile(relPath);
-            }
-        }
-        finally
-        {
-            ftpFs.putClient(ftpClient);
-        }
-
-        if (!ok)
-        {
-            throw new FileSystemException("vfs.provider.ftp/delete-file.error", getName());
-        }
-        this.fileInfo = null;
-        children = EMPTY_FTP_FILE_MAP;
-    }
-
-    /**
-     * Renames the file
-     */
-    protected void doRename(FileObject newfile) throws Exception
-    {
-        final boolean ok;
-        final FtpClient ftpClient = ftpFs.getClient();
-        try
-        {
-            String oldName = getName().getPath();
-            String newName = newfile.getName().getPath();
-            ok = ftpClient.rename(oldName, newName);
-        }
-        finally
-        {
-            ftpFs.putClient(ftpClient);
-        }
-
-        if (!ok)
-        {
-            throw new FileSystemException("vfs.provider.ftp/rename-file.error", new Object[]{getName().toString(),
newfile});
-        }
-        this.fileInfo = null;
-        children = EMPTY_FTP_FILE_MAP;
-    }
-
-    /**
-     * Creates this file as a folder.
-     */
-    protected void doCreateFolder()
-        throws Exception
-    {
-        final boolean ok;
-        final FtpClient client = ftpFs.getClient();
-        try
-        {
-            ok = client.makeDirectory(relPath);
-        }
-        finally
-        {
-            ftpFs.putClient(client);
-        }
-
-        if (!ok)
-        {
-            throw new FileSystemException("vfs.provider.ftp/create-folder.error", getName());
-        }
-    }
-
-    /**
-     * Returns the size of the file content (in bytes).
-     */
-    protected long doGetContentSize() throws Exception
-    {
-        if (this.fileInfo.isSymbolicLink())
-        {
-            return getLinkDestination().getContent().getSize();
-        }
-        else
-        {
-            return this.fileInfo.getSize();
-        }
-    }
-
-    /**
-     * get the last modified time on an ftp file
-     *
-     * @see org.apache.commons.vfs.provider.AbstractFileObject#doGetLastModifiedTime()
-     */
-    protected long doGetLastModifiedTime() throws Exception
-    {
-        if (this.fileInfo.isSymbolicLink())
-        {
-            return getLinkDestination().getContent().getLastModifiedTime();
-        }
-        else
-        {
-            Calendar timestamp = this.fileInfo.getTimestamp();
-            if (timestamp == null)
-            {
-                return 0L;
-            }
-            else
-            {
-                return (timestamp.getTime().getTime());
-            }
-        }
-    }
-
-    /**
-     * Creates an input stream to read the file content from.
-     */
-    protected InputStream doGetInputStream() throws Exception
-    {
-        final FtpClient client = ftpFs.getClient();
-        final InputStream instr = client.retrieveFileStream(relPath);
-        return new FtpInputStream(client, instr);
-    }
-
-    protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws
Exception
-    {
-        return new FtpRandomAccessContent(this, mode);
-    }
-
-    /**
-     * Creates an output stream to write the file content to.
-     */
-    protected OutputStream doGetOutputStream(boolean bAppend)
-        throws Exception
-    {
-        final FtpClient client = ftpFs.getClient();
-        OutputStream out = null;
-        if (bAppend)
-        {
-            out = client.appendFileStream(relPath);
-        }
-        else
-        {
-            out = client.storeFileStream(relPath);
-        }
-
-        if (out == null)
-        {
-            throw new FileSystemException("vfs.provider.ftp/output-error.debug", new Object[]
-                {
-                    this.getName(),
-                    client.getReplyString()
-                });
-        }
-
-        return new FtpOutputStream(client, out);
-    }
-
-    String getRelPath()
-    {
-        return relPath;
-    }
-
-    FtpInputStream getInputStream(long filePointer) throws IOException
-    {
-        final FtpClient client = ftpFs.getClient();
-        final InputStream instr = client.retrieveFileStream(relPath, filePointer);
-        if (instr == null)
-        {
-            throw new FileSystemException("vfs.provider.ftp/input-error.debug", new Object[]
-                {
-                    this.getName(),
-                    client.getReplyString()
-                });
-        }
-        return new FtpInputStream(client, instr);
-    }
-
-    /**
-     * An InputStream that monitors for end-of-file.
-     */
-    class FtpInputStream
-        extends MonitorInputStream
-    {
-        private final FtpClient client;
-
-        public FtpInputStream(final FtpClient client, final InputStream in)
-        {
-            super(in);
-            this.client = client;
-        }
-
-        void abort() throws IOException
-        {
-            client.abort();
-            close();
-        }
-
-        /**
-         * Called after the stream has been closed.
-         */
-        protected void onClose() throws IOException
-        {
-            final boolean ok;
-            try
-            {
-                ok = client.completePendingCommand();
-            }
-            finally
-            {
-                ftpFs.putClient(client);
-            }
-
-            if (!ok)
-            {
-                throw new FileSystemException("vfs.provider.ftp/finish-get.error", getName());
-            }
-        }
-    }
-
-    /**
-     * An OutputStream that monitors for end-of-file.
-     */
-    private class FtpOutputStream
-        extends MonitorOutputStream
-    {
-        private final FtpClient client;
-
-        public FtpOutputStream(final FtpClient client, final OutputStream outstr)
-        {
-            super(outstr);
-            this.client = client;
-        }
-
-        /**
-         * Called after this stream is closed.
-         */
-        protected void onClose() throws IOException
-        {
-            final boolean ok;
-            try
-            {
-                ok = client.completePendingCommand();
-            }
-            finally
-            {
-                ftpFs.putClient(client);
-            }
-
-            if (!ok)
-            {
-                throw new FileSystemException("vfs.provider.ftp/finish-put.error", getName());
-            }
-        }
-    }
+	 * Detaches this file object from its file resource.
+	 */
+	protected void doDetach()
+	{
+		this.fileInfo = null;
+		children = null;
+	}
+
+	/**
+	 * Called when the children of this file change.
+	 */
+	protected void onChildrenChanged(FileName child, FileType newType)
+	{
+		if (children != null && newType.equals(FileType.IMAGINARY))
+		{
+			try
+			{
+				children.remove(UriParser.decode(child.getBaseName()));
+			}
+			catch (FileSystemException e)
+			{
+				throw new RuntimeException(e.getMessage());
+			}
+		}
+		else
+		{
+			// if child was added we have to rescan the children
+			// TODO - get rid of this
+			children = null;
+		}
+	}
+
+	/**
+	 * Called when the type or content of this file changes.
+	 */
+	protected void onChange() throws IOException
+	{
+		children = null;
+
+		if (getType().equals(FileType.IMAGINARY))
+		{
+			// file is deleted, avoid server lookup
+			this.fileInfo = null;
+			return;
+		}
+
+		getInfo(true);
+	}
+
+	/**
+	 * Determines the type of the file, returns null if the file does not
+	 * exist.
+	 */
+	protected FileType doGetType()
+		throws Exception
+	{
+		if (this.fileInfo == null)
+		{
+			return FileType.IMAGINARY;
+		}
+		else if (this.fileInfo.isDirectory())
+		{
+			return FileType.FOLDER;
+		}
+		else if (this.fileInfo.isFile())
+		{
+			return FileType.FILE;
+		}
+		else if (this.fileInfo.isSymbolicLink())
+		{
+			return getLinkDestination().getType();
+		}
+
+		throw new FileSystemException("vfs.provider.ftp/get-type.error", getName());
+	}
+
+	private FileObject getLinkDestination() throws FileSystemException
+	{
+		if (linkDestination == null)
+		{
+			final String path = this.fileInfo.getLink();
+			FileName relativeTo = getName().getParent();
+			if (relativeTo == null)
+			{
+				relativeTo = getName();
+			}
+			FileName linkDestinationName = getFileSystem().getFileSystemManager().resolveName(relativeTo,
path);
+			linkDestination = getFileSystem().resolveFile(linkDestinationName);
+		}
+
+		return linkDestination;
+	}
+
+	protected FileObject[] doListChildrenResolved() throws Exception
+	{
+		if (this.fileInfo.isSymbolicLink())
+		{
+			return getLinkDestination().getChildren();
+		}
+
+		return null;
+	}
+
+	/**
+	 * Returns the file's list of children.
+	 *
+	 * @return The list of children
+	 * @throws FileSystemException If there was a problem listing children
+	 * @see AbstractFileObject#getChildren()
+	 * @since 1.0
+	 */
+	public FileObject[] getChildren() throws FileSystemException
+	{
+		try
+		{
+			/* Wrap our parent implementation, noting that we're refreshing so
+			 * that we don't refresh() ourselves and each of our parents for
+			 * each children. Note that refresh() will list children. Meaning,
+			 * if if this file has C children, P parents, there will be (C * P)
+			 * listings made with (C * (P + 1)) refreshes, when there should
+			 * really only be 1 listing and C refreshes. */
+			
+			this.inRefresh = true;
+			return super.getChildren();
+		}
+		finally
+		{
+			this.inRefresh = false;
+		}
+	}
+
+	/**
+	 * Lists the children of the file.
+	 */
+	protected String[] doListChildren()
+		throws Exception
+	{
+		// List the children of this file
+		doGetChildren();
+
+		// TODO - get rid of this children stuff
+		final String[] childNames = new String[children.size()];
+		int childNum = -1;
+		Iterator iterChildren = children.values().iterator();
+		while (iterChildren.hasNext())
+		{
+			childNum++;
+			final FTPFile child = (FTPFile) iterChildren.next();
+			childNames[childNum] = child.getName();
+		}
+
+		return UriParser.encode(childNames);
+	}
+
+	/**
+	 * Deletes the file.
+	 */
+	protected void doDelete() throws Exception
+	{
+		final boolean ok;
+		final FtpClient ftpClient = ftpFs.getClient();
+		try
+		{
+			if (this.fileInfo.isDirectory())
+			{
+				ok = ftpClient.removeDirectory(relPath);
+			}
+			else
+			{
+				ok = ftpClient.deleteFile(relPath);
+			}
+		}
+		finally
+		{
+			ftpFs.putClient(ftpClient);
+		}
+
+		if (!ok)
+		{
+			throw new FileSystemException("vfs.provider.ftp/delete-file.error", getName());
+		}
+		this.fileInfo = null;
+		children = EMPTY_FTP_FILE_MAP;
+	}
+
+	/**
+	 * Renames the file
+	 */
+	protected void doRename(FileObject newfile) throws Exception
+	{
+		final boolean ok;
+		final FtpClient ftpClient = ftpFs.getClient();
+		try
+		{
+			String oldName = getName().getPath();
+			String newName = newfile.getName().getPath();
+			ok = ftpClient.rename(oldName, newName);
+		}
+		finally
+		{
+			ftpFs.putClient(ftpClient);
+		}
+
+		if (!ok)
+		{
+			throw new FileSystemException("vfs.provider.ftp/rename-file.error", new Object[]{getName().toString(),
newfile});
+		}
+		this.fileInfo = null;
+		children = EMPTY_FTP_FILE_MAP;
+	}
+
+	/**
+	 * Creates this file as a folder.
+	 */
+	protected void doCreateFolder()
+		throws Exception
+	{
+		final boolean ok;
+		final FtpClient client = ftpFs.getClient();
+		try
+		{
+			ok = client.makeDirectory(relPath);
+		}
+		finally
+		{
+			ftpFs.putClient(client);
+		}
+
+		if (!ok)
+		{
+			throw new FileSystemException("vfs.provider.ftp/create-folder.error", getName());
+		}
+	}
+
+	/**
+	 * Returns the size of the file content (in bytes).
+	 */
+	protected long doGetContentSize() throws Exception
+	{
+		if (this.fileInfo.isSymbolicLink())
+		{
+			return getLinkDestination().getContent().getSize();
+		}
+		else
+		{
+			return this.fileInfo.getSize();
+		}
+	}
+
+	/**
+	 * get the last modified time on an ftp file
+	 *
+	 * @see org.apache.commons.vfs.provider.AbstractFileObject#doGetLastModifiedTime()
+	 */
+	protected long doGetLastModifiedTime() throws Exception
+	{
+		if (this.fileInfo.isSymbolicLink())
+		{
+			return getLinkDestination().getContent().getLastModifiedTime();
+		}
+		else
+		{
+			Calendar timestamp = this.fileInfo.getTimestamp();
+			if (timestamp == null)
+			{
+				return 0L;
+			}
+			else
+			{
+				return (timestamp.getTime().getTime());
+			}
+		}
+	}
+
+	/**
+	 * Creates an input stream to read the file content from.
+	 */
+	protected InputStream doGetInputStream() throws Exception
+	{
+		final FtpClient client = ftpFs.getClient();
+		final InputStream instr = client.retrieveFileStream(relPath);
+		return new FtpInputStream(client, instr);
+	}
+
+	protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws
Exception
+	{
+		return new FtpRandomAccessContent(this, mode);
+	}
+
+	/**
+	 * Creates an output stream to write the file content to.
+	 */
+	protected OutputStream doGetOutputStream(boolean bAppend)
+		throws Exception
+	{
+		final FtpClient client = ftpFs.getClient();
+		OutputStream out = null;
+		if (bAppend)
+		{
+			out = client.appendFileStream(relPath);
+		}
+		else
+		{
+			out = client.storeFileStream(relPath);
+		}
+
+		if (out == null)
+		{
+			throw new FileSystemException("vfs.provider.ftp/output-error.debug", new Object[]
+				{
+					this.getName(),
+					client.getReplyString()
+				});
+		}
+
+		return new FtpOutputStream(client, out);
+	}
+
+	String getRelPath()
+	{
+		return relPath;
+	}
+
+	FtpInputStream getInputStream(long filePointer) throws IOException
+	{
+		final FtpClient client = ftpFs.getClient();
+		final InputStream instr = client.retrieveFileStream(relPath, filePointer);
+		if (instr == null)
+		{
+			throw new FileSystemException("vfs.provider.ftp/input-error.debug", new Object[]
+				{
+					this.getName(),
+					client.getReplyString()
+				});
+		}
+		return new FtpInputStream(client, instr);
+	}
+
+	/**
+	 * An InputStream that monitors for end-of-file.
+	 */
+	class FtpInputStream
+		extends MonitorInputStream
+	{
+		private final FtpClient client;
+
+		public FtpInputStream(final FtpClient client, final InputStream in)
+		{
+			super(in);
+			this.client = client;
+		}
+
+		void abort() throws IOException
+		{
+			client.abort();
+			close();
+		}
+
+		/**
+		 * Called after the stream has been closed.
+		 */
+		protected void onClose() throws IOException
+		{
+			final boolean ok;
+			try
+			{
+				ok = client.completePendingCommand();
+			}
+			finally
+			{
+				ftpFs.putClient(client);
+			}
+
+			if (!ok)
+			{
+				throw new FileSystemException("vfs.provider.ftp/finish-get.error", getName());
+			}
+		}
+	}
+
+	/**
+	 * An OutputStream that monitors for end-of-file.
+	 */
+	private class FtpOutputStream
+		extends MonitorOutputStream
+	{
+		private final FtpClient client;
+
+		public FtpOutputStream(final FtpClient client, final OutputStream outstr)
+		{
+			super(outstr);
+			this.client = client;
+		}
+
+		/**
+		 * Called after this stream is closed.
+		 */
+		protected void onClose() throws IOException
+		{
+			final boolean ok;
+			try
+			{
+				ok = client.completePendingCommand();
+			}
+			finally
+			{
+				ftpFs.putClient(client);
+			}
+
+			if (!ok)
+			{
+				throw new FileSystemException("vfs.provider.ftp/finish-put.error", getName());
+			}
+		}
+	}
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message