1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-02 22:55:26 +02:00

[213438] Checked in initial scp filesubsystem contribution by Nikita Shulga (Mentor Graphics).

This commit is contained in:
Anna Dushistova 2010-11-25 11:00:56 +00:00
parent b2ff1be03f
commit 1a03a16e19
17 changed files with 1339 additions and 0 deletions

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.rse.subsystems.files.scp</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,7 @@
#Fri Feb 06 22:40:19 JST 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.5

View file

@ -0,0 +1,19 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.rse.subsystems.files.scp;singleton:=true
Bundle-Version: 0.1.0.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Require-Bundle: org.eclipse.rse.subsystems.files.core;bundle-version="[3.0.0,4.0.0)",
org.eclipse.rse.services.ssh;bundle-version="[3.0.0,3.1.0)",
org.eclipse.rse.connectorservice.ssh;bundle-version="[2.0.0,2.2.0)",
org.eclipse.rse.services;bundle-version="[3.0.0,4.0.0)",
org.eclipse.rse.core;bundle-version="[3.0.0,4.0.0)",
org.eclipse.rse.ui;bundle-version="[3.0.0,4.0.0)",
com.jcraft.jsch;bundle-version="[0.1.31,1.0.0)",
org.eclipse.core.runtime;bundle-version="[3.4.0,3.7.0)"
Bundle-Activator: org.eclipse.rse.internal.subsystems.files.scp.Activator
Export-Package: org.eclipse.rse.internal.subsystems.files.scp;x-internal:=true,
org.eclipse.rse.subsystems.files.scp

View file

@ -0,0 +1,28 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>About</title>
</head>
<body lang="EN-US">
<h2>About This Content</h2>
<p>June 5, 2007</p>
<h3>License</h3>
<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
indicated below, the Content is provided to you under the terms and conditions of the
Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
apply to your use of any object code in the Content. Check the Redistributor's license that was
provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
indicated below, the terms and conditions of the EPL still apply to any source code in the Content
and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
</body>
</html>

View file

@ -0,0 +1,6 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
icons/,\
plugin.properties,\
plugin.xml

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

View file

@ -0,0 +1,16 @@
################################################################################
# Copyright (c) 2010 Mentor Graphics Corporation 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:
# Nikita Shulga - initial API and implementation
################################################################################
pluginName = RSE SCP Files (Incubation)
providerName = Eclipse.org - DSDP
ScpFileSubsystemName=Scp Files
ScpFileSubsystemDescription=Work with files on remote systems using the Secure Shell (ssh) protocol.

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2009, 2010 Mentor Graphics Corporation 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:
Nikita Shulga - initial API and implementation
-->
<?eclipse version="3.1"?>
<plugin>
<extension
point="org.eclipse.rse.core.subsystemConfigurations">
<configuration
category="files"
class="org.eclipse.rse.subsystems.files.scp.ScpFileSubSystemConfiguration"
description="%ScpFileSubsystemName"
icon="icons/full/obj16/systemfiles_obj.gif"
iconlive="icons/full/obj16/systemfileslive_obj.gif"
id="scp.files"
name="%ScpFileSubsystemName"
priority="80"
serviceType="_scp-ssh._tcp"
systemTypeIds="org.eclipse.rse.systemtype.linux;org.eclipse.rse.systemtype.unix;org.eclipse.rse.systemtype.aix;org.eclipse.rse.systemtype.ssh"
vendor="%providerName">
</configuration>
</extension>
</plugin>

View file

@ -0,0 +1,71 @@
/*******************************************************************************
* Copyright (c) 2009, 2010 Mentor Graphics Corporation 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:
* Nikita Shulga (Mentor Graphics) - initial implementation
*******************************************************************************/
package org.eclipse.rse.internal.subsystems.files.scp;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Status;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
public class Activator extends Plugin {
// The plug-in ID
public static final String PLUGIN_ID = Activator.class.getCanonicalName();
private static Activator plugin = null;
private static Bundle bundle = null;
public Activator() {
}
public static Plugin getDefault() {
return plugin;
}
public static Bundle getDefaultBundle() {
return bundle;
}
@Override
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
bundle = context.getBundle();
}
@Override
public void stop(BundleContext context) throws Exception {
plugin = null;
bundle = null;
super.stop(context);
}
public static void log(String msg) {
log(msg, null);
}
public static void log(String msg, Exception e) {
log(IStatus.INFO, msg, e);
}
public static void warn(String msg, Exception e) {
log(IStatus.WARNING, msg, e);
}
public static void log(int sev, String msg, Exception e) {
Platform.getLog(getDefaultBundle()).log(
new Status(sev, PLUGIN_ID, msg, e));
}
}

View file

@ -0,0 +1,59 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 IBM Corporation 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
*
* Initial Contributors:
* The following IBM employees contributed to the Remote System Explorer
* component that contains this file: David McKnight, Kushal Munir,
* Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson,
* Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
*
* Contributors:
* Martin Oberhuber (Wind River) - Adapted from FTPFileAdapter.
* Martin Oberhuber (Wind River) - [235363][api][breaking] IHostFileToRemoteFileAdapter methods should return AbstractRemoteFile
* Nikita Shulga (Mentor Graphics) - Adapted from SftpFileAdapter.
*******************************************************************************/
package org.eclipse.rse.internal.subsystems.files.scp;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.rse.services.files.IHostFile;
import org.eclipse.rse.subsystems.files.core.servicesubsystem.AbstractRemoteFile;
import org.eclipse.rse.subsystems.files.core.servicesubsystem.FileServiceSubSystem;
import org.eclipse.rse.subsystems.files.core.subsystems.IHostFileToRemoteFileAdapter;
import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile;
import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileContext;
public class ScpFileAdapter implements IHostFileToRemoteFileAdapter {
public AbstractRemoteFile convertToRemoteFile(FileServiceSubSystem ss,
IRemoteFileContext context, IRemoteFile parent, IHostFile node) {
ScpRemoteFile file = new ScpRemoteFile(ss, context, parent, node);
ss.cacheRemoteFile(file);
return file;
}
public AbstractRemoteFile[] convertToRemoteFiles(FileServiceSubSystem ss,
IRemoteFileContext context, IRemoteFile parent, IHostFile[] nodes) {
if (nodes == null)
return new AbstractRemoteFile[0];
List<ScpRemoteFile> results = new ArrayList<ScpRemoteFile>();
for (IHostFile node : nodes) {
ScpRemoteFile file = new ScpRemoteFile(ss, context, parent, node);
ss.cacheRemoteFile(file);
results.add(file);
}
return (ScpRemoteFile[]) results.toArray(new ScpRemoteFile[results
.size()]);
}
}

View file

@ -0,0 +1,248 @@
/*******************************************************************************
* Copyright (c) 2009, 2010 Mentor Graphics Corporation 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:
* Nikita Shulga - initial API and implementation
*******************************************************************************/
package org.eclipse.rse.internal.subsystems.files.scp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Stack;
import java.util.regex.Pattern;
import org.eclipse.rse.services.clientserver.messages.SystemMessageException;
import org.eclipse.rse.services.files.HostFilePermissions;
import org.eclipse.rse.services.files.IHostFilePermissions;
import com.jcraft.jsch.Session;
public class ScpFileAttr {
private String lsString;
private String attrString = null;
private int linkNo = 0;
private long mTime = 0;
private String user = null;
private String group = null;
private long size = -1;
private String name = null;
private String linkName = null;
public IHostFilePermissions getFilePermissions() {
return new HostFilePermissions(getAttrs(), getUser(), getGroup());
}
public long getMTime() {
if (!initialized)
doSplit();
return mTime;
}
public long getSize() {
if (!initialized)
doSplit();
return size;
}
public String getUser() {
if (!initialized)
doSplit();
return user;
}
public String getGroup() {
if (!initialized)
doSplit();
return group;
}
public int getLinkNo() {
if (!initialized)
doSplit();
return linkNo;
}
public String getName() {
if (!initialized)
doSplit();
return name;
}
public String getLinkName() {
if (!initialized)
doSplit();
return linkName;
}
public String getAttrs() {
if (!initialized)
doSplit();
if (attrString == null || attrString.length() < 9)
return "---------"; //$NON-NLS-1$
return attrString;
}
private char getFileType() {
String attrs = getAttrs();
if (attrs == null || attrs.length() == 0)
return 0;
return attrs.charAt(0);
}
public boolean isBlockDevice() {
return getFileType() == 'b';
}
public boolean isCharDevice() {
return getFileType() == 'c';
}
public boolean isLink() {
return getFileType() == 'l';
}
public boolean isDirectory() {
return getFileType() == 'd';
}
ScpFileAttr(String str) {
lsString = str;
if (lsString.endsWith("\n")) //$NON-NLS-1$
lsString = lsString.substring(0, lsString.length() - 1);
}
private boolean initialized = false;
private void doSplit() {
if (initialized)
return;
initialized = true;
try {
SplitAux();
} catch (Exception e) {
Activator.warn(
"ScpFileAttr:Exception occured while splitting string "
+ lsString, e);
}
}
/*
* ls command uses two short date formats: - for files modified more than 6
* month ago - for files modified less than 6 month ago
*/
final static DateFormat lessThanSixMonthOldFormat = new SimpleDateFormat(
"MMM dd HH:mm"); //$NON-NLS-1$
final static DateFormat moreThanSixMonthOldFormat = new SimpleDateFormat(
"MMM dd yyyy"); //$NON-NLS-1$
/**
* Parses date time string returned by ls command
*
* @param date
* - file modification date as string
* @return time in seconds since start of epoch until mTime
*/
static long parseDateTime(String date) {
// TODO: Add support for ls -le date format
try {
Date d = lessThanSixMonthOldFormat.parse(date);
Calendar c = Calendar.getInstance();
c.setTime(d);
c.set(Calendar.YEAR, Calendar.getInstance().get(Calendar.YEAR));
return c.getTimeInMillis() / 1000;
} catch (Exception e) {
}
try {
Date d = moreThanSixMonthOldFormat.parse(date);
return d.getTime() / 1000;
} catch (Exception e) {
}
return 0;
}
private static Pattern lsPattern = Pattern.compile("\\s+"); //$NON-NLS-1$
public void SplitAux() throws Exception {
Stack<String> fields = new Stack<String>();
for (String s : lsPattern.split(lsString))
fields.insertElementAt(s, 0);
/* store file attributes */
if (fields.empty())
return;
attrString = fields.pop();
/* store link number */
if (fields.empty())
return;
linkNo = Integer.parseInt(fields.pop());
/* store uid and gid */
if (fields.empty())
return;
user = fields.pop();
if (fields.empty())
return;
group = fields.pop();
/* store file size */
if (fields.empty())
return;
if (!isCharDevice() && !isBlockDevice())
size = Long.parseLong(fields.pop());
else {
/* Size is undefined for character and block devices */
size = 0;
/* And we don't know what to do with devs major/minor */
fields.pop();
if (fields.empty())
return;
fields.pop();
}
/* Date always takes three fields */
if (fields.empty())
return;
String dateField = fields.pop();
if (fields.empty())
return;
dateField = dateField + " " + fields.pop(); //$NON-NLS-1$
if (fields.empty())
return;
dateField = dateField + " " + fields.pop(); //$NON-NLS-1$
mTime = parseDateTime(dateField);
/* The rest of the entry is name ( and may be symlink ) */
String[] namesplit = Pattern.compile(
dateField.replace(" ", "\\s+") + "\\s").split(lsString); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
if (namesplit.length != 2)
return;
name = namesplit[1];
if (isLink()) {
namesplit = name.split(" -> "); //$NON-NLS-1$
if (namesplit.length != 2)
return;
name = namesplit[0];
linkName = namesplit[1];
}
}
public static ScpFileAttr getAttr(Session sess, String path)
throws SystemMessageException {
String attr = ScpFileUtils.execCommandSafe(sess, "ls -land " //$NON-NLS-1$
+ ScpFileUtils.escapePath(path));
if (attr == null || attr.length() < 9)
return null;
return new ScpFileAttr(attr);
}
}

View file

@ -0,0 +1,522 @@
/*******************************************************************************
* Copyright (c) 2009, 2010 Mentor Graphics Corporation 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:
* Nikita Shulga - initial API and implementation
*******************************************************************************/
package org.eclipse.rse.internal.subsystems.files.scp;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.rse.internal.services.ssh.ISshSessionProvider;
import org.eclipse.rse.internal.services.ssh.files.SftpHostFile;
import org.eclipse.rse.services.clientserver.FileTypeMatcher;
import org.eclipse.rse.services.clientserver.IMatcher;
import org.eclipse.rse.services.clientserver.NamePatternMatcher;
import org.eclipse.rse.services.clientserver.messages.SimpleSystemMessage;
import org.eclipse.rse.services.clientserver.messages.SystemMessageException;
import org.eclipse.rse.services.files.AbstractFileService;
import org.eclipse.rse.services.files.HostFilePermissions;
import org.eclipse.rse.services.files.IFilePermissionsService;
import org.eclipse.rse.services.files.IHostFile;
import org.eclipse.rse.services.files.IHostFilePermissions;
import org.eclipse.rse.services.files.IHostFilePermissionsContainer;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.Session;
@SuppressWarnings("restriction")
public class ScpFileService extends AbstractFileService implements
IFilePermissionsService {
private final ISshSessionProvider fSessionProvider;
private String fUserHome = null;
public ISshSessionProvider getSessionProvider() {
return fSessionProvider;
}
public Session getSession() {
return getSessionProvider().getSession();
}
public ScpFileService(ISshSessionProvider provider) {
fSessionProvider = provider;
}
protected static void throwSystemException(String msg)
throws SystemMessageException {
throw new SystemMessageException(new SimpleSystemMessage(
Activator.PLUGIN_ID, IStatus.ERROR, msg));
}
protected static void throwSystemException(Exception e)
throws SystemMessageException {
Activator.warn("ScpFileServie.throwSystemExcpeption", e);
if (e instanceof SystemMessageException)
throw (SystemMessageException) e;
throw new SystemMessageException(new SimpleSystemMessage(
Activator.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
}
@Override
protected IHostFile[] internalFetch(String parentPath, String fileFilter,
int fileType, IProgressMonitor monitor)
throws SystemMessageException {
if (fileFilter == null)
fileFilter = "*";
IMatcher filematcher = null;
if (fileFilter.endsWith(",")) { //$NON-NLS-1$
String[] types = fileFilter.split(","); //$NON-NLS-1$
filematcher = new FileTypeMatcher(types, true);
} else {
filematcher = new NamePatternMatcher(fileFilter, true, true);
}
List<IHostFile> results = new ArrayList<IHostFile>();
Session sess = getSession();
String cmd = "ls -lAn " + ScpFileUtils.escapePath(parentPath); //$NON-NLS-1$
String rc = ScpFileUtils.execCommandSafe(sess, cmd);
for (String lsString : rc.split(ScpFileUtils.EOL_STRING)) {
if (lsString.length() == 0 || lsString.startsWith("total")) //$NON-NLS-1$
continue;
ScpFileAttr attr = new ScpFileAttr(lsString);
if (attr == null || attr.getName() == null) {
Activator.warn("internalFetch(parentPath='" + parentPath
+ "'): Can't get name of " + lsString, null);
continue;
}
if (!filematcher.matches(attr.getName()))
continue;
IHostFile f = makeHostFile(parentPath, null, attr);
if (isRightType(fileType, f))
results.add(f);
}
return (IHostFile[]) results.toArray(new IHostFile[results.size()]);
}
public int getCapabilities(IHostFile host) {
return IFilePermissionsService.FS_CAN_GET_ALL
| IFilePermissionsService.FS_CAN_SET_ALL;
}
public IHostFilePermissions getFilePermissions(IHostFile file,
IProgressMonitor monitor) throws SystemMessageException {
if (file instanceof IHostFilePermissionsContainer) {
return ((IHostFilePermissionsContainer) file).getPermissions();
}
return null;
}
public void setFilePermissions(IHostFile file,
IHostFilePermissions permissions, IProgressMonitor monitor)
throws SystemMessageException {
Session session = getSession();
String path = ScpFileUtils.escapePath(file.getAbsolutePath());
int permBits = permissions.getPermissionBits();
String ownStr = permissions.getUserOwner() + ':'
+ permissions.getGroupOwner();
String cmd = "chmod " + Integer.toOctalString(permBits) + " " + path; //$NON-NLS-1$ //$NON-NLS-2$
ScpFileUtils.execCommandSafe(session, cmd);
ScpFileUtils.execCommandSafe(session, "chown " + ownStr + " " + path); //$NON-NLS-1$ //$NON-NLS-2$
}
public void copy(String arg0, String arg1, String arg2, String arg3,
IProgressMonitor arg4) throws SystemMessageException {
// TODO Auto-generated method stub
}
public void copyBatch(String[] arg0, String[] arg1, String arg2,
IProgressMonitor arg3) throws SystemMessageException {
// TODO Auto-generated method stub
}
public IHostFile createFile(String remotePath, String fileName,
IProgressMonitor arg2) throws SystemMessageException {
Session session = getSession();
String fullPath = ScpFileUtils.concat(remotePath, fileName);
ScpFileUtils.execCommandSafe(session,
"touch " + ScpFileUtils.escapePath(fullPath)); //$NON-NLS-1$
ScpFileAttr attr = ScpFileAttr.getAttr(session, fullPath);
return makeHostFile(remotePath, fileName, attr);
}
public IHostFile createFolder(String remotePath, String fileName,
IProgressMonitor arg2) throws SystemMessageException {
Session session = getSession();
String fullPath = ScpFileUtils.concat(remotePath, fileName);
ScpFileUtils.execCommandSafe(session,
"mkdir " + ScpFileUtils.escapePath(fullPath)); //$NON-NLS-1$
ScpFileAttr attr = ScpFileAttr.getAttr(session, fullPath);
return makeHostFile(remotePath, fileName, attr);
}
public void delete(String remotePath, String fileName, IProgressMonitor arg2)
throws SystemMessageException {
Session session = getSession();
String fullPathEsc = ScpFileUtils.concatEscape(remotePath, fileName);
ScpFileUtils.execCommandSafe(session, "rm -rf " + fullPathEsc); //$NON-NLS-1$
}
private static String lastErrorMessage = null;
private static void setErrorMessage(String s) {
lastErrorMessage = s;
}
public static String getLastError() {
return lastErrorMessage;
}
private static int readAck(InputStream is) throws IOException {
int rc = is.read();
if (rc <= 0)
return rc;
/* In case of non fatal error had to read an error string */
StringBuffer sb = new StringBuffer();
int ch;
do {
ch = is.read();
sb.append((char) ch);
} while (ch != ScpFileUtils.EOL_CHAR);
setErrorMessage(sb.toString());
return rc;
}
public void download(String remoteParent, String fileName, File localFile,
boolean isBinary, String hostEncoding, IProgressMonitor monitor)
throws SystemMessageException {
try {
if (!localFile.exists()) {
File localParentFile = localFile.getParentFile();
if (!localParentFile.exists()) {
localParentFile.mkdirs();
}
}
internalDownload(remoteParent, fileName, localFile, monitor);
} catch (Exception e) {
throwSystemException(e);
}
}
public IHostFile getFile(String remotePath, String fileName,
IProgressMonitor monitor) throws SystemMessageException {
Session session = getSession();
String fullPath = ScpFileUtils.concat(remotePath, fileName);
ScpFileAttr attr = ScpFileAttr.getAttr(session, fullPath);
return makeHostFile(remotePath, fileName, attr);
}
public IHostFile[] getRoots(IProgressMonitor monitor)
throws SystemMessageException {
IHostFile root = null;
try {
root = getFile(null, ScpFileUtils.TARGET_SEPARATOR, monitor);
} catch (SystemMessageException e) {
Activator.warn("Failed to get root file", e);
}
if (root == null)
root = new SftpHostFile(null, ScpFileUtils.TARGET_SEPARATOR, true,
true, false, 0, 0);
return new IHostFile[] { root };
}
public IHostFile getUserHome() {
if (fUserHome == null) {
try {
Session sess = getSession();
fUserHome = ScpFileUtils.execCommand(sess, "pwd").split( //$NON-NLS-1$
ScpFileUtils.EOL_STRING)[0];
} catch (Exception e) {
Activator.warn("Failed to execute pwd", e);
return null;
}
}
if (fUserHome == null)
return null;
int lastSlash = fUserHome
.lastIndexOf(ScpFileUtils.TARGET_SEPARATOR_CHAR);
String name = fUserHome.substring(lastSlash + 1);
String parent = fUserHome.substring(0, lastSlash);
IHostFile rc = null;
try {
rc = getFile(parent, name, null);
} catch (SystemMessageException e) {
Activator.warn("Failed to get user home file ", e);
}
if (rc == null)
rc = new SftpHostFile(null, fUserHome, true, true, false, 0, 0);
return rc;
}
public boolean isCaseSensitive() {
return true;
}
public void move(String oldPath, String oldName, String newPath,
String newName, IProgressMonitor arg4)
throws SystemMessageException {
Session session = getSession();
String oldFullPathEsc = ScpFileUtils.concatEscape(newPath, oldName);
String newFullPathEsc = ScpFileUtils.concatEscape(newPath, newName);
ScpFileUtils.execCommandSafe(session, "mv " + oldFullPathEsc + " " //$NON-NLS-1$ //$NON-NLS-2$
+ newFullPathEsc);
}
public void rename(String remotePath, String oldName, String newName,
IProgressMonitor monitor) throws SystemMessageException {
Session session = getSession();
String oldFullPathEsc = ScpFileUtils.concatEscape(remotePath, oldName);
String newFullPathEsc = ScpFileUtils.concatEscape(remotePath, newName);
ScpFileUtils.execCommandSafe(session, "mv " + oldFullPathEsc + " " //$NON-NLS-1$ //$NON-NLS-2$
+ newFullPathEsc);
}
public void rename(String remotePath, String oldName, String newName,
IHostFile hostFile, IProgressMonitor monitor)
throws SystemMessageException {
// hostFile remains unused
rename(remotePath, oldName, newName, monitor);
}
public void setLastModified(String arg0, String arg1, long arg2,
IProgressMonitor arg3) throws SystemMessageException {
throwSystemException("setLastModified() not supported");
}
public void setReadOnly(String remotePath, String fileName,
boolean disableWrite, IProgressMonitor monitor)
throws SystemMessageException {
Session session = getSession();
String fullPath = ScpFileUtils.concat(remotePath, fileName);
ScpFileAttr attr = ScpFileAttr.getAttr(session, fullPath);
if (attr == null)
throwSystemException("Can't get attribute of file " + fullPath);
int perm = new HostFilePermissions(attr.getAttrs(), "", "") //$NON-NLS-1$ //$NON-NLS-2$
.getPermissionBits();
if (disableWrite)
perm &= ~0222;
else
perm |= 0200;
ScpFileUtils.execCommandSafe(
session,
"chmod " + Integer.toOctalString(perm) + " " //$NON-NLS-1$//$NON-NLS-2$
+ ScpFileUtils.escapePath(fullPath));
}
public void upload(InputStream stream, String remotePath,
String remoteFile, boolean isBinary, String hostEncoding,
IProgressMonitor monitor) throws SystemMessageException {
}
private void internalDownload(String remoteParent, String fileName,
File localFile, IProgressMonitor monitor) throws Exception {
String remotePath = ScpFileUtils.concat(remoteParent, fileName);
String cmd = "scp -f " + ScpFileUtils.escapePath(remotePath); //$NON-NLS-1$
ChannelExec ch = ScpFileUtils.openExecChannel(getSession(), cmd);
InputStream is = ch.getInputStream();
OutputStream os = ch.getOutputStream();
ch.connect();
byte buf[] = new byte[1024];
// send '0'
buf[0] = 0;
os.write(buf, 0, 1);
os.flush();
int c = is.read();
if (c == 1) {
String errmsg = ScpFileUtils.readString(is);
throw new Exception("Error while downloading " + remotePath + " :"
+ errmsg);
}
if (c != 'C')
throw new Exception("Error while downloading " + remotePath
+ ": Can't download file of type" + c);
// read '0644'
is.read(buf, 0, 5);
// get file size
long filesize = 0;
while (true) {
if (is.read(buf, 0, 1) < 0)
break;
if (buf[0] == ' ')
break;
filesize = filesize * 10 + (buf[0] - '0');
}
String fname = ScpFileUtils.readString(is);
Activator.log("filesize=" + filesize + " fname=" + fname);
// Confirm that file description is read by sending '0'
buf[0] = 0;
os.write(buf, 0, 1);
os.flush();
FileOutputStream fos = new FileOutputStream(localFile);
monitor.beginTask("Downloading file", (int) filesize);
long bytesDownloaded = 0;
while (true) {
int len = buf.length;
if (filesize - bytesDownloaded < len)
len = (int) (filesize - bytesDownloaded);
int rc = is.read(buf, 0, len);
if (rc < 0)
break;
monitor.worked(rc);
fos.write(buf, 0, rc);
bytesDownloaded += rc;
if (bytesDownloaded >= filesize)
break;
}
fos.close();
fos = null;
monitor.done();
c = is.read();
if (c == 0) {
// Confirm that file was received by sending '0'
buf[0] = 0;
os.write(buf, 0, 1);
os.flush();
}
os.close();
is.close();
ch.disconnect();
}
private void internalUpload(File localFile, String remotePath,
String remoteFile, IProgressMonitor monitor) throws Exception {
monitor.beginTask("Uploading file", (int) localFile.length() + 10);
Session session = getSession();
String cmd = "scp -p -t " + ScpFileUtils.escapePath(remotePath); //$NON-NLS-1$
ChannelExec ch = ScpFileUtils.openExecChannel(session, cmd);
InputStream is = ch.getInputStream();
OutputStream os = ch.getOutputStream();
ch.connect();
monitor.internalWorked(5);
String fileHeader = "C0644" + " " + localFile.length() + " " //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
+ remoteFile + "\n"; //$NON-NLS-1$
if (readAck(is) != 0)
throw new Exception("upload: wrong Ack! Last error:"
+ getLastError());
os.write(fileHeader.getBytes());
os.flush();
monitor.internalWorked(4);
FileInputStream fis = new FileInputStream(localFile);
byte[] buf = new byte[1024];
while (true) {
int len = fis.read(buf, 0, buf.length);
if (len <= 0)
break;
os.write(buf, 0, len);
monitor.internalWorked(len);
}
fis.close();
buf[0] = 0;
os.write(buf, 0, 1);
os.flush();
if (readAck(is) != 0)
throw new Exception("Error happened while uploading "
+ localFile.getAbsolutePath() + ":" + getLastError());
monitor.internalWorked(1);
os.close();
is.close();
monitor.done();
ch.disconnect();
}
public void upload(File localFile, String remotePath, String remoteFile,
boolean isBinary, String srcEncoding, String hostEncoding,
IProgressMonitor monitor) throws SystemMessageException {
try {
internalUpload(localFile, remotePath, remoteFile, monitor);
} catch (Exception e) {
throwSystemException(e);
}
}
private IHostFile makeHostFile(String remotePath, String fileName,
ScpFileAttr attr) {
boolean isRoot = (remotePath == null || remotePath.length() == 0);
if (attr == null)
return new SftpHostFile(isRoot ? null : remotePath, fileName,
false, isRoot, false, 0, 0);
boolean isLink = attr.isLink();
boolean isDir = attr.isDirectory();
if (fileName == null)
fileName = attr.getName();
SftpHostFile node = new SftpHostFile(isRoot ? null : remotePath,
fileName, isDir, isRoot, isLink, 1000L * attr.getMTime(),
attr.getSize());
if (isLink && attr.getLinkName() != null)
node.setLinkTarget(attr.getLinkName());
node.setPermissions(attr.getFilePermissions());
return node;
}
@Override
public String getDescription() {
return "SSH/SCP File Service can be used to connect to embedded sshd implementations, which often lacks sftp service";
}
@Override
public String getName() {
return "SCP File Service";
}
}

View file

@ -0,0 +1,135 @@
/*******************************************************************************
* Copyright (c) 2009, 2010 Mentor Graphics Corporation 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:
* Nikita Shulga - initial API and implementation
*******************************************************************************/
package org.eclipse.rse.internal.subsystems.files.scp;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.rse.services.clientserver.messages.SystemMessageException;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.Session;
public class ScpFileUtils {
public static final String EOL_STRING = "\n"; //$NON-NLS-1$
public static final String TARGET_SEPARATOR = "/"; //$NON-NLS-1$
public static final String EXEC_CHANNEL = "exec"; //$NON-NLS-1$
public static final String QUOTATION_MARK = "\""; //$NON-NLS-1$
public static char EOL_CHAR = EOL_STRING.charAt(0);
public static char TARGET_SEPARATOR_CHAR = TARGET_SEPARATOR.charAt(0);
/**
* Concatenate a parent directory with a file name to form a new proper path
* name.
*
* This method was cloned from
* {@link org.eclipse.rse.internal.services.ssh.files.SftpFileService#concat}
*/
protected static String concat(String parentDir, String fileName) {
// See also {@link SftpHostFile#getAbsolutePath()}
if (parentDir == null || parentDir.length() == 0) {
// Looking at a Root
return fileName;
}
StringBuffer path = new StringBuffer(parentDir);
if (!parentDir.endsWith(TARGET_SEPARATOR))
path.append(TARGET_SEPARATOR_CHAR);
path.append(fileName);
return path.toString();
}
public static ChannelExec openExecChannel(Session sess) throws Exception {
return (ChannelExec) sess.openChannel(EXEC_CHANNEL);
}
public static ChannelExec openExecChannel(Session sess, String cmd)
throws Exception {
ChannelExec ch = openExecChannel(sess);
if (ch != null)
ch.setCommand(cmd);
return ch;
}
public static String execCommand(Session sess, String command)
throws Exception {
ChannelExec ch = openExecChannel(sess, command);
ch.setInputStream(null);
ch.setErrStream(System.err, true);
InputStream is = ch.getInputStream();
ch.connect();
String str = readStream(ch);
is.close();
ch.disconnect();
return str;
}
public static String execCommandSafe(Session session, String command)
throws SystemMessageException {
String rc = null;
try {
rc = execCommand(session, command);
} catch (Exception e) {
ScpFileService.throwSystemException(e);
}
return rc;
}
public static String escapePath(String path) {
if (path.indexOf(' ') < 0)
return path;
return QUOTATION_MARK + path + QUOTATION_MARK;
}
/**
* Concatenates parent directory with file name and escape the result if
* necessary
*
* @param parentDir
* parent directory
* @param fileName
* file name
* @return escaped concatenated path to the file
*/
protected static String concatEscape(String parentDir, String fileName) {
return escapePath(concat(parentDir, fileName));
}
public static String readString(InputStream is) throws IOException {
StringBuffer buf = new StringBuffer();
int rc = 0;
while (true) {
rc = is.read();
if (rc == EOL_CHAR)
break;
buf.append((char) rc);
}
return buf.toString();
}
public static String readStream(ChannelExec ch) throws IOException {
InputStream is = ch.getInputStream();
byte[] buf = new byte[1024];
String rc = ""; //$NON-NLS-1$
while (!ch.isClosed() || is.available() > 0) {
int cnt = is.read(buf, 0, buf.length);
if (cnt < 0)
break;
rc += new String(buf, 0, cnt);
}
return rc;
}
}

View file

@ -0,0 +1,58 @@
/*******************************************************************************
* Copyright (c) 2005, 2010 IBM Corporation 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
*
* Initial Contributors:
* The following IBM employees contributed to the Remote System Explorer
* component that contains this file: David McKnight, Kushal Munir,
* Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson,
* Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
*
* Contributors:
* Martin Oberhuber (Wind River) - Adapted from FTPRemoteFile.
* Martin Oberhuber (Wind River) - [216343] immediate link targets and canonical paths for Sftp
* Nikita Shulga (Mentor Graphics) - Adapted from SftpRemoteFile.
*******************************************************************************/
package org.eclipse.rse.internal.subsystems.files.scp;
import org.eclipse.rse.internal.services.ssh.files.SftpHostFile;
import org.eclipse.rse.services.files.IHostFile;
import org.eclipse.rse.subsystems.files.core.servicesubsystem.AbstractRemoteFile;
import org.eclipse.rse.subsystems.files.core.servicesubsystem.FileServiceSubSystem;
import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile;
import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileContext;
@SuppressWarnings("restriction")
public class ScpRemoteFile extends AbstractRemoteFile {
public ScpRemoteFile(FileServiceSubSystem ss, IRemoteFileContext context,
IRemoteFile parent, IHostFile hostFile) {
super(ss, context, parent, hostFile);
}
public SftpHostFile getSftpHostFile() {
return (SftpHostFile) getHostFile();
}
public String getCanonicalPath() {
String canonicalPath = getSftpHostFile().getCanonicalPath();
if (canonicalPath.equals(getAbsolutePath()) && _parentFile != null) {
String parentCanonicalPath = _parentFile.getCanonicalPath();
StringBuffer path = new StringBuffer(parentCanonicalPath);
if (!parentCanonicalPath.endsWith(ScpFileUtils.TARGET_SEPARATOR))
path.append(ScpFileUtils.TARGET_SEPARATOR);
path.append(getName());
canonicalPath = path.toString();
}
return canonicalPath;
}
public String getClassification() {
return getSftpHostFile().getClassification();
}
}

View file

@ -0,0 +1,103 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 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:
* Martin Oberhuber (Wind River) - initial API and implementation
* Nikita Shulga (Mentor Graphics) - adapted from SftpFileSubSystemConfiguration.
*******************************************************************************/
package org.eclipse.rse.subsystems.files.scp;
import org.eclipse.rse.core.model.IHost;
import org.eclipse.rse.core.subsystems.IConnectorService;
import org.eclipse.rse.core.subsystems.ISubSystem;
import org.eclipse.rse.internal.connectorservice.ssh.SshConnectorService;
import org.eclipse.rse.internal.connectorservice.ssh.SshConnectorServiceManager;
import org.eclipse.rse.internal.services.ssh.ISshService;
import org.eclipse.rse.internal.subsystems.files.scp.ScpFileAdapter;
import org.eclipse.rse.internal.subsystems.files.scp.ScpFileService;
import org.eclipse.rse.services.clientserver.SystemSearchString;
import org.eclipse.rse.services.files.IFileService;
import org.eclipse.rse.services.search.IHostSearchResultConfiguration;
import org.eclipse.rse.services.search.IHostSearchResultSet;
import org.eclipse.rse.services.search.ISearchService;
import org.eclipse.rse.subsystems.files.core.ILanguageUtilityFactory;
import org.eclipse.rse.subsystems.files.core.servicesubsystem.FileServiceSubSystem;
import org.eclipse.rse.subsystems.files.core.servicesubsystem.FileServiceSubSystemConfiguration;
import org.eclipse.rse.subsystems.files.core.subsystems.IHostFileToRemoteFileAdapter;
import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileSubSystem;
@SuppressWarnings("restriction")
public class ScpFileSubSystemConfiguration extends
FileServiceSubSystemConfiguration {
protected IHostFileToRemoteFileAdapter _hostFileAdapter;
public ScpFileSubSystemConfiguration() {
super();
setIsUnixStyle(true);
}
@Override
public ISubSystem createSubSystemInternal(IHost host) {
IConnectorService connectorService = getConnectorService(host);
IFileService fileService = getFileService(host);
ISubSystem subsys = new FileServiceSubSystem(host, connectorService,
fileService, getHostFileAdapter(), getSearchService(host));
return subsys;
}
public IFileService createFileService(IHost host) {
SshConnectorService connectorService = (SshConnectorService) getConnectorService(host);
return new ScpFileService(connectorService);
}
public IHostFileToRemoteFileAdapter getHostFileAdapter() {
if (_hostFileAdapter == null) {
_hostFileAdapter = new ScpFileAdapter();
}
return _hostFileAdapter;
}
public ILanguageUtilityFactory getLanguageUtilityFactory(
IRemoteFileSubSystem arg0) {
return null;
}
public IConnectorService getConnectorService(IHost host) {
return SshConnectorServiceManager.getInstance().getConnectorService(
host, getServiceImplType());
}
public Class<?> getServiceImplType() {
return ISshService.class;
}
public boolean supportsArchiveManagement() {
return false;
}
public boolean supportsFileTypes() {
return false;
}
public boolean supportsSearch() {
return false;
}
public ISearchService createSearchService(IHost arg0) {
// no search service supported for ssh/scp at moment
return null;
}
public IHostSearchResultConfiguration createSearchConfiguration(IHost arg0,
IHostSearchResultSet arg1, Object arg2, SystemSearchString arg3) {
return null;
}
}