1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-09 18:56:02 +02:00

Add CDT-specific remote support.

Signed-off-by: Greg Watson <g.watson@computer.org>
This commit is contained in:
Greg Watson 2014-03-24 09:22:07 -04:00
parent 1b500f829b
commit 6f3c30a613
14 changed files with 648 additions and 0 deletions

View file

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

View file

@ -0,0 +1 @@
/bin

View file

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.remote.cdt.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>

View file

@ -0,0 +1,7 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7

View file

@ -0,0 +1,13 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.remote.cdt.core;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: org.eclipse.remote.internal.cdt.core.Activator
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.cdt.core,
org.eclipse.remote.core
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ActivationPolicy: lazy
Bundle-Vendor: %pluginProvider
Import-Package: org.eclipse.core.resources

View 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 (&quot;Content&quot;). Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
apply to your use of any object code in the Content. Check the Redistributor's license that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
indicated below, the terms and conditions of the EPL still apply to any source code in the Content and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org.</p>
</body>
</html>

View file

@ -0,0 +1,4 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.

View file

@ -0,0 +1,11 @@
###############################################################################
# Copyright (c) 2014 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
#
###############################################################################
pluginName=Remote Services CDT Utilities
pluginProvider=Eclipse PTP

View 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>1.0.0-SNAPSHOT</version>
<relativePath>../../releng/org.eclipse.remote.build/pom.xml</relativePath>
</parent>
<artifactId>org.eclipse.remote.cdt.core</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>

View file

@ -0,0 +1,234 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.remote.cdt.core;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.util.Map;
import java.util.Properties;
import org.eclipse.cdt.core.CommandLauncher;
import org.eclipse.cdt.core.ICommandLauncher;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.remote.core.IRemoteConnection;
import org.eclipse.remote.core.IRemoteProcess;
import org.eclipse.remote.core.IRemoteProcessBuilder;
import org.eclipse.remote.core.IRemoteResource;
import org.eclipse.remote.core.IRemoteServices;
import org.eclipse.remote.core.RemoteProcessAdapter;
import org.eclipse.remote.core.RemoteServices;
import org.eclipse.remote.internal.cdt.core.messages.Messages;
public class RemoteCommandLauncher implements ICommandLauncher {
private final ICommandLauncher fLocalLauncher = new CommandLauncher();
private boolean fShowCommand;
private String[] fCommandArgs;
private IRemoteConnection fConnection;
private IRemoteProcess fRemoteProcess;
private final Properties fEnvironment = new Properties();
/**
* The number of milliseconds to pause between polling.
*/
private static final long DELAY = 50L;
/**
* Constructs a command array that will be passed to the process
*/
private String[] constructCommandArray(String command, String[] commandArgs) {
String[] args = new String[1 + commandArgs.length];
args[0] = command;
System.arraycopy(commandArgs, 0, args, 1, commandArgs.length);
return args;
}
@Override
public Process execute(IPath commandPath, String[] args, String[] env, IPath workingDirectory, IProgressMonitor monitor)
throws CoreException {
if (fLocalLauncher.getProject() != null) {
IRemoteResource remRes = (IRemoteResource) fLocalLauncher.getProject().getAdapter(IRemoteResource.class);
if (remRes != null) {
URI uri = remRes.getActiveLocationURI();
IRemoteServices remServices = RemoteServices.getRemoteServices(uri);
if (remServices != null) {
fConnection = remServices.getConnectionManager().getConnection(uri);
if (fConnection != null) {
parseEnvironment(env);
fCommandArgs = constructCommandArray(commandPath.toOSString(), args);
IRemoteProcessBuilder processBuilder = fConnection.getProcessBuilder(fCommandArgs);
Map<String, String> processEnv = processBuilder.environment();
for (String key : fEnvironment.stringPropertyNames()) {
processEnv.put(key, fEnvironment.getProperty(key));
}
try {
fRemoteProcess = processBuilder.start();
return new RemoteProcessAdapter(fRemoteProcess);
} catch (IOException e) {
fLocalLauncher.setErrorMessage(e.getMessage());
return null;
}
}
}
}
}
return fLocalLauncher.execute(commandPath, args, env, workingDirectory, monitor);
}
@Override
public String[] getCommandArgs() {
return fCommandArgs;
}
@Override
public String getCommandLine() {
return getCommandLine(fCommandArgs);
}
protected String getCommandLine(String[] commandArgs) {
return getCommandLineQuoted(commandArgs, false);
}
@SuppressWarnings("nls")
private String getCommandLineQuoted(String[] commandArgs, boolean quote) {
String nl = System.getProperty("line.separator", "\n");
if (fConnection != null) {
nl = fConnection.getProperty(IRemoteConnection.LINE_SEPARATOR_PROPERTY);
}
StringBuffer buf = new StringBuffer();
if (commandArgs != null) {
for (String commandArg : commandArgs) {
if (quote && (commandArg.contains(" ") || commandArg.contains("\"") || commandArg.contains("\\"))) {
commandArg = '"' + commandArg.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\"") + '"';
}
buf.append(commandArg);
buf.append(' ');
}
buf.append(nl);
}
return buf.toString();
}
@Override
public Properties getEnvironment() {
return fEnvironment;
}
@Override
public String getErrorMessage() {
return fLocalLauncher.getErrorMessage();
}
@Override
public IProject getProject() {
return fLocalLauncher.getProject();
}
/**
* Parse array of "ENV=value" pairs to Properties.
*/
private void parseEnvironment(String[] env) {
if (env != null) {
fEnvironment.clear();
for (String envStr : env) {
// Split "ENV=value" and put in Properties
int pos = envStr.indexOf('=');
if (pos < 0) {
pos = envStr.length();
}
String key = envStr.substring(0, pos);
String value = envStr.substring(pos + 1);
fEnvironment.put(key, value);
}
}
}
private void printCommandLine(OutputStream os) {
if (os != null) {
try {
os.write(getCommandLineQuoted(getCommandArgs(), true).getBytes());
os.flush();
} catch (IOException e) {
// ignore;
}
}
}
@Override
public void setErrorMessage(String error) {
fLocalLauncher.setErrorMessage(error);
}
@Override
public void setProject(IProject project) {
fLocalLauncher.setProject(project);
}
@Override
public void showCommand(boolean show) {
fLocalLauncher.showCommand(show);
fShowCommand = show;
}
@Override
public int waitAndRead(OutputStream out, OutputStream err) {
if (fShowCommand) {
printCommandLine(out);
}
if (fRemoteProcess == null) {
return ILLEGAL_COMMAND;
}
RemoteProcessClosure closure = new RemoteProcessClosure(fRemoteProcess, out, err);
closure.runBlocking();
return OK;
}
@Override
public int waitAndRead(OutputStream out, OutputStream err, IProgressMonitor monitor) {
if (fShowCommand) {
printCommandLine(out);
}
if (fRemoteProcess == null) {
return ILLEGAL_COMMAND;
}
RemoteProcessClosure closure = new RemoteProcessClosure(fRemoteProcess, out, err);
closure.runNonBlocking();
while (!monitor.isCanceled() && closure.isAlive()) {
try {
Thread.sleep(DELAY);
} catch (InterruptedException ie) {
// ignore
}
}
int state = OK;
// Operation canceled by the user, terminate abnormally.
if (monitor.isCanceled()) {
closure.terminate();
state = COMMAND_CANCELED;
setErrorMessage(Messages.RemoteCommandLauncher_Command_canceled);
}
try {
fRemoteProcess.waitFor();
} catch (InterruptedException e) {
// ignore
}
return state;
}
}

View file

@ -0,0 +1,229 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.remote.cdt.core;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import org.eclipse.core.runtime.Assert;
import org.eclipse.remote.core.IRemoteProcess;
/**
* Bundled state of a launched process including the threads linking the process
* in/output to console documents.
*/
public class RemoteProcessClosure {
/**
* Thread which continuously reads from a input stream and pushes the read
* data to an output stream which is immediately flushed afterwards.
*/
protected static class ReaderThread extends Thread {
private final InputStream fInputStream;
private final OutputStream fOutputStream;
private boolean fFinished = false;
private final String lineSeparator;
public ReaderThread(ThreadGroup group, String name, InputStream in, OutputStream out) {
super(group, name);
Assert.isNotNull(in);
Assert.isNotNull(out);
fOutputStream = out;
fInputStream = in;
setDaemon(true);
lineSeparator = System.getProperty("line.separator"); //$NON-NLS-1$
}
@Override
public void run() {
try {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(fInputStream));
String line;
while ((line = reader.readLine()) != null) {
line += lineSeparator;
fOutputStream.write(line.getBytes());
}
} catch (IOException x) {
// Ignore
} finally {
try {
fOutputStream.flush();
} catch (IOException e) {
// Ignore
}
try {
fInputStream.close();
} catch (IOException e) {
// Ignore
}
}
} finally {
complete();
}
}
public synchronized boolean finished() {
return fFinished;
}
public synchronized void waitFor() {
while (!fFinished) {
try {
wait();
} catch (InterruptedException e) {
// Ignore
}
}
}
public synchronized void complete() {
fFinished = true;
notify();
}
public void close() {
try {
fOutputStream.close();
} catch (IOException e) {
// Ignore
}
}
}
protected static int fCounter = 0;
protected IRemoteProcess fProcess;
protected OutputStream fOutput;
protected OutputStream fError;
protected ReaderThread fOutputReader;
protected ReaderThread fErrorReader;
/**
* Creates a process closure and connects the launched process with output and error streams.
*
* @param outputStream
* process output is written to this stream. Can be <code>null</code>, if not interested in reading the output
* @param errorStream
* process error output is written to this stream. Can be <code>null</code>, if not interested in reading the output
*/
public RemoteProcessClosure(IRemoteProcess process, OutputStream outputStream, OutputStream errorStream) {
fProcess = process;
fOutput = outputStream;
fError = errorStream;
}
/**
* Live links the launched process with the configured in/out streams using
* reader threads.
*/
public void runNonBlocking() {
ThreadGroup group = new ThreadGroup("RemoteProcess" + fCounter++); //$NON-NLS-1$
InputStream stdin = fProcess.getInputStream();
InputStream stderr = fProcess.getErrorStream();
fOutputReader = new ReaderThread(group, "OutputReader", stdin, fOutput); //$NON-NLS-1$
fErrorReader = new ReaderThread(group, "ErrorReader", stderr, fError); //$NON-NLS-1$
fOutputReader.start();
fErrorReader.start();
}
public void runBlocking() {
runNonBlocking();
boolean finished = false;
while (!finished) {
try {
fProcess.waitFor();
} catch (InterruptedException e) {
// Ignore
}
try {
fProcess.exitValue();
finished = true;
} catch (IllegalThreadStateException e) {
// Ignore
}
}
if (!fOutputReader.finished()) {
fOutputReader.waitFor();
}
if (!fErrorReader.finished()) {
fErrorReader.waitFor();
}
fOutputReader.close();
fErrorReader.close();
fProcess = null;
fOutputReader = null;
fErrorReader = null;
}
public boolean isAlive() {
if (fProcess != null) {
if (fOutputReader.isAlive() || fErrorReader.isAlive()) {
return true;
}
fProcess = null;
fOutputReader.close();
fErrorReader.close();
fOutputReader = null;
fErrorReader = null;
}
return false;
}
/**
* The same functionality as "isAlive()"
* but does not affect out streams,
* because they can be shared among processes
*/
public boolean isRunning() {
if (fProcess != null) {
if (fOutputReader.isAlive() || fErrorReader.isAlive()) {
return true;
}
fProcess = null;
}
return false;
}
/**
* Forces the termination the launched process
*/
public void terminate() {
if (fProcess != null) {
fProcess.destroy();
fProcess = null;
}
if (!fOutputReader.finished()) {
fOutputReader.waitFor();
}
if (!fErrorReader.finished()) {
fErrorReader.waitFor();
}
fOutputReader.close();
fErrorReader.close();
fOutputReader = null;
fErrorReader = null;
}
}

View file

@ -0,0 +1,44 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.remote.internal.cdt.core;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class Activator implements BundleActivator {
private static BundleContext context;
static BundleContext getContext() {
return context;
}
/*
* (non-Javadoc)
*
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
@Override
public void start(BundleContext bundleContext) throws Exception {
Activator.context = bundleContext;
}
/*
* (non-Javadoc)
*
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
@Override
public void stop(BundleContext bundleContext) throws Exception {
Activator.context = null;
}
}

View file

@ -0,0 +1,25 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.remote.internal.cdt.core.messages;
import org.eclipse.osgi.util.NLS;
public class Messages extends NLS {
private static final String BUNDLE_NAME = "org.eclipse.remote.internal.cdt.core.messages.messages"; //$NON-NLS-1$
public static String RemoteCommandLauncher_Command_canceled;
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
}
private Messages() {
}
}

View file

@ -0,0 +1 @@
RemoteCommandLauncher_Command_canceled=Command canceled