Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/internal/operations/OpUpload.java')
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/internal/operations/OpUpload.java594
1 files changed, 231 insertions, 363 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/internal/operations/OpUpload.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/internal/operations/OpUpload.java
index 54e20fcd9..47223fec8 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/internal/operations/OpUpload.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/internal/operations/OpUpload.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011, 2012 Wind River Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2011, 2015 Wind River Systems, Inc. and others. All rights reserved.
* This program and the accompanying materials are made available under the terms
* of the Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html
@@ -9,423 +9,291 @@
*******************************************************************************/
package org.eclipse.tcf.te.tcf.filesystem.core.internal.operations;
+import static java.text.MessageFormat.format;
+
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.net.MalformedURLException;
-import java.net.URL;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.LinkedList;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.ISafeRunnable;
-import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.osgi.util.NLS;
+import org.eclipse.tcf.protocol.IToken;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.services.IFileSystem;
+import org.eclipse.tcf.services.IFileSystem.DoneOpen;
+import org.eclipse.tcf.services.IFileSystem.DoneStat;
+import org.eclipse.tcf.services.IFileSystem.FileAttrs;
+import org.eclipse.tcf.services.IFileSystem.FileSystemException;
+import org.eclipse.tcf.services.IFileSystem.IFileHandle;
import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IConfirmCallback;
-import org.eclipse.tcf.te.tcf.filesystem.core.internal.url.TcfURLConnection;
-import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.CacheManager;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.FSTreeNode;
import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.FileState;
import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.PersistenceManager;
-import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.StatusHelper;
import org.eclipse.tcf.te.tcf.filesystem.core.nls.Messages;
+import org.eclipse.tcf.util.TCFFileOutputStream;
/**
- * Upload multiple files from local system to a remote system.
+ * Upload multiple files from local system to a remote system.
*/
-public class OpUpload extends OpStreamOp {
- // The source files to be uploaded.
- File[] srcFiles;
- // The destination URLs to be uploaded to.
- URL[] dstURLs;
- // The confirm callback
- IConfirmCallback confirmCallback;
- // The parent folder map to search files that have same names.
- Map<File, FSTreeNode> parentFolders;
- // The files that are to be committed to its target file system.
- FSTreeNode[] nodes;
-
- /**
- * Constructor.
- *
- * @param srcFile The source file to be uploaded.
- * @param dstURL The destination URL.
- */
- public OpUpload(File srcFile, URL dstURL) {
- this(new File[]{srcFile}, new URL[]{dstURL});
- }
-
- /**
- * Constructor.
- *
- * @param srcFiles The source files to be uploaded.
- * @param dstURLs The destination URLs.
- */
- public OpUpload(File[] srcFiles, URL[] dstURLs) {
- this(srcFiles, dstURLs, null);
+public class OpUpload extends AbstractOperation {
+ private static class WorkItem {
+ final File fSource;
+ final FSTreeNode fDestination;
+ final boolean fDropToDestination;
+ WorkItem(File source, FSTreeNode destination, boolean isDrop) {
+ fSource = source;
+ fDestination = destination;
+ fDropToDestination = isDrop;
+ }
}
-
- /**
- * Constructor.
- *
- * @param sourceFiles The source files in the native file system to be uploaded.
- * @param targetFolder The taret parent folder to upload these files to.
- */
- public OpUpload(String[]sourceFiles, FSTreeNode targetFolder) {
- this(sourceFiles, targetFolder, null);
+
+ IConfirmCallback fConfirmCallback;
+
+ LinkedList<WorkItem> fWork = new LinkedList<WorkItem>();
+ private long fStartTime;
+
+ public OpUpload(IConfirmCallback confirm) {
+ fConfirmCallback = confirm;
}
-
- /**
- * Constructor.
- *
- * @param sourceFiles The source files in the native file system to be uploaded.
- * @param targetFolder The target parent folder to upload these files to.
- * @param confirmCallback the confirmation callback to confirm overwriting.
- */
- public OpUpload(File[] srcFiles, URL[] dstURLs, IConfirmCallback confirmCallback) {
- this.srcFiles = srcFiles;
- this.dstURLs = dstURLs;
- this.confirmCallback = confirmCallback;
+
+ public void addUpload(File source, FSTreeNode destinationFile) {
+ fWork.add(new WorkItem(source, destinationFile, false));
}
-
- /**
- * Constructor that upload the local cache files of the specified nodes.
- *
- * @param nodes The nodes to be uploaded.
- */
- public OpUpload(FSTreeNode... nodes) {
- srcFiles = new File[nodes.length];
- dstURLs = new URL[nodes.length];
- for (int i = 0; i < nodes.length; i++) {
- srcFiles[i] = CacheManager.getCacheFile(nodes[i]);
- dstURLs[i] = nodes[i].getLocationURL();
- }
- this.nodes = nodes;
+
+ public void addDrop(File source, FSTreeNode destiniationFolder) {
+ fWork.add(new WorkItem(source, destiniationFolder, true));
}
-
- /**
- * Create an instance with specified files, target folder and a callback.
- *
- * @param sourceFiles the source files being uploaded.
- * @param targetFolder the target folder to upload the files to.
- * @param callback the callback that is invoked after uploading.
- */
- public OpUpload(String[] sourceFiles, FSTreeNode targetFolder, IConfirmCallback confirmCallback) {
- this.confirmCallback = confirmCallback;
- List<File> fileList = new ArrayList<File>();
- List<URL> urlList = new ArrayList<URL>();
- prepareDirStruct(sourceFiles, fileList, urlList, targetFolder);
- srcFiles = fileList.toArray(new File[fileList.size()]);
- dstURLs = urlList.toArray(new URL[urlList.size()]);
- }
- /*
- * (non-Javadoc)
- * @see org.eclipse.tcf.te.tcf.filesystem.internal.operations.FSOperation#run(org.eclipse.core.runtime.IProgressMonitor)
- */
@Override
- public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
- super.run(monitor);
- try {
- uploadFiles(srcFiles, dstURLs);
- if(monitor.isCanceled()) throw new InterruptedException();
- } catch (MalformedURLException e) {
- throw new InvocationTargetException(e);
- } catch (IOException e) {
- throw new InvocationTargetException(e);
- } finally {
- monitor.done();
+ public IStatus doRun(IProgressMonitor monitor) {
+ fStartTime = System.currentTimeMillis();
+ monitor.beginTask(getName(), IProgressMonitor.UNKNOWN);
+ while (!fWork.isEmpty()) {
+ IStatus s = runWorkItem(fWork.remove(), monitor);
+ if (!s.isOK())
+ return s;
}
- }
- /**
- * Test if the specified file should be confirmed.
- *
- * @param file The file to be confirmed.
- * @return true if it is.
- */
- private boolean requireConfirmation(File file) {
- return parentFolders != null && confirmCallback != null && !yes2All && confirmCallback.requires(file) && findNode(file) != null;
+ return Status.OK_STATUS;
}
-
- /**
- * Upload the specified file list to the specified locations, reporting the progress
- * using the specified monitor.
- *
- * @param files The file list to be uploaded.
- * @param urls The
- * @param monitor
- * @throws IOException
- */
- private void uploadFiles(File[] files, URL[] urls) throws IOException {
- // The buffer used to download the file.
- byte[] data = new byte[DEFAULT_CHUNK_SIZE];
- // Calculate the total size.
- long totalSize = 0;
- for (File file:files) {
- totalSize += file.length();
- }
- // Calculate the chunk size of one percent.
- int chunk_size = (int) totalSize / 100;
- // The current reading percentage.
- int percentRead = 0;
- // The current length of read bytes.
- long bytesRead = 0;
- for (int i = 0; i < files.length && !monitor.isCanceled(); i++) {
- File file = files[i];
- if (requireConfirmation(file)) {
- int result = confirmCallback.confirms(file);
- switch (result) {
- case IConfirmCallback.YES:
- break;
- case IConfirmCallback.YES_TO_ALL:
- yes2All = true;
- break;
- case IConfirmCallback.NO:
- bytesRead += file.length();
- if (chunk_size != 0) {
- int percent = (int) bytesRead / chunk_size;
- if (percent != percentRead) { // Update the progress.
- monitor.worked(percent - percentRead);
- percentRead = percent; // Remember the percentage.
- // Report the progress.
- monitor.subTask(NLS
- .bind(Messages.OpUpload_UploadingProgress, new Object[] { file
- .getName(), formatSize(bytesRead), formatSize(file
- .length()) }));
- }
+
+ protected IStatus runWorkItem(final WorkItem item, IProgressMonitor monitor) {
+ final String path;
+ final FSTreeNode destination = item.fDestination;
+ FSTreeNode existing;
+ final String name;
+ final File source = item.fSource;
+ if (item.fDropToDestination) {
+ IStatus status = refresh(destination, fStartTime, monitor);
+ if (!status.isOK())
+ return status;
+
+ name = item.fSource.getName();
+ existing = destination.findChild(name);
+
+ if (source.isDirectory()) {
+ if (existing != null) {
+ if (!existing.isDirectory()) {
+ return StatusHelper.createStatus(format(Messages.OpCopy_error_noDirectory, existing.getLocation()), null);
}
- continue;
- case IConfirmCallback.CANCEL:
- monitor.setCanceled(true);
- continue;
- }
- }
- BufferedInputStream input = null;
- BufferedOutputStream output = null;
- MessageDigest digest = null;
- try {
- URL url = urls[i];
- TcfURLConnection connection = (TcfURLConnection) url.openConnection();
- connection.setDoInput(false);
- connection.setDoOutput(true);
- if (nodes != null) {
- try {
- digest = MessageDigest.getInstance(MD_ALG);
- input = new BufferedInputStream(new DigestInputStream(new FileInputStream(file), digest));
- }
- catch (NoSuchAlgorithmException e) {
- input = new BufferedInputStream(new FileInputStream(file));
- }
- }
- else {
- input = new BufferedInputStream(new FileInputStream(file));
+ int replace = confirmCallback(existing, fConfirmCallback);
+ if (replace == IConfirmCallback.NO) {
+ return Status.OK_STATUS;
+ }
+ if (replace != IConfirmCallback.YES) {
+ return Status.CANCEL_STATUS;
+ }
+ } else {
+ status = destination.operationNewFolder(name).run(new SubProgressMonitor(monitor, 0));
+ if (!status.isOK())
+ return status;
+ existing = destination.findChild(name);
}
- output = new BufferedOutputStream(connection.getOutputStream());
- // Total size displayed on the progress dialog.
- String fileLength = formatSize(file.length());
- int length;
- while ((length = input.read(data)) >= 0 && !monitor.isCanceled()) {
- output.write(data, 0, length);
- output.flush();
- bytesRead += length;
- if (chunk_size != 0) {
- int percent = (int) bytesRead / chunk_size;
- if (percent != percentRead) { // Update the progress.
- monitor.worked(percent - percentRead);
- percentRead = percent; // Remember the percentage.
- // Report the progress.
- monitor.subTask(NLS.bind(Messages.OpUpload_UploadingProgress, new Object[]{file.getName(), formatSize(bytesRead), fileLength}));
- }
- }
+ for (File child : source.listFiles()) {
+ fWork.addFirst(new WorkItem(child, existing, true));
}
- } finally {
- if (output != null) {
- try {
- output.close();
- } catch (Exception e) {
+ return Status.OK_STATUS;
+ } else if (source.isFile()) {
+ if (existing != null) {
+ if (!existing.isFile()) {
+ return StatusHelper.createStatus(format(Messages.OpCopy_error_noFile, existing.getLocation()), null);
}
- }
- if (input != null) {
- try {
- input.close();
- } catch (Exception e) {
+ int replace = confirmCallback(existing, fConfirmCallback);
+ if (replace == IConfirmCallback.NO) {
+ return Status.OK_STATUS;
+ }
+ if (replace != IConfirmCallback.YES) {
+ return Status.CANCEL_STATUS;
}
}
- if(digest != null && nodes != null) {
- FileState filedigest = PersistenceManager.getInstance().getFileDigest(nodes[i]);
- filedigest.reset(digest.digest());
- }
+ path = getPath(destination, name);
+ } else {
+ return Status.OK_STATUS;
}
+ } else {
+ name = destination.getName();
+ existing = destination;
+ path = destination.getLocation(true);
}
- }
- /**
- * Prepare the directory structure on the remote target, creating necessary intermediate directories
- * and found all files that should be uploaded. The resulting files to be uploaded should be stored
- * to the file list. The resulting corresponding target file URLs should be stored in the url list.
- *
- * @param fileList The file list to store the files that should be uploaded.
- * @param urlList The list containing the corresponding urls.
- */
- private void prepareDirStruct(String[] sourceFiles, List<File> fileList, List<URL> urlList, FSTreeNode targetFolder) {
- parentFolders = Collections.synchronizedMap(new HashMap<File, FSTreeNode>());
- List<File> files = new ArrayList<File>();
- for(String path: sourceFiles) {
- files.add(new File(path));
- }
- // Find the root nodes of these files.
- List<File> topFiles = getTopFiles(files);
- for(File topFile : topFiles) {
- appendFile(topFile, fileList, urlList, targetFolder);
- }
- }
-
- /**
- * Append the specified file object to the file list and url list. If the file object is a file
- * then append it to the two lists. If the file object is a directory, then recursively
- * add its children and grand children to the two list. During this process, the parents of
- * these files and directories traversed should be put into the parent folders map so that
- * it could be queried to check if it has a file/directory with a same name.
- *
- * @param file The file to be added
- * @param fileList The file list
- * @param urlList The url list
- * @param parent The current parent node
- */
- private void appendFile(final File file, final List<File> fileList, final List<URL> urlList, final FSTreeNode parent) {
- parentFolders.put(file, parent);
- if(file.isFile()) {
- SafeRunner.run(new ISafeRunnable(){
- @Override
- public void run() throws Exception {
- URL folderURL = parent.getLocationURL();
- URL url = new URL(folderURL, file.getName());
- fileList.add(file);
- urlList.add(url);
- }
- @Override
- public void handleException(Throwable exception) {
- // Ignore on purpose
- }});
- } else if(file.isDirectory()) {
- FSTreeNode node = findNode(file);
- if(node == null) {
- OpCreateFolder create = new OpCreateFolder(parent, file.getName());
- new NullOpExecutor().execute(create);
- node = create.getNode();
- }
- File[] children = file.listFiles();
- for(File child : children) {
- appendFile(child, fileList, urlList, node);
+ final TCFResult<OutputStream> result = new TCFResult<OutputStream>();
+ monitor.subTask(NLS.bind(Messages.OpUpload_UploadSingleFile, item.fSource));
+ Protocol.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ IFileSystem fs = destination.getRuntimeModel().getFileSystem();
+ if (fs == null) {
+ result.setCancelled();
+ } else {
+ tcfGetOutputStream(fs, path, result);
+ }
}
- }
- }
+ });
+ IStatus status = result.waitDone(monitor);
+ if (!status.isOK())
+ return status;
- /**
- * Get the root files of the specified files/folders in the list.
- *
- * @param files The files to be checked.
- * @return Root nodes of these files that has no parent.
- */
- private List<File> getTopFiles(List<File>files) {
- List<File> result = new ArrayList<File>();
- for(File file : files) {
- if(!hasFileAncestor(file, files)) {
- result.add(file);
+ OutputStream out = new BufferedOutputStream(result.getValue());
+ try {
+ IStatus s = uploadFile(item.fSource, existing, out, new SubProgressMonitor(monitor, 0));
+ if (!s.isOK())
+ return s;
+ } finally {
+ try {
+ out.close();
+ } catch (IOException e) {
}
}
- return result;
- }
- /**
- * Check if the target file has an ancestral parent in the specified list.
- *
- * @param target The target file to be checked.
- * @param files The file list to be searched.
- * @return true if it has an ancestral parent.
- */
- private boolean hasFileAncestor(File target, List<File> files) {
- for(File file : files) {
- if(isFileAncestor(file, target)) {
- return true;
+ return updateNode(path, name, destination, existing, monitor);
+ }
+
+ private IStatus updateNode(final String path, final String name,
+ final FSTreeNode destination, final FSTreeNode existing, IProgressMonitor monitor) {
+ final TCFResult<?> r2 = new TCFResult<Object>();
+ Protocol.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ IFileSystem fs = destination.getRuntimeModel().getFileSystem();
+ if (fs == null) {
+ r2.setCancelled();
+ } else if (!r2.checkCancelled()) {
+ fs.stat(path, new DoneStat() {
+ @Override
+ public void doneStat(IToken token, FileSystemException error, FileAttrs attrs) {
+ if (error != null) {
+ r2.setError(format(Messages.OpUpload_error_upload, name), error);
+ } else if (!r2.checkCancelled()) {
+ if (existing != null) {
+ existing.setAttributes(attrs, true);
+ } else {
+ destination.addNode(new FSTreeNode(destination, name, false, attrs), true);
+ }
+ r2.setDone(null);
+ }
+ }
+ });
+ }
}
+ });
+ return r2.waitDone(monitor);
+ }
+
+ protected void tcfGetOutputStream(IFileSystem fileSystem, final String path, final TCFResult<OutputStream> result) {
+ int flags = IFileSystem.TCF_O_WRITE | IFileSystem.TCF_O_CREAT | IFileSystem.TCF_O_TRUNC;
+ if (!result.checkCancelled()) {
+ fileSystem.open(path, flags, null, new DoneOpen() {
+ @Override
+ public void doneOpen(IToken token, FileSystemException error, IFileHandle handle) {
+ if (error != null) {
+ result.setError(format(Messages.OpUpload_error_openFile, path), error);
+ } else {
+ result.setDone(new TCFFileOutputStream(handle));
+ }
+ }
+ });
}
- return false;
- }
+ }
- /**
- * Check if the specified "file" is an ancestral parent of the "target" file.
- *
- * @param file The ancestral file.
- * @param target The target file.
- * @return true if "file" is an ancestral parent of "target"
- */
- private boolean isFileAncestor(File file, File target) {
- if(target == null) return false;
- File parent = target.getParentFile();
- if(file.equals(parent)) return true;
- return isFileAncestor(file, parent);
- }
+ private IStatus uploadFile(File source, FSTreeNode existing, OutputStream output, IProgressMonitor monitor) {
+ byte[] data = new byte[DEFAULT_CHUNK_SIZE];
+ // Calculate the total size.
+ long totalSize = source.length();
+ // Calculate the chunk size of one percent.
+ int chunk_size = (int) totalSize / 100;
+ // The current reading percentage.
+ int percentRead = 0;
+ // The current length of read bytes.
+ long bytesRead = 0;
+ MessageDigest digest = null;
+ InputStream input = null;
+ try {
+ input = new BufferedInputStream(new FileInputStream(source));
+ if (existing != null) {
+ try {
+ digest = MessageDigest.getInstance(MD_ALG);
+ input = new DigestInputStream(input, digest);
+ } catch (NoSuchAlgorithmException e) {
+ digest = null;
+ }
+ }
- /**
- * Check if the specified file has a same-named file under its corresponding
- * parent folder.
- *
- * @param file The file to checked.
- * @return the node that has the same name with the file.
- */
- private FSTreeNode findNode(File file) {
- final FSTreeNode parent = parentFolders.get(file);
- if (parent != null) {
- final List<FSTreeNode> targetChildren = new ArrayList<FSTreeNode>();
- SafeRunner.run(new ISafeRunnable() {
- @Override
- public void run() throws Exception {
- targetChildren.addAll(getChildren(parent));
+ // Total size displayed on the progress dialog.
+ String fileLength = formatSize(totalSize);
+ int length;
+ while ((length = input.read(data)) >= 0) {
+ output.write(data, 0, length);
+ bytesRead += length;
+ if (chunk_size != 0) {
+ int percent = (int) bytesRead / chunk_size;
+ if (percent != percentRead) { // Update the progress.
+ monitor.worked(percent - percentRead);
+ percentRead = percent; // Remember the percentage.
+ // Report the progress.
+ if (fWork.size() == 0)
+ monitor.subTask(NLS.bind(Messages.OpUpload_UploadingProgress, new Object[]{source.getName(), formatSize(bytesRead), fileLength}));
+ }
}
+ if (monitor.isCanceled())
+ return Status.CANCEL_STATUS;
+ }
- @Override
- public void handleException(Throwable exception) {
- // Ignore on purpose
+ if (digest != null && existing != null) {
+ FileState filedigest = PersistenceManager.getInstance().getFileDigest(existing);
+ filedigest.reset(digest.digest());
+ }
+ return Status.OK_STATUS;
+ } catch (IOException e) {
+ return StatusHelper.createStatus(format(Messages.OpUpload_error_upload, source), e);
+ } finally {
+ if (input != null) {
+ try {
+ input.close();
+ } catch (Exception e) {
}
- });
- String name = file.getName();
- for (FSTreeNode child : targetChildren) {
- if (name.equals(child.name)) return child;
}
}
- return null;
- }
+ }
- /*
- * (non-Javadoc)
- * @see org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IOperation#getName()
- */
@Override
public String getName() {
String message;
- if(srcFiles.length==1)
- message = NLS.bind(Messages.OpUpload_UploadSingleFile, srcFiles[0].getName());
+ if(fWork.size()==1)
+ message = NLS.bind(Messages.OpUpload_UploadSingleFile, fWork.element().fSource);
else
- message = NLS.bind(Messages.OpUpload_UploadNFiles, Long.valueOf(srcFiles.length));
+ message = NLS.bind(Messages.OpUpload_UploadNFiles, Long.valueOf(fWork.size()));
return message;
}
-
- /*
- * (non-Javadoc)
- * @see org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IOperation#getTotalWork()
- */
- @Override
- public int getTotalWork() {
- return 100;
- }
}

Back to the top