diff options
author | Uwe Stieber | 2012-06-22 07:58:46 +0000 |
---|---|---|
committer | Uwe Stieber | 2012-06-22 07:58:46 +0000 |
commit | 32db6e45fc7a79fed714ca7c867ff5b19441e931 (patch) | |
tree | 18343ac14dc4293ad48788a51a5c582d9d71ba87 | |
parent | 5d77d396dfca4fc54a7024799c0a01a8f9c5c280 (diff) | |
download | org.eclipse.tcf-32db6e45fc7a79fed714ca7c867ff5b19441e931.tar.gz org.eclipse.tcf-32db6e45fc7a79fed714ca7c867ff5b19441e931.tar.xz org.eclipse.tcf-32db6e45fc7a79fed714ca7c867ff5b19441e931.zip |
Target Explorer: Fix NPE in FileTransferService
2 files changed, 494 insertions, 487 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/services/FileTransferService.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/services/FileTransferService.java index 8ce709102..7bed5703c 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/services/FileTransferService.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.core/src/org/eclipse/tcf/te/tcf/filesystem/core/services/FileTransferService.java @@ -1,487 +1,491 @@ -/*******************************************************************************
- * Copyright (c) 2012 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
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.tcf.te.tcf.filesystem.core.services;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.ConnectException;
-
-import org.eclipse.core.runtime.Assert;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.osgi.util.NLS;
-import org.eclipse.tcf.protocol.IChannel;
-import org.eclipse.tcf.protocol.IPeer;
-import org.eclipse.tcf.protocol.IToken;
-import org.eclipse.tcf.protocol.Protocol;
-import org.eclipse.tcf.services.IFileSystem;
-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.runtime.interfaces.callback.ICallback;
-import org.eclipse.tcf.te.runtime.services.interfaces.filetransfer.IFileTransferItem;
-import org.eclipse.tcf.te.runtime.utils.ProgressHelper;
-import org.eclipse.tcf.te.runtime.utils.StatusHelper;
-import org.eclipse.tcf.te.tcf.core.Tcf;
-import org.eclipse.tcf.te.tcf.core.concurrent.BlockingCallProxy;
-import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager;
-import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.DoneOpenChannel;
-import org.eclipse.tcf.te.tcf.filesystem.core.internal.exceptions.TCFChannelException;
-import org.eclipse.tcf.te.tcf.filesystem.core.nls.Messages;
-import org.eclipse.tcf.util.TCFFileInputStream;
-import org.eclipse.tcf.util.TCFFileOutputStream;
-
-/**
- * TCF file transfer service.
- */
-public class FileTransferService {
-
- /**
- * Transfer a file between host and target depending on the {@link IFileTransferItem} data.
- *
- * @param peer The peer, must not be <code>null</code>.
- * @param channel The channel or <code>null</code>.
- * @param item The file transfer item, must not be <code>null</code>.
- * @param monitor The progress monitor or <code>null</code>.
- * @param callback The callback or <code>null</code>.
- */
- public static void transfer(IPeer peer, IChannel channel, IFileTransferItem item, IProgressMonitor monitor, ICallback callback) {
-
- boolean ownChannel = false;
- IFileSystem fileSystem;
- try {
- if (channel == null) {
- ownChannel = true;
- channel = openChannel(peer);
- }
- fileSystem = getBlockingFileSystem(channel);
-
- Assert.isNotNull(fileSystem);
-
- // Check the direction of the transfer
- if (item.getDirection() == IFileTransferItem.TARGET_TO_HOST) {
- transferToHost(peer, fileSystem, item, monitor, callback);
- }
- else {
- transferToTarget(peer, fileSystem, item, monitor, callback);
- }
- if (ownChannel) {
- closeChannel(peer, channel);
- }
- }
- catch (Exception e) {
- if (callback != null) {
- callback.done(peer, StatusHelper.getStatus(e));
- }
- }
- }
-
- /**
- * Transfer a file between host and target depending on the {@link IFileTransferItem} data.
- *
- * @param peer The peer, must not be <code>null</code>.
- * @param item The file transfer item, must not be <code>null</code>.
- * @param monitor The progress monitor or <code>null</code>.
- * @param callback The callback or <code>null</code>.
- */
- protected static void transfer(IPeer peer, IFileTransferItem item, IProgressMonitor monitor, ICallback callback) {
-
- // Check if we can skip the transfer
- if (!item.isEnabled()) {
- if (callback != null) {
- callback.done(peer, Status.OK_STATUS);
- }
- return;
- }
-
- try {
- IChannel channel = openChannel(peer);
- transfer(peer, channel, item, monitor, callback);
- closeChannel(peer, channel);
- }
- catch (Exception e) {
- if (callback != null) {
- callback.done(peer, StatusHelper.getStatus(e));
- }
- }
- }
-
- protected static void transferToHost(IPeer peer, IFileSystem fileSystem, IFileTransferItem item, IProgressMonitor monitor, ICallback callback) {
-
- IStatus result = Status.OK_STATUS;
-
- IPath hostPath = item.getHostPath();
- IPath targetPath = item.getTargetPath();
-
- BufferedOutputStream outStream = null;
- TCFFileInputStream inStream = null;
-
- final IFileSystem.IFileHandle[] handle = new IFileSystem.IFileHandle[1];
- final FileSystemException[] error = new FileSystemException[1];
- final IFileSystem.FileAttrs[] attrs = new IFileSystem.FileAttrs[1];
-
- // Create necessary parent directory structure on host side
- boolean rc = hostPath.removeLastSegments(1).toFile().mkdirs();
- if (!rc) {
- IOException e = new IOException(NLS.bind(Messages.FileTransferService_error_mkdirFailed, hostPath.removeLastSegments(1).toOSString()));
- result = StatusHelper.getStatus(e);
- if (callback != null) callback.done(peer, result);
- return;
- }
-
- // If the host file is a directory, append the remote file name
- if (hostPath.toFile().isDirectory()) {
- hostPath = item.getHostPath().append(targetPath.lastSegment());
- }
-
- // Remember the modification time of the remote file.
- // We need this value to set the modification time of the host file
- // _after_ the stream closed.
- long mtime = -1;
-
- try {
- // Open the remote file
- fileSystem.open(targetPath.toString(), IFileSystem.TCF_O_READ, null, new IFileSystem.DoneOpen() {
- @Override
- public void doneOpen(IToken token, FileSystemException e, IFileHandle h) {
- error[0] = e;
- handle[0] = h;
- }
- });
- if (error[0] != null) {
- throw error[0];
- }
- // Get the remote file attributes
- fileSystem.fstat(handle[0], new IFileSystem.DoneStat() {
- @Override
- public void doneStat(IToken token, FileSystemException e, FileAttrs a) {
- error[0] = e;
- attrs[0] = a;
- }
- });
- if (error[0] != null) {
- throw error[0];
- }
- // Remember the modification time
- mtime = attrs[0].mtime;
-
- // Open a output stream to the host file
- outStream = new BufferedOutputStream(new FileOutputStream(hostPath.toFile()));
- // And open the input stream to the target file handle
- inStream = new TCFFileInputStream(handle[0]);
-
- ProgressHelper.setSubTaskName(monitor, "Transfer '" + targetPath.toString() + "' to '" + hostPath.toOSString() + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-
- long bytesTotal = attrs[0].size;
- copy(inStream, outStream, bytesTotal, monitor);
- }
- catch (OperationCanceledException e) {
- result = Status.CANCEL_STATUS;
- }
- catch (Exception e) {
- result = StatusHelper.getStatus(e);
- }
- finally {
- // Close all streams and cleanup
- if (outStream != null) {
- try {
- outStream.close();
- outStream = null;
- }
- catch (IOException e) {
- }
- }
- if (inStream != null) {
- try {
- inStream.close();
- inStream = null;
- }
- catch (IOException e) {
- }
- }
-
- if (result.isOK()) {
- if (mtime >= 0) {
- rc = hostPath.toFile().setLastModified(mtime);
- if (!rc && Platform.inDebugMode()) {
- System.err.println("Failed to set mtime for " + hostPath.toOSString()); //$NON-NLS-1$
- }
- }
- }
- else if (result.getSeverity() == IStatus.ERROR || result.getSeverity() == IStatus.CANCEL) {
- try {
- rc = hostPath.toFile().delete();
- if (!rc && Platform.inDebugMode()) {
- System.err.println("Failed to delete host file " + hostPath.toOSString()); //$NON-NLS-1$
- }
- }
- catch (Throwable e) {
- }
- }
- }
- if (callback != null) callback.done(peer, result);
- }
-
- protected static void transferToTarget(IPeer peer, IFileSystem fileSystem, IFileTransferItem item, IProgressMonitor monitor, ICallback callback) {
-
- IStatus result = Status.OK_STATUS;
-
- IPath targetPath = item.getTargetPath();
- IPath hostPath = item.getHostPath();
-
- BufferedInputStream inStream = null;
- TCFFileOutputStream outStream = null;
-
- final IFileSystem.IFileHandle[] handle = new IFileSystem.IFileHandle[1];
- final FileSystemException[] error = new FileSystemException[1];
- final FileAttrs[] attrs = new FileAttrs[1];
-
- // Check the target destination directory
- fileSystem.stat(targetPath.toString(), new IFileSystem.DoneStat() {
- @Override
- public void doneStat(IToken token, FileSystemException e, FileAttrs a) {
- error[0] = e;
- attrs[0] = a;
- }
- });
- // If we get the attributes back, the name at least exist in the target file system
- if (error[0] != null || (attrs[0] != null && attrs[0].isDirectory())) {
- targetPath = targetPath.append(item.getHostPath().lastSegment());
- }
-
- try {
- // Open the remote file
- fileSystem.open(targetPath.toString(), IFileSystem.TCF_O_CREAT | IFileSystem.TCF_O_WRITE | IFileSystem.TCF_O_TRUNC, null, new IFileSystem.DoneOpen() {
- @Override
- public void doneOpen(IToken token, FileSystemException e, IFileHandle h) {
- error[0] = e;
- handle[0] = h;
- }
- });
- if (error[0] != null) {
- throw error[0];
- }
-
- // Open a input stream from the host file
- inStream = new BufferedInputStream(new FileInputStream(hostPath.toFile()));
- // Open the output stream for the target file handle
- outStream = new TCFFileOutputStream(handle[0]);
-
- ProgressHelper.setSubTaskName(monitor, "Transfer '" + hostPath.toOSString() + "' to '" + targetPath.toString() + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-
- copy(inStream, outStream, hostPath.toFile().length(), monitor);
-
- // Get the remote file attributes
- fileSystem.fstat(handle[0], new IFileSystem.DoneStat() {
- @Override
- public void doneStat(IToken token, FileSystemException e, FileAttrs a) {
- error[0] = e;
- attrs[0] = a;
- }
- });
- // Update the remote file attributes
- IFileSystem.FileAttrs newAttrs = new FileAttrs(attrs[0].flags, attrs[0].size, attrs[0].uid, attrs[0].gid, attrs[0].permissions,
- attrs[0].atime, hostPath.toFile().lastModified(), attrs[0].attributes);
- // Set the remote file attributes
- fileSystem.fsetstat(handle[0], newAttrs, new IFileSystem.DoneSetStat() {
- @Override
- public void doneSetStat(IToken token, FileSystemException e) {
- error[0] = e;
- }
- });
- }
- catch (OperationCanceledException e) {
- result = Status.CANCEL_STATUS;
- }
- catch (Exception e) {
- result = StatusHelper.getStatus(e);
- }
- finally {
- // Close all streams and cleanup
- if (outStream != null) {
- try {
- outStream.close();
- outStream = null;
- }
- catch (IOException e) {
- }
- }
- if (inStream != null) {
- try {
- inStream.close();
- inStream = null;
- }
- catch (IOException e) {
- }
- }
-
- if (result.getSeverity() == IStatus.ERROR || result.getSeverity() == IStatus.CANCEL) {
- fileSystem.remove(targetPath.toString(), null);
- }
- }
- if (callback != null) callback.done(peer, result);
- }
-
- private static void copy(InputStream in, OutputStream out, long bytesTotal, IProgressMonitor monitor) throws IOException {
- long bytesDone = 0;
- long speed;
- long startTimeStamp = System.currentTimeMillis();
- byte[] dataBuffer = new byte[12 * 1024];
-
- // Copy from the input stream to the output stream (always binary).
- while (true) {
- if (ProgressHelper.isCanceled(monitor)) {
- throw new OperationCanceledException();
- }
- // Read the data from the remote file
- int bytesRead = in.read(dataBuffer);
- // If reached EOF, we are done and break the loop
- if (bytesRead < 0) {
- break;
- }
- if (ProgressHelper.isCanceled(monitor)) {
- throw new OperationCanceledException();
- }
- // Write back to the host file
- out.write(dataBuffer, 0, bytesRead);
-
- bytesDone += bytesRead;
- long timestamp = System.currentTimeMillis();
- speed = ((bytesDone) * 1000) / Math.max(timestamp - startTimeStamp, 1);
-
- ProgressHelper.worked(monitor, (int)((bytesRead/bytesTotal) * 1000));
- ProgressHelper.setSubTaskName(monitor, getProgressMessage(bytesDone, bytesTotal, speed));
- }
- }
-
- /**
- * Open a channel for file transfer.
- * @param peer
- * @return
- * @throws TCFChannelException
- */
- protected static IChannel openChannel(final IPeer peer) throws TCFChannelException {
- IChannelManager proxy = BlockingCallProxy.newInstance(IChannelManager.class, Tcf.getChannelManager());
- final TCFChannelException[] errors = new TCFChannelException[1];
- final IChannel[] channels = new IChannel[1];
- proxy.openChannel(peer, null, new DoneOpenChannel() {
- @Override
- public void doneOpenChannel(Throwable error, IChannel channel) {
- if (error != null) {
- if (error instanceof ConnectException) {
- String message = NLS.bind(Messages.Operation_NotResponding, peer.getID());
- errors[0] = new TCFChannelException(IStatus.ERROR, message);
- }
- else {
- String message = NLS.bind(Messages.Operation_OpeningChannelFailureMessage, peer.getID(), error.getMessage());
- errors[0] = new TCFChannelException(IStatus.ERROR, message, error);
- }
- }
- else {
- channels[0] = channel;
- }
- }
- });
- if (errors[0] != null) {
- throw errors[0];
- }
- return channels[0];
- }
-
- /**
- * Close the channel for file transfer.
- * @param peer
- * @param channel
- * @throws TCFChannelException
- */
- protected static void closeChannel(final IPeer peer, final IChannel channel) throws TCFChannelException {
- if (channel != null) {
- IChannelManager proxy = BlockingCallProxy.newInstance(IChannelManager.class, Tcf.getChannelManager());
- proxy.closeChannel(channel);
- }
- }
-
- /**
- * Get a blocking file system.
- * @param channel
- * @return
- */
- protected static IFileSystem getBlockingFileSystem(final IChannel channel) {
- if(Protocol.isDispatchThread()) {
- IFileSystem service = channel.getRemoteService(IFileSystem.class);
- return BlockingCallProxy.newInstance(IFileSystem.class, service);
- }
- final IFileSystem[] service = new IFileSystem[1];
- Protocol.invokeAndWait(new Runnable(){
- @Override
- public void run() {
- service[0] = getBlockingFileSystem(channel);
- }});
- return service[0];
- }
-
- private static String getProgressMessage(long bytesDone, long bytesTotal, long bytesSpeed) {
- String done = "B"; //$NON-NLS-1$
- String total = "B"; //$NON-NLS-1$
- String speed = "B/s"; //$NON-NLS-1$
-
- if (bytesDone > 1024) {
- bytesDone /= 1024;
- done = "KB"; //$NON-NLS-1$
- }
- if (bytesDone > 1024) {
- bytesDone /= 1024;
- done = "MB"; //$NON-NLS-1$
- }
- if (bytesSpeed > 1024) {
- bytesSpeed /= 1024;
- speed = "GB/s"; //$NON-NLS-1$
- }
-
- if (bytesTotal > 1024) {
- bytesTotal /= 1024;
- total = "KB"; //$NON-NLS-1$
- }
- if (bytesTotal > 1024) {
- bytesTotal /= 1024;
- total = "MB"; //$NON-NLS-1$
- }
- if (bytesTotal > 1024) {
- bytesTotal /= 1024;
- total = "GB"; //$NON-NLS-1$
- }
-
- if (bytesSpeed > 1024) {
- bytesSpeed /= 1024;
- speed = "KB/s"; //$NON-NLS-1$
- }
- if (bytesSpeed > 1024) {
- bytesSpeed /= 1024;
- speed = "MB/s"; //$NON-NLS-1$
- }
- if (bytesDone > 1024) {
- bytesDone /= 1024;
- done = "GB"; //$NON-NLS-1$
- }
-
- return bytesDone + done + " of " + bytesTotal + total + " at " + bytesSpeed + speed; //$NON-NLS-1$ //$NON-NLS-2$
- }
-
-}
+/******************************************************************************* + * Copyright (c) 2012 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 + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ + +package org.eclipse.tcf.te.tcf.filesystem.core.services; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.ConnectException; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.util.NLS; +import org.eclipse.tcf.protocol.IChannel; +import org.eclipse.tcf.protocol.IPeer; +import org.eclipse.tcf.protocol.IToken; +import org.eclipse.tcf.protocol.Protocol; +import org.eclipse.tcf.services.IFileSystem; +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.runtime.interfaces.callback.ICallback; +import org.eclipse.tcf.te.runtime.services.interfaces.filetransfer.IFileTransferItem; +import org.eclipse.tcf.te.runtime.utils.ProgressHelper; +import org.eclipse.tcf.te.runtime.utils.StatusHelper; +import org.eclipse.tcf.te.tcf.core.Tcf; +import org.eclipse.tcf.te.tcf.core.concurrent.BlockingCallProxy; +import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager; +import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.DoneOpenChannel; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.exceptions.TCFChannelException; +import org.eclipse.tcf.te.tcf.filesystem.core.nls.Messages; +import org.eclipse.tcf.util.TCFFileInputStream; +import org.eclipse.tcf.util.TCFFileOutputStream; + +/** + * TCF file transfer service. + */ +public class FileTransferService { + + /** + * Transfer a file between host and target depending on the {@link IFileTransferItem} data. + * + * @param peer The peer, must not be <code>null</code>. + * @param channel The channel or <code>null</code>. + * @param item The file transfer item, must not be <code>null</code>. + * @param monitor The progress monitor or <code>null</code>. + * @param callback The callback or <code>null</code>. + */ + public static void transfer(IPeer peer, IChannel channel, IFileTransferItem item, IProgressMonitor monitor, ICallback callback) { + + boolean ownChannel = false; + IFileSystem fileSystem; + try { + if (channel == null) { + ownChannel = true; + channel = openChannel(peer); + } + fileSystem = getBlockingFileSystem(channel); + + Assert.isNotNull(fileSystem); + + // Check the direction of the transfer + if (item.getDirection() == IFileTransferItem.TARGET_TO_HOST) { + transferToHost(peer, fileSystem, item, monitor, callback); + } + else { + transferToTarget(peer, fileSystem, item, monitor, callback); + } + if (ownChannel) { + closeChannel(peer, channel); + } + } + catch (Exception e) { + if (callback != null) { + callback.done(peer, StatusHelper.getStatus(e)); + } + } + } + + /** + * Transfer a file between host and target depending on the {@link IFileTransferItem} data. + * + * @param peer The peer, must not be <code>null</code>. + * @param item The file transfer item, must not be <code>null</code>. + * @param monitor The progress monitor or <code>null</code>. + * @param callback The callback or <code>null</code>. + */ + protected static void transfer(IPeer peer, IFileTransferItem item, IProgressMonitor monitor, ICallback callback) { + + // Check if we can skip the transfer + if (!item.isEnabled()) { + if (callback != null) { + callback.done(peer, Status.OK_STATUS); + } + return; + } + + try { + IChannel channel = openChannel(peer); + transfer(peer, channel, item, monitor, callback); + closeChannel(peer, channel); + } + catch (Exception e) { + if (callback != null) { + callback.done(peer, StatusHelper.getStatus(e)); + } + } + } + + protected static void transferToHost(IPeer peer, IFileSystem fileSystem, IFileTransferItem item, IProgressMonitor monitor, ICallback callback) { + + IStatus result = Status.OK_STATUS; + + IPath hostPath = item.getHostPath(); + IPath targetPath = item.getTargetPath(); + + BufferedOutputStream outStream = null; + TCFFileInputStream inStream = null; + + final IFileSystem.IFileHandle[] handle = new IFileSystem.IFileHandle[1]; + final FileSystemException[] error = new FileSystemException[1]; + final IFileSystem.FileAttrs[] attrs = new IFileSystem.FileAttrs[1]; + + // Create necessary parent directory structure on host side + boolean rc = hostPath.removeLastSegments(1).toFile().mkdirs(); + if (!rc) { + IOException e = new IOException(NLS.bind(Messages.FileTransferService_error_mkdirFailed, hostPath.removeLastSegments(1).toOSString())); + result = StatusHelper.getStatus(e); + if (callback != null) callback.done(peer, result); + return; + } + + // If the host file is a directory, append the remote file name + if (hostPath.toFile().isDirectory()) { + hostPath = item.getHostPath().append(targetPath.lastSegment()); + } + + // Remember the modification time of the remote file. + // We need this value to set the modification time of the host file + // _after_ the stream closed. + long mtime = -1; + + try { + // Open the remote file + fileSystem.open(targetPath.toString(), IFileSystem.TCF_O_READ, null, new IFileSystem.DoneOpen() { + @Override + public void doneOpen(IToken token, FileSystemException e, IFileHandle h) { + error[0] = e; + handle[0] = h; + } + }); + if (error[0] != null) { + throw error[0]; + } + // Get the remote file attributes + fileSystem.fstat(handle[0], new IFileSystem.DoneStat() { + @Override + public void doneStat(IToken token, FileSystemException e, FileAttrs a) { + error[0] = e; + attrs[0] = a; + } + }); + if (error[0] != null) { + throw error[0]; + } + // Remember the modification time + mtime = attrs[0].mtime; + + // Open a output stream to the host file + outStream = new BufferedOutputStream(new FileOutputStream(hostPath.toFile())); + // And open the input stream to the target file handle + inStream = new TCFFileInputStream(handle[0]); + + ProgressHelper.setSubTaskName(monitor, "Transfer '" + targetPath.toString() + "' to '" + hostPath.toOSString() + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + long bytesTotal = attrs[0].size; + copy(inStream, outStream, bytesTotal, monitor); + } + catch (OperationCanceledException e) { + result = Status.CANCEL_STATUS; + } + catch (Exception e) { + result = StatusHelper.getStatus(e); + } + finally { + // Close all streams and cleanup + if (outStream != null) { + try { + outStream.close(); + outStream = null; + } + catch (IOException e) { + } + } + if (inStream != null) { + try { + inStream.close(); + inStream = null; + } + catch (IOException e) { + } + } + + if (result.isOK()) { + if (mtime >= 0) { + rc = hostPath.toFile().setLastModified(mtime); + if (!rc && Platform.inDebugMode()) { + System.err.println("Failed to set mtime for " + hostPath.toOSString()); //$NON-NLS-1$ + } + } + } + else if (result.getSeverity() == IStatus.ERROR || result.getSeverity() == IStatus.CANCEL) { + try { + rc = hostPath.toFile().delete(); + if (!rc && Platform.inDebugMode()) { + System.err.println("Failed to delete host file " + hostPath.toOSString()); //$NON-NLS-1$ + } + } + catch (Throwable e) { + } + } + } + if (callback != null) callback.done(peer, result); + } + + protected static void transferToTarget(IPeer peer, IFileSystem fileSystem, IFileTransferItem item, IProgressMonitor monitor, ICallback callback) { + + IStatus result = Status.OK_STATUS; + + IPath targetPath = item.getTargetPath(); + IPath hostPath = item.getHostPath(); + + BufferedInputStream inStream = null; + TCFFileOutputStream outStream = null; + + final IFileSystem.IFileHandle[] handle = new IFileSystem.IFileHandle[1]; + final FileSystemException[] error = new FileSystemException[1]; + final FileAttrs[] attrs = new FileAttrs[1]; + + // Check the target destination directory + fileSystem.stat(targetPath.toString(), new IFileSystem.DoneStat() { + @Override + public void doneStat(IToken token, FileSystemException e, FileAttrs a) { + error[0] = e; + attrs[0] = a; + } + }); + // If we get the attributes back, the name at least exist in the target file system + if (error[0] != null || (attrs[0] != null && attrs[0].isDirectory())) { + targetPath = targetPath.append(item.getHostPath().lastSegment()); + } + + try { + // Open the remote file + fileSystem.open(targetPath.toString(), IFileSystem.TCF_O_CREAT | IFileSystem.TCF_O_WRITE | IFileSystem.TCF_O_TRUNC, null, new IFileSystem.DoneOpen() { + @Override + public void doneOpen(IToken token, FileSystemException e, IFileHandle h) { + error[0] = e; + handle[0] = h; + } + }); + if (error[0] != null) { + throw error[0]; + } + + // Open a input stream from the host file + inStream = new BufferedInputStream(new FileInputStream(hostPath.toFile())); + // Open the output stream for the target file handle + outStream = new TCFFileOutputStream(handle[0]); + + ProgressHelper.setSubTaskName(monitor, "Transfer '" + hostPath.toOSString() + "' to '" + targetPath.toString() + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + copy(inStream, outStream, hostPath.toFile().length(), monitor); + + // Get the remote file attributes + fileSystem.fstat(handle[0], new IFileSystem.DoneStat() { + @Override + public void doneStat(IToken token, FileSystemException e, FileAttrs a) { + error[0] = e; + attrs[0] = a; + } + }); + // Update the remote file attributes + IFileSystem.FileAttrs newAttrs = new FileAttrs(attrs[0].flags, attrs[0].size, attrs[0].uid, attrs[0].gid, attrs[0].permissions, + attrs[0].atime, hostPath.toFile().lastModified(), attrs[0].attributes); + // Set the remote file attributes + fileSystem.fsetstat(handle[0], newAttrs, new IFileSystem.DoneSetStat() { + @Override + public void doneSetStat(IToken token, FileSystemException e) { + error[0] = e; + } + }); + } + catch (OperationCanceledException e) { + result = Status.CANCEL_STATUS; + } + catch (Exception e) { + result = StatusHelper.getStatus(e); + } + finally { + // Close all streams and cleanup + if (outStream != null) { + try { + outStream.close(); + outStream = null; + } + catch (IOException e) { + } + } + if (inStream != null) { + try { + inStream.close(); + inStream = null; + } + catch (IOException e) { + } + } + + if (result.getSeverity() == IStatus.ERROR || result.getSeverity() == IStatus.CANCEL) { + fileSystem.remove(targetPath.toString(), new IFileSystem.DoneRemove() { + @Override + public void doneRemove(IToken token, FileSystemException error) { + } + }); + } + } + if (callback != null) callback.done(peer, result); + } + + private static void copy(InputStream in, OutputStream out, long bytesTotal, IProgressMonitor monitor) throws IOException { + long bytesDone = 0; + long speed; + long startTimeStamp = System.currentTimeMillis(); + byte[] dataBuffer = new byte[12 * 1024]; + + // Copy from the input stream to the output stream (always binary). + while (true) { + if (ProgressHelper.isCanceled(monitor)) { + throw new OperationCanceledException(); + } + // Read the data from the remote file + int bytesRead = in.read(dataBuffer); + // If reached EOF, we are done and break the loop + if (bytesRead < 0) { + break; + } + if (ProgressHelper.isCanceled(monitor)) { + throw new OperationCanceledException(); + } + // Write back to the host file + out.write(dataBuffer, 0, bytesRead); + + bytesDone += bytesRead; + long timestamp = System.currentTimeMillis(); + speed = ((bytesDone) * 1000) / Math.max(timestamp - startTimeStamp, 1); + + ProgressHelper.worked(monitor, (int)((bytesRead/bytesTotal) * 1000)); + ProgressHelper.setSubTaskName(monitor, getProgressMessage(bytesDone, bytesTotal, speed)); + } + } + + /** + * Open a channel for file transfer. + * @param peer + * @return + * @throws TCFChannelException + */ + protected static IChannel openChannel(final IPeer peer) throws TCFChannelException { + IChannelManager proxy = BlockingCallProxy.newInstance(IChannelManager.class, Tcf.getChannelManager()); + final TCFChannelException[] errors = new TCFChannelException[1]; + final IChannel[] channels = new IChannel[1]; + proxy.openChannel(peer, null, new DoneOpenChannel() { + @Override + public void doneOpenChannel(Throwable error, IChannel channel) { + if (error != null) { + if (error instanceof ConnectException) { + String message = NLS.bind(Messages.Operation_NotResponding, peer.getID()); + errors[0] = new TCFChannelException(IStatus.ERROR, message); + } + else { + String message = NLS.bind(Messages.Operation_OpeningChannelFailureMessage, peer.getID(), error.getMessage()); + errors[0] = new TCFChannelException(IStatus.ERROR, message, error); + } + } + else { + channels[0] = channel; + } + } + }); + if (errors[0] != null) { + throw errors[0]; + } + return channels[0]; + } + + /** + * Close the channel for file transfer. + * @param peer + * @param channel + * @throws TCFChannelException + */ + protected static void closeChannel(final IPeer peer, final IChannel channel) throws TCFChannelException { + if (channel != null) { + IChannelManager proxy = BlockingCallProxy.newInstance(IChannelManager.class, Tcf.getChannelManager()); + proxy.closeChannel(channel); + } + } + + /** + * Get a blocking file system. + * @param channel + * @return + */ + protected static IFileSystem getBlockingFileSystem(final IChannel channel) { + if(Protocol.isDispatchThread()) { + IFileSystem service = channel.getRemoteService(IFileSystem.class); + return BlockingCallProxy.newInstance(IFileSystem.class, service); + } + final IFileSystem[] service = new IFileSystem[1]; + Protocol.invokeAndWait(new Runnable(){ + @Override + public void run() { + service[0] = getBlockingFileSystem(channel); + }}); + return service[0]; + } + + private static String getProgressMessage(long bytesDone, long bytesTotal, long bytesSpeed) { + String done = "B"; //$NON-NLS-1$ + String total = "B"; //$NON-NLS-1$ + String speed = "B/s"; //$NON-NLS-1$ + + if (bytesDone > 1024) { + bytesDone /= 1024; + done = "KB"; //$NON-NLS-1$ + } + if (bytesDone > 1024) { + bytesDone /= 1024; + done = "MB"; //$NON-NLS-1$ + } + if (bytesSpeed > 1024) { + bytesSpeed /= 1024; + speed = "GB/s"; //$NON-NLS-1$ + } + + if (bytesTotal > 1024) { + bytesTotal /= 1024; + total = "KB"; //$NON-NLS-1$ + } + if (bytesTotal > 1024) { + bytesTotal /= 1024; + total = "MB"; //$NON-NLS-1$ + } + if (bytesTotal > 1024) { + bytesTotal /= 1024; + total = "GB"; //$NON-NLS-1$ + } + + if (bytesSpeed > 1024) { + bytesSpeed /= 1024; + speed = "KB/s"; //$NON-NLS-1$ + } + if (bytesSpeed > 1024) { + bytesSpeed /= 1024; + speed = "MB/s"; //$NON-NLS-1$ + } + if (bytesDone > 1024) { + bytesDone /= 1024; + done = "GB"; //$NON-NLS-1$ + } + + return bytesDone + done + " of " + bytesTotal + total + " at " + bytesSpeed + speed; //$NON-NLS-1$ //$NON-NLS-2$ + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tests/src/org/eclipse/tcf/te/tests/tcf/launch/TcfLaunchTests.java b/target_explorer/plugins/org.eclipse.tcf.te.tests/src/org/eclipse/tcf/te/tests/tcf/launch/TcfLaunchTests.java index e31937aca..a1664df9d 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tests/src/org/eclipse/tcf/te/tests/tcf/launch/TcfLaunchTests.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tests/src/org/eclipse/tcf/te/tests/tcf/launch/TcfLaunchTests.java @@ -68,6 +68,9 @@ public class TcfLaunchTests extends TcfTestCase { assertNotNull("Missing java temp directory", tempDir); //$NON-NLS-1$ tempDir = tempDir.append(TcfLaunchTests.class.getSimpleName()); assertNotNull("Cannot append test case specific temp directory", tempDir); //$NON-NLS-1$ + if (!tempDir.toFile().exists()) { + assertTrue("Failed to create path " + tempDir.toString(), tempDir.toFile().mkdirs()); //$NON-NLS-1$ + } IPath tempHelloWorld = tempDir.append(helloWorldLocation.lastSegment()); if (tempHelloWorld.toFile().exists()) { |