mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-23 17:05:26 +02:00
Bug 507699 - Support for proxy agent
Change-Id: Ic09c458d5dbfd18f0826c1463253b4dc09283992 Signed-off-by: Greg Watson <g.watson@computer.org>
This commit is contained in:
parent
28b6d22079
commit
cf33718b51
137 changed files with 9267 additions and 3 deletions
|
@ -41,6 +41,13 @@ public interface IRemoteProcessBuilder {
|
|||
*/
|
||||
public static int FORWARD_X11 = 0x02;
|
||||
|
||||
/**
|
||||
* Flag to request that the supplied environment be apended to the remote environment; otherwise
|
||||
* it is replaced.
|
||||
* @since 3.0
|
||||
*/
|
||||
public static int APPEND_ENVIRONMENT = 0x03;
|
||||
|
||||
/**
|
||||
* Returns this process builder's operating system program and arguments.
|
||||
*
|
||||
|
|
7
bundles/org.eclipse.remote.proxy.core/.classpath
Normal file
7
bundles/org.eclipse.remote.proxy.core/.classpath
Normal 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/JavaSE-1.8"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
1
bundles/org.eclipse.remote.proxy.core/.gitignore
vendored
Normal file
1
bundles/org.eclipse.remote.proxy.core/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/bin
|
34
bundles/org.eclipse.remote.proxy.core/.project
Normal file
34
bundles/org.eclipse.remote.proxy.core/.project
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.eclipse.remote.proxy.core</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>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,11 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
28
bundles/org.eclipse.remote.proxy.core/META-INF/MANIFEST.MF
Normal file
28
bundles/org.eclipse.remote.proxy.core/META-INF/MANIFEST.MF
Normal file
|
@ -0,0 +1,28 @@
|
|||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: %pluginName
|
||||
Bundle-SymbolicName: org.eclipse.remote.proxy.core;singleton:=true
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Activator: org.eclipse.remote.internal.proxy.core.Activator
|
||||
Bundle-Vendor: %pluginProvider
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Export-Package: org.eclipse.remote.internal.proxy.core;x-friends:="org.eclipse.remote.proxy.ui",
|
||||
org.eclipse.remote.internal.proxy.core.commands;x-friends:="org.eclipse.remote.proxy.ui",
|
||||
org.eclipse.remote.internal.proxy.core.messages;x-friends:="org.eclipse.remote.proxy.ui"
|
||||
Bundle-Localization: plugin
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Import-Package:
|
||||
com.jcraft.jsch,
|
||||
org.eclipse.core.filesystem,
|
||||
org.eclipse.core.filesystem.provider,
|
||||
org.eclipse.core.runtime,
|
||||
org.eclipse.core.runtime.jobs,
|
||||
org.eclipse.jsch.core,
|
||||
org.eclipse.osgi.util,
|
||||
org.eclipse.remote.core,
|
||||
org.eclipse.remote.core.exception,
|
||||
org.eclipse.remote.internal.core,
|
||||
org.eclipse.remote.internal.jsch.core,
|
||||
org.eclipse.remote.proxy.protocol.core,
|
||||
org.eclipse.remote.proxy.protocol.core.exceptions,
|
||||
org.osgi.framework
|
22
bundles/org.eclipse.remote.proxy.core/about.html
Normal file
22
bundles/org.eclipse.remote.proxy.core/about.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>About</title>
|
||||
<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
|
||||
</head>
|
||||
<body lang="EN-US">
|
||||
<h2>About This Content</h2>
|
||||
|
||||
<p>May 2, 2006</p>
|
||||
<h3>License</h3>
|
||||
|
||||
<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
|
||||
Eclipse Public License Version 1.0 ("EPL"). 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, "Program" 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 ("Redistributor") 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.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
112
bundles/org.eclipse.remote.proxy.core/bootstrap.sh
Normal file
112
bundles/org.eclipse.remote.proxy.core/bootstrap.sh
Normal file
|
@ -0,0 +1,112 @@
|
|||
installdir="$HOME/.eclipsesettings"
|
||||
if test ! -d $installdir; then
|
||||
mkdir $installdir
|
||||
if test ! -d $installdir; then
|
||||
echo fail:cannot create $installdir
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
cat > $installdir/bootstrap.sh <<-\EOF
|
||||
#!/bin/sh
|
||||
installdir="$HOME/.eclipsesettings"
|
||||
proxytmp=$installdir/proxy.b64
|
||||
success=false
|
||||
|
||||
cleanup() {
|
||||
rm -f $installdir/bootstrap.sh
|
||||
}
|
||||
|
||||
trap 'cleanup' EXIT
|
||||
|
||||
parent_is_not_orphan () {
|
||||
parent=`ps -ef|awk '$2=='$$'{print $3}'`
|
||||
let parent=$parent+0
|
||||
if [[ $parent -eq 1 ]]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
do_check() {
|
||||
java_vers=`java -version 2>&1`
|
||||
vers=`expr "$java_vers" : "java version \"\([0-9]*\.[0-9]*\).*\""`
|
||||
if test "%$vers" != "%1.8"; then
|
||||
echo fail:invalid java version $vers
|
||||
fi
|
||||
case "`uname`" in
|
||||
Linux)
|
||||
osname="linux";
|
||||
osarch=`uname -m`;
|
||||
proxydir=$installdir/proxy;
|
||||
plugins=$proxydir/plugins;;
|
||||
Darwin)
|
||||
osname="macosx";
|
||||
osarch=`uname -m`;
|
||||
proxydir=$installdir/Proxy.app;
|
||||
plugins=$proxydir/Contents/Eclipse/plugins;;
|
||||
*)
|
||||
echo fail:system not supported;;
|
||||
esac
|
||||
proxy=no
|
||||
if test -d $proxydir; then
|
||||
bundle="org.eclipse.remote.proxy.server.core_$1.jar"
|
||||
if test -f $plugins/$bundle; then
|
||||
proxy=yes
|
||||
else
|
||||
mv $proxydir $proxydir.pre_$1
|
||||
fi
|
||||
fi
|
||||
echo ok:$proxy/$osname/$osarch
|
||||
}
|
||||
|
||||
do_download() {
|
||||
dd of=$proxytmp ibs=680 count=$1
|
||||
IFS= read -r last
|
||||
echo "$last" >> $proxytmp
|
||||
base64 --decode < $proxytmp | tar zxf - > /dev/null 2>&1
|
||||
if test $? -eq 0; then
|
||||
echo ok
|
||||
else
|
||||
echo fail:download failed
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Start java in background so we can clean up after connection is dropped. The only way to tell if this
|
||||
# has happened is to poll if ppid has changed to 1 (i.e. we no longer have a controlling terminal)
|
||||
#
|
||||
start_server() {
|
||||
#debugoptions="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=1044,quiet=y"
|
||||
|
||||
java -cp $plugins/org.eclipse.equinox.launcher_1.3.200.v20160318-1642.jar \
|
||||
$debugoptions \
|
||||
org.eclipse.equinox.launcher.Main \
|
||||
-application org.eclipse.remote.proxy.server.core.application \
|
||||
-noExit 0<&0 &
|
||||
|
||||
pid=$!
|
||||
|
||||
trap 'kill $pid; exit' HUP INT TERM
|
||||
|
||||
while parent_is_not_orphan; do
|
||||
sleep 10
|
||||
done
|
||||
|
||||
kill $pid
|
||||
}
|
||||
|
||||
echo running
|
||||
|
||||
while read line arg; do
|
||||
case $line in
|
||||
check) do_check $arg;;
|
||||
download) do_download $arg;;
|
||||
start) start_server;;
|
||||
exit) break;;
|
||||
*) echo fail:unrecognized command:$line; exit 1;;
|
||||
esac
|
||||
done
|
||||
exit 0
|
||||
EOF
|
||||
chmod 755 $installdir/bootstrap.sh
|
||||
exec $installdir/bootstrap.sh
|
10
bundles/org.eclipse.remote.proxy.core/build.properties
Normal file
10
bundles/org.eclipse.remote.proxy.core/build.properties
Normal file
|
@ -0,0 +1,10 @@
|
|||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
plugin.xml,\
|
||||
plugin.properties,\
|
||||
about.html,\
|
||||
bootstrap.sh
|
||||
|
||||
|
11
bundles/org.eclipse.remote.proxy.core/plugin.properties
Normal file
11
bundles/org.eclipse.remote.proxy.core/plugin.properties
Normal file
|
@ -0,0 +1,11 @@
|
|||
###############################################################################
|
||||
# Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
pluginName=Remote Proxy Support
|
||||
pluginProvider=Eclipse PTP
|
72
bundles/org.eclipse.remote.proxy.core/plugin.xml
Normal file
72
bundles/org.eclipse.remote.proxy.core/plugin.xml
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.2"?>
|
||||
<plugin>
|
||||
<extension
|
||||
point="org.eclipse.remote.core.remoteServices">
|
||||
<connectionType
|
||||
id="org.eclipse.remote.Proxy"
|
||||
name="PROXY"
|
||||
scheme="proxy">
|
||||
</connectionType>
|
||||
<connectionService
|
||||
connectionTypeId="org.eclipse.remote.Proxy"
|
||||
factory="org.eclipse.remote.internal.proxy.core.ProxyConnection$Factory"
|
||||
service="org.eclipse.remote.core.IRemoteConnectionControlService">
|
||||
</connectionService>
|
||||
<connectionService
|
||||
connectionTypeId="org.eclipse.remote.Proxy"
|
||||
factory="org.eclipse.remote.internal.proxy.core.ProxyConnection$Factory"
|
||||
service="org.eclipse.remote.core.IRemoteConnectionPropertyService">
|
||||
</connectionService>
|
||||
<connectionService
|
||||
connectionTypeId="org.eclipse.remote.Proxy"
|
||||
factory="org.eclipse.remote.internal.proxy.core.ProxyConnection$Factory"
|
||||
service="org.eclipse.remote.core.IRemoteProcessService">
|
||||
</connectionService>
|
||||
<connectionService
|
||||
connectionTypeId="org.eclipse.remote.Proxy"
|
||||
factory="org.eclipse.remote.internal.proxy.core.ProxyFileManager$Factory"
|
||||
service="org.eclipse.remote.core.IRemoteFileService">
|
||||
</connectionService>
|
||||
<connectionService
|
||||
connectionTypeId="org.eclipse.remote.Proxy"
|
||||
factory="org.eclipse.remote.internal.proxy.core.ProxyConnection$Factory"
|
||||
service="org.eclipse.remote.core.IRemoteConnectionHostService">
|
||||
</connectionService>
|
||||
<connectionService
|
||||
connectionTypeId="org.eclipse.remote.Proxy"
|
||||
factory="org.eclipse.remote.internal.proxy.core.ProxyConnection$Factory"
|
||||
service="org.eclipse.remote.internal.proxy.core.ProxyConnection">
|
||||
</connectionService>
|
||||
<connectionService
|
||||
connectionTypeId="org.eclipse.remote.Proxy"
|
||||
factory="org.eclipse.remote.internal.proxy.core.ProxyCommandShellService$Factory"
|
||||
service="org.eclipse.remote.core.IRemoteCommandShellService">
|
||||
</connectionService>
|
||||
<processService
|
||||
connectionTypeId="org.eclipse.remote.Proxy"
|
||||
factory="org.eclipse.remote.internal.proxy.core.ProxyProcess$Factory"
|
||||
service="org.eclipse.remote.core.IRemoteProcessControlService">
|
||||
</processService>
|
||||
<processService
|
||||
connectionTypeId="org.eclipse.remote.Proxy"
|
||||
factory="org.eclipse.remote.internal.proxy.core.ProxyProcess$Factory"
|
||||
service="org.eclipse.remote.core.IRemoteProcessSignalService">
|
||||
</processService>
|
||||
<processService
|
||||
connectionTypeId="org.eclipse.remote.Proxy"
|
||||
factory="org.eclipse.remote.internal.proxy.core.ProxyProcess$Factory"
|
||||
service="org.eclipse.remote.core.IRemoteProcessTerminalService">
|
||||
</processService>
|
||||
</extension>
|
||||
<extension
|
||||
id="org.eclipse.remote.proxy.filesystem"
|
||||
point="org.eclipse.core.filesystem.filesystems">
|
||||
<filesystem
|
||||
scheme="proxy">
|
||||
<run
|
||||
class="org.eclipse.remote.internal.proxy.core.ProxyFileSystem">
|
||||
</run>
|
||||
</filesystem>
|
||||
</extension>
|
||||
</plugin>
|
16
bundles/org.eclipse.remote.proxy.core/pom.xml
Normal file
16
bundles/org.eclipse.remote.proxy.core/pom.xml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.eclipse.remote</groupId>
|
||||
<artifactId>remote-parent</artifactId>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../releng/org.eclipse.remote.build/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.eclipse.remote.proxy.core</artifactId>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</project>
|
|
@ -0,0 +1,116 @@
|
|||
package org.eclipse.remote.internal.proxy.core;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Plugin;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
|
||||
/**
|
||||
* The activator class controls the plug-in life cycle
|
||||
*/
|
||||
public class Activator extends Plugin {
|
||||
|
||||
// The plug-in ID
|
||||
public static final String PLUGIN_ID = "org.eclipse.remote.proxy.core"; //$NON-NLS-1$
|
||||
|
||||
// The shared instance
|
||||
private static Activator plugin;
|
||||
|
||||
/**
|
||||
* Returns the shared instance
|
||||
*
|
||||
* @return the shared instance
|
||||
*/
|
||||
public static Activator getDefault() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unique identifier
|
||||
*
|
||||
* @return
|
||||
* @since 5.0
|
||||
*/
|
||||
public static String getUniqueIdentifier() {
|
||||
if (getDefault() == null) {
|
||||
return PLUGIN_ID;
|
||||
}
|
||||
return getDefault().getBundle().getSymbolicName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the specified status with this plug-in's log.
|
||||
*
|
||||
* @param status
|
||||
* status to log
|
||||
*/
|
||||
public static void log(IStatus status) {
|
||||
getDefault().getLog().log(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an internal error with the specified message.
|
||||
*
|
||||
* @param message
|
||||
* the error message to log
|
||||
*/
|
||||
public static void log(String message) {
|
||||
log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, message, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an internal error with the specified throwable
|
||||
*
|
||||
* @param e
|
||||
* the exception to be logged
|
||||
*/
|
||||
public static void log(Throwable e) {
|
||||
log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, e.getMessage(), e));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The constructor
|
||||
*/
|
||||
public Activator() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the OSGi service with the given service interface.
|
||||
*
|
||||
* @param service service interface
|
||||
* @return the specified service or null if it's not registered
|
||||
*/
|
||||
public static <T> T getService(Class<T> service) {
|
||||
BundleContext context = plugin.getBundle().getBundleContext();
|
||||
ServiceReference<T> ref = context.getServiceReference(service);
|
||||
return ref != null ? context.getService(ref) : null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext
|
||||
* )
|
||||
*/
|
||||
@Override
|
||||
public void start(BundleContext context) throws Exception {
|
||||
super.start(context);
|
||||
plugin = this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
|
||||
* )
|
||||
*/
|
||||
@Override
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
plugin = null;
|
||||
super.stop(context);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2015 QNX Software Systems 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:
|
||||
* QNX Software Systems - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.remote.core.IRemoteCommandShellService;
|
||||
import org.eclipse.remote.core.IRemoteConnection;
|
||||
import org.eclipse.remote.core.IRemoteProcess;
|
||||
|
||||
public class ProxyCommandShellService implements IRemoteCommandShellService {
|
||||
private IRemoteConnection fRemoteConnection;
|
||||
|
||||
public ProxyCommandShellService(IRemoteConnection remoteConnection) {
|
||||
fRemoteConnection = remoteConnection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRemoteConnection getRemoteConnection() {
|
||||
return fRemoteConnection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRemoteProcess getCommandShell(int flags) throws IOException {
|
||||
return null;
|
||||
// return new JSchProcessBuilder(getRemoteConnection()).start(flags);
|
||||
}
|
||||
|
||||
public static class Factory implements IRemoteConnection.Service.Factory {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.remote.core.IRemoteConnection.Service.Factory#getService(org.eclipse.remote.core.IRemoteConnection,
|
||||
* java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends IRemoteConnection.Service> T getService(IRemoteConnection connection, Class<T> service) {
|
||||
if (IRemoteCommandShellService.class.equals(service)) {
|
||||
return (T) new ProxyCommandShellService(connection);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,458 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.SubMonitor;
|
||||
import org.eclipse.remote.core.IRemoteCommandShellService;
|
||||
import org.eclipse.remote.core.IRemoteConnection;
|
||||
import org.eclipse.remote.core.IRemoteConnectionChangeListener;
|
||||
import org.eclipse.remote.core.IRemoteConnectionControlService;
|
||||
import org.eclipse.remote.core.IRemoteConnectionHostService;
|
||||
import org.eclipse.remote.core.IRemoteConnectionPropertyService;
|
||||
import org.eclipse.remote.core.IRemoteConnectionWorkingCopy;
|
||||
import org.eclipse.remote.core.IRemoteProcess;
|
||||
import org.eclipse.remote.core.IRemoteProcessBuilder;
|
||||
import org.eclipse.remote.core.IRemoteProcessService;
|
||||
import org.eclipse.remote.core.RemoteConnectionChangeEvent;
|
||||
import org.eclipse.remote.core.RemoteServicesUtils;
|
||||
import org.eclipse.remote.core.exception.RemoteConnectionException;
|
||||
import org.eclipse.remote.internal.proxy.core.commands.ExecCommand;
|
||||
import org.eclipse.remote.internal.proxy.core.commands.GetCwdCommand;
|
||||
import org.eclipse.remote.internal.proxy.core.commands.GetEnvCommand;
|
||||
import org.eclipse.remote.internal.proxy.core.commands.GetPropertiesCommand;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannelManager;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
import com.jcraft.jsch.ChannelShell;
|
||||
|
||||
/**
|
||||
* @since 5.0
|
||||
*/
|
||||
public class ProxyConnection implements IRemoteConnectionControlService,
|
||||
IRemoteConnectionChangeListener, IRemoteProcessService,
|
||||
IRemoteCommandShellService, IRemoteConnectionHostService {
|
||||
// Connection Type ID
|
||||
public static final String JSCH_ID = "org.eclipse.remote.Proxy"; //$NON-NLS-1$
|
||||
|
||||
public static final int DEFAULT_PORT = 22;
|
||||
public static final int DEFAULT_TIMEOUT = 0;
|
||||
public static final boolean DEFAULT_USE_PASSWORD = false;
|
||||
public static final boolean DEFAULT_USE_DEFAULT_SERVER = true;
|
||||
public static final String DEFAULT_SERVER_COMMAND = "sh .eclipsesettings/proxy.sh"; //$NON-NLS-1$
|
||||
|
||||
public static final String HOSTNAME_ATTR = "PROXY_HOSTNAME__ATTR"; //$NON-NLS-1$
|
||||
public static final String USERNAME_ATTR = "PROXY_USERNAME_ATTR"; //$NON-NLS-1$
|
||||
public static final String PASSWORD_ATTR = "PROXY_PASSWORD_ATTR"; //$NON-NLS-1$
|
||||
public static final String PORT_ATTR = "PROXY_PORT_ATTR"; //$NON-NLS-1$
|
||||
public static final String USE_PASSWORD_ATTR = "PROXY_USE_PASSWORD_ATTR"; //$NON-NLS-1$
|
||||
public static final String PASSPHRASE_ATTR = "PROXY_PASSPHRASE_ATTR"; //$NON-NLS-1$
|
||||
public static final String TIMEOUT_ATTR = "PROXY_TIMEOUT_ATTR"; //$NON-NLS-1$
|
||||
public static final String SERVER_COMMAND_ATTR = "PROXY_SERVER_COMMAND_ATTR"; //$NON-NLS-1$
|
||||
public static final String USE_DEFAULT_SERVER_ATTR = "PROXY_USE_DEFAULT_SERVER_ATTR"; //$NON-NLS-1$
|
||||
|
||||
private String fWorkingDir;
|
||||
private StreamChannelManager channelMux;
|
||||
private StreamChannel commandChannel;
|
||||
private boolean isOpen;
|
||||
private boolean proxyRunning;
|
||||
|
||||
private final IRemoteConnection fRemoteConnection;
|
||||
|
||||
private final Map<String, String> fEnv = new HashMap<>();
|
||||
private final Map<String, String> fProperties = new HashMap<>();
|
||||
|
||||
private static final Map<IRemoteConnection, ProxyConnection> connectionMap = new HashMap<>();
|
||||
|
||||
public ProxyConnection(IRemoteConnection connection) {
|
||||
fRemoteConnection = connection;
|
||||
connection.addConnectionChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectionChanged(RemoteConnectionChangeEvent event) {
|
||||
if (event.getType() == RemoteConnectionChangeEvent.CONNECTION_REMOVED) {
|
||||
synchronized (connectionMap) {
|
||||
connectionMap.remove(event.getConnection());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.remote.core.IRemoteConnection.Service#getRemoteConnection()
|
||||
*/
|
||||
@Override
|
||||
public IRemoteConnection getRemoteConnection() {
|
||||
return fRemoteConnection;
|
||||
}
|
||||
|
||||
public static class Factory implements IRemoteConnection.Service.Factory {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.remote.core.IRemoteConnection.Service.Factory#getService(org.eclipse.remote.core.IRemoteConnection,
|
||||
* java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends IRemoteConnection.Service> T getService(IRemoteConnection connection, Class<T> service) {
|
||||
// This little trick creates an instance of this class for a connection
|
||||
// then for each interface it implements, it returns the same object.
|
||||
// This works because the connection caches the service so only one gets created.
|
||||
// As a side effect, it makes this class a service too which can be used
|
||||
// by the this plug-in
|
||||
if (ProxyConnection.class.equals(service)) {
|
||||
synchronized (connectionMap) {
|
||||
ProxyConnection conn = connectionMap.get(connection);
|
||||
if (conn == null) {
|
||||
conn = new ProxyConnection(connection);
|
||||
connectionMap.put(connection, conn);
|
||||
}
|
||||
return (T) conn;
|
||||
}
|
||||
} else if (IRemoteConnectionControlService.class.equals(service)
|
||||
|| IRemoteConnectionPropertyService.class.equals(service)
|
||||
|| IRemoteConnectionHostService.class.equals(service)
|
||||
|| IRemoteProcessService.class.equals(service)
|
||||
|| IRemoteCommandShellService.class.equals(service)) {
|
||||
return (T) connection.getService(ProxyConnection.class);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.remote.core.IRemoteConnectionControlService#close()
|
||||
*/
|
||||
@Override
|
||||
public synchronized void close() {
|
||||
if (isOpen) {
|
||||
channelMux.shutdown();
|
||||
isOpen = false;
|
||||
fRemoteConnection.fireConnectionChangeEvent(RemoteConnectionChangeEvent.CONNECTION_CLOSED);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.remote.core.IRemoteConnectionControlService#isOpen()
|
||||
*/
|
||||
@Override
|
||||
public boolean isOpen() {
|
||||
return isOpen;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.remote.core.IRemoteConnectionControlService#open(org.eclipse.core.runtime.IProgressMonitor)
|
||||
*/
|
||||
@Override
|
||||
public void open(IProgressMonitor monitor) throws RemoteConnectionException {
|
||||
SubMonitor subMon = SubMonitor.convert(monitor, "Opening connection...", 20);
|
||||
if (!isOpen) {
|
||||
ProxyConnectionBootstrap bootstrap = new ProxyConnectionBootstrap();
|
||||
channelMux = bootstrap.run(getRemoteConnection(), subMon.newChild(10));
|
||||
new Thread(channelMux, "multiplexer").start();
|
||||
try {
|
||||
commandChannel = channelMux.openChannel();
|
||||
initialize(subMon.newChild(10));
|
||||
} catch (RemoteConnectionException | IOException e) {
|
||||
try {
|
||||
commandChannel.close();
|
||||
} catch (IOException e1) {
|
||||
// Ignore
|
||||
}
|
||||
channelMux.shutdown();
|
||||
throw new RemoteConnectionException(e.getMessage());
|
||||
}
|
||||
|
||||
isOpen = true;
|
||||
fRemoteConnection.fireConnectionChangeEvent(RemoteConnectionChangeEvent.CONNECTION_OPENED);
|
||||
}
|
||||
}
|
||||
|
||||
private void initialize(IProgressMonitor monitor) throws RemoteConnectionException {
|
||||
SubMonitor subMon = SubMonitor.convert(monitor, 30);
|
||||
fWorkingDir = getCwd(subMon.newChild(10));
|
||||
if (subMon.isCanceled()) {
|
||||
throw new RemoteConnectionException("User canceled opening connection");
|
||||
}
|
||||
fEnv.putAll(loadEnv(subMon.newChild(10)));
|
||||
if (subMon.isCanceled()) {
|
||||
throw new RemoteConnectionException("User canceled opening connection");
|
||||
}
|
||||
fProperties.putAll(loadProperties(subMon.newChild(10)));
|
||||
if (subMon.isCanceled()) {
|
||||
throw new RemoteConnectionException("User canceled opening connection");
|
||||
}
|
||||
}
|
||||
|
||||
private String getCwd(IProgressMonitor monitor) throws RemoteConnectionException {
|
||||
try {
|
||||
GetCwdCommand cmd = new GetCwdCommand(this);
|
||||
return cmd.getResult(monitor);
|
||||
} catch (ProxyException e) {
|
||||
throw new RemoteConnectionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> loadEnv(IProgressMonitor monitor) throws RemoteConnectionException {
|
||||
try {
|
||||
GetEnvCommand cmd = new GetEnvCommand(this);
|
||||
return cmd.getResult(monitor);
|
||||
} catch (ProxyException e) {
|
||||
throw new RemoteConnectionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> loadProperties(IProgressMonitor monitor) throws RemoteConnectionException {
|
||||
try {
|
||||
GetPropertiesCommand cmd = new GetPropertiesCommand(this);
|
||||
return cmd.getResult(monitor);
|
||||
} catch (ProxyException e) {
|
||||
throw new RemoteConnectionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, String> getEnv() {
|
||||
return Collections.unmodifiableMap(fEnv);
|
||||
}
|
||||
|
||||
public StreamChannel getCommandChannel() {
|
||||
return commandChannel;
|
||||
}
|
||||
|
||||
public StreamChannel openChannel() throws IOException {
|
||||
return channelMux.openChannel();
|
||||
}
|
||||
|
||||
private StringBuffer stdout = new StringBuffer();
|
||||
private StringBuffer stderr = new StringBuffer();
|
||||
|
||||
private String executeSshCommand(ChannelShell shell, String command) throws RemoteConnectionException {
|
||||
try {
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
ByteArrayOutputStream err = new ByteArrayOutputStream();
|
||||
shell.setOutputStream(stream);
|
||||
shell.setExtOutputStream(err);
|
||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(shell.getOutputStream()));
|
||||
writer.write(command);
|
||||
writer.flush();
|
||||
if (err.size() > 0) {
|
||||
throw new RemoteConnectionException(err.toString());
|
||||
}
|
||||
return stream.toString();
|
||||
} catch (IOException e) {
|
||||
throw new RemoteConnectionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private String executeCommand(List<String> command, IProgressMonitor monitor) throws ProxyException {
|
||||
try {
|
||||
final StreamChannel chanA = channelMux.openChannel();
|
||||
final StreamChannel chanB = channelMux.openChannel();
|
||||
final StreamChannel chanC = channelMux.openChannel();
|
||||
new Thread("cmd stdin reader") {
|
||||
@Override
|
||||
public void run() {
|
||||
byte[] buf = new byte[1024];
|
||||
int n;
|
||||
try {
|
||||
while ((n = chanA.getInputStream().read(buf)) >= 0) {
|
||||
stdout.append(new String(buf, 0, n));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Finish
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
new Thread("cmd stderr reader") {
|
||||
@Override
|
||||
public void run() {
|
||||
byte[] buf = new byte[1024];
|
||||
int n;
|
||||
try {
|
||||
while ((n = chanB.getInputStream().read(buf)) >= 0) {
|
||||
stderr.append(new String(buf, 0, n));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Finish
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
ExecCommand cmd = new ExecCommand(this, command, getEnv(), getWorkingDirectory(), false, false, chanA.getId(), chanB.getId(), chanC.getId());
|
||||
cmd.getResult(monitor);
|
||||
DataInputStream status = new DataInputStream(chanC.getInputStream());
|
||||
int stat = status.readInt();
|
||||
if (stat == 0) {
|
||||
return stdout.toString();
|
||||
}
|
||||
return stderr.toString();
|
||||
} catch (IOException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEnv(String name) {
|
||||
return getEnv().get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRemoteProcessBuilder getProcessBuilder(List<String> command) {
|
||||
return new ProxyProcessBuilder(this, command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRemoteProcessBuilder getProcessBuilder(String... command) {
|
||||
return new ProxyProcessBuilder(this, command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorkingDirectory() {
|
||||
return fWorkingDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWorkingDirectory(String path) {
|
||||
if (RemoteServicesUtils.posixPath(path).isAbsolute()) {
|
||||
fWorkingDir = path;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRemoteProcess getCommandShell(int flags) throws IOException {
|
||||
if (!proxyRunning) {
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHostname() {
|
||||
return fRemoteConnection.getAttribute(HOSTNAME_ATTR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPort() {
|
||||
String portStr = fRemoteConnection.getAttribute(PORT_ATTR);
|
||||
return !portStr.isEmpty() ? Integer.parseInt(portStr) : DEFAULT_PORT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimeout() {
|
||||
String portStr = fRemoteConnection.getAttribute(TIMEOUT_ATTR);
|
||||
return !portStr.isEmpty() ? Integer.parseInt(portStr) : DEFAULT_TIMEOUT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassphrase() {
|
||||
return fRemoteConnection.getSecureAttribute(PASSPHRASE_ATTR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return fRemoteConnection.getSecureAttribute(PASSWORD_ATTR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean usePassword() {
|
||||
String str = fRemoteConnection.getAttribute(USE_PASSWORD_ATTR);
|
||||
return !str.isEmpty() ? Boolean.parseBoolean(str) : DEFAULT_USE_PASSWORD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return fRemoteConnection.getAttribute(USERNAME_ATTR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useLoginShell() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHostname(String hostname) {
|
||||
if (fRemoteConnection instanceof IRemoteConnectionWorkingCopy) {
|
||||
IRemoteConnectionWorkingCopy wc = (IRemoteConnectionWorkingCopy) fRemoteConnection;
|
||||
wc.setAttribute(HOSTNAME_ATTR, hostname);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPassphrase(String passphrase) {
|
||||
if (fRemoteConnection instanceof IRemoteConnectionWorkingCopy) {
|
||||
IRemoteConnectionWorkingCopy wc = (IRemoteConnectionWorkingCopy) fRemoteConnection;
|
||||
wc.setSecureAttribute(PASSPHRASE_ATTR, passphrase);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPassword(String password) {
|
||||
if (fRemoteConnection instanceof IRemoteConnectionWorkingCopy) {
|
||||
IRemoteConnectionWorkingCopy wc = (IRemoteConnectionWorkingCopy) fRemoteConnection;
|
||||
wc.setSecureAttribute(PASSWORD_ATTR, password);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPort(int port) {
|
||||
if (fRemoteConnection instanceof IRemoteConnectionWorkingCopy) {
|
||||
IRemoteConnectionWorkingCopy wc = (IRemoteConnectionWorkingCopy) fRemoteConnection;
|
||||
wc.setAttribute(PORT_ATTR, Integer.toString(port));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTimeout(int timeout) {
|
||||
if (fRemoteConnection instanceof IRemoteConnectionWorkingCopy) {
|
||||
IRemoteConnectionWorkingCopy wc = (IRemoteConnectionWorkingCopy) fRemoteConnection;
|
||||
wc.setAttribute(TIMEOUT_ATTR, Integer.toString(timeout));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUseLoginShell(boolean useLogingShell) {
|
||||
// Not used
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUsePassword(boolean usePassword) {
|
||||
if (fRemoteConnection instanceof IRemoteConnectionWorkingCopy) {
|
||||
IRemoteConnectionWorkingCopy wc = (IRemoteConnectionWorkingCopy) fRemoteConnection;
|
||||
wc.setAttribute(USE_PASSWORD_ATTR, Boolean.toString(usePassword));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUsername(String username) {
|
||||
if (fRemoteConnection instanceof IRemoteConnectionWorkingCopy) {
|
||||
IRemoteConnectionWorkingCopy wc = (IRemoteConnectionWorkingCopy) fRemoteConnection;
|
||||
wc.setAttribute(USERNAME_ATTR, username);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,308 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.FileLocator;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.SubMonitor;
|
||||
import org.eclipse.jsch.core.IJSchService;
|
||||
import org.eclipse.remote.core.IRemoteConnection;
|
||||
import org.eclipse.remote.core.IRemoteConnectionHostService;
|
||||
import org.eclipse.remote.core.IRemoteConnectionWorkingCopy;
|
||||
import org.eclipse.remote.core.IUserAuthenticatorService;
|
||||
import org.eclipse.remote.core.exception.RemoteConnectionException;
|
||||
import org.eclipse.remote.internal.jsch.core.JSchUserInfo;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannelManager;
|
||||
import org.osgi.framework.Bundle;
|
||||
|
||||
import com.jcraft.jsch.Channel;
|
||||
import com.jcraft.jsch.ChannelExec;
|
||||
import com.jcraft.jsch.JSchException;
|
||||
import com.jcraft.jsch.Session;
|
||||
|
||||
public class ProxyConnectionBootstrap {
|
||||
private final IJSchService jSchService;
|
||||
private Session session;
|
||||
private ChannelExec exec;
|
||||
|
||||
private class Context {
|
||||
private State state;
|
||||
private String osName;
|
||||
private String osArch;
|
||||
|
||||
private final SubMonitor monitor;
|
||||
private final BufferedReader reader;
|
||||
private final BufferedWriter writer;
|
||||
|
||||
public Context(BufferedReader reader, BufferedWriter writer, IProgressMonitor monitor) {
|
||||
this.reader = reader;
|
||||
this.writer = writer;
|
||||
this.monitor = SubMonitor.convert(monitor);
|
||||
setState(States.INIT);
|
||||
}
|
||||
|
||||
State getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
SubMonitor getMonitor() {
|
||||
return monitor;
|
||||
}
|
||||
|
||||
void setState(State state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
String getOSName() {
|
||||
return osName;
|
||||
}
|
||||
|
||||
void setOSName(String osName) {
|
||||
this.osName = osName;
|
||||
}
|
||||
|
||||
String getOSArch() {
|
||||
return osArch;
|
||||
}
|
||||
|
||||
void setOSArch(String osArch) {
|
||||
this.osArch = osArch;
|
||||
}
|
||||
}
|
||||
|
||||
private interface State {
|
||||
/**
|
||||
* @return true to keep processing, false to read more data.
|
||||
*/
|
||||
boolean process(Context context) throws IOException;
|
||||
}
|
||||
|
||||
private enum States implements State {
|
||||
INIT {
|
||||
@Override
|
||||
public boolean process(Context context) throws IOException {
|
||||
context.getMonitor().subTask("Initializing");
|
||||
String line = context.reader.readLine();
|
||||
context.getMonitor().worked(1);
|
||||
if (line.equals("running")) {
|
||||
context.setState(States.CHECK);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
CHECK {
|
||||
@Override
|
||||
public boolean process(Context context) throws IOException {
|
||||
context.getMonitor().subTask("Validating environment");
|
||||
String bundleName = "org.eclipse.remote.proxy.server.core";
|
||||
Bundle serverBundle = Platform.getBundle(bundleName);
|
||||
if (serverBundle == null) {
|
||||
throw new IOException("Unable to locate server bundle " + bundleName);
|
||||
}
|
||||
context.writer.write("check " + serverBundle.getVersion() + "\n");
|
||||
context.writer.flush();
|
||||
String line = context.reader.readLine();
|
||||
while (line != null) {
|
||||
context.getMonitor().worked(2);
|
||||
String[] parts = line.split(":");
|
||||
switch (parts[0]) {
|
||||
case "ok":
|
||||
String[] status = parts[1].split("/");
|
||||
context.setOSName(status[1]);
|
||||
context.setOSArch(status[2]);
|
||||
context.setState(status[0].equals("proxy") ? States.START : States.DOWNLOAD);
|
||||
return true;
|
||||
case "fail":
|
||||
System.out.println("fail:"+parts[1]);
|
||||
return false;
|
||||
case "debug":
|
||||
System.err.println(line);
|
||||
break;
|
||||
default:
|
||||
System.err.println("Invalid response from bootstrap script: " + line);
|
||||
return false;
|
||||
}
|
||||
line = context.reader.readLine();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
DOWNLOAD {
|
||||
@Override
|
||||
public boolean process(Context context) throws IOException {
|
||||
context.getMonitor().subTask("Updating server proxy");
|
||||
String bundleName = "org.eclipse.remote.proxy.server." + context.getOSName() + "." + context.getOSArch();
|
||||
Bundle serverBundle = Platform.getBundle(bundleName);
|
||||
if (serverBundle == null) {
|
||||
throw new IOException("Unable to locate server bundle " + bundleName);
|
||||
}
|
||||
URL fileURL = FileLocator.find(serverBundle, new Path("proxy.server.tar.gz"), null);
|
||||
if (fileURL == null) {
|
||||
return false;
|
||||
}
|
||||
File file = new File(FileLocator.toFileURL(fileURL).getFile());
|
||||
long count = file.length() / 510;
|
||||
context.writer.write("download " + count + "\n");
|
||||
context.writer.flush();
|
||||
context.getMonitor().worked(2);
|
||||
if (downloadFile(file, context.writer, context.getMonitor().newChild(5))) {
|
||||
String line = context.reader.readLine();
|
||||
while (line != null) {
|
||||
String[] parts = line.split(":");
|
||||
switch (parts[0]) {
|
||||
case "ok":
|
||||
context.setState(States.START);
|
||||
return true;
|
||||
case "fail":
|
||||
System.out.println("fail:"+parts[1]);
|
||||
return false;
|
||||
case "debug":
|
||||
System.err.println(line);
|
||||
break;
|
||||
default:
|
||||
System.err.println("Invalid response from bootstrap script: " + line);
|
||||
return false;
|
||||
}
|
||||
line = context.reader.readLine();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean downloadFile(File file, BufferedWriter writer, IProgressMonitor monitor) {
|
||||
SubMonitor subMon = SubMonitor.convert(monitor, 10);
|
||||
try {
|
||||
Base64.Encoder encoder = Base64.getEncoder();
|
||||
FileInputStream in = new FileInputStream(file);
|
||||
byte[] buf = new byte[510]; // Multiple of 3
|
||||
int n;
|
||||
while ((n = in.read(buf)) >= 0) {
|
||||
if (n < 510) {
|
||||
writer.write(encoder.encodeToString(Arrays.copyOf(buf, n)) + "\n");
|
||||
} else {
|
||||
writer.write(encoder.encodeToString(buf));
|
||||
}
|
||||
subMon.setWorkRemaining(8);
|
||||
}
|
||||
writer.flush();
|
||||
in.close();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
START {
|
||||
@Override
|
||||
public boolean process(Context context) throws IOException {
|
||||
context.getMonitor().subTask("Starting server");
|
||||
context.writer.write("start\n");
|
||||
context.writer.flush();
|
||||
return false; // Finished
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ProxyConnectionBootstrap() {
|
||||
jSchService = Activator.getService(IJSchService.class);
|
||||
}
|
||||
|
||||
public StreamChannelManager run(IRemoteConnection connection, IProgressMonitor monitor) throws RemoteConnectionException {
|
||||
SubMonitor subMon = SubMonitor.convert(monitor, 20);
|
||||
try {
|
||||
final Channel chan = openChannel(connection, subMon.newChild(10));
|
||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(chan.getOutputStream()));
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(chan.getInputStream()));
|
||||
subMon.beginTask("Checking server installation", 10);
|
||||
subMon.subTask("Loading bootstrap shell");
|
||||
URL fileURL = FileLocator.find(Activator.getDefault().getBundle(), new Path("bootstrap.sh"), null);
|
||||
if (fileURL == null) {
|
||||
throw new RemoteConnectionException("Unable to locate bootstrap shell");
|
||||
}
|
||||
File file = new File(FileLocator.toFileURL(fileURL).getFile());
|
||||
BufferedReader scriptReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
|
||||
String line;
|
||||
while ((line = scriptReader.readLine()) != null) {
|
||||
writer.write(line + "\n");
|
||||
}
|
||||
scriptReader.close();
|
||||
writer.flush();
|
||||
subMon.worked(2);
|
||||
Context context = new Context(reader, writer, subMon.newChild(8));
|
||||
while (context.getState().process(context)) {
|
||||
// do state machine
|
||||
}
|
||||
if (context.getState() != States.START) {
|
||||
context.writer.write("exit\n");
|
||||
context.writer.flush();
|
||||
throw new RemoteConnectionException("Unable to start server");
|
||||
}
|
||||
new Thread("server error stream") {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(chan.getExtInputStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.err.println("server: "+ line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Ignore and terminate thread
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
return new StreamChannelManager(chan.getInputStream(), chan.getOutputStream());
|
||||
} catch (IOException | CoreException e) {
|
||||
throw new RemoteConnectionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Channel openChannel(IRemoteConnection connection, IProgressMonitor monitor) throws RemoteConnectionException {
|
||||
IRemoteConnectionWorkingCopy wc = connection.getWorkingCopy();
|
||||
IRemoteConnectionHostService hostService = wc.getService(IRemoteConnectionHostService.class);
|
||||
IUserAuthenticatorService authService = wc.getService(IUserAuthenticatorService.class);
|
||||
try {
|
||||
session = jSchService.createSession(hostService.getHostname(), hostService.getPort(), hostService.getUsername());
|
||||
session.setUserInfo(new JSchUserInfo(hostService, authService));
|
||||
if (hostService.usePassword()) {
|
||||
session.setConfig("PreferredAuthentications", "password,keyboard-interactive,gssapi-with-mic,publickey"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
} else {
|
||||
session.setConfig("PreferredAuthentications", "publickey,gssapi-with-mic,password,keyboard-interactive"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
String password = hostService.getPassword();
|
||||
if (!password.isEmpty()) {
|
||||
session.setPassword(password);
|
||||
}
|
||||
jSchService.connect(session, hostService.getTimeout() * 1000, monitor);
|
||||
if (monitor.isCanceled()) {
|
||||
throw new RemoteConnectionException("User canceled connection open");
|
||||
}
|
||||
exec = (ChannelExec) session.openChannel("exec"); //$NON-NLS-1$
|
||||
exec.setCommand("/bin/sh -l");
|
||||
exec.connect();
|
||||
return exec;
|
||||
} catch (JSchException e) {
|
||||
throw new RemoteConnectionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core;
|
||||
|
||||
import org.eclipse.remote.core.IRemoteConnectionProviderService;
|
||||
import org.eclipse.remote.core.IRemoteConnectionType;
|
||||
import org.eclipse.remote.core.IRemoteConnectionType.Service;
|
||||
|
||||
public class ProxyConnectionProviderService implements IRemoteConnectionProviderService {
|
||||
|
||||
private IRemoteConnectionType connectionType;
|
||||
|
||||
public static class Factory implements IRemoteConnectionType.Service.Factory {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T extends Service> T getService(IRemoteConnectionType connectionType, Class<T> service) {
|
||||
if (service.equals(IRemoteConnectionProviderService.class)) {
|
||||
return (T) new ProxyConnectionProviderService(connectionType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ProxyConnectionProviderService(IRemoteConnectionType connectionType) {
|
||||
this.connectionType = connectionType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRemoteConnectionType getConnectionType() {
|
||||
return connectionType;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.eclipse.core.filesystem.IFileStore;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.remote.core.IRemoteConnection;
|
||||
import org.eclipse.remote.core.IRemoteConnection.Service;
|
||||
import org.eclipse.remote.core.IRemoteFileService;
|
||||
import org.eclipse.remote.core.IRemoteProcessService;
|
||||
import org.eclipse.remote.core.RemoteServicesUtils;
|
||||
|
||||
public class ProxyFileManager implements IRemoteFileService {
|
||||
private final IRemoteConnection fConnection;
|
||||
|
||||
private ProxyFileManager(IRemoteConnection connection) {
|
||||
fConnection = connection;
|
||||
}
|
||||
|
||||
public static class Factory implements IRemoteFileService.Factory {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T extends Service> T getService(IRemoteConnection remoteConnection, Class<T> service) {
|
||||
if (IRemoteFileService.class.equals(service)) {
|
||||
return (T) new ProxyFileManager(remoteConnection);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRemoteConnection getRemoteConnection() {
|
||||
return fConnection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDirectorySeparator() {
|
||||
return "/"; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFileStore getResource(String pathStr) {
|
||||
IPath path = RemoteServicesUtils.posixPath(pathStr);
|
||||
if (!path.isAbsolute()) {
|
||||
path = RemoteServicesUtils.posixPath(getBaseDirectory()).append(path);
|
||||
}
|
||||
return ProxyFileStore.getInstance(ProxyFileSystem.getURIFor(fConnection.getName(), path.toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBaseDirectory() {
|
||||
return fConnection.getService(IRemoteProcessService.class).getWorkingDirectory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBaseDirectory(String path) {
|
||||
fConnection.getService(IRemoteProcessService.class).setWorkingDirectory(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toPath(URI uri) {
|
||||
return uri.getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI toURI(IPath path) {
|
||||
try {
|
||||
return ProxyFileSystem.getURIFor(fConnection.getName(), path.toString());
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI toURI(String path) {
|
||||
return toURI(RemoteServicesUtils.posixPath(path));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,355 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.core.filesystem.EFS;
|
||||
import org.eclipse.core.filesystem.IFileInfo;
|
||||
import org.eclipse.core.filesystem.IFileStore;
|
||||
import org.eclipse.core.filesystem.provider.FileStore;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.SubMonitor;
|
||||
import org.eclipse.osgi.util.NLS;
|
||||
import org.eclipse.remote.core.IRemoteConnection;
|
||||
import org.eclipse.remote.core.IRemoteConnectionType;
|
||||
import org.eclipse.remote.core.IRemoteServicesManager;
|
||||
import org.eclipse.remote.core.RemoteServicesUtils;
|
||||
import org.eclipse.remote.core.exception.RemoteConnectionException;
|
||||
import org.eclipse.remote.internal.proxy.core.commands.ChildInfosCommand;
|
||||
import org.eclipse.remote.internal.proxy.core.commands.DeleteCommand;
|
||||
import org.eclipse.remote.internal.proxy.core.commands.FetchInfoCommand;
|
||||
import org.eclipse.remote.internal.proxy.core.commands.GetInputStreamCommand;
|
||||
import org.eclipse.remote.internal.proxy.core.commands.GetOutputStreamCommand;
|
||||
import org.eclipse.remote.internal.proxy.core.commands.MkdirCommand;
|
||||
import org.eclipse.remote.internal.proxy.core.commands.PutInfoCommand;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class ProxyFileStore extends FileStore {
|
||||
/**
|
||||
* Public factory method for obtaining ProxyFileStore instances.
|
||||
*
|
||||
* @param uri
|
||||
* URI to get a fileStore for
|
||||
* @return an ProxyFileStore instance for the URI.
|
||||
*/
|
||||
public static ProxyFileStore getInstance(URI uri) {
|
||||
synchronized (instanceMap) {
|
||||
ProxyFileStore store = instanceMap.get(uri.toString());
|
||||
if (store == null) {
|
||||
store = new ProxyFileStore(uri);
|
||||
instanceMap.put(uri.toString(), store);
|
||||
}
|
||||
return store;
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, ProxyFileStore> instanceMap = new HashMap<String, ProxyFileStore>();
|
||||
|
||||
private final IPath fRemotePath;
|
||||
private final URI fURI;
|
||||
|
||||
private ProxyFileStore(URI uri) {
|
||||
fURI = uri;
|
||||
fRemotePath = RemoteServicesUtils.posixPath(uri.getPath());
|
||||
}
|
||||
|
||||
private ProxyConnection checkConnection(IProgressMonitor monitor) throws RemoteConnectionException {
|
||||
IRemoteServicesManager manager = Activator.getService(IRemoteServicesManager.class);
|
||||
IRemoteConnectionType connectionType = manager.getConnectionType(fURI);
|
||||
if (connectionType == null) {
|
||||
throw new RemoteConnectionException(NLS.bind("No remote services found for URI {0}", fURI));
|
||||
}
|
||||
|
||||
try {
|
||||
IRemoteConnection connection = connectionType.getConnection(fURI);
|
||||
if (connection == null) {
|
||||
throw new RemoteConnectionException(NLS.bind("Invalid connection for URI {0}", fURI));
|
||||
}
|
||||
if (!connection.isOpen()) {
|
||||
connection.open(monitor);
|
||||
if (!connection.isOpen()) {
|
||||
throw new RemoteConnectionException("Connection is not open");
|
||||
}
|
||||
}
|
||||
return connection.getService(ProxyConnection.class);
|
||||
} catch (CoreException e) {
|
||||
throw new RemoteConnectionException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.filesystem.provider.FileStore#childInfos(int,
|
||||
* org.eclipse.core.runtime.IProgressMonitor)
|
||||
*/
|
||||
@Override
|
||||
public IFileInfo[] childInfos(int options, IProgressMonitor monitor) throws CoreException {
|
||||
SubMonitor subMon = SubMonitor.convert(monitor, 10);
|
||||
ProxyConnection connection = checkConnection(subMon.newChild(1));
|
||||
ChildInfosCommand command = new ChildInfosCommand(connection, fRemotePath.toString());
|
||||
try {
|
||||
return command.getResult(subMon.newChild(9));
|
||||
} catch (ProxyException e) {
|
||||
throw new CoreException(new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.filesystem.provider.FileStore#childNames(int,
|
||||
* org.eclipse.core.runtime.IProgressMonitor)
|
||||
*/
|
||||
@Override
|
||||
public String[] childNames(int options, IProgressMonitor monitor) throws CoreException {
|
||||
SubMonitor subMon = SubMonitor.convert(monitor, 10);
|
||||
IFileInfo[] infos = childInfos(options, subMon.newChild(10));
|
||||
String[] names = new String[infos.length];
|
||||
for (int i = 0; i < infos.length; i++) {
|
||||
names[i] = infos[i].getName();
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.filesystem.provider.FileStore#delete(int,
|
||||
* org.eclipse.core.runtime.IProgressMonitor)
|
||||
*/
|
||||
@Override
|
||||
public void delete(int options, IProgressMonitor monitor) throws CoreException {
|
||||
SubMonitor subMon = SubMonitor.convert(monitor, 20);
|
||||
ProxyConnection connection = checkConnection(subMon.newChild(1));
|
||||
IFileInfo info = fetchInfo(EFS.NONE, subMon.newChild(9));
|
||||
if (!subMon.isCanceled() && info.exists()) {
|
||||
DeleteCommand command = new DeleteCommand(connection, options, fRemotePath.toString());
|
||||
try {
|
||||
command.getResult(subMon.newChild(10));
|
||||
} catch (ProxyException e) {
|
||||
throw new CoreException(new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), e.getMessage()));
|
||||
}
|
||||
}
|
||||
subMon.setWorkRemaining(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.filesystem.provider.FileStore#fetchInfo(int,
|
||||
* org.eclipse.core.runtime.IProgressMonitor)
|
||||
*/
|
||||
@Override
|
||||
public IFileInfo fetchInfo(int options, IProgressMonitor monitor) throws CoreException {
|
||||
SubMonitor subMon = SubMonitor.convert(monitor, 10);
|
||||
ProxyConnection connection = checkConnection(subMon.newChild(1));
|
||||
FetchInfoCommand command = new FetchInfoCommand(connection, fRemotePath.toString());
|
||||
try {
|
||||
return command.getResult(subMon.newChild(9));
|
||||
} catch (ProxyException e) {
|
||||
throw new CoreException(new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.core.filesystem.provider.FileStore#getChild(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public IFileStore getChild(String name) {
|
||||
URI uri = ProxyFileSystem.getURIFor(ProxyFileSystem.getConnectionNameFor(fURI), fRemotePath.append(name).toString());
|
||||
return getInstance(uri);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.filesystem.provider.FileStore#getName()
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return getNameFromPath(fRemotePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility routing to get the file name from an absolute path.
|
||||
*
|
||||
* @param path
|
||||
* path to extract file name from
|
||||
* @return last segment of path, or the full path if it is root
|
||||
*/
|
||||
private String getNameFromPath(IPath path) {
|
||||
if (path.isRoot()) {
|
||||
return path.toString();
|
||||
}
|
||||
return path.lastSegment();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.filesystem.provider.FileStore#getParent()
|
||||
*/
|
||||
@Override
|
||||
public IFileStore getParent() {
|
||||
if (fRemotePath.isRoot()) {
|
||||
return null;
|
||||
}
|
||||
String parentPath = fRemotePath.toString();
|
||||
if (fRemotePath.segmentCount() > 0) {
|
||||
parentPath = fRemotePath.removeLastSegments(1).toString();
|
||||
}
|
||||
return getInstance(ProxyFileSystem.getURIFor(ProxyFileSystem.getConnectionNameFor(fURI), parentPath));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.filesystem.provider.FileStore#mkdir(int,
|
||||
* org.eclipse.core.runtime.IProgressMonitor)
|
||||
*/
|
||||
@Override
|
||||
public IFileStore mkdir(int options, IProgressMonitor monitor) throws CoreException {
|
||||
SubMonitor subMon = SubMonitor.convert(monitor, 16);
|
||||
ProxyConnection connection = checkConnection(subMon.newChild(1));
|
||||
|
||||
if ((options & EFS.SHALLOW) == EFS.SHALLOW) {
|
||||
IFileStore parent = getParent();
|
||||
if (parent != null && !parent.fetchInfo(EFS.NONE, subMon.newChild(5)).exists()) {
|
||||
throw new CoreException(new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), EFS.ERROR_WRITE,
|
||||
NLS.bind("The parent of directory {0} does not exist", fRemotePath.toString()), null));
|
||||
}
|
||||
if (subMon.isCanceled()) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
subMon.setWorkRemaining(10);
|
||||
|
||||
try {
|
||||
MkdirCommand command = new MkdirCommand(connection, options, fRemotePath.toString());
|
||||
command.getResult(subMon.newChild(5));
|
||||
} catch (Exception e) {
|
||||
// Ignore any exceptions
|
||||
}
|
||||
if (!subMon.isCanceled()) {
|
||||
/*
|
||||
* Check if the result exists and is a directory, throw an exception if neither.
|
||||
*/
|
||||
IFileInfo info = fetchInfo(EFS.NONE, subMon.newChild(5));
|
||||
if (!subMon.isCanceled()) {
|
||||
if (!info.exists()) {
|
||||
throw new CoreException(new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), EFS.ERROR_WRITE,
|
||||
NLS.bind("The directory {0} could not be created", fRemotePath.toString()), null));
|
||||
}
|
||||
if (!info.isDirectory()) {
|
||||
throw new CoreException(new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), EFS.ERROR_WRONG_TYPE,
|
||||
NLS.bind("A file of name {0} already exists", fRemotePath.toString()), null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.filesystem.provider.FileStore#openInputStream(int,
|
||||
* org.eclipse.core.runtime.IProgressMonitor)
|
||||
*/
|
||||
@Override
|
||||
public InputStream openInputStream(int options, IProgressMonitor monitor) throws CoreException {
|
||||
SubMonitor subMon = SubMonitor.convert(monitor, 20);
|
||||
ProxyConnection connection = checkConnection(subMon.newChild(1));
|
||||
IFileInfo info = fetchInfo(EFS.NONE, subMon.newChild(9));
|
||||
if (!subMon.isCanceled()) {
|
||||
if (!info.exists()) {
|
||||
throw new CoreException(new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), EFS.ERROR_READ,
|
||||
NLS.bind("File {0} does not exist", fRemotePath.toString()), null));
|
||||
}
|
||||
if (info.isDirectory()) {
|
||||
throw new CoreException(new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), EFS.ERROR_WRONG_TYPE,
|
||||
NLS.bind("{0} is a directory", fRemotePath.toString()), null));
|
||||
}
|
||||
GetInputStreamCommand command = new GetInputStreamCommand(connection, options, fRemotePath.toString());
|
||||
try {
|
||||
return command.getResult(subMon.newChild(10));
|
||||
} catch (ProxyException e) {
|
||||
throw new CoreException(new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), e.getMessage()));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.filesystem.provider.FileStore#openOutputStream(int,
|
||||
* org.eclipse.core.runtime.IProgressMonitor)
|
||||
*/
|
||||
@Override
|
||||
public OutputStream openOutputStream(int options, IProgressMonitor monitor) throws CoreException {
|
||||
SubMonitor subMon = SubMonitor.convert(monitor, 20);
|
||||
ProxyConnection connection = checkConnection(subMon.newChild(1));
|
||||
IFileInfo info = fetchInfo(EFS.NONE, subMon.newChild(9));
|
||||
if (!subMon.isCanceled()) {
|
||||
if (info.isDirectory()) {
|
||||
throw new CoreException(new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), EFS.ERROR_WRONG_TYPE,
|
||||
NLS.bind("{0} is a directory", fRemotePath.toString()), null));
|
||||
}
|
||||
GetOutputStreamCommand command = new GetOutputStreamCommand(connection, options, fRemotePath.toString());
|
||||
try {
|
||||
return command.getResult(subMon.newChild(10));
|
||||
} catch (ProxyException e) {
|
||||
throw new CoreException(new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), e.getMessage()));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.core.filesystem.provider.FileStore#putInfo(org.eclipse.core
|
||||
* .filesystem.IFileInfo, int, org.eclipse.core.runtime.IProgressMonitor)
|
||||
*/
|
||||
@Override
|
||||
public void putInfo(IFileInfo info, int options, IProgressMonitor monitor) throws CoreException {
|
||||
SubMonitor subMon = SubMonitor.convert(monitor, 10);
|
||||
ProxyConnection connection = checkConnection(subMon.newChild(1));
|
||||
PutInfoCommand command = new PutInfoCommand(connection, info, options, fRemotePath.toString());
|
||||
try {
|
||||
command.getResult(subMon.newChild(9));
|
||||
} catch (ProxyException e) {
|
||||
throw new CoreException(new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.filesystem.provider.FileStore#toURI()
|
||||
*/
|
||||
@Override
|
||||
public URI toURI() {
|
||||
return fURI;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/********************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory and others.
|
||||
* 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
|
||||
********************************************************************************/
|
||||
|
||||
package org.eclipse.remote.internal.proxy.core;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import org.eclipse.core.filesystem.EFS;
|
||||
import org.eclipse.core.filesystem.IFileStore;
|
||||
import org.eclipse.core.filesystem.provider.FileSystem;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
|
||||
public class ProxyFileSystem extends FileSystem {
|
||||
/**
|
||||
* Return the connection name encoded in the URI.
|
||||
*
|
||||
* @param uri
|
||||
* URI specifying a remote tools connection
|
||||
* @return name of the connection or null if the URI is invalid
|
||||
* @since 4.0
|
||||
*/
|
||||
public static String getConnectionNameFor(URI uri) {
|
||||
return uri.getAuthority();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an URI uniquely naming a remote tools remote resource.
|
||||
*
|
||||
* @param connectionName
|
||||
* remote tools connection name
|
||||
* @param path
|
||||
* absolute path to resource as valid on the remote system
|
||||
* @return an URI uniquely naming the remote resource.
|
||||
*/
|
||||
public static URI getURIFor(String connectionName, String path) {
|
||||
try {
|
||||
return new URI("proxy", connectionName, path, null, null); //$NON-NLS-1$
|
||||
} catch (URISyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public ProxyFileSystem() {
|
||||
super();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.filesystem.IFileSystem#attributes()
|
||||
*/
|
||||
@Override
|
||||
public int attributes() {
|
||||
// Attributes supported by JSch IFileService
|
||||
return EFS.ATTRIBUTE_READ_ONLY | EFS.ATTRIBUTE_EXECUTABLE | EFS.ATTRIBUTE_SYMLINK | EFS.ATTRIBUTE_LINK_TARGET;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.filesystem.provider.FileSystem#canDelete()
|
||||
*/
|
||||
@Override
|
||||
public boolean canDelete() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.filesystem.provider.FileSystem#canWrite()
|
||||
*/
|
||||
@Override
|
||||
public boolean canWrite() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.filesystem.provider.FileSystem#getStore(org.eclipse.core.runtime.IPath)
|
||||
*/
|
||||
@Override
|
||||
public IFileStore getStore(IPath path) {
|
||||
return EFS.getNullFileSystem().getStore(path);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.core.filesystem.provider.FileSystem#getStore(java.net.URI)
|
||||
*/
|
||||
@Override
|
||||
public IFileStore getStore(URI uri) {
|
||||
try {
|
||||
return ProxyFileStore.getInstance(uri);
|
||||
} catch (Exception e) {
|
||||
// Could be an URI format exception
|
||||
Activator.log(e);
|
||||
return EFS.getNullFileSystem().getStore(uri);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,207 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.eclipse.remote.core.IRemoteConnection;
|
||||
import org.eclipse.remote.core.IRemoteProcess;
|
||||
import org.eclipse.remote.core.IRemoteProcessBuilder;
|
||||
import org.eclipse.remote.core.IRemoteProcessControlService;
|
||||
import org.eclipse.remote.core.IRemoteProcessSignalService;
|
||||
import org.eclipse.remote.core.IRemoteProcessTerminalService;
|
||||
import org.eclipse.remote.internal.core.RemoteProcess;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
|
||||
public class ProxyProcess extends RemoteProcess implements IRemoteProcessControlService, IRemoteProcessTerminalService {
|
||||
private IRemoteProcess remoteProcess;
|
||||
private final StreamChannel stdIOChan;
|
||||
private final StreamChannel stdErrChan;
|
||||
private final StreamChannel controlChan;
|
||||
private final DataOutputStream cmdStream;
|
||||
private final DataInputStream resultStream;
|
||||
private final Thread cmdThread;
|
||||
|
||||
private volatile int exitValue;
|
||||
private volatile boolean isCompleted;
|
||||
|
||||
public static class Factory implements IRemoteProcess.Service.Factory {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.remote.core.IRemoteProcess.Service.Factory#getService(org.eclipse.remote.core.IRemoteProcess,
|
||||
* java.lang.Class)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T extends IRemoteProcess.Service> T getService(IRemoteProcess remoteProcess, Class<T> service) {
|
||||
if (ProxyProcess.class.equals(service) && remoteProcess instanceof ProxyProcess) {
|
||||
return (T) remoteProcess;
|
||||
}
|
||||
if (IRemoteProcessControlService.class.equals(service) || IRemoteProcessSignalService.class.equals(service)
|
||||
|| IRemoteProcessTerminalService.class.equals(service)) {
|
||||
return (T) remoteProcess.getService(ProxyProcess.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ProxyProcess(IRemoteConnection connection, IRemoteProcessBuilder builder, StreamChannel stdIO, StreamChannel stdErr, StreamChannel control) {
|
||||
super(connection, builder);
|
||||
stdIOChan = stdIO;
|
||||
stdErrChan = stdErr;
|
||||
controlChan = control;
|
||||
cmdStream = new DataOutputStream(control.getOutputStream());
|
||||
resultStream = new DataInputStream(control.getInputStream());
|
||||
isCompleted = false;
|
||||
exitValue = 0;
|
||||
|
||||
cmdThread = new Thread("process " + builder.command().get(0) + " result reader") {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
exitValue = resultStream.readInt();
|
||||
} catch (IOException e) {
|
||||
// Finish
|
||||
}
|
||||
isCompleted = true;
|
||||
try {
|
||||
stdIOChan.close();
|
||||
} catch (IOException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
}
|
||||
try {
|
||||
stdErrChan.close();
|
||||
} catch (IOException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
}
|
||||
// if (stdout == null) {
|
||||
// try {
|
||||
// stdIOChan.getInputStream().close();
|
||||
// } catch (IOException e) {
|
||||
// // Ignore
|
||||
// }
|
||||
// }
|
||||
// if (stdin == null) {
|
||||
// try {
|
||||
// stdIOChan.getOutputStream().close();
|
||||
// } catch (IOException e) {
|
||||
// // Ignore
|
||||
// }
|
||||
// }
|
||||
// if (stderr == null) {
|
||||
// try {
|
||||
// stdErrChan.close();
|
||||
// } catch (IOException e) {
|
||||
// // Ignore
|
||||
// }
|
||||
// }
|
||||
try {
|
||||
controlChan.close();
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
};
|
||||
cmdThread.start();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Process#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
try {
|
||||
cmdStream.writeByte(0);
|
||||
cmdStream.flush();
|
||||
} catch (IOException e) {
|
||||
isCompleted = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Process#exitValue()
|
||||
*/
|
||||
@Override
|
||||
public int exitValue() {
|
||||
if (!isCompleted) {
|
||||
throw new IllegalThreadStateException();
|
||||
}
|
||||
return exitValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Process#getErrorStream()
|
||||
*/
|
||||
@Override
|
||||
public InputStream getErrorStream() {
|
||||
return stdErrChan.getInputStream();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Process#getInputStream()
|
||||
*/
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
return stdIOChan.getInputStream();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Process#getOutputStream()
|
||||
*/
|
||||
@Override
|
||||
public OutputStream getOutputStream() {
|
||||
return stdIOChan.getOutputStream();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Process#waitFor()
|
||||
*/
|
||||
@Override
|
||||
public int waitFor() throws InterruptedException {
|
||||
cmdThread.join();
|
||||
return exitValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.remote.core.RemoteProcess#isCompleted()
|
||||
*/
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return isCompleted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRemoteProcess getRemoteProcess() {
|
||||
return remoteProcess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTerminalSize(int cols, int rows, int pwidth, int pheight) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.remote.core.AbstractRemoteProcessBuilder;
|
||||
import org.eclipse.remote.core.IRemoteFileService;
|
||||
import org.eclipse.remote.core.IRemoteProcess;
|
||||
import org.eclipse.remote.core.IRemoteProcessBuilder;
|
||||
import org.eclipse.remote.internal.proxy.core.commands.ExecCommand;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class ProxyProcessBuilder extends AbstractRemoteProcessBuilder {
|
||||
private final ProxyConnection proxyConnection;
|
||||
private Map<String, String> remoteEnv;
|
||||
|
||||
public ProxyProcessBuilder(ProxyConnection connection, List<String> command) {
|
||||
super(connection.getRemoteConnection(), command);
|
||||
proxyConnection = connection;
|
||||
IRemoteFileService fileSvc = proxyConnection.getRemoteConnection().getService(IRemoteFileService.class);
|
||||
if (fileSvc != null) {
|
||||
directory(fileSvc.getResource(proxyConnection.getWorkingDirectory()));
|
||||
}
|
||||
}
|
||||
|
||||
public ProxyProcessBuilder(ProxyConnection connection, String... command) {
|
||||
this(connection, Arrays.asList(command));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.remote.core.AbstractRemoteProcessBuilder#environment()
|
||||
*/
|
||||
@Override
|
||||
public Map<String, String> environment() {
|
||||
if (remoteEnv == null) {
|
||||
remoteEnv = new HashMap<String, String>(proxyConnection.getEnv());
|
||||
}
|
||||
return remoteEnv;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.remote.core.AbstractRemoteProcessBuilder#getSupportedFlags
|
||||
* ()
|
||||
*/
|
||||
@Override
|
||||
public int getSupportedFlags() {
|
||||
return NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.remote.core.IRemoteProcessBuilder#start(int)
|
||||
*/
|
||||
@Override
|
||||
public IRemoteProcess start(int flags) throws IOException {
|
||||
final List<String> cmdArgs = command();
|
||||
if (cmdArgs.size() < 1) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
/*
|
||||
* If environment has not been touched, then don't send anything
|
||||
*/
|
||||
final Map<String, String> env = new HashMap<String, String>();
|
||||
if (remoteEnv != null) {
|
||||
env.putAll(remoteEnv);
|
||||
}
|
||||
final boolean append = (flags & IRemoteProcessBuilder.APPEND_ENVIRONMENT) != 0 || remoteEnv == null;
|
||||
|
||||
final ProxyConnection conn = getRemoteConnection().getService(ProxyConnection.class);
|
||||
if (conn == null) {
|
||||
throw new IOException("Unable to located connection for this process");
|
||||
}
|
||||
|
||||
final StreamChannel chanStdIO = conn.openChannel();
|
||||
final StreamChannel chanStdErr = conn.openChannel();
|
||||
final StreamChannel chanControl = conn.openChannel();
|
||||
|
||||
Job job = new Job("process executor") {
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
ExecCommand cmd = new ExecCommand(conn, cmdArgs, env, directory().toURI().getPath(), redirectErrorStream(), append,
|
||||
chanStdIO.getId(), chanStdErr.getId(), chanControl.getId());
|
||||
try {
|
||||
cmd.getResult(monitor);
|
||||
} catch (ProxyException e) {
|
||||
return new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), e.getMessage());
|
||||
}
|
||||
return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS;
|
||||
}
|
||||
};
|
||||
job.schedule();
|
||||
try {
|
||||
job.join();
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
if (!job.getResult().isOK()) {
|
||||
throw new IOException(job.getResult().getMessage());
|
||||
}
|
||||
|
||||
ProxyProcess proc = new ProxyProcess(getRemoteConnection(), this, chanStdIO, chanStdErr, chanControl);
|
||||
return proc;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core.commands;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.SubMonitor;
|
||||
import org.eclipse.remote.internal.proxy.core.ProxyConnection;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public abstract class AbstractCommand<T> implements Callable<T> {
|
||||
private IProgressMonitor progressMonitor;
|
||||
|
||||
private static ExecutorService executors = Executors.newSingleThreadExecutor();
|
||||
|
||||
private final ProxyConnection connection;
|
||||
|
||||
|
||||
private Future<T> asyncCmdInThread() throws ProxyException {
|
||||
return executors.submit(this);
|
||||
}
|
||||
|
||||
private void finalizeCmdInThread() {
|
||||
}
|
||||
|
||||
public StreamChannel openChannel() throws IOException {
|
||||
return connection.openChannel();
|
||||
}
|
||||
|
||||
public IProgressMonitor getProgressMonitor() {
|
||||
return progressMonitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function opens exec channel and then executes the exec operation. If
|
||||
* run on the main thread it executes it on a separate thread
|
||||
*/
|
||||
public T getResult(IProgressMonitor monitor) throws ProxyException {
|
||||
Future<T> future = null;
|
||||
progressMonitor = SubMonitor.convert(monitor, 10);
|
||||
try {
|
||||
future = asyncCmdInThread();
|
||||
return waitCmdInThread(future);
|
||||
} finally {
|
||||
finalizeCmdInThread();
|
||||
}
|
||||
}
|
||||
|
||||
private T waitCmdInThread(Future<T> future) throws ProxyException {
|
||||
boolean bInterrupted = Thread.interrupted();
|
||||
while (!getProgressMonitor().isCanceled()) {
|
||||
try {
|
||||
return future.get(100, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
bInterrupted = true;
|
||||
} catch (TimeoutException e) {
|
||||
// ignore
|
||||
} catch (ExecutionException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
getProgressMonitor().worked(1);
|
||||
}
|
||||
if (bInterrupted) {
|
||||
Thread.currentThread().interrupt(); // set current thread flag
|
||||
}
|
||||
future.cancel(true);
|
||||
throw new ProxyException("Operation cancelled by user");
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract T call() throws ProxyException;
|
||||
|
||||
public AbstractCommand(ProxyConnection conn) {
|
||||
this.connection = conn;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core.commands;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.core.filesystem.IFileInfo;
|
||||
import org.eclipse.remote.internal.proxy.core.ProxyConnection;
|
||||
import org.eclipse.remote.proxy.protocol.core.Protocol;
|
||||
import org.eclipse.remote.proxy.protocol.core.SerializableFileInfo;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class ChildInfosCommand extends AbstractCommand<IFileInfo[]> {
|
||||
|
||||
private final DataOutputStream out;
|
||||
private final DataInputStream in;
|
||||
private final String path;
|
||||
|
||||
public ChildInfosCommand(ProxyConnection conn, String path) {
|
||||
super(conn);
|
||||
this.out = new DataOutputStream(conn.getCommandChannel().getOutputStream());
|
||||
this.in = new DataInputStream(conn.getCommandChannel().getInputStream());
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public IFileInfo[] call() throws ProxyException {
|
||||
try {
|
||||
final StreamChannel chan = openChannel();
|
||||
|
||||
out.writeByte(Protocol.PROTO_COMMAND);
|
||||
out.writeShort(Protocol.CMD_CHILDINFOS);
|
||||
out.writeByte(chan.getId());
|
||||
out.writeUTF(path);
|
||||
out.flush();
|
||||
|
||||
byte res = in.readByte();
|
||||
if (res != Protocol.PROTO_OK) {
|
||||
String errMsg = in.readUTF();
|
||||
System.err.println("childinfos command failed:" + errMsg);
|
||||
throw new ProxyException(errMsg);
|
||||
}
|
||||
|
||||
DataInputStream resultStream = new DataInputStream(chan.getInputStream());
|
||||
int length = resultStream.readInt();
|
||||
SerializableFileInfo sInfo = new SerializableFileInfo();
|
||||
IFileInfo[] infos = new IFileInfo[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
sInfo.readObject(resultStream);
|
||||
infos[i] = sInfo.getIFileInfo();
|
||||
}
|
||||
chan.close();
|
||||
return infos;
|
||||
} catch (IOException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core.commands;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.remote.internal.proxy.core.ProxyConnection;
|
||||
import org.eclipse.remote.proxy.protocol.core.Protocol;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class DeleteCommand extends AbstractCommand<Void> {
|
||||
|
||||
private final DataOutputStream out;
|
||||
private final DataInputStream in;
|
||||
private final int options;
|
||||
private final String path;
|
||||
|
||||
public DeleteCommand(ProxyConnection conn, int options, String path) {
|
||||
super(conn);
|
||||
this.out = new DataOutputStream(conn.getCommandChannel().getOutputStream());
|
||||
this.in = new DataInputStream(conn.getCommandChannel().getInputStream());
|
||||
this.options = options;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public Void call() throws ProxyException {
|
||||
try {
|
||||
out.writeByte(Protocol.PROTO_COMMAND);
|
||||
out.writeShort(Protocol.CMD_DELETE);
|
||||
out.writeInt(options);
|
||||
out.writeUTF(path);
|
||||
out.flush();
|
||||
|
||||
byte res = in.readByte();
|
||||
if (res != Protocol.PROTO_OK) {
|
||||
String errMsg = in.readUTF();
|
||||
System.err.println("delete command failed:" + errMsg);
|
||||
throw new ProxyException(errMsg);
|
||||
}
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core.commands;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.remote.internal.proxy.core.ProxyConnection;
|
||||
import org.eclipse.remote.proxy.protocol.core.Protocol;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class ExecCommand extends AbstractCommand<Void> {
|
||||
|
||||
private final DataOutputStream out;
|
||||
private final DataInputStream in;
|
||||
private final List<String> command;
|
||||
private final Map<String, String> env;
|
||||
private final String directory;
|
||||
private final boolean appendEnv;
|
||||
private final boolean redirect;
|
||||
private final int chanA;
|
||||
private final int chanB;
|
||||
private final int chanC;
|
||||
|
||||
public ExecCommand(ProxyConnection conn, List<String> command, Map<String, String> env, String directory, boolean redirect, boolean appendEnv,
|
||||
int chanA, int chanB, int chanC) {
|
||||
super(conn);
|
||||
this.out = new DataOutputStream(conn.getCommandChannel().getOutputStream());
|
||||
this.in = new DataInputStream(conn.getCommandChannel().getInputStream());
|
||||
this.command = command;
|
||||
this.env = env;
|
||||
this.directory = directory;
|
||||
this.redirect = redirect;
|
||||
this.appendEnv = appendEnv;
|
||||
this.chanA = chanA;
|
||||
this.chanB = chanB;
|
||||
this.chanC = chanC;
|
||||
}
|
||||
|
||||
public Void call() throws ProxyException {
|
||||
try {
|
||||
out.writeByte(Protocol.PROTO_COMMAND);
|
||||
out.writeShort(Protocol.CMD_EXEC);
|
||||
out.writeByte(chanA);
|
||||
out.writeByte(chanB);
|
||||
out.writeByte(chanC);
|
||||
out.writeInt(command.size());
|
||||
for (String arg : command) {
|
||||
out.writeUTF(arg);
|
||||
}
|
||||
out.writeInt(env.size());
|
||||
for (Map.Entry<String, String> entry : env.entrySet()) {
|
||||
out.writeUTF(entry.getKey());
|
||||
out.writeUTF(entry.getValue());
|
||||
}
|
||||
out.writeUTF(directory);
|
||||
out.writeBoolean(redirect);
|
||||
out.writeBoolean(appendEnv);
|
||||
out.flush();
|
||||
|
||||
byte res = in.readByte();
|
||||
if (res != Protocol.PROTO_OK) {
|
||||
String errMsg = in.readUTF();
|
||||
System.err.println("exec command failed:" + errMsg);
|
||||
throw new ProxyException(errMsg);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core.commands;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.core.filesystem.IFileInfo;
|
||||
import org.eclipse.remote.internal.proxy.core.ProxyConnection;
|
||||
import org.eclipse.remote.proxy.protocol.core.Protocol;
|
||||
import org.eclipse.remote.proxy.protocol.core.SerializableFileInfo;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class FetchInfoCommand extends AbstractCommand<IFileInfo> {
|
||||
|
||||
private final DataOutputStream out;
|
||||
private final DataInputStream in;
|
||||
private final String path;
|
||||
|
||||
public FetchInfoCommand(ProxyConnection conn, String path) {
|
||||
super(conn);
|
||||
this.out = new DataOutputStream(conn.getCommandChannel().getOutputStream());
|
||||
this.in = new DataInputStream(conn.getCommandChannel().getInputStream());
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public IFileInfo call() throws ProxyException {
|
||||
try {
|
||||
final StreamChannel chan = openChannel();
|
||||
|
||||
out.writeByte(Protocol.PROTO_COMMAND);
|
||||
out.writeShort(Protocol.CMD_FETCHINFO);
|
||||
out.writeByte(chan.getId());
|
||||
out.writeUTF(path);
|
||||
out.flush();
|
||||
|
||||
byte res = in.readByte();
|
||||
if (res != Protocol.PROTO_OK) {
|
||||
String errMsg = in.readUTF();
|
||||
System.err.println("fetchinfo command failed:" + errMsg);
|
||||
throw new ProxyException(errMsg);
|
||||
}
|
||||
|
||||
DataInputStream resultStream = new DataInputStream(chan.getInputStream());
|
||||
SerializableFileInfo info = new SerializableFileInfo();
|
||||
info.readObject(resultStream);
|
||||
chan.close();
|
||||
return info.getIFileInfo();
|
||||
} catch (IOException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core.commands;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.remote.internal.proxy.core.ProxyConnection;
|
||||
import org.eclipse.remote.proxy.protocol.core.Protocol;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class GetCwdCommand extends AbstractCommand<String> {
|
||||
|
||||
private final DataOutputStream out;
|
||||
private final DataInputStream in;
|
||||
|
||||
public GetCwdCommand(ProxyConnection conn) {
|
||||
super(conn);
|
||||
this.out = new DataOutputStream(conn.getCommandChannel().getOutputStream());
|
||||
this.in = new DataInputStream(conn.getCommandChannel().getInputStream());
|
||||
}
|
||||
|
||||
public String call() throws ProxyException {
|
||||
try {
|
||||
final StreamChannel chan = openChannel();
|
||||
DataInputStream resultStream = new DataInputStream(chan.getInputStream());
|
||||
|
||||
out.writeByte(Protocol.PROTO_COMMAND);
|
||||
out.writeShort(Protocol.CMD_GETCWD);
|
||||
out.writeByte(chan.getId());
|
||||
out.flush();
|
||||
|
||||
byte res = in.readByte();
|
||||
if (res != Protocol.PROTO_OK) {
|
||||
String errMsg = in.readUTF();
|
||||
System.err.println("getcwd command failed:" + errMsg);
|
||||
throw new ProxyException(errMsg);
|
||||
}
|
||||
|
||||
String cwd = resultStream.readUTF();
|
||||
chan.close();
|
||||
return cwd;
|
||||
} catch (IOException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core.commands;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.remote.internal.proxy.core.ProxyConnection;
|
||||
import org.eclipse.remote.proxy.protocol.core.Protocol;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class GetEnvCommand extends AbstractCommand<Map<String, String>> {
|
||||
|
||||
private final DataOutputStream out;
|
||||
private final DataInputStream in;
|
||||
|
||||
public GetEnvCommand(ProxyConnection conn) {
|
||||
super(conn);
|
||||
this.out = new DataOutputStream(conn.getCommandChannel().getOutputStream());
|
||||
this.in = new DataInputStream(conn.getCommandChannel().getInputStream());
|
||||
}
|
||||
|
||||
public Map<String, String> call() throws ProxyException {
|
||||
try {
|
||||
final StreamChannel chan = openChannel();
|
||||
DataInputStream resultStream = new DataInputStream(chan.getInputStream());
|
||||
|
||||
out.writeByte(Protocol.PROTO_COMMAND);
|
||||
out.writeShort(Protocol.CMD_GETENV);
|
||||
out.writeByte(chan.getId());
|
||||
out.flush();
|
||||
|
||||
byte res = in.readByte();
|
||||
if (res != Protocol.PROTO_OK) {
|
||||
String errMsg = in.readUTF();
|
||||
System.err.println("getenv command failed:" + errMsg);
|
||||
throw new ProxyException(errMsg);
|
||||
}
|
||||
|
||||
int len = resultStream.readInt();
|
||||
Map<String, String> env = new HashMap<String, String>(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
String key = resultStream.readUTF();
|
||||
String value = resultStream.readUTF();
|
||||
env.put(key, value);
|
||||
}
|
||||
chan.close();
|
||||
return env;
|
||||
} catch (IOException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core.commands;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.eclipse.remote.internal.proxy.core.ProxyConnection;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.Protocol;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class GetInputStreamCommand extends AbstractCommand<InputStream> {
|
||||
|
||||
private final DataOutputStream out;
|
||||
private final DataInputStream in;
|
||||
private final int options;
|
||||
private final String path;
|
||||
|
||||
public GetInputStreamCommand(ProxyConnection conn, int options, String path) {
|
||||
super(conn);
|
||||
this.out = new DataOutputStream(conn.getCommandChannel().getOutputStream());
|
||||
this.in = new DataInputStream(conn.getCommandChannel().getInputStream());
|
||||
this.options = options;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public InputStream call() throws ProxyException {
|
||||
try {
|
||||
StreamChannel chan = openChannel();
|
||||
|
||||
out.writeByte(Protocol.PROTO_COMMAND);
|
||||
out.writeShort(Protocol.CMD_GETINPUTSTREAM);
|
||||
out.writeByte(chan.getId());
|
||||
out.writeInt(options);
|
||||
out.writeUTF(path);
|
||||
out.flush();
|
||||
|
||||
byte res = in.readByte();
|
||||
if (res != Protocol.PROTO_OK) {
|
||||
String errMsg = in.readUTF();
|
||||
System.err.println("getinputstream command failed:" + errMsg);
|
||||
throw new ProxyException(errMsg);
|
||||
}
|
||||
|
||||
return new BufferedInputStream(chan.getInputStream());
|
||||
} catch (IOException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core.commands;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.eclipse.remote.internal.proxy.core.ProxyConnection;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.Protocol;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class GetOutputStreamCommand extends AbstractCommand<OutputStream> {
|
||||
|
||||
private final DataOutputStream out;
|
||||
private final DataInputStream in;
|
||||
private final int options;
|
||||
private final String path;
|
||||
|
||||
public GetOutputStreamCommand(ProxyConnection conn, int options, String path) {
|
||||
super(conn);
|
||||
this.out = new DataOutputStream(conn.getCommandChannel().getOutputStream());
|
||||
this.in = new DataInputStream(conn.getCommandChannel().getInputStream());
|
||||
this.options = options;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public OutputStream call() throws ProxyException {
|
||||
try {
|
||||
StreamChannel chan = openChannel();
|
||||
|
||||
out.writeByte(Protocol.PROTO_COMMAND);
|
||||
out.writeShort(Protocol.CMD_GETOUTPUTSTREAM);
|
||||
out.writeByte(chan.getId());
|
||||
out.writeInt(options);
|
||||
out.writeUTF(path);
|
||||
out.flush();
|
||||
|
||||
byte res = in.readByte();
|
||||
if (res != Protocol.PROTO_OK) {
|
||||
String errMsg = in.readUTF();
|
||||
System.err.println("getoutputstream command failed:" + errMsg);
|
||||
throw new ProxyException(errMsg);
|
||||
}
|
||||
|
||||
return new BufferedOutputStream(chan.getOutputStream());
|
||||
} catch (IOException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core.commands;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.remote.internal.proxy.core.ProxyConnection;
|
||||
import org.eclipse.remote.proxy.protocol.core.Protocol;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class GetPropertiesCommand extends AbstractCommand<Map<String, String>> {
|
||||
|
||||
private final DataOutputStream out;
|
||||
private final DataInputStream in;
|
||||
|
||||
public GetPropertiesCommand(ProxyConnection conn) {
|
||||
super(conn);
|
||||
this.out = new DataOutputStream(conn.getCommandChannel().getOutputStream());
|
||||
this.in = new DataInputStream(conn.getCommandChannel().getInputStream());
|
||||
}
|
||||
|
||||
public Map<String, String> call() throws ProxyException {
|
||||
try {
|
||||
final StreamChannel chan = openChannel();
|
||||
DataInputStream resultStream = new DataInputStream(chan.getInputStream());
|
||||
|
||||
out.writeByte(Protocol.PROTO_COMMAND);
|
||||
out.writeShort(Protocol.CMD_GETPROPERTIES);
|
||||
out.writeByte(chan.getId());
|
||||
out.flush();
|
||||
|
||||
byte res = in.readByte();
|
||||
if (res != Protocol.PROTO_OK) {
|
||||
String errMsg = in.readUTF();
|
||||
System.err.println("getproperties command failed:" + errMsg);
|
||||
throw new ProxyException(errMsg);
|
||||
}
|
||||
|
||||
int len = resultStream.readInt();
|
||||
Map<String, String> props = new HashMap<String, String>(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
String key = resultStream.readUTF();
|
||||
String value = resultStream.readUTF();
|
||||
props.put(key, value);
|
||||
}
|
||||
chan.close();
|
||||
return props;
|
||||
} catch (IOException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core.commands;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.remote.internal.proxy.core.ProxyConnection;
|
||||
import org.eclipse.remote.proxy.protocol.core.Protocol;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class MkdirCommand extends AbstractCommand<Void> {
|
||||
|
||||
private final DataOutputStream out;
|
||||
private final DataInputStream in;
|
||||
private final int options;
|
||||
private final String path;
|
||||
|
||||
public MkdirCommand(ProxyConnection conn, int options, String path) {
|
||||
super(conn);
|
||||
this.out = new DataOutputStream(conn.getCommandChannel().getOutputStream());
|
||||
this.in = new DataInputStream(conn.getCommandChannel().getInputStream());
|
||||
this.options = options;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public Void call() throws ProxyException {
|
||||
try {
|
||||
out.writeByte(Protocol.PROTO_COMMAND);
|
||||
out.writeShort(Protocol.CMD_MKDIR);
|
||||
out.writeInt(options);
|
||||
out.writeUTF(path);
|
||||
out.flush();
|
||||
|
||||
byte res = in.readByte();
|
||||
if (res != Protocol.PROTO_OK) {
|
||||
String errMsg = in.readUTF();
|
||||
System.err.println("mkdir command failed:" + errMsg);
|
||||
throw new ProxyException(errMsg);
|
||||
}
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.core.commands;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.core.filesystem.IFileInfo;
|
||||
import org.eclipse.remote.internal.proxy.core.ProxyConnection;
|
||||
import org.eclipse.remote.proxy.protocol.core.Protocol;
|
||||
import org.eclipse.remote.proxy.protocol.core.SerializableFileInfo;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class PutInfoCommand extends AbstractCommand<Void> {
|
||||
|
||||
private final DataOutputStream out;
|
||||
private final DataInputStream in;
|
||||
private final IFileInfo info;
|
||||
private final int options;
|
||||
private final String path;
|
||||
|
||||
public PutInfoCommand(ProxyConnection conn, IFileInfo info, int options, String path) {
|
||||
super(conn);
|
||||
this.out = new DataOutputStream(conn.getCommandChannel().getOutputStream());
|
||||
this.in = new DataInputStream(conn.getCommandChannel().getInputStream());
|
||||
this.info = info;
|
||||
this.options = options;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public Void call() throws ProxyException {
|
||||
try {
|
||||
out.writeByte(Protocol.PROTO_COMMAND);
|
||||
out.writeShort(Protocol.CMD_PUTINFO);
|
||||
out.writeInt(options);
|
||||
out.writeUTF(path);
|
||||
SerializableFileInfo sInfo = new SerializableFileInfo(info);
|
||||
sInfo.writeObject(out);
|
||||
out.flush();
|
||||
|
||||
byte res = in.readByte();
|
||||
if (res != Protocol.PROTO_OK) {
|
||||
String errMsg = in.readUTF();
|
||||
System.err.println("fetchinfo command failed:" + errMsg);
|
||||
throw new ProxyException(errMsg);
|
||||
}
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* Copyright (c) 2013 IBM Corporation.
|
||||
* 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:
|
||||
* IBM Corporation - Initial Implementation
|
||||
*
|
||||
*/
|
||||
package org.eclipse.remote.internal.proxy.core.messages;
|
||||
|
||||
import org.eclipse.osgi.util.NLS;
|
||||
|
||||
public class Messages extends NLS {
|
||||
private static final String BUNDLE_ID = "org.eclipse.remote.internal.proxy.core.messages.messages"; //$NON-NLS-1$
|
||||
|
||||
public static String AbstractRemoteCommand_format1;
|
||||
public static String AbstractRemoteCommand_format2;
|
||||
public static String AbstractRemoteCommand_Get_symlink_target;
|
||||
public static String AbstractRemoteCommand_Operation_cancelled_by_user;
|
||||
public static String AuthInfo_Authentication_message;
|
||||
public static String ExecCommand_Exec_command;
|
||||
|
||||
public static String GetInputStreamCommand_Receiving;
|
||||
|
||||
public static String GetOutputStreamCommand_Sending;
|
||||
public static String JSchConnection_0;
|
||||
|
||||
public static String JSchConnection_Connection_was_cancelled;
|
||||
public static String JSchConnection_connectionNotOpen;
|
||||
public static String JSchConnection_Executing_command;
|
||||
public static String JSchConnection_remote_address_must_be_set;
|
||||
public static String JSchConnection_remotePort;
|
||||
public static String JSchConnection_forwarding;
|
||||
public static String JSchConnection_Remote_host_does_not_support_sftp;
|
||||
public static String JSchConnection_Unable_to_open_sftp_channel;
|
||||
public static String JSchConnection_username_must_be_set;
|
||||
public static String JSchConnectionManager_connection_with_name_exists;
|
||||
public static String JSchConnectionManager_cannotRemoveOpenConnection;
|
||||
public static String JSchConnectionManager_invalidConnectionType;
|
||||
public static String JSchConnectionProxyFactory_failed;
|
||||
public static String JSchConnectionProxyFactory_ProxyCommandFailed;
|
||||
public static String JSchConnectionProxyFactory_timedOut;
|
||||
public static String JSchConnectionProxyFactory_wasCanceled;
|
||||
public static String JSchProcess_exitValue_exception_msg;
|
||||
public static String JSchProcessBuilder_Connection_is_not_open;
|
||||
public static String JschFileStore_Connection_is_not_open;
|
||||
public static String JschFileStore_File_doesnt_exist;
|
||||
public static String JschFileStore_Invalid_connection_for_URI;
|
||||
public static String JschFileStore_Is_a_directory;
|
||||
public static String JschFileStore_No_remote_services_found_for_URI;
|
||||
public static String JschFileStore_The_directory_could_not_be_created;
|
||||
|
||||
public static String JschFileStore_A_file_of_name_already_exists;
|
||||
public static String JschFileStore_The_parent_of_directory_does_not_exist;
|
||||
|
||||
static {
|
||||
// load message values from bundle file
|
||||
NLS.initializeMessages(BUNDLE_ID, Messages.class);
|
||||
}
|
||||
|
||||
private Messages() {
|
||||
// cannot create new instance
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
###############################################################################
|
||||
# Copyright (c) 2013 IBM Corporation.
|
||||
# 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:
|
||||
# IBM Corporation - initial implementation
|
||||
###############################################################################
|
||||
AbstractRemoteCommand_format1={0,number,integer} {1} completed
|
||||
AbstractRemoteCommand_format2={0,number,integer} {1} of {2,number,integer} {3} complete ({4,number,percent})
|
||||
AbstractRemoteCommand_Get_symlink_target=Get symlink target
|
||||
AbstractRemoteCommand_Operation_cancelled_by_user=Operation cancelled by user
|
||||
AuthInfo_Authentication_message=Authentication Message
|
||||
ExecCommand_Exec_command=Executing command "{0}"
|
||||
GetInputStreamCommand_Receiving=Receiving {0}:
|
||||
GetOutputStreamCommand_Sending=Sending {0}:
|
||||
JSchConnection_0=Connection canceled by user
|
||||
JSchConnection_Connection_was_cancelled=Connection was cancelled
|
||||
JSchConnection_connectionNotOpen=Connection is not open
|
||||
JSchConnection_Executing_command=Executing command "{0}"
|
||||
JSchConnection_remote_address_must_be_set=Remote address must be set before opening connection
|
||||
JSchConnection_remotePort=Could not allocate remote port
|
||||
JSchConnection_forwarding=Setting up remote forwarding
|
||||
JSchConnection_Remote_host_does_not_support_sftp=Remote host does not support sftp. Remote functionality requires sftp to be enabled
|
||||
JSchConnection_Unable_to_open_sftp_channel=Unable to open sftp channel: check sftp is enabled on remote host
|
||||
JSchConnection_username_must_be_set=Username must be set before opening connection
|
||||
JSchConnectionManager_connection_with_name_exists=A connection with name \"{0}\" already exists
|
||||
JSchConnectionManager_cannotRemoveOpenConnection=Cannot remove an open connection
|
||||
JSchConnectionManager_invalidConnectionType=Invalid connection type
|
||||
JSchConnectionProxyFactory_failed=failed
|
||||
JSchConnectionProxyFactory_ProxyCommandFailed=Proxy command "{0}" {1} and printed message "{2}"
|
||||
JSchConnectionProxyFactory_timedOut=timed out
|
||||
JSchConnectionProxyFactory_wasCanceled=was canceled
|
||||
JSchProcess_exitValue_exception_msg=process has not exited
|
||||
JSchProcessBuilder_Connection_is_not_open=Connection is not open
|
||||
JschFileStore_Connection_is_not_open=Connection is not open
|
||||
JschFileStore_File_doesnt_exist=File {0} doesn't exist
|
||||
JschFileStore_Invalid_connection_for_URI=Invalid connection for URI: "{0}"
|
||||
JschFileStore_Is_a_directory={0} is a directory
|
||||
JschFileStore_No_remote_services_found_for_URI=No remote services found for URI: "{0}"
|
||||
JschFileStore_The_directory_could_not_be_created=The directory {0} could not be created
|
||||
JschFileStore_A_file_of_name_already_exists=A file of name {0} already exists
|
||||
JschFileStore_The_parent_of_directory_does_not_exist=The parent of directory {0} does not exist
|
|
@ -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/JavaSE-1.8"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
1
bundles/org.eclipse.remote.proxy.protocol.core/.gitignore
vendored
Normal file
1
bundles/org.eclipse.remote.proxy.protocol.core/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/bin
|
34
bundles/org.eclipse.remote.proxy.protocol.core/.project
Normal file
34
bundles/org.eclipse.remote.proxy.protocol.core/.project
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.eclipse.remote.proxy.protocol.core</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>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,11 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
|
@ -0,0 +1,16 @@
|
|||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: %pluginName
|
||||
Bundle-SymbolicName: org.eclipse.remote.proxy.protocol.core;singleton:=true
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Activator: org.eclipse.remote.internal.proxy.protocol.core.Activator
|
||||
Bundle-Vendor: %pluginProvider
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Export-Package: org.eclipse.remote.proxy.protocol.core,
|
||||
org.eclipse.remote.proxy.protocol.core.exceptions
|
||||
Bundle-Localization: plugin
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Import-Package: org.eclipse.core.filesystem,
|
||||
org.eclipse.core.filesystem.provider,
|
||||
org.eclipse.core.runtime,
|
||||
org.osgi.framework
|
22
bundles/org.eclipse.remote.proxy.protocol.core/about.html
Normal file
22
bundles/org.eclipse.remote.proxy.protocol.core/about.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>About</title>
|
||||
<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
|
||||
</head>
|
||||
<body lang="EN-US">
|
||||
<h2>About This Content</h2>
|
||||
|
||||
<p>May 2, 2006</p>
|
||||
<h3>License</h3>
|
||||
|
||||
<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
|
||||
Eclipse Public License Version 1.0 ("EPL"). 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, "Program" 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 ("Redistributor") 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.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,8 @@
|
|||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
plugin.properties,\
|
||||
about.html
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
###############################################################################
|
||||
# Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
pluginName=Remote Proxy Protocol Support
|
||||
pluginProvider=Eclipse PTP
|
16
bundles/org.eclipse.remote.proxy.protocol.core/pom.xml
Normal file
16
bundles/org.eclipse.remote.proxy.protocol.core/pom.xml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.eclipse.remote</groupId>
|
||||
<artifactId>remote-parent</artifactId>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../releng/org.eclipse.remote.build/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.eclipse.remote.proxy.protocol.core</artifactId>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</project>
|
|
@ -0,0 +1,116 @@
|
|||
package org.eclipse.remote.internal.proxy.protocol.core;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Plugin;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
|
||||
/**
|
||||
* The activator class controls the plug-in life cycle
|
||||
*/
|
||||
public class Activator extends Plugin {
|
||||
|
||||
// The plug-in ID
|
||||
public static final String PLUGIN_ID = "org.eclipse.remote.proxy.protocol.core"; //$NON-NLS-1$
|
||||
|
||||
// The shared instance
|
||||
private static Activator plugin;
|
||||
|
||||
/**
|
||||
* Returns the shared instance
|
||||
*
|
||||
* @return the shared instance
|
||||
*/
|
||||
public static Activator getDefault() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unique identifier
|
||||
*
|
||||
* @return
|
||||
* @since 5.0
|
||||
*/
|
||||
public static String getUniqueIdentifier() {
|
||||
if (getDefault() == null) {
|
||||
return PLUGIN_ID;
|
||||
}
|
||||
return getDefault().getBundle().getSymbolicName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the specified status with this plug-in's log.
|
||||
*
|
||||
* @param status
|
||||
* status to log
|
||||
*/
|
||||
public static void log(IStatus status) {
|
||||
getDefault().getLog().log(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an internal error with the specified message.
|
||||
*
|
||||
* @param message
|
||||
* the error message to log
|
||||
*/
|
||||
public static void log(String message) {
|
||||
log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, message, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an internal error with the specified throwable
|
||||
*
|
||||
* @param e
|
||||
* the exception to be logged
|
||||
*/
|
||||
public static void log(Throwable e) {
|
||||
log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, e.getMessage(), e));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The constructor
|
||||
*/
|
||||
public Activator() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the OSGi service with the given service interface.
|
||||
*
|
||||
* @param service service interface
|
||||
* @return the specified service or null if it's not registered
|
||||
*/
|
||||
public static <T> T getService(Class<T> service) {
|
||||
BundleContext context = plugin.getBundle().getBundleContext();
|
||||
ServiceReference<T> ref = context.getServiceReference(service);
|
||||
return ref != null ? context.getService(ref) : null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext
|
||||
* )
|
||||
*/
|
||||
@Override
|
||||
public void start(BundleContext context) throws Exception {
|
||||
super.start(context);
|
||||
plugin = this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
|
||||
* )
|
||||
*/
|
||||
@Override
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
plugin = null;
|
||||
super.stop(context);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.proxy.protocol.core;
|
||||
|
||||
public class Protocol {
|
||||
public static final int MAGIC = 0xAFFA;
|
||||
|
||||
public final static byte PROTO_COMMAND = 1;
|
||||
public final static byte PROTO_SHUTDOWN = 2;
|
||||
public final static byte PROTO_ERROR = 126;
|
||||
public final static byte PROTO_OK = 0;
|
||||
|
||||
public final static short CmdBase = 100;
|
||||
|
||||
public final static short CMD_EXEC = CmdBase + 1;
|
||||
public final static short CMD_SHELL = CmdBase + 2;
|
||||
public final static short CMD_GETCWD = CmdBase + 3;
|
||||
public final static short CMD_GETENV = CmdBase + 4;
|
||||
public final static short CMD_CHILDINFOS = CmdBase + 5;
|
||||
public final static short CMD_DELETE = CmdBase + 6;
|
||||
public final static short CMD_FETCHINFO = CmdBase + 7;
|
||||
public final static short CMD_GETINPUTSTREAM = CmdBase + 8;
|
||||
public final static short CMD_GETOUTPUTSTREAM = CmdBase + 9;
|
||||
public final static short CMD_MKDIR = CmdBase + 10;
|
||||
public final static short CMD_PUTINFO = CmdBase + 11;
|
||||
public final static short CMD_GETPROPERTIES = CmdBase + 12;
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.proxy.protocol.core;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.eclipse.core.filesystem.EFS;
|
||||
import org.eclipse.core.filesystem.IFileInfo;
|
||||
import org.eclipse.core.filesystem.provider.FileInfo;
|
||||
|
||||
public class SerializableFileInfo implements Serializable {
|
||||
private static final long serialVersionUID = -1986643088683154145L;
|
||||
|
||||
private IFileInfo info;
|
||||
|
||||
public SerializableFileInfo() {
|
||||
}
|
||||
|
||||
public SerializableFileInfo(IFileInfo info) {
|
||||
setIFileInfo(info);
|
||||
}
|
||||
|
||||
public void setIFileInfo(IFileInfo info) {
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public IFileInfo getIFileInfo() {
|
||||
return info;
|
||||
}
|
||||
|
||||
public void writeObject(DataOutputStream out) throws IOException {
|
||||
out.writeUTF(info.getName());
|
||||
boolean symlink = info.getAttribute(EFS.ATTRIBUTE_SYMLINK);
|
||||
out.writeBoolean(symlink);
|
||||
if (symlink) {
|
||||
out.writeUTF(info.getStringAttribute(EFS.ATTRIBUTE_LINK_TARGET));
|
||||
}
|
||||
out.writeBoolean(info.exists());
|
||||
out.writeLong(info.getLastModified());
|
||||
out.writeLong(info.getLength());
|
||||
out.writeBoolean(info.isDirectory());
|
||||
out.writeBoolean(info.getAttribute(EFS.ATTRIBUTE_GROUP_READ));
|
||||
out.writeBoolean(info.getAttribute(EFS.ATTRIBUTE_GROUP_WRITE));
|
||||
out.writeBoolean(info.getAttribute(EFS.ATTRIBUTE_GROUP_EXECUTE));
|
||||
out.writeBoolean(info.getAttribute(EFS.ATTRIBUTE_OTHER_READ));
|
||||
out.writeBoolean(info.getAttribute(EFS.ATTRIBUTE_OTHER_WRITE));
|
||||
out.writeBoolean(info.getAttribute(EFS.ATTRIBUTE_OTHER_EXECUTE));
|
||||
out.writeBoolean(info.getAttribute(EFS.ATTRIBUTE_OWNER_READ));
|
||||
out.writeBoolean(info.getAttribute(EFS.ATTRIBUTE_OWNER_WRITE));
|
||||
out.writeBoolean(info.getAttribute(EFS.ATTRIBUTE_OWNER_EXECUTE));
|
||||
}
|
||||
|
||||
public void readObject(DataInputStream in) throws IOException {
|
||||
FileInfo newInfo = new FileInfo();
|
||||
|
||||
try {
|
||||
newInfo.setName(in.readUTF());
|
||||
boolean symlink = in.readBoolean();
|
||||
newInfo.setAttribute(EFS.ATTRIBUTE_SYMLINK, symlink);
|
||||
if (symlink) {
|
||||
newInfo.setStringAttribute(EFS.ATTRIBUTE_LINK_TARGET, in.readUTF());
|
||||
}
|
||||
newInfo.setExists(in.readBoolean());
|
||||
newInfo.setLastModified(in.readLong());
|
||||
newInfo.setLength(in.readLong());
|
||||
newInfo.setDirectory(in.readBoolean());
|
||||
newInfo.setAttribute(EFS.ATTRIBUTE_GROUP_READ, in.readBoolean());
|
||||
newInfo.setAttribute(EFS.ATTRIBUTE_GROUP_WRITE, in.readBoolean());
|
||||
newInfo.setAttribute(EFS.ATTRIBUTE_GROUP_EXECUTE, in.readBoolean());
|
||||
newInfo.setAttribute(EFS.ATTRIBUTE_OTHER_READ, in.readBoolean());
|
||||
newInfo.setAttribute(EFS.ATTRIBUTE_OTHER_WRITE, in.readBoolean());
|
||||
newInfo.setAttribute(EFS.ATTRIBUTE_OTHER_EXECUTE, in.readBoolean());
|
||||
newInfo.setAttribute(EFS.ATTRIBUTE_OWNER_READ, in.readBoolean());
|
||||
newInfo.setAttribute(EFS.ATTRIBUTE_OWNER_WRITE, in.readBoolean());
|
||||
newInfo.setAttribute(EFS.ATTRIBUTE_OWNER_EXECUTE, in.readBoolean());
|
||||
} catch (IOException e) {
|
||||
newInfo.setError(IFileInfo.IO_ERROR);
|
||||
}
|
||||
|
||||
setIFileInfo(newInfo);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,365 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.proxy.protocol.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class StreamChannel {
|
||||
public static final int CAPACITY = 8192;
|
||||
|
||||
private class ChannelInputStream extends InputStream {
|
||||
private final Lock lock = new ReentrantLock();
|
||||
private final Condition cond = lock.newCondition();
|
||||
private final StreamChannel channel;
|
||||
|
||||
private int currentPos;
|
||||
private int currentSize;
|
||||
private boolean connected = true;
|
||||
private int inputRequestCount;
|
||||
private byte[] buffer = new byte[CAPACITY];
|
||||
|
||||
public ChannelInputStream(StreamChannel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int read() throws IOException {
|
||||
byte[] b = new byte[1];
|
||||
if (read(b, 0, 1) != 1) {
|
||||
return -1;
|
||||
}
|
||||
return b[0] & 0xff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
lock.lock();
|
||||
try {
|
||||
return currentSize - currentPos;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized int read(byte b[], int off, int len) throws IOException {
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int moreSpace;
|
||||
lock.lock();
|
||||
try {
|
||||
if (currentPos >= currentSize) {
|
||||
currentPos = currentSize = 0;
|
||||
} else if (currentPos >= CAPACITY/2) {
|
||||
System.arraycopy(buffer, currentPos, buffer, 0, currentSize - currentPos);
|
||||
currentSize -= currentPos;
|
||||
currentPos = 0;
|
||||
}
|
||||
int freeSpace = CAPACITY - currentSize;
|
||||
moreSpace = Math.max(freeSpace - inputRequestCount, 0);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
if (moreSpace > 0) {
|
||||
mux.sendRequestCmd(StreamChannel.this, moreSpace);
|
||||
}
|
||||
lock.lock();
|
||||
try {
|
||||
inputRequestCount += moreSpace;
|
||||
while (currentPos >= currentSize && connected) {
|
||||
try {
|
||||
cond.await();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (!connected && currentPos >= currentSize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int available = currentSize - currentPos;
|
||||
if (len < available) {
|
||||
System.arraycopy(buffer, currentPos, b, off, len);
|
||||
currentPos += len;
|
||||
return len;
|
||||
} else {
|
||||
System.arraycopy(buffer, currentPos, b, off, available);
|
||||
currentPos = currentSize = 0;
|
||||
return available;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
channel.closeOutput();
|
||||
disconnect();
|
||||
}
|
||||
|
||||
void receive(byte[] buf, int len) throws IOException {
|
||||
lock.lock();
|
||||
try {
|
||||
if (currentPos > 0 && (CAPACITY - currentSize) < len) {
|
||||
System.arraycopy(buffer, currentPos, buffer, 0, currentSize - currentPos);
|
||||
currentSize -= currentPos;
|
||||
currentPos = 0;
|
||||
}
|
||||
if (CAPACITY - currentSize < len) {
|
||||
throw new IOException("Receive buffer overflow");
|
||||
}
|
||||
System.arraycopy(buf, 0, buffer, currentSize, len);
|
||||
currentSize += len;
|
||||
inputRequestCount -= len;
|
||||
cond.signalAll();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void disconnect() {
|
||||
lock.lock();
|
||||
try {
|
||||
connected = false;
|
||||
cond.signalAll();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
boolean isConnected() {
|
||||
lock.lock();
|
||||
try {
|
||||
return connected;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ChannelOutputStream extends OutputStream {
|
||||
private final Lock lock = new ReentrantLock();
|
||||
private final Condition cond = lock.newCondition();
|
||||
private final StreamChannel channel;
|
||||
|
||||
private int currentPos;
|
||||
private byte[] buffer = new byte[CAPACITY];
|
||||
private boolean connected = true;
|
||||
private int outputRequestCount;
|
||||
|
||||
public ChannelOutputStream(StreamChannel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void write(int b) throws IOException {
|
||||
while (currentPos >= CAPACITY) {
|
||||
send();
|
||||
}
|
||||
buffer[currentPos++] = (byte)b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void flush() throws IOException {
|
||||
while (currentPos > 0) {
|
||||
send();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void write(byte[] b, int off, int len) throws IOException {
|
||||
if (len <= 0) {
|
||||
return;
|
||||
}
|
||||
if (len <= CAPACITY - currentPos) {
|
||||
System.arraycopy(b, off, buffer, currentPos, len);
|
||||
currentPos += len;
|
||||
return;
|
||||
}
|
||||
flush();
|
||||
int canSend;
|
||||
while (true) {
|
||||
lock.lock();
|
||||
try {
|
||||
while ((canSend = outputRequestCount) == 0 && connected) {
|
||||
try {
|
||||
cond.await();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (!connected) {
|
||||
throw new IOException("channel closed");
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
if (canSend < len) {
|
||||
mux.sendTransmitCmd(StreamChannel.this, b, off, canSend);
|
||||
off += canSend;
|
||||
len -= canSend;
|
||||
lock.lock();
|
||||
outputRequestCount -= canSend;
|
||||
lock.unlock();
|
||||
} else {
|
||||
mux.sendTransmitCmd(StreamChannel.this, b, off, len);
|
||||
lock.lock();
|
||||
outputRequestCount -= len;
|
||||
lock.unlock();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void send() throws IOException {
|
||||
int canSend;
|
||||
lock.lock();
|
||||
try {
|
||||
while ((canSend = outputRequestCount) == 0 && connected) {
|
||||
try {
|
||||
cond.await();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (!connected) {
|
||||
throw new IOException("channel closed");
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
if (canSend < currentPos) {
|
||||
mux.sendTransmitCmd(StreamChannel.this, buffer, 0, canSend);
|
||||
currentPos -= canSend;
|
||||
System.arraycopy(buffer, canSend, buffer, 0, currentPos);
|
||||
lock.lock();
|
||||
outputRequestCount -= canSend;
|
||||
lock.unlock();
|
||||
} else {
|
||||
mux.sendTransmitCmd(StreamChannel.this, buffer, 0, currentPos);
|
||||
lock.lock();
|
||||
outputRequestCount -= currentPos;
|
||||
lock.unlock();
|
||||
currentPos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
flush();
|
||||
channel.closeInput();
|
||||
disconnect();
|
||||
}
|
||||
|
||||
void request(int len) {
|
||||
lock.lock();
|
||||
outputRequestCount += len;
|
||||
cond.signalAll();
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
void disconnect() {
|
||||
lock.lock();
|
||||
try {
|
||||
connected = false;
|
||||
cond.signalAll();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
boolean isConnected() {
|
||||
lock.lock();
|
||||
try {
|
||||
return connected;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private final StreamChannelManager mux;
|
||||
private final int channelId;
|
||||
private final ChannelInputStream min = new ChannelInputStream(this);
|
||||
private final ChannelOutputStream mout = new ChannelOutputStream(this);
|
||||
|
||||
private boolean open;
|
||||
|
||||
public StreamChannel(StreamChannelManager mux, int id) {
|
||||
this.mux = mux;
|
||||
channelId = id;
|
||||
open = true;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return channelId;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
return min;
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() {
|
||||
return mout;
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return open;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
mux.sendCloseCmd(this);
|
||||
}
|
||||
|
||||
void receive(byte[] buf, int len) throws IOException {
|
||||
min.receive(buf, len);
|
||||
}
|
||||
|
||||
void request(int len) {
|
||||
mout.request(len);
|
||||
}
|
||||
|
||||
void disconnect() {
|
||||
min.disconnect();
|
||||
mout.disconnect();
|
||||
}
|
||||
|
||||
void setClosed() {
|
||||
open = false;
|
||||
}
|
||||
|
||||
void disconnectInput() {
|
||||
min.disconnect();
|
||||
}
|
||||
|
||||
void disconnectOutput() {
|
||||
mout.disconnect();
|
||||
}
|
||||
|
||||
void closeInput() throws IOException {
|
||||
mux.sendCloseInputCmd(this);
|
||||
}
|
||||
|
||||
void closeOutput() throws IOException {
|
||||
mux.sendCloseOutputCmd(this);
|
||||
}
|
||||
|
||||
boolean isInputConnected() {
|
||||
return min.isConnected();
|
||||
}
|
||||
|
||||
boolean isOutputConnected() {
|
||||
return mout.isConnected();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,562 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.proxy.protocol.core;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
public class StreamChannelManager implements Runnable {
|
||||
public interface IChannelListener {
|
||||
public void newChannel(StreamChannel chan);
|
||||
public void closeChannel(StreamChannel chan);
|
||||
}
|
||||
|
||||
private class Sender implements Runnable {
|
||||
private OutputStream out;
|
||||
private BlockingQueue<ByteArrayOutputStream> queue = new LinkedBlockingQueue<ByteArrayOutputStream>();
|
||||
private boolean running = true;
|
||||
|
||||
public Sender(OutputStream out) {
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
public void sendOpenCmd(int id) throws IOException {
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
DataOutputStream data = new DataOutputStream(bytes);
|
||||
data.writeByte(CMD_OPEN);
|
||||
data.writeByte(id);
|
||||
try {
|
||||
queue.put(bytes);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void sendTransmitCmd(int id, byte buf[], int off, int len) throws IOException {
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
DataOutputStream data = new DataOutputStream(bytes);
|
||||
data.writeByte(CMD_TRANSMIT);
|
||||
data.writeByte(id);
|
||||
data.writeInt(len);
|
||||
data.write(buf, off, len);
|
||||
try {
|
||||
queue.put(bytes);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void sendCloseCmd(int id) throws IOException {
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
DataOutputStream data = new DataOutputStream(bytes);
|
||||
data.writeByte(CMD_CLOSE);
|
||||
data.writeByte(id);
|
||||
try {
|
||||
queue.put(bytes);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void sendCloseAckCmd(int id) throws IOException {
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
DataOutputStream data = new DataOutputStream(bytes);
|
||||
data.writeByte(CMD_CLOSEACK);
|
||||
data.writeByte(id);
|
||||
try {
|
||||
queue.put(bytes);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void sendRequestCmd(int id, int len) throws IOException {
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
DataOutputStream data = new DataOutputStream(bytes);
|
||||
data.writeByte(CMD_REQUEST);
|
||||
data.writeByte(id);
|
||||
data.writeInt(len);
|
||||
try {
|
||||
queue.put(bytes);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void sendCloseInputCmd(int id) throws IOException {
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
DataOutputStream data = new DataOutputStream(bytes);
|
||||
data.writeByte(CMD_CLOSE_INPUT);
|
||||
data.writeByte(id);
|
||||
try {
|
||||
queue.put(bytes);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void sendCloseOutputCmd(int id) throws IOException {
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
DataOutputStream data = new DataOutputStream(bytes);
|
||||
data.writeByte(CMD_CLOSE_OUTPUT);
|
||||
data.writeByte(id);
|
||||
try {
|
||||
queue.put(bytes);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
running = false;
|
||||
try {
|
||||
queue.put(new ByteArrayOutputStream());
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (running) {
|
||||
ByteArrayOutputStream bytes = queue.take();
|
||||
if (bytes != null) {
|
||||
bytes.writeTo(out);
|
||||
out.flush();
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean isMyChannel(int id) {
|
||||
return !(isServer ^ ((id & SERVER_ID_MASK) == SERVER_ID_MASK));
|
||||
}
|
||||
|
||||
private class Receiver implements Runnable {
|
||||
private DataInputStream dataIn;
|
||||
|
||||
public Receiver(InputStream in) {
|
||||
this.dataIn = new DataInputStream(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
StreamChannel chan;
|
||||
running = true;
|
||||
try {
|
||||
while (true) {
|
||||
debugPrint("start read");
|
||||
int cmd = dataIn.readByte() & 0xff;
|
||||
int id = dataIn.readByte() & 0xff;
|
||||
|
||||
switch (cmd) {
|
||||
case CMD_OPEN:
|
||||
debugPrint("received cmd=OPEN id="+id);
|
||||
chan = channels.get(id);
|
||||
if (chan != null) {
|
||||
throw new IOException("Channel already exists");
|
||||
}
|
||||
if (!isServer && (id & SERVER_ID_MASK) != SERVER_ID_MASK) {
|
||||
throw new IOException("Client received invalid server channel id: " + id);
|
||||
}
|
||||
if (isServer && (id & SERVER_ID_MASK) == SERVER_ID_MASK) {
|
||||
throw new IOException("Server received invalid client channel id: " + id);
|
||||
}
|
||||
chan = new StreamChannel(StreamChannelManager.this, id);
|
||||
channels.put(id, chan);
|
||||
newChannelCallback(chan);
|
||||
break;
|
||||
|
||||
case CMD_CLOSE:
|
||||
/*
|
||||
* Received a command to close the channel.
|
||||
* Clean up channel and free channel ID if we allocated it.
|
||||
*/
|
||||
debugPrint("received cmd=CLOSE id="+id);
|
||||
chan = channels.get(id);
|
||||
if (chan == null) {
|
||||
throw new IOException("CLOSE: Invalid channel id: " + id);
|
||||
}
|
||||
chan.disconnect();
|
||||
if (chan.isOpen()) {
|
||||
sendCloseAckCmd(chan);
|
||||
}
|
||||
closeChannelCallback(chan);
|
||||
channels.remove(id);
|
||||
if (isMyChannel(id)) {
|
||||
freeId(id);
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_CLOSEACK:
|
||||
/*
|
||||
* Received acknowledgement for our close command.
|
||||
* Clean up channel and free channel ID if we allocated it.
|
||||
*/
|
||||
debugPrint("received cmd=CLOSEACK id="+id);
|
||||
chan = channels.get(id);
|
||||
if (chan == null) {
|
||||
throw new IOException("CLOSEACK: Invalid channel id");
|
||||
}
|
||||
if (chan.isOpen()) {
|
||||
throw new IOException("Channel is still open");
|
||||
}
|
||||
chan.disconnect();
|
||||
channels.remove(id);
|
||||
if (isMyChannel(id)) {
|
||||
freeId(id);
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_TRANSMIT:
|
||||
debugPrint("received cmd=TRANSMIT id="+id);
|
||||
chan = channels.get(id);
|
||||
if (chan == null) {
|
||||
throw new IOException("TRANSMIT: Invalid channel id: " + id);
|
||||
}
|
||||
int len = dataIn.readInt();
|
||||
byte[] buf = new byte[len];
|
||||
dataIn.readFully(buf, 0, len);
|
||||
chan.receive(buf, len);
|
||||
break;
|
||||
|
||||
case CMD_REQUEST:
|
||||
chan = channels.get(id);
|
||||
if (chan == null) {
|
||||
throw new IOException("REQUEST: Invalid channel id: " + id);
|
||||
}
|
||||
int req = dataIn.readInt();
|
||||
debugPrint("received cmd=REQUEST id="+id+ " len="+req);
|
||||
chan.request(req);
|
||||
break;
|
||||
|
||||
case CMD_CLOSE_INPUT:
|
||||
/*
|
||||
* Received a command to close the input side of the channel.
|
||||
*/
|
||||
debugPrint("received cmd=CLOSE_INPUT id="+id);
|
||||
chan = channels.get(id);
|
||||
if (chan == null) {
|
||||
throw new IOException("CLOSE: Invalid channel id: " + id);
|
||||
}
|
||||
chan.disconnectInput();
|
||||
break;
|
||||
|
||||
|
||||
case CMD_CLOSE_OUTPUT:
|
||||
/*
|
||||
* Received a command to close the output side of the channel.
|
||||
*/
|
||||
debugPrint("received cmd=CLOSE_OUTPUT id="+id);
|
||||
chan = channels.get(id);
|
||||
if (chan == null) {
|
||||
throw new IOException("CLOSE: Invalid channel id: " + id);
|
||||
}
|
||||
chan.disconnectOutput();
|
||||
break;
|
||||
|
||||
default:
|
||||
synchronized (System.err) {
|
||||
System.err.print("invalid command: "+ dump_byte((byte)cmd) + dump_byte((byte)id));
|
||||
}
|
||||
try {
|
||||
while (true) {
|
||||
byte b = dataIn.readByte();
|
||||
System.err.print(dump_byte(b));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
throw new IOException("Invalid command: " + cmd);
|
||||
}
|
||||
}
|
||||
} catch (EOFException e) {
|
||||
// Finish
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
debugPrint("run got exception:" + e.getMessage());
|
||||
} finally {
|
||||
debugPrint("shutting down manager");
|
||||
StreamChannelManager.this.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
try {
|
||||
dataIn.close();
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final static int CMD_OPEN = 0xA1; // Open a new channel
|
||||
private final static int CMD_CLOSE = 0xA2; // Close a channel; acknowledgement required
|
||||
private final static int CMD_CLOSEACK = 0xA3; // Channel close acknowledgement
|
||||
private final static int CMD_REQUEST = 0xA4; // Request buffer space
|
||||
private final static int CMD_TRANSMIT = 0xA5; // Transmit a buffer
|
||||
private final static int CMD_CLOSE_INPUT = 0xA6; // Close input side of the channel; no acknowledgement required
|
||||
private final static int CMD_CLOSE_OUTPUT = 0xA7; // Close output side of the channel; no acknowledgement required
|
||||
|
||||
private final static int SERVER_ID_MASK = 1 << 15;
|
||||
private final static int MAX_CHANNELS = SERVER_ID_MASK >> 1;
|
||||
|
||||
private final Map<Integer, StreamChannel> channels = (Map<Integer, StreamChannel>) Collections.synchronizedMap(new HashMap<Integer,StreamChannel>());
|
||||
private final List<IChannelListener> listeners = (List<IChannelListener>)Collections.synchronizedList(new ArrayList<IChannelListener>());
|
||||
|
||||
private Set<Short> usedIds = new HashSet<>();
|
||||
private int nextUnusedChannelId;
|
||||
private boolean isServer;
|
||||
|
||||
private volatile boolean running = true;
|
||||
|
||||
private Sender sender;
|
||||
private Receiver receiver;
|
||||
|
||||
private boolean debug = true;
|
||||
|
||||
public StreamChannelManager(InputStream in, OutputStream out) {
|
||||
sender = new Sender(new BufferedOutputStream(out));
|
||||
receiver = new Receiver(new BufferedInputStream(in));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clients allocate IDs with leading bit 0
|
||||
* Servers allocate IDs with leading bit 1
|
||||
*
|
||||
* Reuse an ID if it is not longer being used.
|
||||
*
|
||||
* @return new ID
|
||||
*/
|
||||
synchronized int newId() throws IOException {
|
||||
if (!usedIds.isEmpty()) {
|
||||
Short id = usedIds.iterator().next();
|
||||
usedIds.remove(id);
|
||||
debugPrint("recover id="+id);
|
||||
return id;
|
||||
}
|
||||
int nextId = nextUnusedChannelId;
|
||||
if (nextUnusedChannelId++ > (MAX_CHANNELS - 1)) {
|
||||
throw new IOException("Maximum number of channels exceeded");
|
||||
}
|
||||
return nextId | (isServer ? SERVER_ID_MASK : 0);
|
||||
}
|
||||
|
||||
synchronized void freeId(int id) {
|
||||
debugPrint("free id="+id);
|
||||
usedIds.add((short)id);
|
||||
}
|
||||
|
||||
void dump_buf(String pref, byte[] b, int off, int len) {
|
||||
System.err.print(pref + ": ");
|
||||
for (int i = off; i < len+off; i++) {
|
||||
if (b[i] <= 32 || b[i] > 126) {
|
||||
System.err.print(String.format(" 0x%02x ", b[i]));
|
||||
} else {
|
||||
System.err.print((char)b[i]);
|
||||
}
|
||||
}
|
||||
System.err.println();
|
||||
}
|
||||
|
||||
public boolean isServer() {
|
||||
return isServer;
|
||||
}
|
||||
|
||||
public void setServer(boolean server) {
|
||||
isServer = server;
|
||||
}
|
||||
|
||||
public void addListener(IChannelListener listener) {
|
||||
if (!listeners.contains(listener)) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeListener(IChannelListener listener) {
|
||||
if (listeners.contains(listener)) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
protected void newChannelCallback(StreamChannel chan) {
|
||||
for (IChannelListener listener : listeners.toArray(new IChannelListener[listeners.size()])) {
|
||||
listener.newChannel(chan);
|
||||
}
|
||||
}
|
||||
|
||||
protected void closeChannelCallback(StreamChannel chan) {
|
||||
for (IChannelListener listener : listeners.toArray(new IChannelListener[listeners.size()])) {
|
||||
listener.closeChannel(chan);
|
||||
}
|
||||
}
|
||||
|
||||
public String dump_byte(byte b) {
|
||||
if (b <= 32 || b > 126) {
|
||||
return String.format(" 0x%02x ", b);
|
||||
}
|
||||
|
||||
return String.valueOf((char)b);
|
||||
}
|
||||
|
||||
public StreamChannel openChannel() throws IOException {
|
||||
if (!running) {
|
||||
throw new IOException("Multiplexer is not running");
|
||||
}
|
||||
|
||||
StreamChannel chan = new StreamChannel(this, newId());
|
||||
channels.put(chan.getId(), chan);
|
||||
|
||||
debugPrint("send cmd=OPEN id="+chan.getId());
|
||||
sender.sendOpenCmd(chan.getId());
|
||||
|
||||
return chan;
|
||||
}
|
||||
|
||||
synchronized void sendTransmitCmd(StreamChannel chan, byte buf[], int off, int len) throws IOException {
|
||||
if (running && chan.isOpen()) {
|
||||
debugPrint("send cmd=TRANSMIT id="+chan.getId()+" len="+len + " off=" + off + " buflen="+buf.length);
|
||||
sender.sendTransmitCmd(chan.getId(), buf, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void sendCloseCmd(StreamChannel chan) throws IOException {
|
||||
if (running && chan.isOpen()) {
|
||||
debugPrint("send cmd=CLOSE id="+chan.getId());
|
||||
chan.disconnect();
|
||||
sender.sendCloseCmd(chan.getId());
|
||||
chan.setClosed();
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void sendCloseAckCmd(StreamChannel chan) throws IOException {
|
||||
if (running && chan.isOpen()) {
|
||||
debugPrint("send cmd=CLOSEACK id="+chan.getId());
|
||||
sender.sendCloseAckCmd(chan.getId());
|
||||
chan.setClosed();
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void sendRequestCmd(StreamChannel chan, int len) throws IOException {
|
||||
if (running && chan.isOpen()) {
|
||||
debugPrint("send cmd=REQUEST id="+chan.getId()+" len="+len);
|
||||
sender.sendRequestCmd(chan.getId(), len);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void sendCloseInputCmd(StreamChannel chan) throws IOException {
|
||||
if (running && chan.isOpen()) {
|
||||
if (!chan.isOutputConnected()) {
|
||||
sendCloseCmd(chan);
|
||||
} else {
|
||||
debugPrint("send cmd=CLOSE_INPUT id="+chan.getId());
|
||||
sender.sendCloseInputCmd(chan.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void sendCloseOutputCmd(StreamChannel chan) throws IOException {
|
||||
if (running && chan.isOpen()) {
|
||||
if (!chan.isInputConnected()) {
|
||||
sendCloseCmd(chan);
|
||||
} else {
|
||||
debugPrint("send cmd=CLOSE_OUTPUT id="+chan.getId());
|
||||
sender.sendCloseOutputCmd(chan.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void debugPrint(String x) {
|
||||
if (debug) {
|
||||
synchronized (System.err) {
|
||||
System.err.println(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
if (!running) {
|
||||
return;
|
||||
}
|
||||
running = false;
|
||||
|
||||
synchronized (channels) {
|
||||
for (StreamChannel c : channels.values()) {
|
||||
c.disconnect();
|
||||
}
|
||||
}
|
||||
channels.clear();
|
||||
|
||||
sender.shutdown();
|
||||
receiver.shutdown();
|
||||
debugPrint("chan mpx stopped");
|
||||
// Should in and out be closed also?
|
||||
}
|
||||
|
||||
private String asString(int v) {
|
||||
switch (v) {
|
||||
case CMD_OPEN:
|
||||
return "OPEN";
|
||||
|
||||
case CMD_CLOSE:
|
||||
return "CLOSE";
|
||||
|
||||
case CMD_CLOSEACK:
|
||||
return "CLOSEACK";
|
||||
|
||||
case CMD_TRANSMIT:
|
||||
return "TRANSMIT";
|
||||
|
||||
case CMD_REQUEST:
|
||||
return "REQUEST";
|
||||
}
|
||||
return "<UNKNOWN>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
debugPrint("mux starting");
|
||||
new Thread(sender, "mux sender").start();
|
||||
receiver.run();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.proxy.protocol.core.exceptions;
|
||||
|
||||
public class ProxyException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ProxyException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
7
bundles/org.eclipse.remote.proxy.server.core/.classpath
Normal file
7
bundles/org.eclipse.remote.proxy.server.core/.classpath
Normal 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/JavaSE-1.8"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
1
bundles/org.eclipse.remote.proxy.server.core/.gitignore
vendored
Normal file
1
bundles/org.eclipse.remote.proxy.server.core/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/bin/
|
28
bundles/org.eclipse.remote.proxy.server.core/.project
Normal file
28
bundles/org.eclipse.remote.proxy.server.core/.project
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.eclipse.remote.proxy.server.core</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>
|
|
@ -0,0 +1,7 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
|
@ -0,0 +1,4 @@
|
|||
eclipse.preferences.version=1
|
||||
pluginProject.equinox=false
|
||||
pluginProject.extensions=true
|
||||
resolve.requirebundle=false
|
|
@ -0,0 +1,17 @@
|
|||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: %pluginName
|
||||
Bundle-SymbolicName: org.eclipse.remote.proxy.server.core;singleton:=true
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Import-Package: org.eclipse.core.filesystem,
|
||||
org.eclipse.core.runtime,
|
||||
org.eclipse.core.runtime.adaptor,
|
||||
org.eclipse.equinox.app,
|
||||
org.eclipse.remote.core,
|
||||
org.eclipse.remote.proxy.protocol.core,
|
||||
org.eclipse.remote.proxy.protocol.core.exceptions,
|
||||
org.osgi.framework,
|
||||
org.osgi.framework.launch
|
||||
Bundle-Vendor: %pluginProvider
|
||||
Bundle-Localization: plugin
|
|
@ -0,0 +1,6 @@
|
|||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
plugin.xml,\
|
||||
plugin.properties
|
|
@ -0,0 +1,11 @@
|
|||
###############################################################################
|
||||
# Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
pluginName=Remote Proxy Server Support
|
||||
pluginProvider=Eclipse PTP
|
17
bundles/org.eclipse.remote.proxy.server.core/plugin.xml
Normal file
17
bundles/org.eclipse.remote.proxy.server.core/plugin.xml
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.4"?>
|
||||
<plugin>
|
||||
<extension
|
||||
id="application"
|
||||
point="org.eclipse.core.runtime.applications">
|
||||
<application
|
||||
cardinality="singleton-global"
|
||||
thread="main"
|
||||
visible="true">
|
||||
<run
|
||||
class="org.eclipse.remote.internal.proxy.server.core.Application">
|
||||
</run>
|
||||
</application>
|
||||
</extension>
|
||||
|
||||
</plugin>
|
16
bundles/org.eclipse.remote.proxy.server.core/pom.xml
Normal file
16
bundles/org.eclipse.remote.proxy.server.core/pom.xml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.eclipse.remote</groupId>
|
||||
<artifactId>remote-parent</artifactId>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../releng/org.eclipse.remote.build/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.eclipse.remote.proxy.server.core</artifactId>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</project>
|
|
@ -0,0 +1,14 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.server.commands;
|
||||
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public abstract class AbstractServerCommand {
|
||||
public abstract void exec() throws ProxyException;
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.server.commands;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
|
||||
import org.eclipse.core.filesystem.EFS;
|
||||
import org.eclipse.core.filesystem.IFileInfo;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.SerializableFileInfo;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class ServerChildInfosCommand extends AbstractServerCommand {
|
||||
private IFileInfo[] infos;
|
||||
|
||||
private final URI uri;
|
||||
private final OutputStream out;
|
||||
|
||||
private class CommandRunner implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
DataOutputStream result = new DataOutputStream(out);
|
||||
result.writeInt(infos.length);
|
||||
for (int i = 0; i < infos.length; i++) {
|
||||
SerializableFileInfo sInfo = new SerializableFileInfo(infos[i]);
|
||||
sInfo.writeObject(result);
|
||||
}
|
||||
result.flush();
|
||||
} catch (IOException e) {
|
||||
// Failed
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ServerChildInfosCommand(StreamChannel chan, String path) {
|
||||
this.out = chan.getOutputStream();
|
||||
this.uri = URI.create("file:" + path);
|
||||
}
|
||||
|
||||
public void exec() throws ProxyException {
|
||||
try {
|
||||
infos = EFS.getStore(uri).childInfos(EFS.NONE, null);
|
||||
} catch (CoreException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
new Thread(new CommandRunner()).start();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.server.commands;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.eclipse.core.filesystem.EFS;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class ServerDeleteCommand extends AbstractServerCommand {
|
||||
private final int options;
|
||||
private final URI uri;
|
||||
|
||||
public ServerDeleteCommand(int options, String path) {
|
||||
this.options = options;
|
||||
this.uri = URI.create("file:" + path);
|
||||
}
|
||||
|
||||
public void exec() throws ProxyException {
|
||||
try {
|
||||
EFS.getStore(uri).delete(options, new NullProgressMonitor());
|
||||
} catch (CoreException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,243 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.server.commands;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
/**
|
||||
* TODO: Fix hang if command fails...
|
||||
*
|
||||
*/
|
||||
public class ServerExecCommand extends AbstractServerCommand {
|
||||
|
||||
private final List<String> command;
|
||||
private final Map<String, String> env;
|
||||
private final boolean redirect;
|
||||
private final boolean appendEnv;
|
||||
private final String directory;
|
||||
private final InputStream stdin;
|
||||
private final OutputStream stdout;
|
||||
private final OutputStream stderr;
|
||||
private final DataOutputStream result;
|
||||
private final DataInputStream cmd;
|
||||
|
||||
private Process proc;
|
||||
|
||||
private class CommandRunner implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
ProcessBuilder builder = new ProcessBuilder(command);
|
||||
try {
|
||||
if (!appendEnv) {
|
||||
builder.environment().clear();
|
||||
builder.environment().putAll(env);
|
||||
} else {
|
||||
for (Map.Entry<String, String> entry : env.entrySet()) {
|
||||
String val = builder.environment().get(entry.getKey());
|
||||
if (val == null || !val.equals(entry.getValue())) {
|
||||
builder.environment().put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (UnsupportedOperationException | IllegalArgumentException e) {
|
||||
// Leave environment untouched
|
||||
}
|
||||
File dir = new File(directory);
|
||||
if (dir.exists() && dir.isAbsolute()) {
|
||||
builder.directory(dir);
|
||||
}
|
||||
builder.redirectErrorStream(redirect);
|
||||
try {
|
||||
int exit = 0;
|
||||
try {
|
||||
proc = builder.start();
|
||||
Forwarder stdoutFwd = startForwarder("stdout", proc.getInputStream(), stdout); //$NON-NLS-1$
|
||||
Forwarder stderrFwd = null;
|
||||
if (!redirect) {
|
||||
stderrFwd = startForwarder("stderr", proc.getErrorStream(), stderr); //$NON-NLS-1$
|
||||
}
|
||||
startForwarder("stdin", stdin, proc.getOutputStream()); //$NON-NLS-1$
|
||||
new Thread(new ProcMonitor(), "process monitor").start(); //$NON-NLS-1$
|
||||
System.err.println("wait for process");
|
||||
exit = proc.waitFor();
|
||||
System.err.println("wait for process close in");
|
||||
// stdoutFwd.terminate();
|
||||
// if (!redirect) {
|
||||
// stderrFwd.terminate();
|
||||
// }
|
||||
System.err.println("wait for readers");
|
||||
/*
|
||||
* After the process has finished, wait for the stdout and stderr forwarders to finish to
|
||||
* ensure that all output is flushed.
|
||||
*/
|
||||
// stdoutFwd.waitFor();
|
||||
// System.err.println("wait for process finished out");
|
||||
// if (stderrFwd != null) {
|
||||
// stderrFwd.waitFor();
|
||||
// }
|
||||
System.err.println("wait for readers done");
|
||||
} catch (IOException e) {
|
||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stderr));
|
||||
try {
|
||||
writer.write(e.getMessage());
|
||||
writer.flush();
|
||||
} catch (IOException e1) {
|
||||
// Things look pretty hopeless
|
||||
}
|
||||
exit = -1;
|
||||
}
|
||||
try {
|
||||
result.writeInt(exit);
|
||||
result.flush();
|
||||
} catch (IOException e) {
|
||||
// We're finished anyway
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// Ignore?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ProcMonitor implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
cmd.readByte();
|
||||
if (proc.isAlive()) {
|
||||
proc.destroyForcibly();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Finish
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Forwarder implements Runnable {
|
||||
private final InputStream in;
|
||||
private final OutputStream out;
|
||||
private final String name;
|
||||
|
||||
private volatile boolean running = true;
|
||||
private boolean terminated = false;
|
||||
|
||||
private final Lock lock = new ReentrantLock();
|
||||
private final Condition cond = lock.newCondition();
|
||||
|
||||
public Forwarder(String name, InputStream in, OutputStream out) {
|
||||
this.name = name;
|
||||
this.in = new BufferedInputStream(in);
|
||||
this.out = new BufferedOutputStream(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
byte[] buf = new byte[8192];
|
||||
int n;
|
||||
try {
|
||||
while (true) {
|
||||
// if (in.available() == 0) {
|
||||
// System.err.println("avail=0");
|
||||
// /* Avoid spinning if no data */
|
||||
// lock.lock();
|
||||
// try {
|
||||
// cond.await(100, TimeUnit.MILLISECONDS);
|
||||
// } catch (InterruptedException e) {
|
||||
// } finally {
|
||||
// lock.unlock();
|
||||
// }
|
||||
// continue;
|
||||
// }
|
||||
n = in.read(buf);
|
||||
if (n > 0) {
|
||||
out.write(buf, 0, n);
|
||||
out.flush();
|
||||
}
|
||||
if (n==0) System.err.println("forwarder n=0");
|
||||
if (n < 0) break;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Finish
|
||||
System.err.println("forwarder "+e.getMessage());
|
||||
}
|
||||
System.err.println("forwarder closing name="+name);
|
||||
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
// Best effort
|
||||
}
|
||||
lock.lock();
|
||||
terminated = true;
|
||||
try {
|
||||
cond.signalAll();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void terminate() {
|
||||
running = false;
|
||||
}
|
||||
|
||||
public synchronized void waitFor() {
|
||||
lock.lock();
|
||||
try {
|
||||
if (!terminated) {
|
||||
try {
|
||||
cond.await();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ServerExecCommand(List<String> command, Map<String, String> env, String directory, boolean redirect, boolean appendEnv, StreamChannel chanA, StreamChannel chanB, StreamChannel chanC) {
|
||||
this.command = command;
|
||||
this.env = env;
|
||||
this.directory = directory;
|
||||
this.redirect = redirect;
|
||||
this.appendEnv = appendEnv;
|
||||
this.stdin = chanA.getInputStream();
|
||||
this.stdout = chanA.getOutputStream();
|
||||
this.stderr = chanB.getOutputStream();
|
||||
|
||||
this.result = new DataOutputStream(chanC.getOutputStream());
|
||||
this.cmd = new DataInputStream(chanC.getInputStream());
|
||||
}
|
||||
|
||||
public void exec() throws ProxyException {
|
||||
new Thread(new CommandRunner(), command.get(0)).start();
|
||||
}
|
||||
|
||||
private Forwarder startForwarder(String name, InputStream in, OutputStream out) {
|
||||
Forwarder forwarder = new Forwarder(name, in, out);
|
||||
Thread thread = new Thread(forwarder, command.get(0) + " " + name); //$NON-NLS-1$
|
||||
thread.start();
|
||||
return forwarder;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.server.commands;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
|
||||
import org.eclipse.core.filesystem.EFS;
|
||||
import org.eclipse.core.filesystem.IFileInfo;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.SerializableFileInfo;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class ServerFetchInfoCommand extends AbstractServerCommand {
|
||||
private IFileInfo info;
|
||||
|
||||
private final URI uri;
|
||||
private final OutputStream out;
|
||||
|
||||
private class CommandRunner implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
DataOutputStream result = new DataOutputStream(out);
|
||||
SerializableFileInfo sInfo = new SerializableFileInfo(info);
|
||||
sInfo.writeObject(result);
|
||||
result.flush();
|
||||
} catch (IOException e) {
|
||||
// Failed
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ServerFetchInfoCommand(StreamChannel chan, String path) {
|
||||
this.out = chan.getOutputStream();
|
||||
this.uri = URI.create("file:" + path);
|
||||
}
|
||||
|
||||
public void exec() throws ProxyException {
|
||||
try {
|
||||
info = EFS.getStore(uri).fetchInfo();
|
||||
} catch (CoreException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
new Thread(new CommandRunner()).start();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.server.commands;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class ServerGetCwdCommand extends AbstractServerCommand {
|
||||
|
||||
private String cwd;
|
||||
private final DataOutputStream result;
|
||||
|
||||
private class CommandRunner implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
result.writeUTF(cwd);
|
||||
result.flush();
|
||||
} catch (IOException e) {
|
||||
// Failed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ServerGetCwdCommand(StreamChannel chan) {
|
||||
this.result = new DataOutputStream(chan.getOutputStream());
|
||||
}
|
||||
|
||||
public void exec() throws ProxyException {
|
||||
cwd = System.getProperty("user.dir");
|
||||
new Thread(new CommandRunner()).start();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.server.commands;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class ServerGetEnvCommand extends AbstractServerCommand {
|
||||
|
||||
private final DataOutputStream result;
|
||||
|
||||
private class CommandRunner implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Map<String,String> env = System.getenv();
|
||||
result.writeInt(env.size());
|
||||
for (Map.Entry<String, String> entry : env.entrySet()) {
|
||||
result.writeUTF(entry.getKey());
|
||||
result.writeUTF(entry.getValue());
|
||||
}
|
||||
result.flush();
|
||||
} catch (IOException e) {
|
||||
// Failed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ServerGetEnvCommand(StreamChannel chan) {
|
||||
this.result = new DataOutputStream(chan.getOutputStream());
|
||||
}
|
||||
|
||||
public void exec() throws ProxyException {
|
||||
new Thread(new CommandRunner()).start();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.server.commands;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
|
||||
import org.eclipse.core.filesystem.EFS;
|
||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
/**
|
||||
* TODO: Fix hang if command fails...
|
||||
*
|
||||
*/
|
||||
public class ServerGetInputStreamCommand extends AbstractServerCommand {
|
||||
|
||||
private final OutputStream out;
|
||||
private final URI uri;
|
||||
private final int options;
|
||||
|
||||
private class Forwarder implements Runnable {
|
||||
private final InputStream in;
|
||||
private final OutputStream out;
|
||||
|
||||
public Forwarder(InputStream in, OutputStream out) {
|
||||
this.in = in;
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
byte[] buf = new byte[8192];
|
||||
int n;
|
||||
try {
|
||||
while ((n = in.read(buf)) >= 0) {
|
||||
if (n > 0) {
|
||||
out.write(buf, 0, n); // should block if no-one is reading
|
||||
out.flush();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Finish
|
||||
}
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ServerGetInputStreamCommand(StreamChannel chan, int options, String path) {
|
||||
this.out = chan.getOutputStream();
|
||||
this.options = options;
|
||||
this.uri = URI.create("file:" + path); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public void exec() throws ProxyException {
|
||||
try {
|
||||
InputStream in = new BufferedInputStream(EFS.getStore(uri).openInputStream(options, new NullProgressMonitor()));
|
||||
startForwarder(in, out);
|
||||
} catch (Exception e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void startForwarder(InputStream in, OutputStream out) {
|
||||
Forwarder forwarder = new Forwarder(in, out);
|
||||
new Thread(forwarder).start();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.server.commands;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
|
||||
import org.eclipse.core.filesystem.EFS;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
/**
|
||||
* TODO: Fix hang if command fails...
|
||||
*
|
||||
*/
|
||||
public class ServerGetOutputStreamCommand extends AbstractServerCommand {
|
||||
|
||||
private final InputStream in;
|
||||
private final URI uri;
|
||||
private final int options;
|
||||
|
||||
private class Forwarder implements Runnable {
|
||||
private final InputStream in;
|
||||
private final OutputStream out;
|
||||
|
||||
public Forwarder(InputStream in, OutputStream out) {
|
||||
this.in = in;
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
byte[] buf = new byte[8192];
|
||||
int n;
|
||||
try {
|
||||
while ((n = in.read(buf)) >= 0) {
|
||||
if (n > 0) {
|
||||
out.write(buf, 0, n); // should block if no-one is reading
|
||||
}
|
||||
}
|
||||
out.flush();
|
||||
} catch (IOException e) {
|
||||
// Finish
|
||||
}
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ServerGetOutputStreamCommand(StreamChannel chan, int options, String path) {
|
||||
this.in = chan.getInputStream();
|
||||
this.options = options;
|
||||
this.uri = URI.create("file:" + path); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public void exec() throws ProxyException {
|
||||
try {
|
||||
OutputStream out = new BufferedOutputStream(EFS.getStore(uri).openOutputStream(options, new NullProgressMonitor()));
|
||||
startForwarder(in, out);
|
||||
} catch (CoreException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void startForwarder(InputStream in, OutputStream out) {
|
||||
Forwarder forwarder = new Forwarder(in, out);
|
||||
new Thread(forwarder).start();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.server.commands;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.remote.core.IRemoteConnection;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class ServerGetPropertiesCommand extends AbstractServerCommand {
|
||||
|
||||
private final DataOutputStream result;
|
||||
|
||||
private class CommandRunner implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Map<String,String> props = new HashMap<String, String>();
|
||||
props.put(IRemoteConnection.FILE_SEPARATOR_PROPERTY, System.getProperty(IRemoteConnection.FILE_SEPARATOR_PROPERTY));
|
||||
props.put(IRemoteConnection.PATH_SEPARATOR_PROPERTY, System.getProperty(IRemoteConnection.PATH_SEPARATOR_PROPERTY));
|
||||
props.put(IRemoteConnection.LINE_SEPARATOR_PROPERTY, System.getProperty(IRemoteConnection.LINE_SEPARATOR_PROPERTY));
|
||||
props.put(IRemoteConnection.USER_HOME_PROPERTY, System.getProperty(IRemoteConnection.USER_HOME_PROPERTY));
|
||||
props.put(IRemoteConnection.OS_NAME_PROPERTY, System.getProperty(IRemoteConnection.OS_NAME_PROPERTY));
|
||||
props.put(IRemoteConnection.OS_VERSION_PROPERTY, System.getProperty(IRemoteConnection.OS_VERSION_PROPERTY));
|
||||
props.put(IRemoteConnection.OS_ARCH_PROPERTY, System.getProperty(IRemoteConnection.OS_ARCH_PROPERTY));
|
||||
props.put(IRemoteConnection.LOCALE_CHARMAP_PROPERTY, System.getProperty("file.encoding"));
|
||||
|
||||
result.writeInt(props.size());
|
||||
for (Map.Entry<String, String> entry : props.entrySet()) {
|
||||
result.writeUTF(entry.getKey());
|
||||
result.writeUTF(entry.getValue());
|
||||
}
|
||||
result.flush();
|
||||
} catch (IOException e) {
|
||||
// Failed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ServerGetPropertiesCommand(StreamChannel chan) {
|
||||
this.result = new DataOutputStream(chan.getOutputStream());
|
||||
}
|
||||
|
||||
public void exec() throws ProxyException {
|
||||
new Thread(new CommandRunner()).start();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.server.commands;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.eclipse.core.filesystem.EFS;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class ServerMkdirCommand extends AbstractServerCommand {
|
||||
private final int options;
|
||||
private final URI uri;
|
||||
|
||||
public ServerMkdirCommand(int options, String path) {
|
||||
this.options = options;
|
||||
this.uri = URI.create("file:" + path);
|
||||
}
|
||||
|
||||
public void exec() throws ProxyException {
|
||||
try {
|
||||
EFS.getStore(uri).mkdir(options, new NullProgressMonitor());
|
||||
} catch (CoreException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.server.commands;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.eclipse.core.filesystem.EFS;
|
||||
import org.eclipse.core.filesystem.IFileInfo;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class ServerPutInfoCommand extends AbstractServerCommand {
|
||||
private final IFileInfo info;
|
||||
private final int options;
|
||||
private final URI uri;
|
||||
|
||||
public ServerPutInfoCommand(IFileInfo info, int options, String path) {
|
||||
this.info = info;
|
||||
this.options = options;
|
||||
this.uri = URI.create("file:" + path);
|
||||
}
|
||||
|
||||
public void exec() throws ProxyException {
|
||||
try {
|
||||
EFS.getStore(uri).putInfo(info, options, new NullProgressMonitor());;
|
||||
} catch (CoreException e) {
|
||||
throw new ProxyException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.server.core;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.equinox.app.IApplication;
|
||||
import org.eclipse.equinox.app.IApplicationContext;
|
||||
import org.eclipse.remote.proxy.protocol.core.Protocol;
|
||||
|
||||
/**
|
||||
* This class controls all aspects of the application's execution
|
||||
*/
|
||||
public class Application implements IApplication {
|
||||
private Server server = new Server();
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext)
|
||||
*/
|
||||
public Object start(IApplicationContext context) throws Exception {
|
||||
String[] args = (String[])context.getArguments().get(IApplicationContext.APPLICATION_ARGS);
|
||||
for (String arg : args) {
|
||||
if (arg.equals("-magic")) {
|
||||
ByteBuffer b = ByteBuffer.allocate(4);
|
||||
b.putInt(Protocol.MAGIC);
|
||||
System.out.write(b.array());
|
||||
};
|
||||
}
|
||||
server.start();
|
||||
server.waitFor();
|
||||
return IApplication.EXIT_OK;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.equinox.app.IApplication#stop()
|
||||
*/
|
||||
public void stop() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,281 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.server.core;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.remote.internal.proxy.server.commands.AbstractServerCommand;
|
||||
import org.eclipse.remote.internal.proxy.server.commands.ServerChildInfosCommand;
|
||||
import org.eclipse.remote.internal.proxy.server.commands.ServerDeleteCommand;
|
||||
import org.eclipse.remote.internal.proxy.server.commands.ServerExecCommand;
|
||||
import org.eclipse.remote.internal.proxy.server.commands.ServerFetchInfoCommand;
|
||||
import org.eclipse.remote.internal.proxy.server.commands.ServerGetCwdCommand;
|
||||
import org.eclipse.remote.internal.proxy.server.commands.ServerGetEnvCommand;
|
||||
import org.eclipse.remote.internal.proxy.server.commands.ServerGetInputStreamCommand;
|
||||
import org.eclipse.remote.internal.proxy.server.commands.ServerGetOutputStreamCommand;
|
||||
import org.eclipse.remote.internal.proxy.server.commands.ServerGetPropertiesCommand;
|
||||
import org.eclipse.remote.internal.proxy.server.commands.ServerMkdirCommand;
|
||||
import org.eclipse.remote.internal.proxy.server.commands.ServerPutInfoCommand;
|
||||
import org.eclipse.remote.proxy.protocol.core.Protocol;
|
||||
import org.eclipse.remote.proxy.protocol.core.SerializableFileInfo;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
import org.eclipse.remote.proxy.protocol.core.exceptions.ProxyException;
|
||||
|
||||
public class CommandServer implements Runnable {
|
||||
private Server server;
|
||||
private DataInputStream cmdIn;
|
||||
private DataOutputStream cmdOut;
|
||||
private boolean running = true;
|
||||
private StreamChannel chan;
|
||||
|
||||
public CommandServer(StreamChannel chan, Server server) {
|
||||
this.chan = chan;
|
||||
this.server = server;
|
||||
this.cmdIn = new DataInputStream(chan.getInputStream());
|
||||
this.cmdOut = new DataOutputStream(chan.getOutputStream());
|
||||
}
|
||||
|
||||
public void run() {
|
||||
new Thread("cmd reader") {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (running) {
|
||||
byte proto = cmdIn.readByte();
|
||||
switch (proto) {
|
||||
case Protocol.PROTO_COMMAND:
|
||||
try {
|
||||
dispatchCommand(cmdIn);
|
||||
sendOKResult();
|
||||
} catch (ProxyException e) {
|
||||
sendErrorResult(e.getMessage());
|
||||
}
|
||||
break;
|
||||
|
||||
case Protocol.PROTO_SHUTDOWN:
|
||||
running = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("Invalid protocol ID: " + proto);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (EOFException e) {
|
||||
// Exit server
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
private void sendOKResult() throws IOException {
|
||||
cmdOut.writeByte(Protocol.PROTO_OK);
|
||||
cmdOut.flush();
|
||||
}
|
||||
|
||||
private void sendErrorResult(String error) throws IOException {
|
||||
cmdOut.writeByte(Protocol.PROTO_ERROR);
|
||||
cmdOut.writeUTF(error);
|
||||
cmdOut.flush();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TODO replace with dynamic dispatcher
|
||||
*/
|
||||
private void dispatchCommand(DataInputStream in) throws ProxyException, IOException {
|
||||
AbstractServerCommand serverCmd;
|
||||
|
||||
short cmd = in.readShort();
|
||||
switch (cmd) {
|
||||
case Protocol.CMD_CHILDINFOS:
|
||||
serverCmd = cmdChildInfos(in);
|
||||
break;
|
||||
|
||||
case Protocol.CMD_DELETE:
|
||||
serverCmd = cmdDelete(in);
|
||||
break;
|
||||
|
||||
case Protocol.CMD_EXEC:
|
||||
serverCmd = cmdExec(in);
|
||||
break;
|
||||
|
||||
case Protocol.CMD_FETCHINFO:
|
||||
serverCmd = cmdFetchInfo(in);
|
||||
break;
|
||||
|
||||
case Protocol.CMD_GETCWD:
|
||||
serverCmd = cmdGetCwd(in);
|
||||
break;
|
||||
|
||||
case Protocol.CMD_GETENV:
|
||||
serverCmd = cmdGetEnv(in);
|
||||
break;
|
||||
|
||||
case Protocol.CMD_GETINPUTSTREAM:
|
||||
serverCmd = cmdGetInputStream(in);
|
||||
break;
|
||||
|
||||
case Protocol.CMD_GETOUTPUTSTREAM:
|
||||
serverCmd = cmdGetOutputStream(in);
|
||||
break;
|
||||
|
||||
case Protocol.CMD_GETPROPERTIES:
|
||||
serverCmd = cmdGetProperties(in);
|
||||
break;
|
||||
|
||||
case Protocol.CMD_MKDIR:
|
||||
serverCmd = cmdMkdir(in);
|
||||
break;
|
||||
|
||||
case Protocol.CMD_PUTINFO:
|
||||
serverCmd = cmdPutInfo(in);
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("Invalid command ID: " + cmd);
|
||||
throw new ProxyException("Invalid command ID: " + cmd);
|
||||
}
|
||||
|
||||
serverCmd.exec();
|
||||
}
|
||||
|
||||
private AbstractServerCommand cmdExec(DataInputStream in) throws ProxyException, IOException {
|
||||
int chanAId = in.readByte();
|
||||
int chanBId = in.readByte();
|
||||
int chanCId = in.readByte();
|
||||
int length = in.readInt();
|
||||
List<String> command = new ArrayList<String>(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
command.add(in.readUTF());
|
||||
}
|
||||
length = in.readInt();
|
||||
Map<String, String> env = new HashMap<String, String>(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
String key = in.readUTF();
|
||||
String val = in.readUTF();
|
||||
env.put(key, val);
|
||||
}
|
||||
String dir = in.readUTF();
|
||||
boolean redirect = in.readBoolean();
|
||||
boolean appendEnv = in.readBoolean();
|
||||
System.err.print("dispatch: ");
|
||||
for (String s:command) {
|
||||
System.err.print(" " + s);
|
||||
}
|
||||
System.err.println(" [" + chanAId + "," + chanBId+ ","+ chanCId + "]");
|
||||
StreamChannel chanA = server.getChannel(chanAId);
|
||||
StreamChannel chanB = server.getChannel(chanBId);
|
||||
StreamChannel chanC= server.getChannel(chanCId);
|
||||
if (chanA == null || chanB == null || chanC == null) {
|
||||
throw new ProxyException("Unable to locate channels for command");
|
||||
}
|
||||
return new ServerExecCommand(command, env, dir, redirect, appendEnv, chanA, chanB, chanC);
|
||||
}
|
||||
|
||||
private AbstractServerCommand cmdGetCwd(DataInputStream in) throws ProxyException, IOException {
|
||||
int chanId = in.readByte();
|
||||
StreamChannel chan = server.getChannel(chanId);
|
||||
if (chan == null) {
|
||||
throw new ProxyException("Unable to locate channel for command");
|
||||
}
|
||||
return new ServerGetCwdCommand(chan);
|
||||
}
|
||||
|
||||
private AbstractServerCommand cmdGetEnv(DataInputStream in) throws ProxyException, IOException {
|
||||
int chanId = in.readByte();
|
||||
StreamChannel chan = server.getChannel(chanId);
|
||||
if (chan == null) {
|
||||
throw new ProxyException("Unable to locate channel for command");
|
||||
}
|
||||
return new ServerGetEnvCommand(chan);
|
||||
}
|
||||
|
||||
private AbstractServerCommand cmdGetProperties(DataInputStream in) throws ProxyException, IOException {
|
||||
int chanId = in.readByte();
|
||||
StreamChannel chan = server.getChannel(chanId);
|
||||
if (chan == null) {
|
||||
throw new ProxyException("Unable to locate channel for command");
|
||||
}
|
||||
return new ServerGetPropertiesCommand(chan);
|
||||
}
|
||||
|
||||
private AbstractServerCommand cmdChildInfos(DataInputStream in) throws ProxyException, IOException {
|
||||
int chanId = in.readByte();
|
||||
StreamChannel chan = server.getChannel(chanId);
|
||||
if (chan == null) {
|
||||
throw new ProxyException("Unable to locate channel for command");
|
||||
}
|
||||
String path = in.readUTF();
|
||||
return new ServerChildInfosCommand(chan, path);
|
||||
}
|
||||
|
||||
private AbstractServerCommand cmdFetchInfo(DataInputStream in) throws ProxyException, IOException {
|
||||
int chanId = in.readByte();
|
||||
StreamChannel chan = server.getChannel(chanId);
|
||||
if (chan == null) {
|
||||
throw new ProxyException("Unable to locate channel for command");
|
||||
}
|
||||
String path = in.readUTF();
|
||||
return new ServerFetchInfoCommand(chan, path);
|
||||
}
|
||||
|
||||
private AbstractServerCommand cmdGetInputStream(DataInputStream in) throws ProxyException, IOException {
|
||||
int chanId = in.readByte();
|
||||
StreamChannel chan = server.getChannel(chanId);
|
||||
if (chan == null) {
|
||||
throw new ProxyException("Unable to locate channel for command");
|
||||
}
|
||||
int options = in.readInt();
|
||||
String path = in.readUTF();
|
||||
return new ServerGetInputStreamCommand(chan, options, path);
|
||||
}
|
||||
|
||||
private AbstractServerCommand cmdGetOutputStream(DataInputStream in) throws ProxyException, IOException {
|
||||
int chanId = in.readByte();
|
||||
StreamChannel chan = server.getChannel(chanId);
|
||||
if (chan == null) {
|
||||
throw new ProxyException("Unable to locate channel for command");
|
||||
}
|
||||
int options = in.readInt();
|
||||
String path = in.readUTF();
|
||||
return new ServerGetOutputStreamCommand(chan, options, path);
|
||||
}
|
||||
|
||||
private AbstractServerCommand cmdDelete(DataInputStream in) throws ProxyException, IOException {
|
||||
int options = in.readInt();
|
||||
String path = in.readUTF();
|
||||
return new ServerDeleteCommand(options, path);
|
||||
}
|
||||
|
||||
private AbstractServerCommand cmdMkdir(DataInputStream in) throws ProxyException, IOException {
|
||||
int options = in.readInt();
|
||||
String path = in.readUTF();
|
||||
return new ServerMkdirCommand(options, path);
|
||||
}
|
||||
|
||||
private AbstractServerCommand cmdPutInfo(DataInputStream in) throws ProxyException, IOException {
|
||||
int options = in.readInt();
|
||||
String path = in.readUTF();
|
||||
SerializableFileInfo info = new SerializableFileInfo();
|
||||
info.readObject(in);
|
||||
return new ServerPutInfoCommand(info.getIFileInfo(), options, path);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.server.core;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannelManager;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannelManager.IChannelListener;
|
||||
import org.eclipse.remote.proxy.protocol.core.StreamChannel;
|
||||
|
||||
public class Server {
|
||||
private volatile boolean running;
|
||||
private Thread serverThread;
|
||||
private StreamChannel cmdChannel;
|
||||
private Map<Integer, StreamChannel> auxChannel = Collections.synchronizedMap(new HashMap<Integer, StreamChannel>());
|
||||
|
||||
|
||||
public void start() {
|
||||
final StreamChannelManager mux = new StreamChannelManager(System.in, System.out);
|
||||
mux.setServer(true);
|
||||
mux.addListener(new IChannelListener() {
|
||||
|
||||
@Override
|
||||
public void newChannel(StreamChannel chan) {
|
||||
Runnable runnable;
|
||||
System.err.println("newChannel: " + chan.getId());
|
||||
// First channel opened becomes command channel
|
||||
if (cmdChannel == null) {
|
||||
cmdChannel = chan;
|
||||
runnable = new CommandServer(chan, Server.this);
|
||||
new Thread(runnable).start();
|
||||
} else {
|
||||
auxChannel.put(chan.getId(), chan);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeChannel(StreamChannel chan) {
|
||||
System.err.println("closeChannel: " + chan.getId());
|
||||
auxChannel.remove(chan.getId());
|
||||
}
|
||||
|
||||
});
|
||||
serverThread = new Thread(mux) {
|
||||
@Override
|
||||
public void run() {
|
||||
running = true;
|
||||
mux.run();
|
||||
running = false;
|
||||
}
|
||||
};
|
||||
serverThread.start();
|
||||
}
|
||||
|
||||
public StreamChannel getChannel(int id) {
|
||||
System.err.println("getChannel: "+id);
|
||||
return auxChannel.get(id);
|
||||
}
|
||||
|
||||
public void waitFor() {
|
||||
if (running && serverThread != null) {
|
||||
try {
|
||||
serverThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
7
bundles/org.eclipse.remote.proxy.ui/.classpath
Normal file
7
bundles/org.eclipse.remote.proxy.ui/.classpath
Normal 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/JavaSE-1.8"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
1
bundles/org.eclipse.remote.proxy.ui/.gitignore
vendored
Normal file
1
bundles/org.eclipse.remote.proxy.ui/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/bin
|
34
bundles/org.eclipse.remote.proxy.ui/.project
Normal file
34
bundles/org.eclipse.remote.proxy.ui/.project
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.eclipse.remote.proxy.ui</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>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,11 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
42
bundles/org.eclipse.remote.proxy.ui/META-INF/MANIFEST.MF
Normal file
42
bundles/org.eclipse.remote.proxy.ui/META-INF/MANIFEST.MF
Normal file
|
@ -0,0 +1,42 @@
|
|||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: %pluginName
|
||||
Bundle-SymbolicName: org.eclipse.remote.proxy.ui;singleton:=true
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Activator: org.eclipse.remote.internal.proxy.ui.Activator
|
||||
Bundle-Vendor: %pluginProvider
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Export-Package: org.eclipse.remote.internal.proxy.ui;x-internal:=true,
|
||||
org.eclipse.remote.internal.proxy.ui.messages;x-internal:=true
|
||||
Bundle-Localization: plugin
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Import-Package: com.jcraft.jsch,
|
||||
org.eclipse.core.filesystem,
|
||||
org.eclipse.core.runtime,
|
||||
org.eclipse.jface.dialogs,
|
||||
org.eclipse.jface.operation,
|
||||
org.eclipse.jface.preference,
|
||||
org.eclipse.jface.resource,
|
||||
org.eclipse.jface.viewers,
|
||||
org.eclipse.jface.window,
|
||||
org.eclipse.jface.wizard,
|
||||
org.eclipse.jsch.core,
|
||||
org.eclipse.jsch.ui,
|
||||
org.eclipse.osgi.util,
|
||||
org.eclipse.remote.core,
|
||||
org.eclipse.remote.core.exception,
|
||||
org.eclipse.remote.internal.proxy.core,
|
||||
org.eclipse.remote.ui,
|
||||
org.eclipse.remote.ui.dialogs,
|
||||
org.eclipse.remote.ui.widgets,
|
||||
org.eclipse.swt,
|
||||
org.eclipse.swt.events,
|
||||
org.eclipse.swt.graphics,
|
||||
org.eclipse.swt.layout,
|
||||
org.eclipse.swt.widgets,
|
||||
org.eclipse.ui.dialogs,
|
||||
org.eclipse.ui.forms.events,
|
||||
org.eclipse.ui.forms.widgets,
|
||||
org.eclipse.ui.ide.fileSystem,
|
||||
org.eclipse.ui.plugin,
|
||||
org.osgi.framework
|
22
bundles/org.eclipse.remote.proxy.ui/about.html
Normal file
22
bundles/org.eclipse.remote.proxy.ui/about.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>About</title>
|
||||
<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
|
||||
</head>
|
||||
<body lang="EN-US">
|
||||
<h2>About This Content</h2>
|
||||
|
||||
<p>May 2, 2006</p>
|
||||
<h3>License</h3>
|
||||
|
||||
<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
|
||||
Eclipse Public License Version 1.0 ("EPL"). 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, "Program" 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 ("Redistributor") 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.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
9
bundles/org.eclipse.remote.proxy.ui/build.properties
Normal file
9
bundles/org.eclipse.remote.proxy.ui/build.properties
Normal file
|
@ -0,0 +1,9 @@
|
|||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
plugin.xml,\
|
||||
plugin.properties,\
|
||||
about.html,\
|
||||
icons/
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 160 B |
BIN
bundles/org.eclipse.remote.proxy.ui/icons/ssh.png
Normal file
BIN
bundles/org.eclipse.remote.proxy.ui/icons/ssh.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 512 B |
13
bundles/org.eclipse.remote.proxy.ui/plugin.properties
Normal file
13
bundles/org.eclipse.remote.proxy.ui/plugin.properties
Normal file
|
@ -0,0 +1,13 @@
|
|||
###############################################################################
|
||||
# Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
pluginName=Proxy UI Remote Support
|
||||
pluginProvider=Eclipse PTP
|
||||
ProxyTransferConnections.name=Remote Connections
|
||||
ProxyTransferConnections.description=All remote proxy connections
|
56
bundles/org.eclipse.remote.proxy.ui/plugin.xml
Normal file
56
bundles/org.eclipse.remote.proxy.ui/plugin.xml
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.2"?>
|
||||
<plugin>
|
||||
<extension
|
||||
point="org.eclipse.ui.ide.filesystemSupport">
|
||||
<filesystemContributor
|
||||
class="org.eclipse.remote.internal.proxy.ui.ProxyFileSystemContributor"
|
||||
label="Proxy"
|
||||
scheme="proxy">
|
||||
</filesystemContributor>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.preferenceTransfer">
|
||||
<transfer
|
||||
icon="icons/full/obj16/connection.gif"
|
||||
id="org.eclipse.remote.proxy.transfer.connections"
|
||||
name="%ProxyTransferConnections.name">
|
||||
<mapping
|
||||
scope="instance">
|
||||
<entry
|
||||
node="org.eclipse.remote.proxy.core/connections">
|
||||
</entry>
|
||||
</mapping>
|
||||
<description>
|
||||
%ProxyTransferConnections.description
|
||||
</description>
|
||||
</transfer>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.remote.core.authenticator">
|
||||
<authenticator
|
||||
class="org.eclipse.remote.internal.proxy.ui.ProxyUserAuthenticator"
|
||||
id="org.eclipse.remote.Proxy"
|
||||
priority="0">
|
||||
</authenticator>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.remote.core.remoteServices">
|
||||
<connectionTypeService
|
||||
connectionTypeId="org.eclipse.remote.Proxy"
|
||||
factory="org.eclipse.remote.internal.proxy.ui.ProxyUIConnectionService$Factory"
|
||||
service="org.eclipse.remote.ui.IRemoteUIConnectionService">
|
||||
</connectionTypeService>
|
||||
<connectionTypeService
|
||||
connectionTypeId="org.eclipse.remote.Proxy"
|
||||
factory="org.eclipse.remote.ui.RemoteUIFileService$Factory"
|
||||
service="org.eclipse.remote.ui.IRemoteUIFileService">
|
||||
</connectionTypeService>
|
||||
<connectionService
|
||||
connectionTypeId="org.eclipse.remote.Proxy"
|
||||
factory="org.eclipse.remote.internal.proxy.ui.ProxyUserAuthenticator$Factory"
|
||||
service="org.eclipse.remote.core.IUserAuthenticatorService">
|
||||
</connectionService>
|
||||
</extension>
|
||||
|
||||
</plugin>
|
16
bundles/org.eclipse.remote.proxy.ui/pom.xml
Normal file
16
bundles/org.eclipse.remote.proxy.ui/pom.xml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.eclipse.remote</groupId>
|
||||
<artifactId>remote-parent</artifactId>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../releng/org.eclipse.remote.build/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.eclipse.remote.proxy.ui</artifactId>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</project>
|
|
@ -0,0 +1,128 @@
|
|||
package org.eclipse.remote.internal.proxy.ui;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.jsch.core.IJSchService;
|
||||
import org.eclipse.ui.plugin.AbstractUIPlugin;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
|
||||
/**
|
||||
* The activator class controls the plug-in life cycle
|
||||
*/
|
||||
public class Activator extends AbstractUIPlugin {
|
||||
|
||||
// The plug-in ID
|
||||
private static final String PLUGIN_ID = "org.eclipse.remote.jsch.ui"; //$NON-NLS-1$
|
||||
|
||||
// Image Keys
|
||||
public static final String IMG_CONNECTION_TYPE = PLUGIN_ID + ".connectionType"; //$NON-NLS-1$
|
||||
|
||||
// The shared instance
|
||||
private static Activator plugin;
|
||||
|
||||
/**
|
||||
* Returns the shared instance
|
||||
*
|
||||
* @return the shared instance
|
||||
*/
|
||||
public static Activator getDefault() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unique identifier
|
||||
*
|
||||
* @return
|
||||
* @since 5.0
|
||||
*/
|
||||
public static String getUniqueIdentifier() {
|
||||
if (getDefault() == null) {
|
||||
return PLUGIN_ID;
|
||||
}
|
||||
return getDefault().getBundle().getSymbolicName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the specified status with this plug-in's log.
|
||||
*
|
||||
* @param status
|
||||
* status to log
|
||||
*/
|
||||
public static void log(IStatus status) {
|
||||
getDefault().getLog().log(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an internal error with the specified message.
|
||||
*
|
||||
* @param message
|
||||
* the error message to log
|
||||
*/
|
||||
public static void log(String message) {
|
||||
log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, message, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an internal error with the specified throwable
|
||||
*
|
||||
* @param e
|
||||
* the exception to be logged
|
||||
*/
|
||||
public static void log(Throwable e) {
|
||||
log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, e.getMessage(), e));
|
||||
}
|
||||
|
||||
private IJSchService fJSchService;
|
||||
|
||||
/**
|
||||
* The constructor
|
||||
*/
|
||||
public Activator() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the OSGi service with the given service interface.
|
||||
*
|
||||
* @param service service interface
|
||||
* @return the specified service or null if it's not registered
|
||||
*/
|
||||
public static <T> T getService(Class<T> service) {
|
||||
BundleContext context = plugin.getBundle().getBundleContext();
|
||||
ServiceReference<T> ref = context.getServiceReference(service);
|
||||
return ref != null ? context.getService(ref) : null;
|
||||
}
|
||||
|
||||
public IJSchService getService() {
|
||||
return fJSchService;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext
|
||||
* )
|
||||
*/
|
||||
@Override
|
||||
public void start(BundleContext context) throws Exception {
|
||||
super.start(context);
|
||||
plugin = this;
|
||||
ServiceReference<IJSchService> reference = context.getServiceReference(IJSchService.class);
|
||||
fJSchService = context.getService(reference);
|
||||
getImageRegistry().put(IMG_CONNECTION_TYPE, imageDescriptorFromPlugin(PLUGIN_ID, "/icons/ssh.png")); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
|
||||
* )
|
||||
*/
|
||||
@Override
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
plugin = null;
|
||||
super.stop(context);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/********************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
********************************************************************************/
|
||||
|
||||
package org.eclipse.remote.internal.proxy.ui;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import org.eclipse.remote.core.IRemoteConnection;
|
||||
import org.eclipse.remote.core.IRemoteConnectionType;
|
||||
import org.eclipse.remote.core.IRemoteServicesManager;
|
||||
import org.eclipse.remote.internal.proxy.core.ProxyConnection;
|
||||
import org.eclipse.remote.internal.proxy.core.ProxyFileSystem;
|
||||
import org.eclipse.remote.internal.proxy.ui.messages.Messages;
|
||||
import org.eclipse.remote.ui.IRemoteUIFileService;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.ui.ide.fileSystem.FileSystemContributor;
|
||||
|
||||
public class ProxyFileSystemContributor extends FileSystemContributor {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.ui.ide.fileSystem.FileSystemContributor#browseFileSystem(
|
||||
* java.lang.String, org.eclipse.swt.widgets.Shell)
|
||||
*/
|
||||
@Override
|
||||
public URI browseFileSystem(String initialPath, Shell shell) {
|
||||
IRemoteServicesManager manager = Activator.getService(IRemoteServicesManager.class);
|
||||
IRemoteConnectionType connectionType = manager.getConnectionType(ProxyConnection.JSCH_ID);
|
||||
IRemoteUIFileService uiFileMgr = connectionType.getService(IRemoteUIFileService.class);
|
||||
uiFileMgr.showConnections(true);
|
||||
String path = uiFileMgr.browseDirectory(shell, Messages.ProxyFileSystemContributor_0, initialPath, 0);
|
||||
if (path != null) {
|
||||
IRemoteConnection conn = uiFileMgr.getConnection();
|
||||
if (conn != null) {
|
||||
return ProxyFileSystem.getURIFor(conn.getName(), path);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.ui.ide.fileSystem.FileSystemContributor#getURI(java.lang.
|
||||
* String)
|
||||
*/
|
||||
@Override
|
||||
public URI getURI(String string) {
|
||||
try {
|
||||
return new URI(string);
|
||||
} catch (URISyntaxException e) {
|
||||
// Ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.ui;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.jface.dialogs.ErrorDialog;
|
||||
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
|
||||
import org.eclipse.jface.operation.IRunnableContext;
|
||||
import org.eclipse.jface.operation.IRunnableWithProgress;
|
||||
import org.eclipse.jface.viewers.ILabelProvider;
|
||||
import org.eclipse.remote.core.IRemoteConnection;
|
||||
import org.eclipse.remote.core.IRemoteConnectionType;
|
||||
import org.eclipse.remote.core.IRemoteConnectionType.Service;
|
||||
import org.eclipse.remote.core.exception.RemoteConnectionException;
|
||||
import org.eclipse.remote.internal.proxy.ui.messages.Messages;
|
||||
import org.eclipse.remote.internal.proxy.ui.wizards.ProxyConnectionWizard;
|
||||
import org.eclipse.remote.ui.AbstractRemoteUIConnectionService;
|
||||
import org.eclipse.remote.ui.IRemoteUIConnectionService;
|
||||
import org.eclipse.remote.ui.IRemoteUIConnectionWizard;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
|
||||
public class ProxyUIConnectionService extends AbstractRemoteUIConnectionService {
|
||||
|
||||
private final IRemoteConnectionType fConnectionType;
|
||||
|
||||
public ProxyUIConnectionService(IRemoteConnectionType connectionType) {
|
||||
fConnectionType = connectionType;
|
||||
}
|
||||
|
||||
public static class Factory implements IRemoteConnectionType.Service.Factory {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T extends Service> T getService(IRemoteConnectionType connectionType, Class<T> service) {
|
||||
if (IRemoteUIConnectionService.class.equals(service)) {
|
||||
return (T) new ProxyUIConnectionService(connectionType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRemoteConnectionType getConnectionType() {
|
||||
return fConnectionType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRemoteUIConnectionWizard getConnectionWizard(Shell shell) {
|
||||
return new ProxyConnectionWizard(shell, fConnectionType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openConnectionWithProgress(Shell shell, IRunnableContext context, final IRemoteConnection connection) {
|
||||
if (!connection.isOpen()) {
|
||||
IRunnableWithProgress op = new IRunnableWithProgress() {
|
||||
@Override
|
||||
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
|
||||
try {
|
||||
connection.open(monitor);
|
||||
} catch (RemoteConnectionException e) {
|
||||
throw new InvocationTargetException(e);
|
||||
}
|
||||
if (monitor.isCanceled()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
}
|
||||
};
|
||||
try {
|
||||
if (context != null) {
|
||||
context.run(true, true, op);
|
||||
} else {
|
||||
new ProgressMonitorDialog(shell).run(true, true, op);
|
||||
}
|
||||
} catch (InvocationTargetException e) {
|
||||
ErrorDialog.openError(shell, Messages.ProxyUIConnectionManager_Connection_Error,
|
||||
Messages.ProxyUIConnectionManager_Could_not_open_connection,
|
||||
new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), e.getCause().getMessage()));
|
||||
} catch (InterruptedException e) {
|
||||
ErrorDialog.openError(shell, Messages.ProxyUIConnectionManager_Connection_Error,
|
||||
Messages.ProxyUIConnectionManager_Could_not_open_connection,
|
||||
new Status(IStatus.ERROR, Activator.getUniqueIdentifier(), e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ILabelProvider getLabelProvider() {
|
||||
return new DefaultLabelProvider() {
|
||||
@Override
|
||||
public Image getImage(Object element) {
|
||||
return Activator.getDefault().getImageRegistry().get(Activator.IMG_CONNECTION_TYPE);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.proxy.ui;
|
||||
|
||||
import java.net.PasswordAuthentication;
|
||||
|
||||
import org.eclipse.jface.dialogs.IDialogConstants;
|
||||
import org.eclipse.jface.dialogs.MessageDialog;
|
||||
import org.eclipse.jsch.ui.UserInfoPrompter;
|
||||
import org.eclipse.remote.core.IRemoteConnection;
|
||||
import org.eclipse.remote.core.IRemoteConnectionHostService;
|
||||
import org.eclipse.remote.core.IUserAuthenticatorService;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
|
||||
import com.jcraft.jsch.JSch;
|
||||
import com.jcraft.jsch.JSchException;
|
||||
|
||||
public class ProxyUserAuthenticator implements IUserAuthenticatorService {
|
||||
|
||||
private final IRemoteConnection remoteConnection;
|
||||
private UserInfoPrompter prompter;
|
||||
|
||||
public ProxyUserAuthenticator(IRemoteConnection conn) {
|
||||
this.remoteConnection = conn;
|
||||
IRemoteConnectionHostService hostService = conn.getService(IRemoteConnectionHostService.class);
|
||||
if (hostService != null) {
|
||||
try {
|
||||
prompter = new UserInfoPrompter(new JSch().getSession(hostService.getUsername(), hostService.getHostname()));
|
||||
} catch (JSchException e) {
|
||||
// Not allowed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRemoteConnection getRemoteConnection() {
|
||||
return remoteConnection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PasswordAuthentication prompt(String username, String message) {
|
||||
if (prompter.promptPassword(message)) {
|
||||
String sessionUserName = prompter.getSession().getUserName();
|
||||
if (sessionUserName != null) {
|
||||
username = sessionUserName;
|
||||
}
|
||||
PasswordAuthentication auth = new PasswordAuthentication(username, prompter.getPassword().toCharArray());
|
||||
return auth;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] prompt(String destination, String name, String message, String[] prompt, boolean[] echo) {
|
||||
return prompter.promptKeyboardInteractive(destination, name, message, prompt, echo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int prompt(final int promptType, final String title, final String message, final int[] promptResponses,
|
||||
final int defaultResponseIndex) {
|
||||
final Display display = getDisplay();
|
||||
final int[] retval = new int[1];
|
||||
final String[] buttons = new String[promptResponses.length];
|
||||
for (int i = 0; i < promptResponses.length; i++) {
|
||||
int prompt = promptResponses[i];
|
||||
switch (prompt) {
|
||||
case IDialogConstants.OK_ID:
|
||||
buttons[i] = IDialogConstants.OK_LABEL;
|
||||
break;
|
||||
case IDialogConstants.CANCEL_ID:
|
||||
buttons[i] = IDialogConstants.CANCEL_LABEL;
|
||||
break;
|
||||
case IDialogConstants.NO_ID:
|
||||
buttons[i] = IDialogConstants.NO_LABEL;
|
||||
break;
|
||||
case IDialogConstants.YES_ID:
|
||||
buttons[i] = IDialogConstants.YES_LABEL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
display.syncExec(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final MessageDialog dialog = new MessageDialog(display.getActiveShell(), title, null /* title image */, message,
|
||||
promptType, buttons, defaultResponseIndex);
|
||||
retval[0] = dialog.open();
|
||||
}
|
||||
});
|
||||
return promptResponses[retval[0]];
|
||||
}
|
||||
|
||||
private Display getDisplay() {
|
||||
Display display = Display.getCurrent();
|
||||
if (display == null) {
|
||||
display = Display.getDefault();
|
||||
}
|
||||
return display;
|
||||
}
|
||||
|
||||
public static class Factory implements IRemoteConnection.Service.Factory {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends IRemoteConnection.Service> T getService(IRemoteConnection connection, Class<T> service) {
|
||||
if (IUserAuthenticatorService.class.equals(service)) {
|
||||
return (T) new ProxyUserAuthenticator(connection);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* Copyright (c) 2013 IBM Corporation.
|
||||
* 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:
|
||||
* IBM Corporation - Initial Implementation
|
||||
*
|
||||
*/
|
||||
package org.eclipse.remote.internal.proxy.ui.messages;
|
||||
|
||||
import org.eclipse.osgi.util.NLS;
|
||||
|
||||
public class Messages extends NLS {
|
||||
private static final String BUNDLE_ID = "org.eclipse.remote.internal.proxy.ui.messages.messages"; //$NON-NLS-1$
|
||||
|
||||
static {
|
||||
// load message values from bundle file
|
||||
NLS.initializeMessages(BUNDLE_ID, Messages.class);
|
||||
}
|
||||
|
||||
public static String ProxyConnectionPage_0;
|
||||
public static String ProxyConnectionPage_1;
|
||||
public static String ProxyConnectionPage_2;
|
||||
public static String ProxyConnectionPage_A_connection_with_that_name_already_exists;
|
||||
public static String ProxyConnectionPage_Edit_Connection;
|
||||
public static String ProxyConnectionPage_Edit_properties_of_an_existing_connection;
|
||||
public static String ProxyConnectionPage_Initial_Message;
|
||||
public static String ProxyConnectionPage_Proxy;
|
||||
public static String ProxyConnectionPage_Help;
|
||||
public static String ProxyConnectionPage_KeysAtSSH2;
|
||||
public static String ProxyConnectionPage_SelectCommand;
|
||||
public static String ProxyConnectionPage_SelectConnection;
|
||||
public static String ProxyConnectionPage_Settings0;
|
||||
public static String ProxyConnectionPage_selectProxyConnection;
|
||||
public static String ProxyFileSystemContributor_0;
|
||||
public static String ProxyNewConnectionPage_Advanced;
|
||||
public static String ProxyNewConnectionPage_Connection_name;
|
||||
public static String ProxyNewConnectionPage_File_with_private_key;
|
||||
public static String ProxyNewConnectionPage_Host;
|
||||
public static String ProxyNewConnectionPage_Host_information;
|
||||
public static String ProxyNewConnectionPage_Host_name_cannot_be_empty;
|
||||
public static String ProxyNewConnectionPage_New_Connection;
|
||||
public static String ProxyNewConnectionPage_New_connection_properties;
|
||||
public static String ProxyNewConnectionPage_Passphrase;
|
||||
public static String ProxyNewConnectionPage_Password;
|
||||
public static String ProxyNewConnectionPage_Password_based_authentication;
|
||||
public static String ProxyNewConnectionPage_Please_enter_a_connection_name;
|
||||
public static String ProxyNewConnectionPage_Port;
|
||||
public static String ProxyNewConnectionPage_Port_is_not_valid;
|
||||
public static String ProxyNewConnectionPage_Private_key_file_cannot_be_read;
|
||||
public static String ProxyNewConnectionPage_Private_key_file_does_not_exist;
|
||||
public static String ProxyNewConnectionPage_Private_key_file_is_invalid;
|
||||
public static String ProxyNewConnectionPage_Private_key_path_cannot_be_empty;
|
||||
public static String ProxyNewConnectionPage_Public_key_based_authentication;
|
||||
public static String ProxyNewConnectionPage_Timeout;
|
||||
public static String ProxyNewConnectionPage_Timeout_is_not_valid;
|
||||
public static String ProxyNewConnectionPage_User;
|
||||
public static String ProxyNewConnectionPage_User_name_cannot_be_empty;
|
||||
public static String ProxyUIConnectionManager_Connection_Error;
|
||||
public static String ProxyUIConnectionManager_Could_not_open_connection;
|
||||
|
||||
private Messages() {
|
||||
// cannot create new instance
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
###############################################################################
|
||||
# Copyright (c) 2013 IBM Corporation.
|
||||
# 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:
|
||||
# IBM Corporation - initial implementation
|
||||
###############################################################################
|
||||
ProxyConnectionPage_0=Use login shell
|
||||
ProxyConnectionPage_1=Login shell command
|
||||
ProxyConnectionPage_2=Login shell command cannot be empty
|
||||
ProxyConnectionPage_A_connection_with_that_name_already_exists=A connection with that name already exists
|
||||
ProxyConnectionPage_Edit_Connection=Edit Connection
|
||||
ProxyConnectionPage_Edit_properties_of_an_existing_connection=Edit properties of an existing connection
|
||||
ProxyConnectionPage_Initial_Message=Specify properties of a new connection
|
||||
ProxyConnectionPage_Proxy=SSH Proxy Settings
|
||||
ProxyConnectionPage_Help=If 'Local' is selected and proxy command is empty, no proxy is used.\nSee <a>Network Connections</a> for SOCKS and HTTP proxy options.
|
||||
ProxyConnectionPage_KeysAtSSH2=Keys are set at <a>Network Connections, SSH2</a>
|
||||
ProxyConnectionPage_SelectCommand=Enter a local or remote command such as 'nc %h %p'. Can be empty for an ssh gateway.
|
||||
ProxyConnectionPage_SelectConnection=Select 'Remote' for an ssh gateway or a remote proxy command.
|
||||
ProxyConnectionPage_Settings0=Connection Settings
|
||||
ProxyConnectionPage_selectProxyConnection=Please select a proxy connection
|
||||
ProxyFileSystemContributor_0=Browse File System
|
||||
ProxyNewConnectionPage_Advanced=Advanced
|
||||
ProxyNewConnectionPage_Connection_name=Connection name:
|
||||
ProxyNewConnectionPage_File_with_private_key=File with private key:
|
||||
ProxyNewConnectionPage_Host=Host:
|
||||
ProxyNewConnectionPage_Host_information=Host information
|
||||
ProxyNewConnectionPage_Host_name_cannot_be_empty=Host name cannot be empty
|
||||
ProxyNewConnectionPage_New_Connection=New Connection
|
||||
ProxyNewConnectionPage_New_connection_properties=New connection properties
|
||||
ProxyNewConnectionPage_Passphrase=Passphrase:
|
||||
ProxyNewConnectionPage_Password=Password:
|
||||
ProxyNewConnectionPage_Password_based_authentication=Password based authentication
|
||||
ProxyNewConnectionPage_Please_enter_a_connection_name=Please enter a connection name
|
||||
ProxyNewConnectionPage_Port=Port:
|
||||
ProxyNewConnectionPage_Port_is_not_valid=Port is not valid
|
||||
ProxyNewConnectionPage_Private_key_file_cannot_be_read=Private key file cannot be read
|
||||
ProxyNewConnectionPage_Private_key_file_does_not_exist=Private key file does not exist
|
||||
ProxyNewConnectionPage_Private_key_file_is_invalid=Private key file is invalid
|
||||
ProxyNewConnectionPage_Private_key_path_cannot_be_empty=Private key path cannot be empty
|
||||
ProxyNewConnectionPage_Public_key_based_authentication=Public key based authentication
|
||||
ProxyNewConnectionPage_Timeout=Timeout:
|
||||
ProxyNewConnectionPage_Timeout_is_not_valid=Timeout is not valid
|
||||
ProxyNewConnectionPage_User=User:
|
||||
ProxyNewConnectionPage_User_name_cannot_be_empty=User name cannot be empty
|
||||
ProxyUIConnectionManager_Connection_Error=Connection Error
|
||||
ProxyUIConnectionManager_Could_not_open_connection=Could not open connection
|
|
@ -0,0 +1,497 @@
|
|||
/**
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*/
|
||||
package org.eclipse.remote.internal.proxy.ui.wizards;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.jface.preference.PreferenceDialog;
|
||||
import org.eclipse.jface.wizard.WizardPage;
|
||||
import org.eclipse.remote.core.IRemoteConnectionType;
|
||||
import org.eclipse.remote.core.IRemoteConnectionWorkingCopy;
|
||||
import org.eclipse.remote.core.IRemoteServicesManager;
|
||||
import org.eclipse.remote.core.exception.RemoteConnectionException;
|
||||
import org.eclipse.remote.internal.proxy.core.ProxyConnection;
|
||||
import org.eclipse.remote.internal.proxy.ui.Activator;
|
||||
import org.eclipse.remote.internal.proxy.ui.messages.Messages;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.ModifyEvent;
|
||||
import org.eclipse.swt.events.ModifyListener;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.events.SelectionListener;
|
||||
import org.eclipse.swt.graphics.FontMetrics;
|
||||
import org.eclipse.swt.graphics.GC;
|
||||
import org.eclipse.swt.graphics.Point;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Control;
|
||||
import org.eclipse.swt.widgets.Group;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Link;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
import org.eclipse.ui.dialogs.PreferencesUtil;
|
||||
import org.eclipse.ui.forms.events.ExpansionEvent;
|
||||
import org.eclipse.ui.forms.events.IExpansionListener;
|
||||
import org.eclipse.ui.forms.widgets.ExpandableComposite;
|
||||
|
||||
public class ProxyConnectionPage extends WizardPage {
|
||||
|
||||
private class DataModifyListener implements ModifyListener {
|
||||
@Override
|
||||
public synchronized void modifyText(ModifyEvent e) {
|
||||
validateFields();
|
||||
getContainer().updateButtons();
|
||||
}
|
||||
}
|
||||
|
||||
private Text fConnectionName;
|
||||
private Button fPasswordButton;
|
||||
private Button fPublicKeyButton;
|
||||
private Button fDefaultServerButton;
|
||||
private Text fHostText;
|
||||
private Text fUserText;
|
||||
private Text fPasswordText;
|
||||
private Text fPassphraseText;
|
||||
private Text fPortText;
|
||||
private Text fTimeoutText;
|
||||
private Text fServerCommandText;
|
||||
|
||||
private String fInitialName = "Remote Host"; //$NON-NLS-1$
|
||||
private Set<String> fInvalidConnectionNames;
|
||||
private final Map<String, String> fInitialAttributes = new HashMap<String, String>();
|
||||
private IRemoteConnectionWorkingCopy fConnection;
|
||||
|
||||
private final IRemoteConnectionType fConnectionType;
|
||||
|
||||
private final DataModifyListener fDataModifyListener = new DataModifyListener();
|
||||
|
||||
public ProxyConnectionPage(IRemoteConnectionType connectionType) {
|
||||
super(Messages.ProxyNewConnectionPage_New_connection_properties);
|
||||
fConnectionType = connectionType;
|
||||
setPageComplete(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create controls for the bottom (hideable) advanced composite
|
||||
*
|
||||
* @param mold
|
||||
*
|
||||
*/
|
||||
private void createAdvancedControls(final Composite parent) {
|
||||
ExpandableComposite expComp = new ExpandableComposite(parent, ExpandableComposite.TWISTIE);
|
||||
expComp.setText(Messages.ProxyNewConnectionPage_Advanced);
|
||||
expComp.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
|
||||
expComp.setExpanded(false);
|
||||
expComp.addExpansionListener(new IExpansionListener() {
|
||||
|
||||
@Override
|
||||
public void expansionStateChanged(ExpansionEvent e) {
|
||||
for (int i = 0; i < 2; i++) { // sometimes the size compute isn't correct on first try
|
||||
Point newSize = parent.computeSize(SWT.DEFAULT, SWT.DEFAULT);
|
||||
Point currentSize = parent.getSize();
|
||||
int deltaY = newSize.y - currentSize.y;
|
||||
Point shellSize = getShell().getSize();
|
||||
shellSize.y += deltaY;
|
||||
getShell().setSize(shellSize);
|
||||
getShell().layout(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expansionStateChanging(ExpansionEvent e) {
|
||||
// Ignore
|
||||
}
|
||||
});
|
||||
|
||||
Composite advancedComp = new Composite(expComp, SWT.NONE);
|
||||
advancedComp.setLayout(new GridLayout(1, false));
|
||||
advancedComp.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
|
||||
|
||||
Group settingsComp = new Group(advancedComp, SWT.NONE);
|
||||
settingsComp.setText(Messages.ProxyConnectionPage_Settings0);
|
||||
settingsComp.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
|
||||
settingsComp.setLayout(new GridLayout(2, false));
|
||||
|
||||
Label portLabel = new Label(settingsComp, SWT.NONE);
|
||||
portLabel.setText(Messages.ProxyNewConnectionPage_Port);
|
||||
fPortText = new Text(settingsComp, SWT.BORDER | SWT.SINGLE);
|
||||
fPortText.setText(Integer.toString(ProxyConnection.DEFAULT_PORT));
|
||||
fPortText.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false));
|
||||
setTextFieldWidthInChars(fPortText, 5);
|
||||
|
||||
Label timeoutLabel = new Label(settingsComp, SWT.NONE);
|
||||
timeoutLabel.setText(Messages.ProxyNewConnectionPage_Timeout);
|
||||
fTimeoutText = new Text(settingsComp, SWT.BORDER | SWT.SINGLE);
|
||||
fTimeoutText.setText(Integer.toString(ProxyConnection.DEFAULT_TIMEOUT));
|
||||
|
||||
fDefaultServerButton = new Button(settingsComp, SWT.CHECK);
|
||||
fDefaultServerButton.setText("Use default server");
|
||||
fDefaultServerButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1));
|
||||
fDefaultServerButton.addSelectionListener(new SelectionAdapter() {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
|
||||
*/
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
validateFields();
|
||||
updateEnablement();
|
||||
}
|
||||
});
|
||||
Label serverLabel = new Label(settingsComp, SWT.NONE);
|
||||
serverLabel.setText("Server command");
|
||||
fServerCommandText = new Text(settingsComp, SWT.BORDER | SWT.SINGLE);
|
||||
fServerCommandText.setText(ProxyConnection.DEFAULT_SERVER_COMMAND);
|
||||
fServerCommandText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
|
||||
fDefaultServerButton.setSelection(ProxyConnection.DEFAULT_USE_DEFAULT_SERVER);
|
||||
|
||||
expComp.setClient(advancedComp);
|
||||
}
|
||||
|
||||
private void createAuthControls(Composite parent) {
|
||||
Composite controls = new Composite(parent, SWT.NONE);
|
||||
controls.setLayout(new GridLayout(3, false));
|
||||
controls.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
|
||||
|
||||
Label hostLabel = new Label(controls, SWT.NONE);
|
||||
hostLabel.setText(Messages.ProxyNewConnectionPage_Host);
|
||||
fHostText = new Text(controls, SWT.BORDER | SWT.SINGLE);
|
||||
fHostText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
|
||||
|
||||
Label userLabel = new Label(controls, SWT.NONE);
|
||||
userLabel.setText(Messages.ProxyNewConnectionPage_User);
|
||||
fUserText = new Text(controls, SWT.BORDER | SWT.SINGLE);
|
||||
fUserText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
|
||||
|
||||
// Key option box
|
||||
fPublicKeyButton = new Button(controls, SWT.RADIO);
|
||||
fPublicKeyButton.setText(Messages.ProxyNewConnectionPage_Public_key_based_authentication);
|
||||
fPublicKeyButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1));
|
||||
fPublicKeyButton.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
validateFields();
|
||||
updateEnablement();
|
||||
}
|
||||
});
|
||||
|
||||
Link link = new Link(controls, SWT.WRAP);
|
||||
final GridData linkLayoutData = new GridData(GridData.FILL_HORIZONTAL);
|
||||
link.setLayoutData(linkLayoutData);
|
||||
final String PREFS_PAGE_ID_NET_SSH = "org.eclipse.jsch.ui.SSHPreferences"; //$NON-NLS-1$
|
||||
link.addSelectionListener(new SelectionListener() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
PreferenceDialog dlg = PreferencesUtil.createPreferenceDialogOn(getShell(), PREFS_PAGE_ID_NET_SSH,
|
||||
new String[] { PREFS_PAGE_ID_NET_SSH }, null);
|
||||
dlg.open();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void widgetDefaultSelected(SelectionEvent e) {
|
||||
// ignore
|
||||
}
|
||||
});
|
||||
link.setText(Messages.ProxyConnectionPage_KeysAtSSH2);
|
||||
|
||||
// Passphrase field
|
||||
Label passphraseLabel = new Label(controls, SWT.NONE);
|
||||
passphraseLabel.setText(Messages.ProxyNewConnectionPage_Passphrase);
|
||||
fPassphraseText = new Text(controls, SWT.BORDER | SWT.SINGLE | SWT.PASSWORD);
|
||||
fPassphraseText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
|
||||
|
||||
// User option box
|
||||
fPasswordButton = new Button(controls, SWT.RADIO);
|
||||
fPasswordButton.setText(Messages.ProxyNewConnectionPage_Password_based_authentication);
|
||||
fPasswordButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 3, 1));
|
||||
fPasswordButton.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
validateFields();
|
||||
updateEnablement();
|
||||
}
|
||||
});
|
||||
|
||||
// Password field
|
||||
Label passwordLabel = new Label(controls, SWT.NONE);
|
||||
passwordLabel.setText(Messages.ProxyNewConnectionPage_Password);
|
||||
fPasswordText = new Text(controls, SWT.BORDER | SWT.SINGLE | SWT.PASSWORD);
|
||||
fPasswordText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
|
||||
|
||||
fPasswordButton.setSelection(ProxyConnection.DEFAULT_USE_PASSWORD);
|
||||
fPublicKeyButton.setSelection(!ProxyConnection.DEFAULT_USE_PASSWORD);
|
||||
controls.setTabList(
|
||||
new Control[] { fHostText, fUserText, fPublicKeyButton, fPassphraseText, fPasswordButton, fPasswordText });
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createControl(Composite parent) {
|
||||
if (fConnection == null) {
|
||||
setDescription(Messages.ProxyNewConnectionPage_New_connection_properties);
|
||||
setTitle(Messages.ProxyNewConnectionPage_New_connection_properties);
|
||||
setMessage(Messages.ProxyConnectionPage_Initial_Message);
|
||||
} else {
|
||||
setDescription(Messages.ProxyConnectionPage_Edit_properties_of_an_existing_connection);
|
||||
setTitle(Messages.ProxyConnectionPage_Edit_Connection);
|
||||
}
|
||||
setErrorMessage(null);
|
||||
|
||||
GridLayout topLayout = new GridLayout(2, false);
|
||||
final Composite topControl = new Composite(parent, SWT.NONE);
|
||||
setControl(topControl);
|
||||
topControl.setLayout(topLayout);
|
||||
|
||||
Label label = new Label(topControl, SWT.NONE);
|
||||
label.setText(Messages.ProxyNewConnectionPage_Connection_name);
|
||||
|
||||
fConnectionName = new Text(topControl, SWT.BORDER | SWT.SINGLE);
|
||||
fConnectionName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
|
||||
fConnectionName.setEnabled(fConnection == null);
|
||||
|
||||
final Group authGroup = new Group(topControl, SWT.NONE);
|
||||
authGroup.setText(Messages.ProxyNewConnectionPage_Host_information);
|
||||
authGroup.setLayout(new GridLayout(1, false));
|
||||
authGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
|
||||
|
||||
createAuthControls(authGroup);
|
||||
createAdvancedControls(authGroup);
|
||||
|
||||
try {
|
||||
loadValues();
|
||||
} catch (CoreException e) {
|
||||
Activator.log(e.getStatus());
|
||||
}
|
||||
|
||||
/*
|
||||
* Register listeners after loading values so we don't trigger listeners
|
||||
*/
|
||||
registerListeners();
|
||||
|
||||
if (fConnection != null) {
|
||||
validateFields();
|
||||
}
|
||||
|
||||
updateEnablement();
|
||||
}
|
||||
|
||||
public IRemoteConnectionWorkingCopy getConnection() {
|
||||
return fConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the connection name is invalid. This only applies to new connections (when fConnection is null).
|
||||
*
|
||||
* @param name
|
||||
* connection name
|
||||
* @return true if the name is invalid, false otherwise
|
||||
*/
|
||||
private boolean isInvalidName(String name) {
|
||||
if (fConnection == null) {
|
||||
if (fInvalidConnectionNames == null) {
|
||||
return fConnectionType.getConnection(name) != null;
|
||||
}
|
||||
return fInvalidConnectionNames.contains(name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void loadValues() throws CoreException {
|
||||
IRemoteServicesManager manager = Activator.getService(IRemoteServicesManager.class);
|
||||
if (fConnection != null) {
|
||||
fConnectionName.setText(fConnection.getName());
|
||||
fHostText.setText(fConnection.getAttribute(ProxyConnection.HOSTNAME_ATTR));
|
||||
fUserText.setText(fConnection.getAttribute(ProxyConnection.USERNAME_ATTR));
|
||||
String portStr = fConnection.getAttribute(ProxyConnection.PORT_ATTR);
|
||||
fPortText.setText(portStr.isEmpty() ? Integer.toString(ProxyConnection.DEFAULT_PORT) : portStr);
|
||||
String timeoutStr = fConnection.getAttribute(ProxyConnection.TIMEOUT_ATTR);
|
||||
fTimeoutText.setText(timeoutStr.isEmpty() ? Integer.toString(ProxyConnection.DEFAULT_TIMEOUT) : timeoutStr);
|
||||
String isPwdStr = fConnection.getAttribute(ProxyConnection.USE_PASSWORD_ATTR);
|
||||
boolean isPwd = isPwdStr.isEmpty() ? ProxyConnection.DEFAULT_USE_PASSWORD : Boolean.parseBoolean(isPwdStr);
|
||||
fPasswordButton.setSelection(isPwd);
|
||||
fPublicKeyButton.setSelection(!isPwd);
|
||||
fPasswordText.setText(fConnection.getSecureAttribute(ProxyConnection.PASSWORD_ATTR));
|
||||
fPassphraseText.setText(fConnection.getSecureAttribute(ProxyConnection.PASSPHRASE_ATTR));
|
||||
String useDefaultServerStr = fConnection.getAttribute(ProxyConnection.USE_DEFAULT_SERVER_ATTR);
|
||||
boolean useDefaultServer = useDefaultServerStr.isEmpty() ? ProxyConnection.DEFAULT_USE_DEFAULT_SERVER
|
||||
: Boolean.parseBoolean(useDefaultServerStr);
|
||||
fDefaultServerButton.setSelection(useDefaultServer);
|
||||
String serverCommandStr = fConnection.getAttribute(ProxyConnection.SERVER_COMMAND_ATTR);
|
||||
fServerCommandText.setText(serverCommandStr.isEmpty() ? ProxyConnection.DEFAULT_SERVER_COMMAND : serverCommandStr);
|
||||
|
||||
} else {
|
||||
fConnectionName.setText(fInitialName);
|
||||
String host = fInitialAttributes.get(ProxyConnection.HOSTNAME_ATTR);
|
||||
if (host != null) {
|
||||
fHostText.setText(host);
|
||||
}
|
||||
String username = fInitialAttributes.get(ProxyConnection.USERNAME_ATTR);
|
||||
if (username != null) {
|
||||
fUserText.setText(username);
|
||||
}
|
||||
String port = fInitialAttributes.get(ProxyConnection.PORT_ATTR);
|
||||
if (port != null) {
|
||||
fPortText.setText(port);
|
||||
}
|
||||
String timeout = fInitialAttributes.get(ProxyConnection.TIMEOUT_ATTR);
|
||||
if (timeout != null) {
|
||||
fTimeoutText.setText(timeout);
|
||||
}
|
||||
String isPwd = fInitialAttributes.get(ProxyConnection.USE_PASSWORD_ATTR);
|
||||
if (isPwd != null) {
|
||||
fPasswordButton.setSelection(Boolean.parseBoolean(isPwd));
|
||||
}
|
||||
String password = fInitialAttributes.get(ProxyConnection.PASSWORD_ATTR);
|
||||
if (password != null) {
|
||||
fPasswordText.setText(password);
|
||||
}
|
||||
String passphrase = fInitialAttributes.get(ProxyConnection.PASSPHRASE_ATTR);
|
||||
if (passphrase != null) {
|
||||
fPassphraseText.setText(passphrase);
|
||||
}
|
||||
String useDefaultServer = fInitialAttributes.get(ProxyConnection.USE_DEFAULT_SERVER_ATTR);
|
||||
if (useDefaultServer != null) {
|
||||
fDefaultServerButton.setSelection(Boolean.parseBoolean(useDefaultServer));
|
||||
}
|
||||
String serverCommand = fInitialAttributes.get(ProxyConnection.SERVER_COMMAND_ATTR);
|
||||
if (serverCommand != null) {
|
||||
fServerCommandText.setText(serverCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void registerListeners() {
|
||||
fConnectionName.addModifyListener(fDataModifyListener);
|
||||
fHostText.addModifyListener(fDataModifyListener);
|
||||
fUserText.addModifyListener(fDataModifyListener);
|
||||
fPasswordText.addModifyListener(fDataModifyListener);
|
||||
fPassphraseText.addModifyListener(fDataModifyListener);
|
||||
fPortText.addModifyListener(fDataModifyListener);
|
||||
fTimeoutText.addModifyListener(fDataModifyListener);
|
||||
fServerCommandText.addModifyListener(fDataModifyListener);
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
fInitialAttributes.put(ProxyConnection.HOSTNAME_ATTR, address);
|
||||
}
|
||||
|
||||
public void setAttributes(Map<String, String> attributes) {
|
||||
fInitialAttributes.putAll(attributes);
|
||||
}
|
||||
|
||||
public void setConnection(IRemoteConnectionWorkingCopy connection) {
|
||||
fConnection = connection;
|
||||
}
|
||||
|
||||
public void setConnectionName(String name) {
|
||||
fInitialName = name;
|
||||
}
|
||||
|
||||
public void setInvalidConnectionNames(Set<String> names) {
|
||||
fInvalidConnectionNames = names;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPageComplete(boolean complete) {
|
||||
super.setPageComplete(complete);
|
||||
if (complete) {
|
||||
storeValues();
|
||||
}
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
fInitialAttributes.put(ProxyConnection.PORT_ATTR, Integer.toString(port));
|
||||
}
|
||||
|
||||
private void setTextFieldWidthInChars(Text text, int chars) {
|
||||
text.setTextLimit(chars);
|
||||
Object data = text.getLayoutData();
|
||||
if (data instanceof GridData) {
|
||||
GC gc = new GC(text);
|
||||
FontMetrics fm = gc.getFontMetrics();
|
||||
int width = chars * fm.getAverageCharWidth();
|
||||
gc.dispose();
|
||||
((GridData) data).widthHint = width;
|
||||
}
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
fInitialAttributes.put(ProxyConnection.USERNAME_ATTR, username);
|
||||
}
|
||||
|
||||
private void storeValues() {
|
||||
if (fConnection == null) {
|
||||
try {
|
||||
fConnection = fConnectionType.newConnection(fConnectionName.getText().trim());
|
||||
} catch (RemoteConnectionException e) {
|
||||
Activator.log(e);
|
||||
}
|
||||
}
|
||||
if (fConnection != null) {
|
||||
fConnection.setName(fConnectionName.getText().trim());
|
||||
fConnection.setAttribute(ProxyConnection.HOSTNAME_ATTR, fHostText.getText().trim());
|
||||
fConnection.setAttribute(ProxyConnection.USERNAME_ATTR, fUserText.getText().trim());
|
||||
fConnection.setSecureAttribute(ProxyConnection.PASSWORD_ATTR, fPasswordText.getText().trim());
|
||||
fConnection.setSecureAttribute(ProxyConnection.PASSPHRASE_ATTR, fPassphraseText.getText().trim());
|
||||
fConnection.setAttribute(ProxyConnection.USE_PASSWORD_ATTR, Boolean.toString(fPasswordButton.getSelection()));
|
||||
fConnection.setAttribute(ProxyConnection.TIMEOUT_ATTR, fTimeoutText.getText().trim());
|
||||
fConnection.setAttribute(ProxyConnection.PORT_ATTR, fPortText.getText().trim());
|
||||
fConnection.setAttribute(ProxyConnection.USE_DEFAULT_SERVER_ATTR, Boolean.toString(fDefaultServerButton.getSelection()));
|
||||
fConnection.setAttribute(ProxyConnection.SERVER_COMMAND_ATTR, fServerCommandText.getText().trim());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateEnablement() {
|
||||
boolean isPasswordAuth = fPasswordButton.getSelection();
|
||||
fPasswordText.setEnabled(isPasswordAuth);
|
||||
fPassphraseText.setEnabled(!isPasswordAuth);
|
||||
fServerCommandText.setEnabled(!fDefaultServerButton.getSelection());
|
||||
}
|
||||
|
||||
private String validateAdvanced() {
|
||||
try {
|
||||
Integer.parseInt(fPortText.getText().trim());
|
||||
} catch (NumberFormatException ne) {
|
||||
return Messages.ProxyNewConnectionPage_Port_is_not_valid;
|
||||
}
|
||||
try {
|
||||
Integer.parseInt(fTimeoutText.getText().trim());
|
||||
} catch (NumberFormatException ne) {
|
||||
return Messages.ProxyNewConnectionPage_Timeout_is_not_valid;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void validateFields() {
|
||||
String message = null;
|
||||
if (fConnectionName.getText().trim().length() == 0) {
|
||||
message = Messages.ProxyNewConnectionPage_Please_enter_a_connection_name;
|
||||
} else if (isInvalidName(fConnectionName.getText().trim())) {
|
||||
message = Messages.ProxyConnectionPage_A_connection_with_that_name_already_exists;
|
||||
} else if (fHostText.getText().trim().length() == 0) {
|
||||
message = Messages.ProxyNewConnectionPage_Host_name_cannot_be_empty;
|
||||
} else if (fUserText.getText().trim().length() == 0) {
|
||||
message = Messages.ProxyNewConnectionPage_User_name_cannot_be_empty;
|
||||
} else if (!fDefaultServerButton.getSelection() && fServerCommandText.getText().trim().length() == 0) {
|
||||
message = "Server command cannot be empty";
|
||||
}
|
||||
if (message == null) {
|
||||
message = validateAdvanced();
|
||||
}
|
||||
|
||||
setErrorMessage(message);
|
||||
setPageComplete(message == null);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* Copyright (c) 2016 Oak Ridge National Laboratory 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
|
||||
*/
|
||||
package org.eclipse.remote.internal.proxy.ui.wizards;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jface.wizard.Wizard;
|
||||
import org.eclipse.jface.wizard.WizardDialog;
|
||||
import org.eclipse.remote.core.IRemoteConnectionType;
|
||||
import org.eclipse.remote.core.IRemoteConnectionWorkingCopy;
|
||||
import org.eclipse.remote.ui.IRemoteUIConnectionWizard;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
|
||||
public class ProxyConnectionWizard extends Wizard implements IRemoteUIConnectionWizard {
|
||||
|
||||
private final Shell fShell;
|
||||
private final ProxyConnectionPage fPage;
|
||||
|
||||
public ProxyConnectionWizard(Shell shell, IRemoteConnectionType connectionType) {
|
||||
fShell = shell;
|
||||
fPage = new ProxyConnectionPage(connectionType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPages() {
|
||||
super.addPages();
|
||||
addPage(fPage);
|
||||
}
|
||||
|
||||
public IRemoteConnectionWorkingCopy open() {
|
||||
WizardDialog dialog = new WizardDialog(fShell, this);
|
||||
dialog.setBlockOnOpen(true);
|
||||
if (dialog.open() == WizardDialog.OK) {
|
||||
return fPage.getConnection();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRemoteConnectionWorkingCopy getConnection() {
|
||||
return fPage.getConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performCancel() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performFinish() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setConnection(IRemoteConnectionWorkingCopy connection) {
|
||||
fPage.setConnection(connection);
|
||||
}
|
||||
|
||||
public void setConnectionName(String name) {
|
||||
fPage.setConnectionName(name);
|
||||
}
|
||||
|
||||
public void setInvalidConnectionNames(Set<String> names) {
|
||||
fPage.setInvalidConnectionNames(names);
|
||||
}
|
||||
|
||||
}
|
17
features/org.eclipse.remote.proxy-feature/.project
Normal file
17
features/org.eclipse.remote.proxy-feature/.project
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.eclipse.remote.proxy-feature</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.FeatureBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.FeatureNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,4 @@
|
|||
bin.includes = feature.xml,\
|
||||
feature.properties,\
|
||||
eclipse_update_120.jpg,\
|
||||
epl-v10.html
|
BIN
features/org.eclipse.remote.proxy-feature/eclipse_update_120.jpg
Normal file
BIN
features/org.eclipse.remote.proxy-feature/eclipse_update_120.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
328
features/org.eclipse.remote.proxy-feature/epl-v10.html
Normal file
328
features/org.eclipse.remote.proxy-feature/epl-v10.html
Normal file
|
@ -0,0 +1,328 @@
|
|||
<html xmlns:o="urn:schemas-microsoft-com:office:office"
|
||||
xmlns:w="urn:schemas-microsoft-com:office:word"
|
||||
xmlns="http://www.w3.org/TR/REC-html40">
|
||||
|
||||
<head>
|
||||
<meta http-equiv=Content-Type content="text/html; charset=windows-1252">
|
||||
<meta name=ProgId content=Word.Document>
|
||||
<meta name=Generator content="Microsoft Word 9">
|
||||
<meta name=Originator content="Microsoft Word 9">
|
||||
<link rel=File-List
|
||||
href="./Eclipse%20EPL%202003_11_10%20Final_files/filelist.xml">
|
||||
<title>Eclipse Public License - Version 1.0</title>
|
||||
<!--[if gte mso 9]><xml>
|
||||
<o:DocumentProperties>
|
||||
<o:Revision>2</o:Revision>
|
||||
<o:TotalTime>3</o:TotalTime>
|
||||
<o:Created>2004-03-05T23:03:00Z</o:Created>
|
||||
<o:LastSaved>2004-03-05T23:03:00Z</o:LastSaved>
|
||||
<o:Pages>4</o:Pages>
|
||||
<o:Words>1626</o:Words>
|
||||
<o:Characters>9270</o:Characters>
|
||||
<o:Lines>77</o:Lines>
|
||||
<o:Paragraphs>18</o:Paragraphs>
|
||||
<o:CharactersWithSpaces>11384</o:CharactersWithSpaces>
|
||||
<o:Version>9.4402</o:Version>
|
||||
</o:DocumentProperties>
|
||||
</xml><![endif]--><!--[if gte mso 9]><xml>
|
||||
<w:WordDocument>
|
||||
<w:TrackRevisions/>
|
||||
</w:WordDocument>
|
||||
</xml><![endif]-->
|
||||
<style>
|
||||
<!--
|
||||
/* Font Definitions */
|
||||
@font-face
|
||||
{font-family:Tahoma;
|
||||
panose-1:2 11 6 4 3 5 4 4 2 4;
|
||||
mso-font-charset:0;
|
||||
mso-generic-font-family:swiss;
|
||||
mso-font-pitch:variable;
|
||||
mso-font-signature:553679495 -2147483648 8 0 66047 0;}
|
||||
/* Style Definitions */
|
||||
p.MsoNormal, li.MsoNormal, div.MsoNormal
|
||||
{mso-style-parent:"";
|
||||
margin:0in;
|
||||
margin-bottom:.0001pt;
|
||||
mso-pagination:widow-orphan;
|
||||
font-size:12.0pt;
|
||||
font-family:"Times New Roman";
|
||||
mso-fareast-font-family:"Times New Roman";}
|
||||
p
|
||||
{margin-right:0in;
|
||||
mso-margin-top-alt:auto;
|
||||
mso-margin-bottom-alt:auto;
|
||||
margin-left:0in;
|
||||
mso-pagination:widow-orphan;
|
||||
font-size:12.0pt;
|
||||
font-family:"Times New Roman";
|
||||
mso-fareast-font-family:"Times New Roman";}
|
||||
p.BalloonText, li.BalloonText, div.BalloonText
|
||||
{mso-style-name:"Balloon Text";
|
||||
margin:0in;
|
||||
margin-bottom:.0001pt;
|
||||
mso-pagination:widow-orphan;
|
||||
font-size:8.0pt;
|
||||
font-family:Tahoma;
|
||||
mso-fareast-font-family:"Times New Roman";}
|
||||
@page Section1
|
||||
{size:8.5in 11.0in;
|
||||
margin:1.0in 1.25in 1.0in 1.25in;
|
||||
mso-header-margin:.5in;
|
||||
mso-footer-margin:.5in;
|
||||
mso-paper-source:0;}
|
||||
div.Section1
|
||||
{page:Section1;}
|
||||
-->
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body lang=EN-US style='tab-interval:.5in'>
|
||||
|
||||
<div class=Section1>
|
||||
|
||||
<p align=center style='text-align:center'><b>Eclipse Public License - v 1.0</b>
|
||||
</p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER
|
||||
THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE,
|
||||
REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE
|
||||
OF THIS AGREEMENT.</span> </p>
|
||||
|
||||
<p><b><span style='font-size:10.0pt'>1. DEFINITIONS</span></b> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>"Contribution" means:</span> </p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
|
||||
in the case of the initial Contributor, the initial code and documentation
|
||||
distributed under this Agreement, and<br clear=left>
|
||||
b) in the case of each subsequent Contributor:</span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>i)
|
||||
changes to the Program, and</span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>ii)
|
||||
additions to the Program;</span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>where
|
||||
such changes and/or additions to the Program originate from and are distributed
|
||||
by that particular Contributor. A Contribution 'originates' from a Contributor
|
||||
if it was added to the Program by such Contributor itself or anyone acting on
|
||||
such Contributor's behalf. Contributions do not include additions to the
|
||||
Program which: (i) are separate modules of software distributed in conjunction
|
||||
with the Program under their own license agreement, and (ii) are not derivative
|
||||
works of the Program. </span></p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>"Contributor" means any person or
|
||||
entity that distributes the Program.</span> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>"Licensed Patents " mean patent
|
||||
claims licensable by a Contributor which are necessarily infringed by the use
|
||||
or sale of its Contribution alone or when combined with the Program. </span></p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>"Program" means the Contributions
|
||||
distributed in accordance with this Agreement.</span> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>"Recipient" means anyone who
|
||||
receives the Program under this Agreement, including all Contributors.</span> </p>
|
||||
|
||||
<p><b><span style='font-size:10.0pt'>2. GRANT OF RIGHTS</span></b> </p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
|
||||
Subject to the terms of this Agreement, each Contributor hereby grants Recipient
|
||||
a non-exclusive, worldwide, royalty-free copyright license to<span
|
||||
style='color:red'> </span>reproduce, prepare derivative works of, publicly
|
||||
display, publicly perform, distribute and sublicense the Contribution of such
|
||||
Contributor, if any, and such derivative works, in source code and object code
|
||||
form.</span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b)
|
||||
Subject to the terms of this Agreement, each Contributor hereby grants
|
||||
Recipient a non-exclusive, worldwide,<span style='color:green'> </span>royalty-free
|
||||
patent license under Licensed Patents to make, use, sell, offer to sell, import
|
||||
and otherwise transfer the Contribution of such Contributor, if any, in source
|
||||
code and object code form. This patent license shall apply to the combination
|
||||
of the Contribution and the Program if, at the time the Contribution is added
|
||||
by the Contributor, such addition of the Contribution causes such combination
|
||||
to be covered by the Licensed Patents. The patent license shall not apply to
|
||||
any other combinations which include the Contribution. No hardware per se is
|
||||
licensed hereunder. </span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>c)
|
||||
Recipient understands that although each Contributor grants the licenses to its
|
||||
Contributions set forth herein, no assurances are provided by any Contributor
|
||||
that the Program does not infringe the patent or other intellectual property
|
||||
rights of any other entity. Each Contributor disclaims any liability to Recipient
|
||||
for claims brought by any other entity based on infringement of intellectual
|
||||
property rights or otherwise. As a condition to exercising the rights and
|
||||
licenses granted hereunder, each Recipient hereby assumes sole responsibility
|
||||
to secure any other intellectual property rights needed, if any. For example,
|
||||
if a third party patent license is required to allow Recipient to distribute
|
||||
the Program, it is Recipient's responsibility to acquire that license before
|
||||
distributing the Program.</span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>d)
|
||||
Each Contributor represents that to its knowledge it has sufficient copyright
|
||||
rights in its Contribution, if any, to grant the copyright license set forth in
|
||||
this Agreement. </span></p>
|
||||
|
||||
<p><b><span style='font-size:10.0pt'>3. REQUIREMENTS</span></b> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>A Contributor may choose to distribute the
|
||||
Program in object code form under its own license agreement, provided that:</span>
|
||||
</p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
|
||||
it complies with the terms and conditions of this Agreement; and</span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b)
|
||||
its license agreement:</span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>i)
|
||||
effectively disclaims on behalf of all Contributors all warranties and
|
||||
conditions, express and implied, including warranties or conditions of title
|
||||
and non-infringement, and implied warranties or conditions of merchantability
|
||||
and fitness for a particular purpose; </span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>ii)
|
||||
effectively excludes on behalf of all Contributors all liability for damages,
|
||||
including direct, indirect, special, incidental and consequential damages, such
|
||||
as lost profits; </span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>iii)
|
||||
states that any provisions which differ from this Agreement are offered by that
|
||||
Contributor alone and not by any other party; and</span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>iv)
|
||||
states that source code for the Program is available from such Contributor, and
|
||||
informs licensees how to obtain it in a reasonable manner on or through a
|
||||
medium customarily used for software exchange.<span style='color:blue'> </span></span></p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>When the Program is made available in source
|
||||
code form:</span> </p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
|
||||
it must be made available under this Agreement; and </span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b) a
|
||||
copy of this Agreement must be included with each copy of the Program. </span></p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>Contributors may not remove or alter any
|
||||
copyright notices contained within the Program. </span></p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>Each Contributor must identify itself as the
|
||||
originator of its Contribution, if any, in a manner that reasonably allows
|
||||
subsequent Recipients to identify the originator of the Contribution. </span></p>
|
||||
|
||||
<p><b><span style='font-size:10.0pt'>4. COMMERCIAL DISTRIBUTION</span></b> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>Commercial distributors of software may
|
||||
accept certain responsibilities with respect to end users, business partners
|
||||
and the like. While this license is intended to facilitate the commercial use
|
||||
of the Program, the Contributor who includes the Program in a commercial
|
||||
product offering should do so in a manner which does not create potential
|
||||
liability for other Contributors. Therefore, if a Contributor includes the
|
||||
Program in a commercial product offering, such Contributor ("Commercial
|
||||
Contributor") hereby agrees to defend and indemnify every other
|
||||
Contributor ("Indemnified Contributor") against any losses, damages and
|
||||
costs (collectively "Losses") arising from claims, lawsuits and other
|
||||
legal actions brought by a third party against the Indemnified Contributor to
|
||||
the extent caused by the acts or omissions of such Commercial Contributor in
|
||||
connection with its distribution of the Program in a commercial product
|
||||
offering. The obligations in this section do not apply to any claims or Losses
|
||||
relating to any actual or alleged intellectual property infringement. In order
|
||||
to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
|
||||
Contributor in writing of such claim, and b) allow the Commercial Contributor
|
||||
to control, and cooperate with the Commercial Contributor in, the defense and
|
||||
any related settlement negotiations. The Indemnified Contributor may participate
|
||||
in any such claim at its own expense.</span> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>For example, a Contributor might include the
|
||||
Program in a commercial product offering, Product X. That Contributor is then a
|
||||
Commercial Contributor. If that Commercial Contributor then makes performance
|
||||
claims, or offers warranties related to Product X, those performance claims and
|
||||
warranties are such Commercial Contributor's responsibility alone. Under this
|
||||
section, the Commercial Contributor would have to defend claims against the
|
||||
other Contributors related to those performance claims and warranties, and if a
|
||||
court requires any other Contributor to pay any damages as a result, the
|
||||
Commercial Contributor must pay those damages.</span> </p>
|
||||
|
||||
<p><b><span style='font-size:10.0pt'>5. NO WARRANTY</span></b> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>EXCEPT AS EXPRESSLY SET FORTH IN THIS
|
||||
AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING,
|
||||
WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
|
||||
responsible for determining the appropriateness of using and distributing the
|
||||
Program and assumes all risks associated with its exercise of rights under this
|
||||
Agreement , including but not limited to the risks and costs of program errors,
|
||||
compliance with applicable laws, damage to or loss of data, programs or
|
||||
equipment, and unavailability or interruption of operations. </span></p>
|
||||
|
||||
<p><b><span style='font-size:10.0pt'>6. DISCLAIMER OF LIABILITY</span></b> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>EXCEPT AS EXPRESSLY SET FORTH IN THIS
|
||||
AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY
|
||||
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF
|
||||
THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF
|
||||
THE POSSIBILITY OF SUCH DAMAGES.</span> </p>
|
||||
|
||||
<p><b><span style='font-size:10.0pt'>7. GENERAL</span></b> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>If any provision of this Agreement is invalid
|
||||
or unenforceable under applicable law, it shall not affect the validity or
|
||||
enforceability of the remainder of the terms of this Agreement, and without
|
||||
further action by the parties hereto, such provision shall be reformed to the
|
||||
minimum extent necessary to make such provision valid and enforceable.</span> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>If Recipient institutes patent litigation
|
||||
against any entity (including a cross-claim or counterclaim in a lawsuit)
|
||||
alleging that the Program itself (excluding combinations of the Program with
|
||||
other software or hardware) infringes such Recipient's patent(s), then such
|
||||
Recipient's rights granted under Section 2(b) shall terminate as of the date
|
||||
such litigation is filed. </span></p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>All Recipient's rights under this Agreement
|
||||
shall terminate if it fails to comply with any of the material terms or
|
||||
conditions of this Agreement and does not cure such failure in a reasonable
|
||||
period of time after becoming aware of such noncompliance. If all Recipient's
|
||||
rights under this Agreement terminate, Recipient agrees to cease use and
|
||||
distribution of the Program as soon as reasonably practicable. However,
|
||||
Recipient's obligations under this Agreement and any licenses granted by
|
||||
Recipient relating to the Program shall continue and survive. </span></p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>Everyone is permitted to copy and distribute
|
||||
copies of this Agreement, but in order to avoid inconsistency the Agreement is
|
||||
copyrighted and may only be modified in the following manner. The Agreement
|
||||
Steward reserves the right to publish new versions (including revisions) of
|
||||
this Agreement from time to time. No one other than the Agreement Steward has
|
||||
the right to modify this Agreement. The Eclipse Foundation is the initial
|
||||
Agreement Steward. The Eclipse Foundation may assign the responsibility to
|
||||
serve as the Agreement Steward to a suitable separate entity. Each new version
|
||||
of the Agreement will be given a distinguishing version number. The Program
|
||||
(including Contributions) may always be distributed subject to the version of
|
||||
the Agreement under which it was received. In addition, after a new version of
|
||||
the Agreement is published, Contributor may elect to distribute the Program
|
||||
(including its Contributions) under the new version. Except as expressly stated
|
||||
in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to
|
||||
the intellectual property of any Contributor under this Agreement, whether
|
||||
expressly, by implication, estoppel or otherwise. All rights in the Program not
|
||||
expressly granted under this Agreement are reserved.</span> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>This Agreement is governed by the laws of the
|
||||
State of New York and the intellectual property laws of the United States of
|
||||
America. No party to this Agreement will bring a legal action under this
|
||||
Agreement more than one year after the cause of action arose. Each party waives
|
||||
its rights to a jury trial in any resulting litigation.</span> </p>
|
||||
|
||||
<p class=MsoNormal><![if !supportEmptyParas]> <![endif]><o:p></o:p></p>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue