Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorslewis2014-10-14 20:11:49 +0000
committerslewis2014-10-14 20:11:49 +0000
commit194b6887237a00b6be8c4614babffa4fce6cc18c (patch)
tree1dc02ec2ce76dda3e93e5f4702befb9fc2278cd0
parentd42f18de0bd535101a7866edb94f58bba5a2819b (diff)
downloadorg.eclipse.ecf-194b6887237a00b6be8c4614babffa4fce6cc18c.tar.gz
org.eclipse.ecf-194b6887237a00b6be8c4614babffa4fce6cc18c.tar.xz
org.eclipse.ecf-194b6887237a00b6be8c4614babffa4fce6cc18c.zip
Changes associated with bug
https://bugs.eclipse.org/bugs/show_bug.cgi?id=445729 As per comment https://bugs.eclipse.org/bugs/show_bug.cgi?id=445729#c3 these changes were originally submitted by J Langley via gerrit https://git.eclipse.org/r/#/c/34754/ Small changes needed to be made to the original submission, and he and I apparently did not do the right thing to make those changes via gerrit. So I applied these changes to master directly. Change-Id: I286fe2325ee9fd724067b4281882eb39fffdd440
-rw-r--r--providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/META-INF/MANIFEST.MF2
-rw-r--r--providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/plugin.xml8
-rw-r--r--providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/src/org/eclipse/ecf/internal/provider/filetransfer/scp/ScpBrowseFileTransferFactory.java82
-rw-r--r--providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/src/org/eclipse/ecf/internal/provider/filetransfer/scp/ScpFileSystemBrowser.java244
-rw-r--r--tests/bundles/org.eclipse.ecf.tests.filetransfer/src/org/eclipse/ecf/tests/filetransfer/ScpFileBrowseTest.java110
5 files changed, 445 insertions, 1 deletions
diff --git a/providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/META-INF/MANIFEST.MF b/providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/META-INF/MANIFEST.MF
index d1f06ee60..96c59dbb0 100644
--- a/providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/META-INF/MANIFEST.MF
+++ b/providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %plugin.name
Bundle-SymbolicName: org.eclipse.ecf.provider.filetransfer.scp;singleton:=true
-Bundle-Version: 2.0.100.qualifier
+Bundle-Version: 2.1.0.qualifier
Bundle-Activator: org.eclipse.ecf.internal.provider.filetransfer.scp.Activator
Bundle-Vendor: %plugin.provider
Import-Package: com.jcraft.jsch,
diff --git a/providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/plugin.xml b/providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/plugin.xml
index db397a12d..3ce5bd334 100644
--- a/providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/plugin.xml
+++ b/providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/plugin.xml
@@ -15,4 +15,12 @@
protocol="scp">
</retrieveFileTransferProtocolFactory>
</extension>
+ <extension
+ point="org.eclipse.ecf.provider.filetransfer.browseFileTransferProtocolFactory">
+ <browseFileTransferProtocolFactory
+ class="org.eclipse.ecf.internal.provider.filetransfer.scp.ScpBrowseFileTransferFactory"
+ priority="45"
+ protocol="scp">
+ </browseFileTransferProtocolFactory>
+ </extension>
</plugin>
diff --git a/providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/src/org/eclipse/ecf/internal/provider/filetransfer/scp/ScpBrowseFileTransferFactory.java b/providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/src/org/eclipse/ecf/internal/provider/filetransfer/scp/ScpBrowseFileTransferFactory.java
new file mode 100644
index 000000000..7cabdb651
--- /dev/null
+++ b/providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/src/org/eclipse/ecf/internal/provider/filetransfer/scp/ScpBrowseFileTransferFactory.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2014 CohesionForce Inc
+ * 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:
+ * CohesionForce Inc - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.ecf.internal.provider.filetransfer.scp;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.ecf.core.identity.IDFactory;
+import org.eclipse.ecf.core.identity.Namespace;
+import org.eclipse.ecf.core.security.IConnectContext;
+import org.eclipse.ecf.core.util.Proxy;
+import org.eclipse.ecf.filetransfer.*;
+import org.eclipse.ecf.filetransfer.identity.IFileID;
+import org.eclipse.ecf.filetransfer.service.IRemoteFileSystemBrowser;
+import org.eclipse.ecf.filetransfer.service.IRemoteFileSystemBrowserFactory;
+import org.eclipse.ecf.provider.filetransfer.identity.FileTransferNamespace;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Factory for creating a remote file browser. This class is registered in the
+ * plugin to handle the "scp://" protocol.
+ *
+ */
+public class ScpBrowseFileTransferFactory implements
+ IRemoteFileSystemBrowserFactory {
+
+ public IRemoteFileSystemBrowser newInstance() {
+ return new IRemoteFileSystemBrowser() {
+
+ private Proxy proxy;
+ private IConnectContext connectContext;
+
+ public Namespace getBrowseNamespace() {
+ return IDFactory.getDefault().getNamespaceByName(
+ FileTransferNamespace.PROTOCOL);
+ }
+
+ public IRemoteFileSystemRequest sendBrowseRequest(
+ IFileID directoryOrFileId,
+ IRemoteFileSystemListener listener)
+ throws RemoteFileSystemException {
+
+ Assert.isNotNull(directoryOrFileId);
+ Assert.isNotNull(listener);
+ URL url;
+ try {
+ url = directoryOrFileId.getURL();
+ } catch (final MalformedURLException e) {
+ throw new RemoteFileSystemException(
+ NLS.bind(
+ "Exception creating URL for {0}", directoryOrFileId)); //$NON-NLS-1$
+ }
+
+ ScpFileSystemBrowser browser = new ScpFileSystemBrowser(
+ directoryOrFileId, listener, url, connectContext, proxy);
+ return browser.sendBrowseRequest();
+ }
+
+ public void setConnectContextForAuthentication(
+ IConnectContext connectContext) {
+ this.connectContext = connectContext;
+ }
+
+ public void setProxy(Proxy proxy) {
+ this.proxy = proxy;
+ }
+
+ public Object getAdapter(Class adapter) {
+ return null;
+ }
+ };
+ }
+}
diff --git a/providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/src/org/eclipse/ecf/internal/provider/filetransfer/scp/ScpFileSystemBrowser.java b/providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/src/org/eclipse/ecf/internal/provider/filetransfer/scp/ScpFileSystemBrowser.java
new file mode 100644
index 000000000..9334ea32e
--- /dev/null
+++ b/providers/bundles/org.eclipse.ecf.provider.filetransfer.scp/src/org/eclipse/ecf/internal/provider/filetransfer/scp/ScpFileSystemBrowser.java
@@ -0,0 +1,244 @@
+/*******************************************************************************
+ * Copyright (c) 2014 CohesionForce Inc
+ * 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:
+ * CohesionForce Inc - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.ecf.internal.provider.filetransfer.scp;
+
+import com.jcraft.jsch.ChannelExec;
+import com.jcraft.jsch.Session;
+import java.io.*;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Map;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ecf.core.identity.IDFactory;
+import org.eclipse.ecf.core.security.IConnectContext;
+import org.eclipse.ecf.core.util.Proxy;
+import org.eclipse.ecf.filetransfer.IRemoteFile;
+import org.eclipse.ecf.filetransfer.IRemoteFileSystemListener;
+import org.eclipse.ecf.filetransfer.identity.*;
+import org.eclipse.ecf.provider.filetransfer.browse.AbstractFileSystemBrowser;
+import org.eclipse.ecf.provider.filetransfer.browse.URLRemoteFile;
+import org.eclipse.ecf.provider.filetransfer.identity.FileTransferNamespace;
+
+/**
+ * The ScpFileSystemBrowser uses the JCraft JSch package to run remote commands
+ * using SSH to list files in a directory.
+ *
+ */
+public class ScpFileSystemBrowser extends AbstractFileSystemBrowser implements
+ IScpFileTransfer {
+
+ protected InputStream inputStream;
+
+ protected OutputStream outputStream;
+
+ protected ScpUtil scpUtil;
+
+ protected ChannelExec channel;
+ protected String username;
+
+ protected static final String SCP_EXEC = System.getProperty(
+ "org.eclipse.ecf.filetransfer.scp.filebrowse.exec", "exec"); //$NON-NLS-1$
+ protected static final String LS_START_COMMAND = System.getProperty(
+ "org.eclipse.ecf.filetransfer.scp.filebrowse.lscommand.start",
+ "for file in "); //$NON-NLS-1$; //$NON-NLS-1$
+ protected static final String LS_END_COMMAND = System.getProperty(
+ "org.eclipse.ecf.filetransfer.scp.filebrowse.lscommand.end",
+ "/*; do stat --format='%F|%s|%Y|%n' $file; done "); //$NON-NLS-1$; //$NON-NLS-1$
+
+ /**
+ * Constructor for creating a ScpFileSystemBrowser.
+ *
+ * @param directoryOrFileID
+ * - ID of the remote location to browse
+ * @param listener
+ * - will be called asynchronously with events resulting from
+ * file browsing.
+ * @param url
+ * - URL of the parent directory to browse.
+ * @param connectContext
+ * - contains username/password to use for the ssh connection
+ * @param proxy
+ * - proxy to be used if set.
+ */
+ public ScpFileSystemBrowser(IFileID directoryOrFileID,
+ IRemoteFileSystemListener listener, URL url,
+ IConnectContext connectContext, Proxy proxy) {
+ super(directoryOrFileID, listener, url, connectContext, proxy);
+ username = directoryOrFile.getUserInfo();
+ }
+
+ /**
+ * Method called from super class to build the list of remote files.
+ */
+ protected void runRequest() throws Exception {
+ try {
+
+ scpUtil = new ScpUtil(this);
+ final Session s = scpUtil.getSession();
+ s.connect();
+ if (s.isConnected()) {
+ final String targetFileName = scpUtil
+ .trimTargetFile(directoryOrFile.getPath());
+ final String command = LS_START_COMMAND + targetFileName
+ + LS_END_COMMAND;
+ channel = (ChannelExec) s.openChannel(SCP_EXEC);
+ channel.setCommand(command);
+ final OutputStream outs = channel.getOutputStream();
+ inputStream = channel.getInputStream();
+ channel.connect();
+
+ setOutputStream(outs);
+
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(inputStream));
+ String line = reader.readLine();
+ ArrayList strings = new ArrayList();
+ while (line != null) {
+ strings.add(line);
+ line = reader.readLine();
+ }
+ remoteFiles = new IRemoteFile[strings.size()];
+ for (int i = 0; i < strings.size(); i++) {
+ remoteFiles[i] = createRemoteFile((String) strings.get(i));
+ }
+ }
+ } catch (final Exception e) {
+ Activator.getDefault().log(
+ new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ IStatus.ERROR, "runRequest", e)); //$NON-NLS-1$
+ }
+ }
+
+ private IRemoteFile createRemoteFile(String string)
+ throws FileCreateException, SecurityException {
+ URLRemoteFile file = null;
+ IFileID id = null;
+ String[] parts = string.split("\\|");
+
+ // Check to see if this string can be parsed
+ if (parts.length < 4) {
+ id = FileIDFactory.getDefault().createFileID(
+ IDFactory.getDefault().getNamespaceByName(
+ FileTransferNamespace.PROTOCOL), "scp://unknown");
+ file = new URLRemoteFile(0, 0, id);
+ } else {
+
+ // Build the filename back up, since the filename may also contain
+ // "|"
+ // characters
+ StringBuilder builder = new StringBuilder("scp://");
+ for (int i = 3; i < parts.length; i++) {
+ builder.append(parts[i]);
+
+ // Put the | back into the name
+ if (i > 3 && i < parts.length - 1) {
+ builder.append("|");
+ }
+ }
+
+ // If it's a directory, then make sure it ends with /
+ if (parts[0].equals("directory")
+ && !builder.toString().endsWith("/")) {
+ builder.append("/");
+ } else if (!parts[0].equals("directory")
+ && builder.toString().endsWith("/")) {
+ builder.deleteCharAt(builder.length() - 1);
+ }
+
+ // Create the FileID
+ id = FileIDFactory.getDefault()
+ .createFileID(
+ IDFactory.getDefault().getNamespaceByName(
+ FileTransferNamespace.PROTOCOL),
+ builder.toString());
+ long size = Long.parseLong(parts[1]);
+ long modification = Long.parseLong(parts[2]);
+ file = new URLRemoteFile(modification, size, id);
+ }
+ return file;
+ }
+
+ protected void cleanUp() {
+ super.cleanUp();
+ // FIXME - This code is from ScpOutgoingFileTransfer, but it throws
+ // exceptions
+ // if (scpUtil != null) {
+ // scpUtil.sendZeroToStream(outputStream);
+ // scpUtil.checkAck(inputStream);
+ // }
+ if (channel != null) {
+ channel.disconnect();
+ channel = null;
+ }
+ if (scpUtil != null) {
+ scpUtil.dispose();
+ scpUtil = null;
+ }
+ try {
+ if (inputStream != null)
+ inputStream.close();
+ } catch (final IOException e) {
+ Activator.getDefault().log(
+ new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ IStatus.ERROR, "cleanup", e)); //$NON-NLS-1$
+ }
+ try {
+ if (outputStream != null)
+ outputStream.close();
+ } catch (final IOException e) {
+ Activator.getDefault().log(
+ new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ IStatus.ERROR, "cleanup", e)); //$NON-NLS-1$
+ }
+ inputStream = null;
+ outputStream = null;
+ }
+
+ protected void setupProxy(Proxy proxy) {
+ this.proxy = proxy;
+ this.setupProxies();
+ }
+
+ protected void setInputStream(InputStream ins) {
+ inputStream = ins;
+ }
+
+ protected void setOutputStream(OutputStream outs) {
+ outputStream = outs;
+ }
+
+ public IConnectContext getConnectContext() {
+ return connectContext;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public Proxy getProxy() {
+ return proxy;
+ }
+
+ public URL getTargetURL() {
+ return directoryOrFile;
+ }
+
+ public Map getOptions() {
+ return null;
+ }
+
+}
diff --git a/tests/bundles/org.eclipse.ecf.tests.filetransfer/src/org/eclipse/ecf/tests/filetransfer/ScpFileBrowseTest.java b/tests/bundles/org.eclipse.ecf.tests.filetransfer/src/org/eclipse/ecf/tests/filetransfer/ScpFileBrowseTest.java
new file mode 100644
index 000000000..de582fabd
--- /dev/null
+++ b/tests/bundles/org.eclipse.ecf.tests.filetransfer/src/org/eclipse/ecf/tests/filetransfer/ScpFileBrowseTest.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2014 CohesionForce Inc
+ * 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:
+ * CohesionForce Inc - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.ecf.tests.filetransfer;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.ecf.core.security.ConnectContextFactory;
+import org.eclipse.ecf.core.security.IConnectContext;
+import org.eclipse.ecf.filetransfer.events.IRemoteFileSystemBrowseEvent;
+
+public class ScpFileBrowseTest extends AbstractBrowseTestCase {
+
+ protected File[] roots;
+
+ protected File[] files;
+
+ // Using a countdown latch to wait until we get the proper number
+ // of browse results
+ CountDownLatch latch = new CountDownLatch(1);
+
+ String username;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ IConnectContext cctx;
+ username = System.getProperty("user.name");
+ cctx = ConnectContextFactory.createUsernamePasswordConnectContext(
+ username, null);
+
+ this.adapter.setConnectContextForAuthentication(cctx);
+
+ roots = File.listRoots();
+ final List files = new ArrayList();
+ for (int i = 0; i < roots.length; i++) {
+ final File[] fs = roots[i].listFiles();
+ if (fs != null)
+ for (int j = 0; j < fs.length; j++) {
+ if (fs[j].exists())
+ files.add(fs[j]);
+ }
+ }
+ this.files = (File[]) files.toArray(new File[] {});
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ this.roots = null;
+ this.files = null;
+ }
+
+ public void testBrowseRoots() throws Exception {
+ latch = new CountDownLatch(roots.length);
+ for (int i = 0; i < roots.length; i++) {
+ if (roots[i].exists()) {
+ URL url = new URL("scp://"+username+"@localhost:"
+ + roots[i].getAbsolutePath());
+ System.out.println("Browsing: " + url);
+ testBrowse(url);
+ } else {
+ System.out.println("Skipping: " + roots[i].toString());
+ latch.countDown();
+ }
+ // Need to sleep to give the connection time to close out
+ Thread.sleep(100);
+ }
+ assertTrue(latch.await(60, TimeUnit.SECONDS));
+ }
+
+ @Override
+ protected void handleFileSystemBrowseEvent(IRemoteFileSystemBrowseEvent event) {
+ trace("handleFileSystemBrowseEvent(" + event + ")");
+ if (event.getException() != null) {
+ trace(event.getException().toString());
+ }
+ latch.countDown();
+ }
+
+ public void testFileBrowse() throws Exception {
+ latch = new CountDownLatch(files.length);
+ for (int i = 0; i < files.length; i++) {
+ if (files[i].isDirectory() && files[i].exists()) {
+ URL url = new URL("scp://"+username+"@localhost:"
+ + files[i].getAbsolutePath());
+ System.out.println("Browsing: " + url);
+ testBrowse(url);
+ } else {
+ System.out.println("Skipping: " + files[i].toString());
+ latch.countDown();
+ }
+ // Need to sleep to give the connection time to close out
+ Thread.sleep(100);
+ }
+ assertTrue(latch.await(60, TimeUnit.SECONDS));
+ }
+
+}

Back to the top