001package com.hfg.util.io;
002
003import java.io.InputStream;
004import java.io.IOException;
005import java.io.BufferedInputStream;
006import java.io.OutputStream;
007import java.util.Calendar;
008
009import org.apache.commons.net.ftp.FTPFile;
010import org.apache.commons.net.ftp.FTPClient;
011import org.apache.commons.net.ftp.FTP;
012import com.hfg.util.StringUtil;
013
014//------------------------------------------------------------------------------
015/**
016 * Implementation of RemoteFile for FTP files
017 * <p>
018 * This class depends on Jakarta's commons-net library (which depends on jakarta-oro).
019 * </p>
020 * @author J. Alex Taylor, hairyfatguy.com
021 */
022//------------------------------------------------------------------------------
023// com.hfg XML/HTML Coding Library
024//
025// This library is free software; you can redistribute it and/or
026// modify it under the terms of the GNU Lesser General Public
027// License as published by the Free Software Foundation; either
028// version 2.1 of the License, or (at your option) any later version.
029//
030// This library is distributed in the hope that it will be useful,
031// but WITHOUT ANY WARRANTY; without even the implied warranty of
032// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
033// Lesser General Public License for more details.
034//
035// You should have received a copy of the GNU Lesser General Public
036// License along with this library; if not, write to the Free Software
037// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
038//
039// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
040// jataylor@hairyfatguy.com
041//------------------------------------------------------------------------------
042
043
044public class FTPRemoteFile extends AbstractRemoteFile
045{
046
047   //###########################################################################
048   // PRIVATE FIELDS
049   //###########################################################################
050
051   private FTPClient mFTP;
052   private String    mFTPServer;
053   private FTPFile   mFTPFile;
054   private String    mParentDirPath;
055   private String    mName;
056   private String    mRequestedFilePath;
057
058   private int       mFileTransferMode = sDefaultFileTransferMode;
059
060   private static int sDefaultFileTransferMode = FTP.BINARY_FILE_TYPE;
061
062   //###########################################################################
063   // CONSTRUCTORS
064   //###########################################################################
065
066   //---------------------------------------------------------------------------
067   public FTPRemoteFile(FTPClient inFTP, String inFTPServer, String inParentDirPath, FTPFile inFTPFile)
068   {
069      StringBuilder path = new StringBuilder(StringUtil.isSet(inParentDirPath) ? inParentDirPath : "");
070      if (path.length() == 0 || path.charAt(path.length() - 1) != '/') path.append("/");
071      if (inFTPFile.getName().startsWith(path.toString()))
072      {
073         path.append(inFTPFile.getName().substring(path.length()));
074      }
075      else
076      {
077         path.append(inFTPFile.getName());
078      }
079
080      mParentDirPath = path.substring(0, path.lastIndexOf("/"));
081//      mParentDirPath = inParentDirPath;
082      mName      = path.substring(path.lastIndexOf("/") + 1);
083      mFTP       = inFTP;
084      mFTPServer = inFTPServer;
085      mFTPFile   = inFTPFile;
086   }
087
088
089
090   //###########################################################################
091   // PUBLIC METHODS
092   //###########################################################################
093
094   //---------------------------------------------------------------------------
095   @Override
096   public String getName()
097   {
098//      return mFTPFile.getName();
099      return mName;
100   }
101
102   //---------------------------------------------------------------------------
103   public FTPRemoteFile setRequestedPath(String inValue)
104   {
105      mRequestedFilePath = inValue;
106      return this;
107   }
108
109   //---------------------------------------------------------------------------
110   @Override
111   public String getRequestedPath()
112   {
113      return mRequestedFilePath != null ? mRequestedFilePath : getPath();
114   }
115
116   //---------------------------------------------------------------------------
117   @Override
118   public String getPath()
119   {
120      return mParentDirPath + "/" + getName();
121   }
122
123   //---------------------------------------------------------------------------
124   @Override
125   public String getURL()
126   {
127      return "ftp://" + mFTPServer + (mParentDirPath.startsWith("/") ? "" : "/") + mParentDirPath + "/" + getName();
128   }
129
130   //---------------------------------------------------------------------------
131   @Override
132   public long getSize()
133   {
134      return mFTPFile.getSize();
135   }
136
137   //---------------------------------------------------------------------------
138   @Override
139   public Calendar getTimestamp()
140   {
141      // Round to seconds since I was seeing some odd behavior with millis precision.
142      Calendar cal = mFTPFile.getTimestamp();
143      cal.setTimeInMillis((cal.getTimeInMillis() / 1000) * 1000);
144      return cal;
145   }
146
147   //---------------------------------------------------------------------------
148   /**
149    * Use FTP.ASCII_FILE_TYPE or FTP.BINARY_FILE_TYPE (default).
150    */
151
152   public void setFileTransferMode(int inValue)
153   {
154      mFileTransferMode = FTP.ASCII_FILE_TYPE;
155   }
156
157   //---------------------------------------------------------------------------
158   /**
159    * Note that the FTP connection is closed when the returned InputStream is closed.
160    */
161   @Override
162   public InputStream getInputStream()
163   throws IOException
164   {
165      mFTP.setFileType(mFileTransferMode);
166      InputStream stream = mFTP.retrieveFileStream(mParentDirPath + "/" + getName());
167
168      return new BufferedInputStream(stream);
169   }
170
171   //---------------------------------------------------------------------------
172   @Override
173   public long writeToStream(OutputStream stream)
174   throws IOException
175   {
176      mFTP.setFileType(mFileTransferMode);
177      mFTP.changeWorkingDirectory(mParentDirPath);
178      mFTP.retrieveFile(getName(), stream);
179//      mFTP.retrieveFile(mParentDirPath + "/" + getName(), stream);
180      return getSize();
181   }
182}