All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hfg.util.io.FTPFileObj Maven / Gradle / Ivy

There is a newer version: 20240423
Show newest version
package com.hfg.util.io;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import com.hfg.security.LoginCredentials;
import com.hfg.units.TimeUnit;

//------------------------------------------------------------------------------
/**
 * Implementation of FileObj for FTP files
 * 

* This class depends on Jakarta's commons-net library. *

* @author J. Alex Taylor, hairyfatguy.com */ //------------------------------------------------------------------------------ // com.hfg XML/HTML Coding Library // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library 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 // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com // [email protected] //------------------------------------------------------------------------------ public class FTPFileObj extends FileObjImpl { //########################################################################### // PRIVATE FIELDS //########################################################################### private URL mURL; private FTPClient mFTP; private String mFTPServer; private FTPFile mFTPFile; private String mParentDirPath; private String mName; private String mRequestedFilePath; private LoginCredentials mCredentials = sDefaultCredentials; private int mFileTransferMode = sDefaultFileTransferMode; private static final int sDefaultFileTransferMode = FTP.BINARY_FILE_TYPE; private static LoginCredentials sDefaultCredentials = new LoginCredentials("anonymous", getUserAtHostPassword().toCharArray()); private static final String SCHEME = "ftp"; //########################################################################### // CONSTRUCTORS //########################################################################### //--------------------------------------------------------------------------- public FTPFileObj(String inURL) throws MalformedURLException { this(new URL(inURL)); } //--------------------------------------------------------------------------- public FTPFileObj(URI inURI) throws MalformedURLException { this(inURI.toURL()); } //--------------------------------------------------------------------------- public FTPFileObj(URL inURL) { mURL = inURL; String path = inURL.getPath(); if (path.endsWith("/")) { path = path.substring(0, path.length() - 1); } mName = path.substring(path.lastIndexOf("/") + 1); if (path.length() > 0) { int index = path.lastIndexOf("/"); mParentDirPath = (index >= 0 ? path.substring(0, index) : ""); } mFTPServer = inURL.getHost(); } //########################################################################### // PUBLIC METHODS //########################################################################### //--------------------------------------------------------------------------- @Override public String getScheme() { return SCHEME; } //--------------------------------------------------------------------------- @Override public String getName() { return mName; } //--------------------------------------------------------------------------- public FTPFileObj setRequestedPath(String inValue) { mRequestedFilePath = inValue; return this; } //--------------------------------------------------------------------------- @Override public String getRequestedPath() { return mRequestedFilePath != null ? mRequestedFilePath : getPath(); } //--------------------------------------------------------------------------- @Override public String getPath() { return mURL.getPath(); } //--------------------------------------------------------------------------- @Override public URI getURI() { URI uri; try { uri = new URI(getScheme(), mFTPServer, getPath(), null); } catch (URISyntaxException e) { throw new RuntimeIOException(e); } return uri; } //--------------------------------------------------------------------------- public String getURL() { return mURL.toString(); } //--------------------------------------------------------------------------- @Override public long length() { return getFTPFile().getSize(); } //--------------------------------------------------------------------------- @Override public Long lastModified() { Long lastModifiedOverride = super.lastModified(); return lastModifiedOverride != null ? lastModifiedOverride : getFTPFile().getTimestamp().getTimeInMillis(); } //--------------------------------------------------------------------------- @Override public Calendar getTimestamp() { // Round to seconds since I was seeing some odd behavior with millis precision. Calendar cal = getFTPFile().getTimestamp(); cal.setTimeInMillis((cal.getTimeInMillis() / 1000) * 1000); return cal; } //--------------------------------------------------------------------------- public FTPFileObj setCredentials(LoginCredentials inValue) { mCredentials = inValue; return this; } //--------------------------------------------------------------------------- public LoginCredentials getCredentials() { return mCredentials; } //--------------------------------------------------------------------------- @Override public List listFiles() { List fileObjs = null; if (isDirectory()) { try { FTPFile[] files = getFTPClient(mURL).listFiles(getPath()); if (files.length > 0) { fileObjs = new ArrayList<>(files.length); for (FTPFile file : files) { URL url = new URL(mURL.getProtocol(), mURL.getHost(), getPath() + (getPath().endsWith("/") ? "" : "/") + file.getName()); fileObjs.add(new FTPFileObj(url)); } } } catch (Exception e) { throw new RuntimeIOException(e); } } return fileObjs; } //--------------------------------------------------------------------------- /** * Use FTP.ASCII_FILE_TYPE or FTP.BINARY_FILE_TYPE (default). */ public void setFileTransferMode(int inValue) { mFileTransferMode = FTP.ASCII_FILE_TYPE; } //--------------------------------------------------------------------------- @Override public boolean exists() { boolean result; try { result = getFTPClient(mURL).list(getPath()) > 0; } catch (IOException e) { throw new RuntimeIOException(e); } return result; } //--------------------------------------------------------------------------- @Override public boolean canRead() { FTPFile ftpFile = getFTPFile(); return ftpFile.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.READ_PERMISSION) || (ftpFile.hasPermission(FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION) && ftpFile.getUser().equals(getCredentials().getUser())) || (ftpFile.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.READ_PERMISSION) && ftpFile.getGroup().equals("???")); //TODO: How to determine the group(s) for the logged in FTP user? } //--------------------------------------------------------------------------- @Override public boolean canWrite() { FTPFile ftpFile = getFTPFile(); return ftpFile.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.WRITE_PERMISSION) || (ftpFile.hasPermission(FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION) && ftpFile.getUser().equals(getCredentials().getUser())) || (ftpFile.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.WRITE_PERMISSION) && ftpFile.getGroup().equals("???")); //TODO: How to determine the group(s) for the logged in FTP user? } //--------------------------------------------------------------------------- @Override public boolean isFile() { return getFTPFile().isFile(); } //--------------------------------------------------------------------------- @Override public boolean isDirectory() { FTPFile ftpFile = getFTPFile(); return (ftpFile != null ? ftpFile.isDirectory() : true); // The root won't return an ftpFile } //--------------------------------------------------------------------------- @Override public FTPFileObj getParentDir() throws IOException { FTPFileObj parentDir = null; if (getPath().length() > 1) { URL url = new URL(getScheme(), mURL.getHost(), getParentDirPath()); parentDir = new FTPFileObj(url); } return parentDir; } //--------------------------------------------------------------------------- @Override public boolean mkdirs() throws IOException { return getFTPClient(mURL).makeDirectory(getPath()); } //--------------------------------------------------------------------------- @Override public boolean delete() throws IOException { return getFTPClient(mURL).deleteFile(getPath()); } //--------------------------------------------------------------------------- /** * Note that the FTP connection is closed when the returned InputStream is closed. */ @Override public InputStream getInputStream() throws IOException { FTPClient ftpClient = getFTPClient(mURL); ftpClient.setFileType(mFileTransferMode); InputStream stream = ftpClient.retrieveFileStream(mURL.getPath()); return new BufferedInputStream(stream); } //--------------------------------------------------------------------------- @Override public OutputStream getOutputStream() throws IOException { FTPClient ftpClient = getFTPClient(mURL); ftpClient.setFileType(mFileTransferMode); OutputStream stream = ftpClient.appendFileStream(mURL.getPath()); return new BufferedOutputStream(stream); } //--------------------------------------------------------------------------- @Override public long writeToStream(OutputStream stream) throws IOException { FTPClient ftpClient = getFTPClient(mURL); ftpClient.setFileType(mFileTransferMode); ftpClient.changeWorkingDirectory(getParentDirPath()); ftpClient.retrieveFile(getName(), stream); return length(); } //--------------------------------------------------------------------------- private FTPClient getFTPClient(URL inURL) { if (null == mFTP) { FTPClient client = new FTPClient(); client.setRemoteVerificationEnabled(false); // Bad with caching firewalls client.setDataTimeout((int) TimeUnit.hour.getMilliseconds()); try { int reply; if (inURL.getPort() > 0) { client.connect(inURL.getHost(), inURL.getPort()); } else { client.connect(inURL.getHost()); } // After connection attempt, check the reply code to verify success. reply = client.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { throw new RuntimeException("FTP server '" + inURL.getHost() + "' refused connection."); } client.login(mCredentials.getUser(), new String(mCredentials.getPassword())); // Hmmm. Data connections on my mac never seem to go anywhere unless I do this to force passive mode. client.enterLocalPassiveMode(); } catch (IOException e) { if (client.isConnected()) { try { client.disconnect(); } catch (IOException f) { // do nothing } } throw new RuntimeException(e); } mFTP = client; } return mFTP; } //--------------------------------------------------------------------------- private static String getUserAtHostPassword() { String passwd; try { passwd = System.getProperty("user.name") + "@" + InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { throw new RuntimeException(e); } return passwd; } //--------------------------------------------------------------------------- private FTPFile getFTPFile() { if (null == mFTPFile) { try { FTPFile[] files = getFTPClient(mURL).listFiles(getParentDirPath()); if (files.length > 0) { for (FTPFile file : files) { if (file.getName().equals(getName())) { mFTPFile = file; break; } } } } catch (IOException e) { throw new RuntimeIOException(e); } } return mFTPFile; } //--------------------------------------------------------------------------- private String getParentDirPath() { String parentDirPath = ""; String path = mURL.getPath(); if (path.length() > 0) { int index = path.substring(0,path.length() - 1).lastIndexOf("/"); if (index >= 0) { parentDirPath = path.substring(0, index + 1); } } return parentDirPath; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy