/* * Copyright 2012 jMethods, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.myjavaworld.jftp; import java.awt.BorderLayout; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.io.File; import java.io.IOException; import java.text.MessageFormat; import java.text.ParseException; import java.util.Hashtable; import java.util.ResourceBundle; import javax.swing.JOptionPane; import javax.swing.JSplitPane; import javax.swing.Timer; import javax.swing.filechooser.FileSystemView; import com.myjavaworld.ftp.ConnectionException; import com.myjavaworld.ftp.ControlConnectionEvent; import com.myjavaworld.ftp.ControlConnectionListener; import com.myjavaworld.ftp.DataConnectionEvent; import com.myjavaworld.ftp.DataConnectionListener; import com.myjavaworld.ftp.FTPClient; import com.myjavaworld.ftp.FTPConnectionEvent; import com.myjavaworld.ftp.FTPConnectionListener; import com.myjavaworld.ftp.FTPConstants; import com.myjavaworld.ftp.FTPException; import com.myjavaworld.ftp.FTPUtil; import com.myjavaworld.ftp.ListParser; import com.myjavaworld.ftp.RemoteFile; import com.myjavaworld.gui.GUIUtil; import com.myjavaworld.gui.MScrollPane; import com.myjavaworld.gui.SwingWorker; import com.myjavaworld.jftp.ssl.JFTPSSLContext; import com.myjavaworld.util.FileChangeEvent; import com.myjavaworld.util.FileChangeListener; import com.myjavaworld.util.FileChangeMonitor; import com.myjavaworld.util.Filter; import com.myjavaworld.util.ProgressEvent; import com.myjavaworld.util.ProgressListener; import com.myjavaworld.util.ResourceLoader; import com.myjavaworld.zip.ZipEvent; import com.myjavaworld.zip.ZipListener; /** * FTP session. Contains the main interface and connection and data transfer * logic. * * @author Sai Pullabhotla, psai [at] jMethods [dot] com * @version 2.0 */ public class FTPSession extends SessionPanel implements FTPConnectionListener, ControlConnectionListener, DataConnectionListener, ActionListener, FileChangeListener, ProgressListener, ZipListener { private static final ResourceBundle resources = ResourceLoader .getBundle("com.myjavaworld.jftp.FTPSession"); private LocalPane localPane = null; private JFTP jftp = null; private RemotePane remotePane = null; private FTPClient client = null; private ListParser listParser = null; private LocalFile lwd = null; private RemoteFile rwd = null; private StatusWindow statusWindow = null; private StatusBar statusBar = null; private Timer timer = null; private int timeElapsed = 0; private long bytesTransferred = 0L; private MessageFormat connectStatusFormat = null; private MessageFormat downloadStatusFormat = null; private MessageFormat uploadStatusFormat = null; private MessageFormat listStatusFormat = null; private String listParentStatus = null; private JSplitPane splitPane1 = null; private JSplitPane splitPane2 = null; private static int sessionId = 0; private int id = 0; private RemoteHost remoteHost = null; private int transferType = FTPConstants.TYPE_BINARY; private boolean autoDetect = true; private boolean abort = false; private Filter localFileFilter = null; private Filter remoteFileFilter = null; private FileChangeMonitor fileChangeMonitor = null; private Hashtable monitoredTransfers = null; private MessageFormat zipStatusFormat = null; private MessageFormat unzipStatusFormat = null; private Timer progressTimer = null; private int progress = 0; public FTPSession(JFTP jftp) { super(); this.jftp = jftp; this.id = ++sessionId; setName("cmd.session" + id); updateTitle(); localFileFilter = new LocalFileFilter(null, null, false); connectStatusFormat = new MessageFormat( resources.getString("status.connect")); downloadStatusFormat = new MessageFormat( resources.getString("status.download")); uploadStatusFormat = new MessageFormat( resources.getString("status.upload")); listStatusFormat = new MessageFormat(resources.getString("status.list")); listParentStatus = resources.getString("status.listParent"); timer = new Timer(1000, this); getContentPane().setLayout(new BorderLayout(0, 0)); getContentPane().add(getCenterPanel(), BorderLayout.CENTER); getContentPane().add(getSouthPanel(), BorderLayout.SOUTH); File lwd = new File(JFTP.prefs.getLocalDirectory()); // if (!lwd.exists() || !lwd.isDirectory()) // lwd = JFTP.USER_HOME; if (!lwd.exists() || !lwd.isDirectory()) { lwd = FileSystemView.getFileSystemView().getDefaultDirectory(); } setLocalWorkingDirectory(new LocalFile(lwd)); addComponentListener(new ComponentAdapter() { @Override public void componentShown(ComponentEvent arg0) { splitPane1.setDividerLocation(0.5); splitPane2.setDividerLocation(0.2); } }); fileChangeMonitor = new FileChangeMonitor(); fileChangeMonitor.addFileChangeListener(this); monitoredTransfers = new Hashtable(); zipStatusFormat = new MessageFormat(resources.getString("status.zip")); unzipStatusFormat = new MessageFormat( resources.getString("status.unzip")); progressTimer = new Timer(1000, this); } public void fileChanged(FileChangeEvent evt) { File file = evt.getFile(); TransferObject transferObject = (TransferObject) monitoredTransfers .get(file); if (transferObject == null) { return; } final LocalFile localFile = transferObject.getLocalFile(); final RemoteFile remoteFile = transferObject.getRemoteFile(); MessageFormat formatter = new MessageFormat( resources.getString("confirm.uploadChangedFile")); String message = formatter.format(new Object[] { remoteFile, getRemoteHost() }); int confirm = GUIUtil.showConfirmation(this, message); if (confirm != JOptionPane.YES_OPTION) { return; } setBusy(true); new SwingWorker() { private RemoteFile[] children = null; @Override public Object construct() { upload(localFile, remoteFile); try { children = client.list(remoteFileFilter); } catch (FTPException exp) { ftpException(exp); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError("<ERROR> " + exp); exp.printStackTrace(); } return null; } @Override public void finished() { remotePane.setData(rwd, children); setBusy(false); } }.start(); } public int getId() { return id; } @Override public void setBusy(boolean busy) { super.setBusy(busy); } public void setTransferType(int transferType) { this.transferType = transferType; } public int getTransferType() { return transferType; } public void setAutoDetect(boolean autoDetect) { this.autoDetect = autoDetect; } public boolean isAutoDetect() { return autoDetect; } public int getTransferType(String ext) { if (autoDetect) { Object obj = JFTP.prefs.getTransferTypes().get(ext); if (obj == null) { return JFTP.prefs.getDefaultTransferType(); } else { return ((Integer) obj).intValue(); } } return transferType; } public void actionPerformed(ActionEvent evt) { Object source = evt.getSource(); if (source == timer) { timeElapsed++; statusBar.setProgress((int) bytesTransferred); statusBar.setSpeed(bytesTransferred / timeElapsed); statusBar.setTimeElapsed(JFTPUtil.getTimeString(timeElapsed)); } else if (source == progressTimer) { timeElapsed++; statusBar.setProgress(progress); statusBar.setTimeElapsed(JFTPUtil.getTimeString(timeElapsed)); } } @Override public String toString() { return getTitle(); } /** * @param filter */ public void setLocalFileFilter(Filter filter) { this.localFileFilter = filter; localPane.refresh(); } /** * @return current filter set on local files. */ public Filter getLocalFileFilter() { return localFileFilter; } /** * @param filter */ public void setRemoteFileFilter(Filter filter) { this.remoteFileFilter = filter; remotePane.refresh(); } /** * @return current filter set on local files. */ public Filter getRemoteFileFilter() { return remoteFileFilter; } private void updateTitle() { jftp.updateSessionTitle(this); } private Component getCenterPanel() { localPane = new LocalPane(this); remotePane = new RemotePane(this); statusWindow = new StatusWindow(); MScrollPane scroller = new MScrollPane(statusWindow); splitPane1 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, localPane, remotePane); splitPane1.setOneTouchExpandable(true); splitPane1.setResizeWeight(0.5d); splitPane1.setContinuousLayout(true); splitPane2 = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scroller, splitPane1); splitPane2.setOneTouchExpandable(true); splitPane2.setContinuousLayout(true); splitPane2.setResizeWeight(0.2d); return splitPane2; } private Component getSouthPanel() { statusBar = new StatusBar(); return statusBar; } public void closeSession() { if (client != null && client.isConnected()) { try { client.disconnect(); } catch (FTPException exp) { ftpException(exp); } catch (Exception exp) { exp.printStackTrace(); } } fileChangeMonitor.stopMonitor(); cleanup(); System.gc(); } public RemoteHost getRemoteHost() { return remoteHost; } public FTPClient getFTPClient() { return client; } public void setLocalWorkingDirectory(String dir) { File file = new File(dir); if (!file.isAbsolute()) { file = new File(lwd.getFile(), dir); } setLocalWorkingDirectory(new LocalFile(file)); } public void setLocalWorkingDirectory(final LocalFile dir) { if (dir == null || !dir.isDirectory() || !dir.canRead()) { GUIUtil.showError(this, resources.getString("error.changeLocalDirectory")); return; } setBusy(true); new SwingWorker() { LocalFile[] data = null; @Override public Object construct() { data = dir.list(localFileFilter); lwd = dir; return null; } @Override public void finished() { localPane.setData(dir, data); setBusy(false); } }.start(); } public LocalFile getLocalWorkingDirectory() { return lwd; } public void upLocalWorkingDirectory() { if (lwd == null) { return; } LocalFile parent = lwd.getParent(); if (parent == null) { return; } setLocalWorkingDirectory(parent); } public void refreshLocalPane() { localPane.refresh(); } public void setRemoteWorkingDirectory(String name) { RemoteFile dir = listParser.createRemoteFile(name, true); setRemoteWorkingDirectory(dir); } public RemoteFile getRemoteWorkingDirectory() { return rwd; } public void setRemoteWorkingDirectory(final RemoteFile dir) { if (dir == null || !(dir.isDirectory() || dir.isLink())) { return; } Object args = new Object[] { dir.getName() }; String status = listStatusFormat.format(args); statusBar.setStatus(status); statusBar.setIndeterminate(true); setBusy(true); new SwingWorker() { RemoteFile[] data = null; @Override public Object construct() { try { client.setWorkingDirectory(dir); RemoteFile wd = client.getWorkingDirectory(); rwd = wd; data = client.list(remoteFileFilter); } catch (FTPException exp) { ftpException(exp); } catch (ParseException exp) { statusWindow .addError("<ERROR> Could not parse the LIST command output. " + "The original data returned by the server is: \n" + exp.getMessage()); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError("<ERROR> " + exp); exp.printStackTrace(); } finally { return null; } } @Override public void finished() { remotePane.setData(rwd, data); statusBar.reset(); setBusy(false); } }.start(); } public void upRemoteWorkingDirectory() { if (!isConnected()) { return; } statusBar.setStatus(listParentStatus); statusBar.setIndeterminate(true); setBusy(true); new SwingWorker() { RemoteFile[] data = null; @Override public Object construct() { try { client.setToParentDirectory(); RemoteFile wd = client.getWorkingDirectory(); rwd = wd; data = client.list(remoteFileFilter); } catch (FTPException exp) { ftpException(exp); } catch (ParseException exp) { statusWindow .addError("<ERROR> Could not parse the LIST command output. " + "The original data returned by the server is: \n" + exp.getMessage()); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError("<ERROR> " + exp); exp.printStackTrace(); } finally { return null; } } @Override public void finished() { remotePane.setData(rwd, data); statusBar.reset(); setBusy(false); } }.start(); } public void refreshRemotePane() { remotePane.refresh(); } public int getLocalFileSelectionCount() { return localPane.getSelectionCount(); } public LocalFile getSelectedLocalFile() { return localPane.getSelectedFile(); } public LocalFile[] getSelectedLocalFiles() { return localPane.getSelectedFiles(); } public int getRemoteFileSelectionCount() { return remotePane.getSelectionCount(); } public RemoteFile getSelectedRemoteFile() { return remotePane.getSelectedFile(); } public RemoteFile[] getSelectedRemoteFiles() { return remotePane.getSelectedFiles(); } public void connectionOpened(FTPConnectionEvent evt) { statusWindow.addStatus("<STATUS> " + evt.getMessage()); statusBar.setSecured(client.isSecured()); jftp.updateToolBar(); } public void connectionClosed(FTPConnectionEvent evt) { setBusy(false); statusWindow.addStatus("<STATUS> " + evt.getMessage()); jftp.updateToolBar(); timer.stop(); this.timeElapsed = 0; this.bytesTransferred = 0L; statusBar.reset(); statusBar.setSecured(false); remotePane.clearAll(); updateTitle(); } public void commandSent(ControlConnectionEvent evt) { statusWindow.addCommand("<COMMAND> " + evt.getMessage()); } public void replyReceived(ControlConnectionEvent evt) { statusWindow.addReply("<REPLY> " + evt.getMessage()); } public void connectionDropped(ControlConnectionEvent evt) { statusWindow.addStatus("<STATUS>" + evt.getMessage()); } public void dataTransferStarted(DataConnectionEvent evt) { } public void dataTransferFinished(DataConnectionEvent evt) { statusBar.setProgress(0); } public void dataTransferProgress(DataConnectionEvent evt) { bytesTransferred = evt.getBytesTransferred(); } public void dataTransferAborted(DataConnectionEvent evt) { statusWindow.addStatus("<STATUS> Data transfer aborted by the user. "); timer.stop(); this.timeElapsed = 0; this.bytesTransferred = 0L; statusBar.reset(); } public void dataTransferError(DataConnectionEvent evt) { } public void ftpException(Exception exp) { statusWindow.addError(exp.getMessage()); } public void exception(Throwable t) { statusWindow.addError(t.toString()); t.printStackTrace(); } public void connectionException(Exception exp) { setBusy(false); statusWindow.addError(exp.getMessage()); jftp.updateToolBar(); timer.stop(); this.timeElapsed = 0; this.bytesTransferred = 0L; statusBar.reset(); remotePane.clearAll(); updateTitle(); exp.printStackTrace(); } public void connect(final RemoteHost remoteHost) { if (isConnected()) { MessageFormat format = new MessageFormat( resources.getString("confirm.reconnect")); int option = GUIUtil .showConfirmation( this, format.format(new Object[] { this.remoteHost, remoteHost })); if (option != JOptionPane.YES_OPTION) { return; } disconnect(); } this.remoteHost = remoteHost; Object args = new Object[] { remoteHost.getHostName(), (remoteHost.getSSLUsage() == FTPConstants.USE_IMPLICIT_SSL ? new Integer( remoteHost.getImplicitSSLPort()) : new Integer( remoteHost.getPort())) }; String status = connectStatusFormat.format(args); statusBar.setStatus(status); statusBar.setIndeterminate(true); setBusy(true); new SwingWorker() { RemoteFile[] data = null; @Override public Object construct() { try { client = (FTPClient) Class.forName( remoteHost.getFTPClientClassName()).newInstance(); listParser = (ListParser) Class.forName( remoteHost.getListParserClassName()).newInstance(); client.setListParser(listParser); client.setPassive(remoteHost.isPassive()); client.setTimeout(JFTP.prefs.getTimeout()); client.setBufferSize(JFTP.prefs.getBufferSize()); client.setSSLUsage(remoteHost.getSSLUsage()); client.setDataChannelUnencrypted(remoteHost .isDataChannelUnencrypted()); if (remoteHost.getSSLUsage() != FTPConstants.USE_NO_SSL) { client.setSSLContext(JFTPSSLContext.getSSLContext(jftp, remoteHost.getHostName())); } client.addControlConnectionListener(FTPSession.this); client.addDataConnectionListener(FTPSession.this); client.addFTPConnectionListener(FTPSession.this); try { int port = 0; if (remoteHost.getSSLUsage() == FTPConstants.USE_IMPLICIT_SSL) { port = remoteHost.getImplicitSSLPort(); } else { port = remoteHost.getPort(); } client.connect(remoteHost.getHostName(), port); client.login(remoteHost.getUser(), remoteHost.getPassword(), remoteHost.getAccount()); } catch (FTPException exp) { ftpException(exp); client.disconnect(); client = null; return null; } String[] commands = remoteHost.getCommands(); for (int i = 0; i < commands.length; i++) { client.executeCommand(commands[i]); } String initialRemoteDirectory = remoteHost .getInitialRemoteDirectory(); if (initialRemoteDirectory != null && initialRemoteDirectory.trim().length() > 0) { RemoteFile remoteDir = listParser .createRemoteFile(initialRemoteDirectory); client.setWorkingDirectory(remoteDir); } RemoteFile dir = client.getWorkingDirectory(); data = client.list(remoteFileFilter); rwd = dir; } catch (FTPException exp) { ftpException(exp); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError("<ERROR> " + exp.getMessage()); exp.printStackTrace(); } finally { return null; } } @Override public void finished() { if (client != null && client.isConnected()) { remotePane.setData(rwd, data); updateTitle(); } statusBar.reset(); setBusy(false); String initialLocalDirectory = remoteHost .getInitialLocalDirectory(); setLocalWorkingDirectory(initialLocalDirectory); } }.start(); } public void reconnect() { if (remoteHost != null) { connect(this.remoteHost); } } public void download() { if (!isConnected()) { return; } final RemoteFile[] selectedFiles = remotePane.getSelectedFiles(); if (selectedFiles == null || selectedFiles.length == 0) { return; } abort = false; setBusy(true); new SwingWorker() { LocalFile[] children = null; @Override public Object construct() { for (int i = 0; i < selectedFiles.length; i++) { if (!client.isConnected() || abort) { break; } download(rwd, lwd.getFile(), selectedFiles[i]); } children = lwd.list(localFileFilter); return null; } @Override public void finished() { localPane.setData(lwd, children); setBusy(false); } }.start(); } public void download(RemoteFile sourceDir, File targetDir, RemoteFile source) { download(sourceDir, targetDir, source, null); } public void download(RemoteFile sourceDir, File targetDir, RemoteFile source, String targetName) { if (client == null || !client.isConnected() || abort) { return; } if (source.isDirectory() && (source.getName().equals(".") || source.getName().equals( ".."))) { return; } if (targetName == null) { targetName = source.getNormalizedName(); } if (source.isFile()) { File destination = new File(targetDir, targetName); // int type = getTransferType(source.getExtension()); // Object[] args = {source.getName()}; // statusBar.setStatus(downloadStatusFormat.format(args)); // statusBar.setMaximum((int) source.getSize()); // timeElapsed = 0; // timer.start(); // try { // client.download(source, destination, type, false); // } // catch(FTPException exp) { // ftpException(exp); // } // catch(ConnectionException exp) { // connectionException(exp); // } // catch(Exception exp) { // statusWindow.addError("<ERROR> " + exp); // exp.printStackTrace(); // } // finally { // timer.stop(); // timeElapsed = 0; // statusBar.reset(); // } downloadDataFile(source, destination); } else if (source.isDirectory()) { // File target = new File(targetDir, source.getName()); File target = new File(targetDir, targetName); if (!target.exists()) { target.mkdirs(); } RemoteFile[] children = null; try { client.setWorkingDirectory(source); children = client.list(remoteFileFilter); } catch (FTPException exp) { ftpException(exp); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError("<ERROR> " + exp); exp.printStackTrace(); } if (children != null) { for (int i = 0; i < children.length; i++) { download(source, target, children[i], null); } } } } public void downloadDataFile(RemoteFile source, File target) { int type = getTransferType(source.getExtension()); Object[] args = { source.getName() }; statusBar.setStatus(downloadStatusFormat.format(args)); statusBar.setMaximum((int) source.getSize()); timeElapsed = 0; timer.start(); try { client.download(source, target, type, false); } catch (FTPException exp) { ftpException(exp); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError("<ERROR> " + exp); exp.printStackTrace(); } finally { timer.stop(); timeElapsed = 0; statusBar.reset(); } } public void upload() { if (!isConnected()) { return; } final LocalFile[] selectedFiles = localPane.getSelectedFiles(); if (selectedFiles == null || selectedFiles.length == 0) { return; } abort = false; setBusy(true); new SwingWorker() { RemoteFile[] children = null; @Override public Object construct() { for (int i = 0; i < selectedFiles.length; i++) { if (!client.isConnected() || abort) { break; } upload(lwd, rwd, selectedFiles[i]); } try { children = client.list(remoteFileFilter); } catch (FTPException exp) { ftpException(exp); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError("<ERROR> " + exp); exp.printStackTrace(); } finally { return null; } } @Override public void finished() { remotePane.setData(rwd, children); setBusy(false); } }.start(); } public void upload(LocalFile sourceDir, RemoteFile targetDir, LocalFile source) { upload(sourceDir, targetDir, source, null); } public void upload(LocalFile sourceDir, RemoteFile targetDir, LocalFile source, String targetName) { if (client == null || !client.isConnected() || abort) { return; } if (source.isDirectory() && (source.getName().equals(".") || source.getName().equals( ".."))) { return; } if (targetName == null) { targetName = source.getName(); } if (source.isFile()) { // RemoteFile destination = listParser.createRemoteFile(targetDir, // source.getName(), false); RemoteFile destination = listParser.createRemoteFile(targetDir, targetName, false); int type = getTransferType(source.getExtension()); Object[] args = { destination.getName() }; statusBar.setStatus(uploadStatusFormat.format(args)); statusBar.setMaximum((int) source.getSize()); timeElapsed = 0; timer.start(); try { client.upload(source.getFile(), destination, type, false, 0L); } catch (FTPException exp) { ftpException(exp); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError("<ERROR> " + exp); exp.printStackTrace(); } finally { timer.stop(); timeElapsed = 0; statusBar.reset(); } } else if (source.isDirectory()) { // RemoteFile destination = listParser.createRemoteFile(targetDir, // source.getName(), true); RemoteFile destination = listParser.createRemoteFile(targetDir, targetName, true); try { client.createDirectory(destination); } catch (FTPException exp) { ftpException(exp); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError("<ERROR> " + exp); exp.printStackTrace(); } LocalFile[] children = source.list(localFileFilter); for (int i = 0; i < children.length; i++) { upload(source, destination, children[i], null); } } } public void upload(LocalFile localFile, String remoteFileName) { RemoteFile remoteFile = listParser .createRemoteFile(rwd, remoteFileName); upload(localFile, remoteFile); } public void upload(LocalFile localFile, RemoteFile destination) { int type = getTransferType(localFile.getExtension()); Object[] args = { destination.getName() }; statusBar.setStatus(uploadStatusFormat.format(args)); statusBar.setMaximum((int) localFile.getSize()); timeElapsed = 0; timer.start(); try { client.upload(localFile.getFile(), destination, type, false, 0L); } catch (FTPException exp) { ftpException(exp); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError("<ERROR> " + exp); exp.printStackTrace(); } finally { timer.stop(); timeElapsed = 0; statusBar.reset(); } } public void createRemoteDirectory(final String directory) { setBusy(true); new SwingWorker() { RemoteFile[] data = null; @Override public Object construct() { RemoteFile dir = listParser.createRemoteFile(directory, true); try { client.createDirectory(dir); data = client.list(remoteFileFilter); } catch (FTPException exp) { ftpException(exp); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError("<ERROR> " + exp.getMessage()); exp.printStackTrace(); } finally { return null; } } @Override public void finished() { if (data != null) { remotePane.setData(rwd, data); } setBusy(false); } }.start(); } public void createRemoteFile(final String file) { setBusy(true); new SwingWorker() { RemoteFile[] data = null; @Override public Object construct() { RemoteFile newFile = listParser.createRemoteFile(file, false); try { client.createFile(newFile); data = client.list(remoteFileFilter); } catch (FTPException exp) { ftpException(exp); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError("<ERROR> " + exp.getMessage()); exp.printStackTrace(); } finally { return null; } } @Override public void finished() { if (data != null) { remotePane.setData(rwd, data); } setBusy(false); } }.start(); } public void renameRemoteFile(final String fromName, final String toName) { setBusy(true); new SwingWorker() { RemoteFile[] data = null; @Override public Object construct() { RemoteFile from = listParser.createRemoteFile(fromName); RemoteFile to = listParser.createRemoteFile(toName); try { client.rename(from, to); data = client.list(remoteFileFilter); } catch (FTPException exp) { ftpException(exp); } catch (Exception exp) { System.err.println(exp); exp.printStackTrace(); } finally { return null; } } @Override public void finished() { if (data != null) { remotePane.setData(rwd, data); } setBusy(false); } }.start(); } public void changeRemoteFilePermissions(final RemoteFile oldFile, final RemoteFile newFile, final boolean recursive) { setBusy(true); new SwingWorker() { RemoteFile[] data = null; @Override public Object construct() { try { String newAttributes = newFile.getAttributes(); newAttributes = newAttributes.substring(1); if (recursive) { changeRemoteFilePermissions(oldFile, FTPUtil.parseAttributes(newAttributes)); } else { String fileName = oldFile.getNormalizedPath(); // if(fileName.indexOf(' ') > 0) { // fileName = "\"" + fileName + "\""; // } client.executeCommand("SITE CHMOD " + FTPUtil.parseAttributes(newAttributes) + " " + fileName); } client.setWorkingDirectory(rwd); data = client.list(remoteFileFilter); } catch (FTPException exp) { ftpException(exp); } catch (Exception exp) { System.err.println(exp); exp.printStackTrace(); } finally { return null; } } @Override public void finished() { if (data != null) { remotePane.setData(rwd, data); } setBusy(false); } }.start(); } private void changeRemoteFilePermissions(RemoteFile file, String attributes) { if (client == null || !client.isConnected() || abort) { return; } if (file.isDirectory() && (file.getName().equals(".") || file.getName().equals(".."))) { return; } String fileName = file.getNormalizedPath(); // if(fileName.indexOf(' ') > 0) { // fileName = "\"" + fileName + "\""; // } try { client.executeCommand("SITE CHMOD " + attributes + " " + fileName); } catch (FTPException exp) { ftpException(exp); } catch (ConnectionException exp) { connectionException(exp); } if (file.isDirectory()) { RemoteFile[] children = null; try { client.setWorkingDirectory(file); children = client.list(remoteFileFilter); } catch (FTPException exp) { ftpException(exp); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError("<ERROR> " + exp); exp.printStackTrace(); } if (children != null) { for (int i = 0; i < children.length; i++) { changeRemoteFilePermissions(children[i], attributes); } } } } public void updateRemoteFile(final RemoteFile oldFile, final RemoteFile newFile) { setBusy(true); new SwingWorker() { RemoteFile[] data = null; @Override public Object construct() { try { boolean reload = false; String oldName = oldFile.getName(); String newName = newFile.getName(); if (!oldName.equals(newName)) { client.rename(oldFile, newFile); reload = true; } String oldAttributes = oldFile.getAttributes(); String newAttributes = newFile.getAttributes(); if (!oldAttributes.equals(newAttributes)) { newAttributes = newAttributes.substring(1); client.executeCommand("SITE CHMOD " + newName + " " + FTPUtil.parseAttributes(newAttributes)); reload = true; } if (reload) { data = client.list(remoteFileFilter); } } catch (Exception exp) { System.err.println(exp); exp.printStackTrace(); } finally { return null; } } @Override public void finished() { if (data != null) { remotePane.setData(rwd, data); } setBusy(false); } }.start(); } public void deleteRemoteFiles() { final RemoteFile[] selectedFiles = remotePane.getSelectedFiles(); if (selectedFiles == null || selectedFiles.length == 0) { return; } int option = GUIUtil.showConfirmation(jftp, resources.getString("confirm.deleteRemoteFiles")); if (option != JOptionPane.YES_OPTION) { return; } setBusy(true); new SwingWorker() { RemoteFile[] data = null; @Override public Object construct() { for (int i = 0; i < selectedFiles.length; i++) { delete(selectedFiles[i]); } try { client.setWorkingDirectory(rwd); data = client.list(remoteFileFilter); } catch (FTPException exp) { ftpException(exp); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError("<ERROR> " + exp); exp.printStackTrace(); } finally { return null; } } @Override public void finished() { remotePane.setData(rwd, data); setBusy(false); } }.start(); } private void delete(RemoteFile file) { if (client == null || !client.isConnected()) { return; } if (file.isDirectory() && (file.getName().equals(".") || file.getName().equals(".."))) { return; } try { if (file.isFile()) { client.delete(file); } else if (file.isDirectory()) { RemoteFile[] children = null; client.setWorkingDirectory(file); children = client.list(remoteFileFilter); for (int i = 0; i < children.length; i++) { delete(children[i]); } client.setToParentDirectory(); client.delete(file); } } catch (FTPException exp) { ftpException(exp); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError("<ERROR> " + exp); exp.printStackTrace(); } } public void createLocalDirectory(final String dir) { setBusy(true); new SwingWorker() { LocalFile[] data = null; boolean created = true; @Override public Object construct() { File file = new File(dir); if (!file.isAbsolute()) { file = new File(lwd.getFile(), dir); } created = file.mkdirs(); if (created) { data = lwd.list(localFileFilter); } return null; } @Override public void finished() { if (!created) { GUIUtil.showError(jftp, resources.getString("error.createLocalDirectory")); } else { localPane.setData(lwd, data); } setBusy(false); } }.start(); } public void createLocalFile(final String fileName) { setBusy(true); new SwingWorker() { LocalFile[] data = null; boolean created = true; @Override public Object construct() { File file = new File(fileName); if (!file.isAbsolute()) { file = new File(lwd.getFile(), fileName); } try { created = file.createNewFile(); if (created) { data = lwd.list(localFileFilter); } } catch (Exception exp) { GUIUtil.showError(jftp, exp); } return null; } @Override public void finished() { if (!created) { GUIUtil.showError(jftp, resources.getString("error.createLocalFile")); } else { localPane.setData(lwd, data); } setBusy(false); } }.start(); } public void renameLocalFile(String fromName, String toName) { File fromFile = new File(fromName); File toFile = new File(toName); if (!fromFile.isAbsolute()) { fromFile = new File(lwd.getFile(), fromName); } if (!toFile.isAbsolute()) { toFile = new File(lwd.getFile(), toName); } boolean renamed = fromFile.renameTo(toFile); if (renamed) { LocalFile[] children = lwd.list(localFileFilter); localPane.setData(lwd, children); } else { GUIUtil.showError(this, resources.getString("error.renameLocalFile")); } } public void deleteLocalFiles() { final LocalFile[] selectedFiles = localPane.getSelectedFiles(); if (selectedFiles == null || selectedFiles.length == 0) { return; } int option = GUIUtil.showConfirmation(this, resources.getString("conform.deleteLocalFiles")); if (option != JOptionPane.YES_OPTION) { return; } setBusy(true); new SwingWorker() { LocalFile[] data = null; @Override public Object construct() { for (int i = 0; i < selectedFiles.length; i++) { // delete(selectedFiles[i].getFile()); delete(selectedFiles[i]); } data = lwd.list(localFileFilter); return null; } @Override public void finished() { setBusy(false); localPane.setData(lwd, data); } }.start(); } private void delete(LocalFile file) { if (file.isDirectory() && (file.getName().equals(".") || file.getName().equals(".."))) { return; } if (file.isFile()) { file.delete(); } else if (file.isDirectory()) { LocalFile[] children = file.list(localFileFilter); for (int i = 0; i < children.length; i++) { delete(children[i]); } file.delete(); } } public void executeCommand(final String command) { if (client == null || !client.isConnected()) { return; } setBusy(true); new SwingWorker() { @Override public Object construct() { try { client.executeCommand(command); } catch (FTPException exp) { ftpException(exp); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError(exp.toString()); exp.printStackTrace(); } finally { return null; } } @Override public void finished() { setBusy(false); } }.start(); } public void executeCommands(final String[] commands) { if (commands == null || client == null || !client.isConnected()) { return; } setBusy(true); new SwingWorker() { @Override public Object construct() { try { for (int i = 0; i < commands.length; i++) { String command = commands[i].toUpperCase(); if (!(command.startsWith("LIST") || command.startsWith("NLST") || command.startsWith("RETR") || command.startsWith("STOR") || command.startsWith("STOU") || command.startsWith("APPE") || command.startsWith("PASV") || command.startsWith("PORT") || command.startsWith("DATA") || command.startsWith("CWD") || command .startsWith("CDUP"))) { client.executeCommand(commands[i]); } } } catch (FTPException exp) { ftpException(exp); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError(exp.toString()); exp.printStackTrace(); } finally { return null; } } @Override public void finished() { setBusy(false); } }.start(); } public void disconnect() { if (client == null || !client.isConnected()) { return; } setBusy(true); new SwingWorker() { @Override public Object construct() { try { client.disconnect(); } catch (FTPException exp) { ftpException(exp); } catch (ConnectionException exp) { connectionException(exp); } catch (Exception exp) { statusWindow.addError("<ERROR> " + exp); exp.printStackTrace(); } finally { return null; } } @Override public void finished() { if (timer.isRunning()) { timer.stop(); } statusBar.reset(); bytesTransferred = 0L; timeElapsed = 0; remotePane.clearAll(); updateTitle(); setBusy(false); } }.start(); } public boolean isConnected() { if (client == null) { return false; } return client.isConnected(); } private void cleanup() { localPane = null; remotePane = null; client = null; listParser = null; lwd = null; rwd = null; statusWindow = null; statusBar = null; timer = null; downloadStatusFormat = null; uploadStatusFormat = null; listStatusFormat = null; splitPane1 = null; splitPane2 = null; remoteHost = null; } public File downloadToTempFile(RemoteFile source, boolean monitor) { if (!source.isFile()) { return null; } File destination = null; try { destination = File.createTempFile("jftp", "." + source.getExtension()); destination.deleteOnExit(); } catch (IOException exp) { statusWindow.addError("<ERROR> " + exp); exp.printStackTrace(); return null; } int type = getTransferType(source.getExtension()); Object[] args = { source.getName() }; statusBar.setStatus(downloadStatusFormat.format(args)); statusBar.setMaximum((int) source.getSize()); timeElapsed = 0; timer.start(); try { client.download(source, destination, type, false); if (monitor) { fileChangeMonitor.add(destination); monitoredTransfers.put(destination, new TransferObject( TransferObject.UPLOAD, new LocalFile(destination), source)); } return destination; } catch (FTPException exp) { ftpException(exp); return null; } catch (ConnectionException exp) { connectionException(exp); return null; } catch (Exception exp) { statusWindow.addError("<ERROR> " + exp); exp.printStackTrace(); return null; } finally { timer.stop(); timeElapsed = 0; statusBar.reset(); } } public void updateToolBar() { jftp.updateToolBar(); } public void setAbortFlag(boolean abort) { this.abort = abort; } public void clearAbortFlag() { abort = false; } public JFTP getJFTP() { return jftp; } public void setStatus(String status) { statusBar.setStatus(status); } public void resetStatusBar() { statusBar.reset(); } public void setProgress(int progress) { statusBar.setProgress(progress); } public void progressChanged(ProgressEvent evt) { progress = evt.getProgress(); } public void beginFile(ZipEvent evt) { Object[] args = { evt.getFile() }; if (evt.getType() == ZipEvent.ZIP) { statusBar.setStatus(zipStatusFormat.format(args)); } else if (evt.getType() == ZipEvent.UNZIP) { statusBar.setStatus(unzipStatusFormat.format(args)); } progressTimer.start(); } public void endFile(ZipEvent evt) { progressTimer.stop(); timeElapsed = 0; statusBar.reset(); } public void selectAllLocalFiles() { localPane.selectAll(); } public void invertLocalFileSelection() { localPane.invertSelection(); } public void selectAllRemoteFiles() { remotePane.selectAll(); } public void invertRemoteFileSelection() { remotePane.invertSelection(); } }