From: YoonKi Park
Date: Mon, 21 Nov 2011 01:53:13 +0000 (+0900)
Subject: [Title] add ansicode console
X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=957c8b612703b4210edeafd4cc3ea7783c72fa88;p=sdk%2Fide%2Fcommon-eplugin.git
[Title] add ansicode console
[Redmine#] 2029
---
diff --git a/com.samsung.slp.common/src/com/samsung/slp/common/console/AnsicodeAdapter.java b/com.samsung.slp.common/src/com/samsung/slp/common/console/AnsicodeAdapter.java
new file mode 100644
index 0000000..a3a9c2c
--- /dev/null
+++ b/com.samsung.slp.common/src/com/samsung/slp/common/console/AnsicodeAdapter.java
@@ -0,0 +1,193 @@
+package com.samsung.slp.common.console;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.LineStyleEvent;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Display;
+
+public class AnsicodeAdapter {
+ public static final char ESCAPE = '\033'; // ANSI Escape Character that starts commands
+
+/* public static final Color BLACK = Color.BLACK;
+ public static final Color RED = Color.RED.darker();
+ public static final Color GREEN = Color.GREEN.darker();
+ public static final Color YELLOW = Color.YELLOW.darker();
+ public static final Color BLUE = new Color(66, 66, 255).darker();
+ public static final Color MAGENTA = Color.MAGENTA.darker();
+ public static final Color CYAN = Color.CYAN.darker();
+ public static final Color WHITE = Color.GRAY.brighter();
+
+ public static final Color INTENSE_BLACK = Color.GRAY.darker();
+ public static final Color INTENSE_RED = Color.RED;
+ public static final Color INTENSE_GREEN = Color.GREEN;
+ public static final Color INTENSE_YELLOW = Color.YELLOW;
+ public static final Color INTENSE_BLUE = new Color(66, 66, 255);
+ public static final Color INTENSE_MAGENTA = Color.MAGENTA;
+ public static final Color INTENSE_CYAN = Color.CYAN;
+ public static final Color INTENSE_WHITE = Color.WHITE;
+
+ private static final Color normal[] = {BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE};
+ private static final Color bright[] = {INTENSE_BLACK, INTENSE_RED, INTENSE_GREEN, INTENSE_YELLOW, INTENSE_BLUE, INTENSE_MAGENTA,
+ INTENSE_CYAN, INTENSE_WHITE};*/
+
+ private Color foreground;
+ private Color background;
+ private int fontStyles;
+
+ //"\e[31mHello World\e[m"
+ private static String ansiString;
+ private static LineStyleEvent lineEvent;
+ private static AnsicodeAdapter instance;
+ private static boolean hasAnsicode = false;
+
+ private static int commandSGR = 'm';
+ private static int commandDSR = 'n';
+ private static int[] commands = {'m','n'};
+ private static List styles = new ArrayList();
+ public AnsicodeAdapter() {}
+
+ /**
+ * Get instance of AnsicodeAdapter
+ * @param string The String should end with '\n'
+ * @return Returns the AnsicodeAdapter's incstance
+ */
+ public static AnsicodeAdapter getInstance(LineStyleEvent event)
+ {
+ if (instance == null)
+ instance = new AnsicodeAdapter();
+ lineEvent = event;
+ ansiString = event.lineText;
+ parseLineStyle();
+ return instance;
+ }
+ public static AnsicodeAdapter getDefault()
+ {
+ if (instance == null)
+ instance = new AnsicodeAdapter();
+ return instance;
+ }
+ public static List getRangeStyle() {
+ return styles;
+ }
+ private static void parseLineStyle() {
+ String str;
+
+ for (int i = 0; i < ansiString.length(); i++) {
+ if (ansiString.charAt(i) == '\033') {
+ if (ansiString.indexOf(commandSGR, i) < ansiString.length()) {
+
+ int startCommand = ansiString.indexOf('m', i);
+ if (startCommand < 0) {
+ //
+ return;
+ }
+ String colorCodes = ansiString.substring(i+2,startCommand);
+ String codes[] = colorCodes.split(";");
+
+ int styleStart = startCommand+1;
+ int styleEnd = 0;
+ int endCommand = ansiString.indexOf('\033',styleStart);
+ if (endCommand < 0 ) {
+ styleEnd = ansiString.length()-1;
+ } else {
+ styleEnd = endCommand;
+ }
+ String styleString = ansiString.substring(styleStart, styleEnd); //remove [m
+
+ StyleRange currentStyle = new StyleRange();
+ currentStyle.start = lineEvent.lineOffset;
+ //currentStyle.start = event.lineOffset + styleStart;
+ currentStyle.length= styleString.length();
+ Display display = Display.getCurrent();
+ Color blue = display.getSystemColor(SWT.COLOR_BLUE);
+
+ //currentStyle.background = blue;
+ currentStyle.foreground = blue;
+ styles.add(currentStyle);
+ ////////
+ i = styleEnd;
+
+ }
+ }
+ }
+ }
+ private void getStyleAttribute(String codes[]) {
+ boolean brighter = false;
+ for (int j = 0; j < codes.length; j++) {
+
+ if (codes[j].matches("[\\d]*")) {
+ int code = Integer.parseInt(codes[j]);
+ if (code == 0) {
+ brighter = false; //reset / normal
+ } else if (code == 1) {
+ brighter = true;
+ } else if (code >= 30 && code <= 37) {
+
+ }
+ }
+ }
+ }
+ public Color getForeground() {
+ return foreground;
+ }
+ public Color getBackground() {
+ return background;
+ }
+ public int getFontStyle() {
+ return fontStyles;
+ }
+ public String getStripAnsiString(String ansiString) {
+ StringBuilder sb = new StringBuilder();
+
+ char command = 0;
+ for (int i=0; i startCommand && startCommand > -1) {
+ min = startCommand;
+ }
+ }
+ command=ansiString.charAt(min);
+ startCommand=min;
+
+ if ( startCommand < ansiString.length()) {
+
+ String colorCodes = ansiString.substring(i+2,startCommand);
+ String codes[] = colorCodes.split(";");
+
+ int styleStart = startCommand+1;
+ int styleEnd = 0;
+ int endEscape = ansiString.indexOf(ESCAPE,styleStart);
+ if (endEscape < 0 ) {
+ styleEnd = ansiString.length();
+ i = ansiString.length();
+ } else {
+ int endCommand = ansiString.indexOf(command,endEscape);
+ if (endCommand < 0 ) {
+ styleEnd = ansiString.length();
+ i = ansiString.length();
+ } else {
+ styleEnd = endEscape;
+ i = endCommand;
+ }
+ }
+ String styleString = null;
+ styleString = ansiString.substring(styleStart, styleEnd);
+ sb.append(styleString);
+ }
+ }else {
+ sb.append(ansiString.charAt(i));
+ }
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/com.samsung.slp.common/src/com/samsung/slp/common/process/PTY.java b/com.samsung.slp.common/src/com/samsung/slp/common/process/PTY.java
new file mode 100644
index 0000000..5c248eef0
--- /dev/null
+++ b/com.samsung.slp.common/src/com/samsung/slp/common/process/PTY.java
@@ -0,0 +1,173 @@
+package com.samsung.slp.common.process;
+
+/*******************************************************************************
+ * Copyright (c) 2002, 2010 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
+ * Wind River Systems, Inc. - bug 248071
+ *******************************************************************************/
+
+import java.io.IOException;
+import com.samsung.slp.common.log.Logger;
+
+/**
+ * PTY - pseudo terminal support.
+ */
+public class PTY {
+
+ final boolean console;
+ String slave;
+ PTYInputStream in;
+ PTYOutputStream out;
+ /**
+ * NOTE: Field is accessed by the native layer. Do not refactor!
+ */
+ int master;
+
+ private static boolean hasPTY;
+ private static boolean setTerminalSizeErrorAlreadyLogged;
+
+ /**
+ * The master fd is used on two streams. We need to wrap the fd
+ * so that when stream.close() is called the other stream is disabled.
+ */
+ public class MasterFD {
+
+ public int getFD() {
+ return master;
+ }
+
+ void setFD(int fd) {
+ master = fd;
+ }
+ }
+
+ /**
+ * Create PTY for use with Eclipse console.
+ * Identical to {@link PTY#PTY(boolean) PTY(true)}.
+ */
+ public PTY() throws IOException {
+ this(true);
+ }
+
+ /**
+ * Create pseudo terminal.
+ *
+ *
+ * The provided flag indicates whether the pseudo terminal is used with the interactive
+ * Eclipse console:
+ *
+ * - If
true
the terminal is configured with no echo and stderr is
+ * redirected to a pipe instead of the PTY.
+ * - If
false
the terminal is configured with echo and stderr is
+ * connected to the PTY. This mode is best suited for use with a proper terminal emulation.
+ * Note that this mode might not be supported on all platforms.
+ * Known platforms which support this mode are:
+ * linux-x86
, linux-x86_64
, solaris-sparc
, macosx
.
+ *
+ *
+ *
+ *
+ * @param console whether terminal is used with Eclipse console
+ * @throws IOException if the PTY could not be created
+ * @since 5.2
+ */
+ public PTY(boolean console) throws IOException {
+ this.console = console;
+
+ if (hasPTY) {
+ slave= openMaster(console);
+ }
+
+ if (slave == null) {
+ //throw new IOException(CCorePlugin.getResourceString("Util.exception.cannotCreatePty")); //$NON-NLS-1$
+ throw new IOException("Util.exception.cannotCreatePty"); //$NON-NLS-1$
+ }
+
+ in = new PTYInputStream(new MasterFD());
+ out = new PTYOutputStream(new MasterFD());
+ }
+
+ public String getSlaveName() {
+ return slave;
+ }
+
+ public MasterFD getMasterFD() {
+ return new MasterFD();
+ }
+
+ /**
+ * @return whether this pseudo terminal is for use with the Eclipse console.
+ *
+ * @since 5.2
+ */
+ public final boolean isConsole() {
+ return console;
+ }
+
+ public PTYOutputStream getOutputStream() {
+ return out;
+ }
+
+ public PTYInputStream getInputStream() {
+ return in;
+ }
+
+ /**
+ * Change terminal window size to given width and height.
+ *
+ * This should only be used when the pseudo terminal is configured
+ * for use with a terminal emulation, i.e. when {@link #isConsole()}
+ * returns false
.
+ *
+ *
+ * Note: This method may not be supported on all platforms.
+ * Known platforms which support this method are:
+ * linux-x86
, linux-x86_64
, solaris-sparc
, macosx
.
+ *
+ *
+ * @since 5.2
+ */
+ public final void setTerminalSize(int width, int height) {
+ try {
+ change_window_size(master, width, height);
+ } catch (UnsatisfiedLinkError ule) {
+ if (!setTerminalSizeErrorAlreadyLogged) {
+ setTerminalSizeErrorAlreadyLogged = true;
+ //CCorePlugin.log(CCorePlugin.getResourceString("Util.exception.cannotSetTerminalSize"), ule); //$NON-NLS-1$
+ Logger.error(ule.getMessage() , ule);
+ }
+ }
+ }
+
+ /**
+ * @return whether PTY support is available on this platform
+ */
+ public static boolean isSupported() {
+ return hasPTY;
+ }
+
+ native String openMaster(boolean console);
+
+ native int change_window_size(int fdm, int width, int height);
+
+ static {
+ try {
+ System.loadLibrary("pty"); //$NON-NLS-1$
+ hasPTY = true;
+ } catch (SecurityException e) {
+ // Comment out it worries the users too much
+ //CCorePlugin.log(e);
+ } catch (UnsatisfiedLinkError e) {
+ // Comment out it worries the users too much
+ //CCorePlugin.log(e);
+ }
+ }
+
+}
+
diff --git a/com.samsung.slp.common/src/com/samsung/slp/common/process/PTYInputStream.java b/com.samsung.slp.common/src/com/samsung/slp/common/process/PTYInputStream.java
new file mode 100644
index 0000000..59ef2e2
--- /dev/null
+++ b/com.samsung.slp.common/src/com/samsung/slp/common/process/PTYInputStream.java
@@ -0,0 +1,96 @@
+package com.samsung.slp.common.process;
+
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 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
+ * Wind River Systems - bug 286162
+ *******************************************************************************/
+import java.io.IOException;
+import java.io.InputStream;
+
+import com.samsung.slp.common.process.PTY.MasterFD;
+
+class PTYInputStream extends InputStream {
+
+ MasterFD master;
+
+ /**
+ * From a Unix valid file descriptor set a Reader.
+ * @param fd file descriptor.
+ */
+ public PTYInputStream(MasterFD fd) {
+ master = fd;
+ }
+
+ /**
+ * Implementation of read for the InputStream.
+ *
+ * @exception IOException on error.
+ */
+ @Override
+ public int read() throws IOException {
+ byte b[] = new byte[1];
+ if (1 != read(b, 0, 1))
+ return -1;
+ return b[0];
+ }
+
+ /**
+ * @see InputStream#read(byte[], int, int)
+ */
+ @Override
+ public int read(byte[] buf, int off, int len) throws IOException {
+ if (buf == null) {
+ throw new NullPointerException();
+ } else if ((off < 0) || (off > buf.length)
+ || (len < 0) || ((off + len) > buf.length)
+ || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return 0;
+ }
+ byte[] tmpBuf = new byte[len];
+
+ len = read0(master.getFD(), tmpBuf, len);
+ if (len <= 0)
+ return -1;
+
+ System.arraycopy(tmpBuf, 0, buf, off, len);
+ return len;
+ }
+
+ /**
+ * Close the Reader
+ * @exception IOException on error.
+ */
+ @Override
+ public void close() throws IOException {
+ if (master.getFD() == -1)
+ return;
+ close0(master.getFD());
+ // ignore error on close - see bug 286162
+// if (status == -1)
+// throw new IOException(CCorePlugin.getResourceString("Util.exception.closeError")); //$NON-NLS-1$
+ master.setFD(-1);
+ }
+
+ @Override
+ protected void finalize() throws IOException {
+ close();
+ }
+
+ private native int read0(int fd, byte[] buf, int len) throws IOException;
+ private native int close0(int fd) throws IOException;
+
+ static {
+ System.loadLibrary("pty"); //$NON-NLS-1$
+ }
+
+}
+
diff --git a/com.samsung.slp.common/src/com/samsung/slp/common/process/PTYOutputStream.java b/com.samsung.slp.common/src/com/samsung/slp/common/process/PTYOutputStream.java
new file mode 100644
index 0000000..57ceb35
--- /dev/null
+++ b/com.samsung.slp.common/src/com/samsung/slp/common/process/PTYOutputStream.java
@@ -0,0 +1,89 @@
+package com.samsung.slp.common.process;
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 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
+ *******************************************************************************/
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import com.samsung.slp.common.process.PTY.MasterFD;
+
+public class PTYOutputStream extends OutputStream {
+
+ MasterFD master;
+
+ /**
+ * From a Unix valid file descriptor set a Reader.
+ * @param fd file descriptor.
+ */
+ public PTYOutputStream(MasterFD fd) {
+ master = fd;
+ }
+
+ /**
+ * @see OutputStream#write(byte[], int, int)
+ */
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ if (b == null) {
+ throw new NullPointerException();
+ } else if (
+ (off < 0)
+ || (off > b.length)
+ || (len < 0)
+ || ((off + len) > b.length)
+ || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return;
+ }
+ byte[] tmpBuf = new byte[len];
+ System.arraycopy(b, off, tmpBuf, off, len);
+ write0(master.getFD(), tmpBuf, len);
+ }
+ /**
+ * Implementation of read for the InputStream.
+ *
+ * @exception IOException on error.
+ */
+ @Override
+ public void write(int b) throws IOException {
+ byte[] buf = new byte[1];
+ buf[0] = (byte) b;
+ write(buf, 0, 1);
+ }
+
+ /**
+ * Close the Reader
+ * @exception IOException on error.
+ */
+ @Override
+ public void close() throws IOException {
+ if (master.getFD() == -1)
+ return;
+ int status = close0(master.getFD());
+ if (status == -1)
+ throw new IOException("close error"); //$NON-NLS-1$
+ master.setFD(-1);
+ }
+
+ @Override
+ protected void finalize() throws IOException {
+ close();
+ }
+
+ private native int write0(int fd, byte[] b, int len) throws IOException;
+ private native int close0(int fd) throws IOException;
+
+ static {
+ System.loadLibrary("pty"); //$NON-NLS-1$
+ }
+
+}
diff --git a/com.samsung.slp.common/src/com/samsung/slp/common/process/ProcessClosure.java b/com.samsung.slp.common/src/com/samsung/slp/common/process/ProcessClosure.java
new file mode 100644
index 0000000..61cca31
--- /dev/null
+++ b/com.samsung.slp.common/src/com/samsung/slp/common/process/ProcessClosure.java
@@ -0,0 +1,236 @@
+package com.samsung.slp.common.process;
+
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ *******************************************************************************/
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+
+import com.samsung.slp.common.console.AnsicodeAdapter;
+
+/**
+ * Bundled state of a launched process including the threads linking the process
+ * in/output to console documents.
+ */
+public class ProcessClosure {
+
+ /**
+ * 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 InputStream fInputStream;
+ private OutputStream fOutputStream;
+ private boolean fFinished = false;
+ private String lineSeparator;
+ /*
+ * outputStream can be null
+ */
+ public ReaderThread(ThreadGroup group, String name, InputStream in, OutputStream out) {
+ super(group, name);
+ 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 = AnsicodeAdapter.getDefault().getStripAnsiString(line);
+ line += lineSeparator;
+ fOutputStream.write(line.getBytes());
+ }
+ } catch (IOException x) {
+ // ignore
+ } finally {
+ try {
+ // writer.flush();
+ 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) {
+ }
+ }
+ }
+
+ public synchronized void complete() {
+ fFinished = true;
+ notify();
+ }
+
+ public void close() {
+ try {
+ fOutputStream.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+
+ protected static int fCounter = 0;
+
+ protected Process fProcess;
+
+ protected OutputStream fOutput;
+ protected OutputStream fError;
+
+ protected ReaderThread fOutputReader;
+ protected ReaderThread fErrorReader;
+
+ /**
+ * Creates a process closure and connects the launched process with a
+ * console document.
+ *
+ * @param outputStream
+ * prcess stdout is written to this stream. Can be
+ * null
, if not interested in reading the output
+ * @param errorStream
+ * prcess stderr is written to this stream. Can be
+ * null
, if not interested in reading the output
+ */
+ public ProcessClosure(Process 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("SRuncher" + 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) {
+ //System.err.println("Closure exception " +e);
+ }
+ try {
+ fProcess.exitValue();
+ finished = true;
+ } catch (IllegalThreadStateException e) {
+ //System.err.println("Closure exception " +e);
+ }
+ }
+
+ // @@@FIXME: Windows 2000 is screwed; double-check using output threads
+ if (!fOutputReader.finished()) {
+ fOutputReader.waitFor();
+ }
+
+ if (!fErrorReader.finished()) {
+ fErrorReader.waitFor();
+ }
+
+ fOutputReader.close();
+ fErrorReader.close();
+ // it seems that thread termination and stream closing is working
+ // without
+ // any help
+ 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;
+ }
+}
+
diff --git a/com.samsung.slp.common/src/com/samsung/slp/common/process/ProcessFactory.java b/com.samsung.slp.common/src/com/samsung/slp/common/process/ProcessFactory.java
new file mode 100644
index 0000000..39428ae
--- /dev/null
+++ b/com.samsung.slp.common/src/com/samsung/slp/common/process/ProcessFactory.java
@@ -0,0 +1,99 @@
+package com.samsung.slp.common.process;
+
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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
+ *******************************************************************************/
+
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @noextend This class is not intended to be subclassed by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ProcessFactory {
+
+ static private ProcessFactory instance;
+ private boolean hasSpawner;
+ private Runtime runtime;
+
+ private ProcessFactory() {
+ hasSpawner = false;
+ String OS = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$
+ runtime = Runtime.getRuntime();
+ try {
+ // Spawner does not work for Windows 98 fallback
+ if (OS != null && OS.equals("windows 98")) { //$NON-NLS-1$
+ hasSpawner = false;
+ } else {
+ System.loadLibrary("spawner"); //$NON-NLS-1$
+ hasSpawner = true;
+ }
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ } catch (UnsatisfiedLinkError e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static ProcessFactory getFactory() {
+ if (instance == null)
+ instance = new ProcessFactory();
+ return instance;
+ }
+
+ public Process exec(String cmd) throws IOException {
+ if (hasSpawner)
+ return new Spawner(cmd);
+ return runtime.exec(cmd);
+ }
+
+ public Process exec(String[] cmdarray) throws IOException {
+ if (hasSpawner)
+ return new Spawner(cmdarray);
+ return runtime.exec(cmdarray);
+ }
+
+ public Process exec(String[] cmdarray, String[] envp) throws IOException {
+ if (hasSpawner)
+ return new Spawner(cmdarray, envp);
+ return runtime.exec(cmdarray, envp);
+ }
+
+ public Process exec(String cmd, String[] envp) throws IOException {
+ if (hasSpawner)
+ return new Spawner(cmd, envp);
+ return runtime.exec(cmd, envp);
+ }
+
+ public Process exec(String cmd, String[] envp, File dir)
+ throws IOException {
+ if (hasSpawner)
+ return new Spawner(cmd, envp, dir);
+ return runtime.exec(cmd, envp, dir);
+ }
+
+ public Process exec(String cmdarray[], String[] envp, File dir)
+ throws IOException {
+ if (hasSpawner)
+ return new Spawner(cmdarray, envp, dir);
+ return runtime.exec(cmdarray, envp, dir);
+ }
+
+ public Process exec(String cmdarray[], String[] envp, File dir, PTY pty)
+ throws IOException {
+ if (hasSpawner)
+ return new Spawner(cmdarray, envp, dir, pty);
+ //throw new UnsupportedOperationException(CCorePlugin.getResourceString("Util.exception.cannotCreatePty")); //$NON-NLS-1$
+ throw new UnsupportedOperationException("Util.exception.cannotCreatePty"); //$NON-NLS-1$
+ }
+}
+
diff --git a/com.samsung.slp.common/src/com/samsung/slp/common/process/ProcessLauncher.java b/com.samsung.slp.common/src/com/samsung/slp/common/process/ProcessLauncher.java
new file mode 100644
index 0000000..dab4a47
--- /dev/null
+++ b/com.samsung.slp.common/src/com/samsung/slp/common/process/ProcessLauncher.java
@@ -0,0 +1,190 @@
+package com.samsung.slp.common.process;
+
+/*******************************************************************************
+ * Copyright (c) 2006 Intel 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:
+ * Intel Corporation - Initial API and implementation
+ *******************************************************************************/
+
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * This class implements external process launching for internal builder.
+ *
+ * NOTE: This class is subject to change and discuss,
+ * and is currently available in experimental mode only
+ */
+public class ProcessLauncher {
+ public final static int STATE_DONE = 0;
+ public final static int STATE_RUNNING = 1;
+ public final static int STATE_CANCELED = 2;
+ public final static int STATE_ILLEGAL = -1;
+
+ protected String[] cmd;
+ protected String[] env;
+ protected File cwd;
+ protected OutputStream out;
+ protected OutputStream err;
+ protected IProgressMonitor monitor;
+ protected boolean show;
+ protected String error;
+ protected String lineSeparator;
+ protected Process process;
+ protected ProcessClosure closure = null;
+ protected int state;
+
+ /**
+ * Returns command line as a string array
+ */
+ public String[] getCommandArray() {
+ return cmd;
+ }
+
+ /**
+ * Returns command line in a single string
+ */
+ public String getCommandLine() {
+ StringBuffer buf = new StringBuffer();
+ if (cmd != null) {
+ for (int i = 0; i < cmd.length; i++) {
+ buf.append(cmd[i]);
+ buf.append(' ');
+ }
+ buf.append(lineSeparator);
+ }
+
+ return buf.toString();
+ }
+
+ /**
+ * Returns process environment
+ */
+ public String[] getEnvironment() {
+ return env;
+ }
+
+ /**
+ * Returns command working directory
+ */
+ public File getWorkingDir() {
+ return cwd;
+ }
+
+ /**
+ * Returns error message (if any)
+ */
+ public String getErrorMessage() {
+ return error;
+ }
+
+ /**
+ * Returns exit code of a process
+ */
+ public int getExitCode() {
+ if (process == null || closure.isAlive()) return 0;
+ try { return process.waitFor(); }
+ catch (InterruptedException e) { return 0; }
+ }
+
+ /**
+ * Initializes launcher
+ * @param _cmd Command path
+ * @param args Command arguments
+ * @param _env Environment
+ * @param _cwd Working directory
+ * @param _out Output stream
+ * @param _err Error output stream
+ * @param _monitor Progress monitor
+ * @param _show If true, print command line before launching
+ */
+ public ProcessLauncher(IPath _cmd, String[] args, String[] _env, IPath _cwd, OutputStream _out, OutputStream _err, IProgressMonitor _monitor, boolean _show) {
+ cmd = createCmdArray(_cmd.toOSString(), args);
+ env = _env;
+ cwd = _cwd.toFile();
+ out = _out;
+ err = _err;
+ monitor = _monitor;
+ show = _show;
+ error = ""; //$NON-NLS-1$
+ lineSeparator = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * Launches a process
+ */
+ public void launch() {
+ try {
+ if (show)
+ printCommandLine();
+ state = STATE_RUNNING;
+ process = ProcessFactory.getFactory().exec(cmd, env, cwd);
+ closure = new ProcessClosure(process, out, err);
+ // Close the input of the process since we will never write to it
+ try {
+ process.getOutputStream().close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ closure.runNonBlocking();
+ } catch (IOException e) {
+ error = e.getMessage();
+ closure = null;
+ }
+ }
+
+ /**
+ * Returns process state
+ */
+ public int queryState() {
+ if (state == STATE_RUNNING) {
+ if (closure == null)
+ state = STATE_ILLEGAL;
+ else if (monitor.isCanceled()) {
+ closure.terminate();
+ error = "CommandLauncher.error.commandCanceled"; //$NON-NLS-1$
+ state = STATE_CANCELED;
+ } else if (!closure.isRunning()) {
+ state = STATE_DONE;
+ }
+ }
+
+ return state;
+ }
+
+ /**
+ * Creates a string array representing the command that will be passed
+ * to the process
+ */
+ protected String[] createCmdArray(String cmdPath, String[] cmdArgs) {
+ String[] args = new String[1 + cmdArgs.length];
+ args[0] = cmdPath;
+ System.arraycopy(cmdArgs, 0, args, 1, cmdArgs.length);
+
+ return args;
+ }
+
+ /**
+ * Prints command line
+ */
+ protected void printCommandLine() {
+ if (out != null) {
+ try {
+ out.write(getCommandLine().getBytes());
+ out.flush();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ }
+}
diff --git a/com.samsung.slp.common/src/com/samsung/slp/common/process/Spawner.java b/com.samsung.slp.common/src/com/samsung/slp/common/process/Spawner.java
new file mode 100644
index 0000000..a920154
--- /dev/null
+++ b/com.samsung.slp.common/src/com/samsung/slp/common/process/Spawner.java
@@ -0,0 +1,513 @@
+package com.samsung.slp.common.process;
+
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 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
+ * Wind River Systems - bug 248071, bug 286162
+ *******************************************************************************/
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.osgi.util.NLS;
+
+import com.samsung.slp.common.log.Logger;
+
+public class Spawner extends Process {
+
+ public int NOOP = 0;
+ public int HUP = 1;
+ public int KILL = 9;
+ public int TERM = 15;
+
+ /**
+ * On Windows, what this does is far from easy to explain.
+ * Some of the logic is in the JNI code, some in the spawner.exe code.
+ *
+ *
+ * - If the process this is being raised against was launched by us (the Spawner)
+ *
+ * - If the process is a cygwin program (has the cygwin1.dll loaded), then issue a 'kill -SIGINT'. If
+ * the 'kill' utility isn't available, send the process a CTRL-C
+ *
- If the process is not a cygwin program, send the process a CTRL-C
+ *
+ * - If the process this is being raised against was not launched by us, use
+ * DebugBreakProcess to interrupt it (sending a CTRL-C is easy only if we share a console
+ * with the target process)
+ *
+ *
+ * On non-Windows, raising this just raises a POSIX SIGINT
+ *
+ */
+ public int INT = 2;
+
+ /**
+ * A fabricated signal number for use on Windows only. Tells the starter program to send a CTRL-C
+ * regardless of whether the process is a Cygwin one or not.
+ *
+ * @since 5.2
+ */
+ public int CTRLC = 1000; // arbitrary high number to avoid collision
+
+ int pid = 0;
+ int status;
+ final int[] fChannels = new int[3];
+ boolean isDone;
+ OutputStream out;
+ InputStream in;
+ InputStream err;
+ private PTY fPty;
+
+ public Spawner(String command, boolean bNoRedirect) throws IOException {
+ StringTokenizer tokenizer = new StringTokenizer(command);
+ String[] cmdarray = new String[tokenizer.countTokens()];
+ for (int n = 0; tokenizer.hasMoreTokens(); n++)
+ cmdarray[n] = tokenizer.nextToken();
+ if (bNoRedirect)
+ exec_detached(cmdarray, new String[0], "."); //$NON-NLS-1$
+ else
+ exec(cmdarray, new String[0], "."); //$NON-NLS-1$
+ }
+ /**
+ * Executes the specified command and arguments in a separate process with the
+ * specified environment and working directory.
+ **/
+ protected Spawner(String[] cmdarray, String[] envp, File dir) throws IOException {
+ String dirpath = "."; //$NON-NLS-1$
+ if (dir != null)
+ dirpath = dir.getAbsolutePath();
+ exec(cmdarray, envp, dirpath);
+ }
+
+ protected Spawner(String[] cmdarray, String[] envp, File dir, PTY pty) throws IOException {
+ String dirpath = "."; //$NON-NLS-1$
+ if (dir != null)
+ dirpath = dir.getAbsolutePath();
+ fPty = pty;
+ exec_pty(cmdarray, envp, dirpath, pty);
+ }
+ /**
+ * Executes the specified string command in a separate process.
+ **/
+ protected Spawner(String command) throws IOException {
+ this(command, null);
+ }
+
+ /**
+ * Executes the specified command and arguments in a separate process.
+ **/
+ protected Spawner(String[] cmdarray) throws IOException {
+ this(cmdarray, null);
+ }
+
+ /**
+ * Executes the specified command and arguments in a separate process with the
+ * specified environment.
+ **/
+ protected Spawner(String[] cmdarray, String[] envp) throws IOException {
+ this(cmdarray, envp, null);
+ }
+
+ /**
+ * Executes the specified string command in a separate process with the specified
+ * environment.
+ **/
+ protected Spawner(String cmd, String[] envp) throws IOException {
+ this(cmd, envp, null);
+ }
+
+ /**
+ * Executes the specified string command in a separate process with the specified
+ * environment and working directory.
+ **/
+ protected Spawner(String command, String[] envp, File dir) throws IOException {
+ StringTokenizer tokenizer = new StringTokenizer(command);
+ String[] cmdarray = new String[tokenizer.countTokens()];
+ for (int n = 0; tokenizer.hasMoreTokens(); n++)
+ cmdarray[n] = tokenizer.nextToken();
+ String dirpath = "."; //$NON-NLS-1$
+ if (dir != null)
+ dirpath = dir.getAbsolutePath();
+ exec(cmdarray, envp, dirpath);
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ closeUnusedStreams();
+ }
+
+ /**
+ * See java.lang.Process#getInputStream ();
+ * The client is responsible for closing the stream explicitly.
+ **/
+ @Override
+ public synchronized InputStream getInputStream() {
+ if(null == in) {
+ if (fPty != null) {
+ in = fPty.getInputStream();
+ } else {
+ in = new SpawnerInputStream(fChannels[1]);
+ }
+ }
+ return in;
+ }
+
+ /**
+ * See java.lang.Process#getOutputStream ();
+ * The client is responsible for closing the stream explicitly.
+ **/
+ @Override
+ public synchronized OutputStream getOutputStream() {
+ if(null == out) {
+ if (fPty != null) {
+ out = fPty.getOutputStream();
+ } else {
+ out = new SpawnerOutputStream(fChannels[0]);
+ }
+ }
+ return out;
+ }
+
+ /**
+ * See java.lang.Process#getErrorStream ();
+ * The client is responsible for closing the stream explicitly.
+ **/
+ @Override
+ public synchronized InputStream getErrorStream() {
+ if(null == err) {
+ if (fPty != null && !fPty.isConsole()) {
+ // If PTY is used and it's not in "Console" mode, then stderr is
+ // redirected to the PTY's output stream. Therefore, return a
+ // dummy stream for error stream.
+ err = new InputStream() {
+ @Override
+ public int read() throws IOException {
+ return -1;
+ }
+ };
+ } else {
+ err = new SpawnerInputStream(fChannels[2]);
+ }
+ }
+ return err;
+ }
+
+ /**
+ * See java.lang.Process#waitFor ();
+ **/
+ @Override
+ public synchronized int waitFor() throws InterruptedException {
+ while (!isDone) {
+ wait();
+ }
+
+ // For situations where the user does not call destroy(),
+ // we try to kill the streams that were not used here.
+ // We check for streams that were not created, we create
+ // them to attach to the pipes, and then we close them
+ // to release the pipes.
+ // Streams that were created by the client need to be
+ // closed by the client itself.
+ //
+ // But 345164
+ closeUnusedStreams();
+ return status;
+ }
+
+ /**
+ * See java.lang.Process#exitValue ();
+ **/
+ @Override
+ public synchronized int exitValue() {
+ if (!isDone) {
+ throw new IllegalThreadStateException("Process not Terminated"); //$NON-NLS-1$
+ }
+ return status;
+ }
+
+ /**
+ * See java.lang.Process#destroy ();
+ *
+ * Clients are responsible for explicitly closing any streams
+ * that they have requested through
+ * getErrorStream(), getInputStream() or getOutputStream()
+ **/
+ @Override
+ public synchronized void destroy() {
+ // Sends the TERM
+ terminate();
+
+ // Close the streams on this side.
+ //
+ // We only close the streams that were
+ // never used by any client.
+ // So, if the stream was not created yet,
+ // we create it ourselves and close it
+ // right away, so as to release the pipe.
+ // Note that even if the stream was never
+ // created, the pipe has been allocated in
+ // native code, so we need to create the
+ // stream and explicitly close it.
+ //
+ // We don't close streams the clients have
+ // created because we don't know when the
+ // client will be finished using them.
+ // It is up to the client to close those
+ // streams.
+ //
+ // But 345164
+ closeUnusedStreams();
+
+ // Grace before using the heavy gone.
+ if (!isDone) {
+ try {
+ wait(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ if (!isDone) {
+ kill();
+ }
+ }
+
+ /**
+ * On Windows, interrupt the spawned program by using Cygwin's utility 'kill -SIGINT' if it's a Cgywin
+ * program, otherwise send it a CTRL-C. If Cygwin's 'kill' command is not available, send a CTRL-C. On
+ * linux, interrupt it by raising a SIGINT.
+ */
+ public int interrupt() {
+ return raise(pid, INT);
+ }
+
+ /**
+ * On Windows, interrupt the spawned program by send it a CTRL-C (even if it's a Cygwin program). On
+ * linux, interrupt it by raising a SIGINT.
+ *
+ * @since 5.2
+ */
+ public int interruptCTRLC() {
+ if (Platform.getOS().equals(Platform.OS_WIN32)) {
+ return raise(pid, CTRLC);
+ }
+ else {
+ return interrupt();
+ }
+ }
+
+ public int hangup() {
+ return raise(pid, HUP);
+ }
+
+ public int kill() {
+ return raise(pid, KILL);
+ }
+
+ public int terminate() {
+ return raise(pid, TERM);
+ }
+
+ public boolean isRunning() {
+ return (raise(pid, NOOP) == 0);
+ }
+
+ private void exec(String[] cmdarray, String[] envp, String dirpath) throws IOException {
+ String command = cmdarray[0];
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkExec(command);
+ if (envp == null)
+ envp = new String[0];
+
+ Reaper reaper = new Reaper(cmdarray, envp, dirpath);
+ reaper.setDaemon(true);
+ reaper.start();
+
+ // Wait until the subprocess is started or error.
+ synchronized (this) {
+ while (pid == 0) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ // Check for errors.
+ if (pid == -1) {
+ throw new IOException(reaper.getErrorMessage());
+ }
+ }
+
+ private void exec_pty(String[] cmdarray, String[] envp, String dirpath, PTY pty) throws IOException {
+ String command = cmdarray[0];
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkExec(command);
+ if (envp == null)
+ envp = new String[0];
+
+ final String slaveName = pty.getSlaveName();
+ final int masterFD = pty.getMasterFD().getFD();
+ final boolean console = pty.isConsole();
+ //int fdm = pty.get
+ Reaper reaper = new Reaper(cmdarray, envp, dirpath) {
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.utils.spawner.Spawner.Reaper#execute(java.lang.String[], java.lang.String[], java.lang.String, int[])
+ */
+ @Override
+ int execute(String[] cmd, String[] env, String dir, int[] channels) throws IOException {
+ return exec2(cmd, env, dir, channels, slaveName, masterFD, console);
+ }
+ };
+ reaper.setDaemon(true);
+ reaper.start();
+
+ // Wait until the subprocess is started or error.
+ synchronized (this) {
+ while (pid == 0) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ // Check for errors.
+ if (pid == -1) {
+ throw new IOException("Exec_tty error:" + reaper.getErrorMessage()); //$NON-NLS-1$
+ }
+ }
+
+ public void exec_detached(String[] cmdarray, String[] envp, String dirpath) throws IOException {
+ String command = cmdarray[0];
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkExec(command);
+
+ if (envp == null)
+ envp = new String[0];
+ pid = exec1(cmdarray, envp, dirpath);
+ if (pid == -1) {
+ throw new IOException("Exec error"); //$NON-NLS-1$
+ }
+ fChannels[0] = -1;
+ fChannels[1] = -1;
+ fChannels[2] = -1;
+ }
+
+ /**
+ * Close any streams not used by clients.
+ */
+ private synchronized void closeUnusedStreams() {
+ try {
+ if(null == err)
+ getErrorStream().close();
+ } catch (IOException e) {}
+ try {
+ if(null == in)
+ getInputStream().close();
+ } catch (IOException e) {}
+ try {
+ if(null == out)
+ getOutputStream().close();
+ } catch (IOException e) {}
+ }
+
+ /**
+ * Native method use in normal exec() calls.
+ */
+ native int exec0( String[] cmdarray, String[] envp, String dir, int[] chan) throws IOException;
+
+ /**
+ * Native method use in no redirect meaning to streams will created.
+ */
+ native int exec1( String[] cmdarray, String[] envp, String dir) throws IOException;
+
+ /**
+ * Native method when executing with a terminal emulation.
+ */
+ native int exec2( String[] cmdarray, String[] envp, String dir, int[] chan, String slaveName, int masterFD, boolean console) throws IOException;
+
+ /**
+ * Native method to drop a signal on the process with pid.
+ */
+ public native int raise(int processID, int sig);
+
+ /*
+ * Native method to wait(3) for process to terminate.
+ */
+ native int waitFor(int processID);
+
+ static {
+ try {
+ System.loadLibrary("spawner"); //$NON-NLS-1$
+ } catch (SecurityException e) {
+ Logger.error(e.getMessage() , e);
+ } catch (UnsatisfiedLinkError e) {
+ Logger.error(e.getMessage() , e);
+ }
+ }
+
+ // Spawn a thread to handle the forking and waiting
+ // We do it this way because on linux the SIGCHLD is
+ // send to the one thread. So do the forking and
+ // the wait in the same thread.
+ class Reaper extends Thread {
+ String[] fCmdarray;
+ String[] fEnvp;
+ String fDirpath;
+ volatile Throwable fException;
+
+ public Reaper(String[] array, String[] env, String dir) {
+ super("Spawner Reaper"); //$NON-NLS-1$
+ fCmdarray = array;
+ fEnvp = env;
+ fDirpath = dir;
+ fException = null;
+ }
+
+ int execute(String[] cmdarray, String[] envp, String dir, int[] channels) throws IOException {
+ return exec0(cmdarray, envp, dir, channels);
+ }
+
+ @Override
+ public void run() {
+ try {
+ pid = execute(fCmdarray, fEnvp, fDirpath, fChannels);
+ } catch (Exception e) {
+ pid = -1;
+ fException= e;
+ }
+
+ // Tell spawner that the process started.
+ synchronized (Spawner.this) {
+ Spawner.this.notifyAll();
+ }
+
+ if (pid != -1) {
+ // Sync with spawner and notify when done.
+ status = waitFor(pid);
+ synchronized (Spawner.this) {
+ isDone = true;
+ Spawner.this.notifyAll();
+ }
+ }
+ }
+
+ public String getErrorMessage() {
+ final String reason= fException != null ? fException.getMessage() : "Unknown reason"; //$NON-NLS-1$
+ //return NLS.bind(CCorePlugin.getResourceString("Util.error.cannotRun"), fCmdarray[0], reason); //$NON-NLS-1$
+ return "Util.error.cannotRun";
+ }
+ }
+}
+
diff --git a/com.samsung.slp.common/src/com/samsung/slp/common/process/SpawnerInputStream.java b/com.samsung.slp.common/src/com/samsung/slp/common/process/SpawnerInputStream.java
new file mode 100644
index 0000000..80d89fc
--- /dev/null
+++ b/com.samsung.slp.common/src/com/samsung/slp/common/process/SpawnerInputStream.java
@@ -0,0 +1,114 @@
+package com.samsung.slp.common.process;
+/*******************************************************************************
+ *Copyright (c) 2000, 2011 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
+ *******************************************************************************/
+
+
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @noextend This class is not intended to be subclassed by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+class SpawnerInputStream extends InputStream {
+ private int fd;
+
+ /**
+ * From a Unix valid file descriptor set a Reader.
+ * @param fd file descriptor.
+ */
+ public SpawnerInputStream(int fd) {
+ this.fd = fd;
+ }
+
+ /**
+ * Implementation of read for the InputStream.
+ *
+ * @exception IOException on error.
+ */
+ @Override
+ public int read() throws IOException {
+ byte b[] = new byte[1];
+ if (1 != read(b, 0, 1))
+ return -1;
+ return b[0];
+ }
+
+ /**
+ * @see InputStream#read(byte[], int, int)
+ */
+ @Override
+ public int read(byte[] buf, int off, int len) throws IOException {
+ if (buf == null) {
+ throw new NullPointerException();
+ } else if (
+ (off < 0)
+ || (off > buf.length)
+ || (len < 0)
+ || ((off + len) > buf.length)
+ || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return 0;
+ }
+ byte[] tmpBuf = off > 0 ? new byte[len] : buf;
+
+ len = read0(fd, tmpBuf, len);
+ if (len <= 0)
+ return -1;
+
+ if (tmpBuf != buf) {
+ System.arraycopy(tmpBuf, 0, buf, off, len);
+ }
+ return len;
+ }
+
+ /**
+ * Close the Reader
+ * @exception IOException on error.
+ */
+ @Override
+ public void close() throws IOException {
+ if (fd == -1)
+ return;
+ int status = close0(fd);
+ if (status == -1)
+ throw new IOException("Util.exception.closeError"); //$NON-NLS-1$
+ fd = -1;
+ }
+
+ @Override
+ public int available() throws IOException {
+ try {
+ return available0(fd);
+ }
+ catch (UnsatisfiedLinkError e) {
+ // for those platforms that do not implement available0
+ return super.available();
+ }
+ }
+
+ @Override
+ protected void finalize() throws IOException {
+ close();
+ }
+
+ private native int read0(int fileDesc, byte[] buf, int len) throws IOException;
+ private native int close0(int fileDesc) throws IOException;
+ private native int available0(int fileDesc) throws IOException;
+
+ static {
+ System.loadLibrary("spawner"); //$NON-NLS-1$
+ }
+
+
+}
diff --git a/com.samsung.slp.common/src/com/samsung/slp/common/process/SpawnerOutputStream.java b/com.samsung.slp.common/src/com/samsung/slp/common/process/SpawnerOutputStream.java
new file mode 100644
index 0000000..8a0bbb0
--- /dev/null
+++ b/com.samsung.slp.common/src/com/samsung/slp/common/process/SpawnerOutputStream.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 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 com.samsung.slp.common.process;
+
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * @noextend This class is not intended to be subclassed by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SpawnerOutputStream extends OutputStream {
+ private int fd;
+
+ /**
+ * From a Unix valid file descriptor set a Reader.
+ * @param fd file descriptor.
+ */
+ public SpawnerOutputStream(int fd) {
+ this.fd = fd;
+ }
+
+ /**
+ * @see OutputStream#write(byte[], int, int)
+ */
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ if (b == null) {
+ throw new NullPointerException();
+ } else if (
+ (off < 0)
+ || (off > b.length)
+ || (len < 0)
+ || ((off + len) > b.length)
+ || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return;
+ }
+ byte[] tmpBuf = new byte[len];
+ System.arraycopy(b, off, tmpBuf, off, len);
+ write0(fd, tmpBuf, len);
+ }
+ /**
+ * Implementation of read for the InputStream.
+ *
+ * @exception IOException on error.
+ */
+ @Override
+ public void write(int b) throws IOException {
+ byte[] buf = new byte[1];
+ buf[0] = (byte) b;
+ write(buf, 0, 1);
+ }
+
+ /**
+ * Close the Reader
+ * @exception IOException on error.
+ */
+ @Override
+ public void close() throws IOException {
+ if (fd == -1)
+ return;
+ int status = close0(fd);
+ if (status == -1)
+ throw new IOException("close error"); //$NON-NLS-1$
+ fd = -1;
+ }
+
+ @Override
+ protected void finalize() throws IOException {
+ close();
+ }
+
+ private native int write0(int fd, byte[] b, int len) throws IOException;
+ private native int close0(int fd);
+
+ static {
+ System.loadLibrary("spawner"); //$NON-NLS-1$
+ }
+
+}
diff --git a/com.samsung.slp.common/src/com/samsung/slp/common/util/ConsoleManager.java b/com.samsung.slp.common/src/com/samsung/slp/common/util/ConsoleManager.java
index f23cf9a..0e59a30 100644
--- a/com.samsung.slp.common/src/com/samsung/slp/common/util/ConsoleManager.java
+++ b/com.samsung.slp.common/src/com/samsung/slp/common/util/ConsoleManager.java
@@ -33,12 +33,14 @@ import org.eclipse.ui.console.IConsoleView;
import org.eclipse.ui.console.MessageConsole;
import org.eclipse.ui.console.MessageConsoleStream;
+import com.samsung.slp.common.process.ProcessClosure;
+
public class ConsoleManager
{
private static IConsoleManager consoleManager = ConsolePlugin.getDefault().getConsoleManager();
private String consoleName;
private boolean consoleFocus;
-
+ private MessageConsole console;
/**
* Constructs a new console manager.
*
@@ -50,9 +52,8 @@ public class ConsoleManager
this.consoleFocus = focus;
}
- private MessageConsole getConsole(){
+ private MessageConsole getMessageConsole(){
boolean found = false;
- MessageConsole console = null;
IConsole[] consoles = consoleManager.getConsoles();
for (int i = 0; i < consoles.length; i++) {
@@ -73,6 +74,9 @@ public class ConsoleManager
return console;
}
+ public IConsole getConsole() {
+ return console;
+ }
/**
* Remove a MessageConsole instance specified key title from list, if it is present
*
@@ -99,7 +103,7 @@ public class ConsoleManager
* @return the MessageConsoleStream connected to MessageConsole
*/
public MessageConsoleStream getMessageConsoleStream(boolean isError) {
- final MessageConsoleStream output = getConsole().newMessageStream();
+ final MessageConsoleStream output = getMessageConsole().newMessageStream();
output.setActivateOnWrite(false);
final int colorId;
@@ -127,12 +131,12 @@ public class ConsoleManager
* @return the MessageConsoleStream connected to MessageConsole
*/
public MessageConsoleStream getMessageConsoleStream() {
- return getConsole().newMessageStream();
+ return getMessageConsole().newMessageStream();
}
public void print(final String line) {
Runnable runnable = new Runnable() {
public void run() {
- final MessageConsoleStream output = getConsole().newMessageStream();
+ final MessageConsoleStream output = getMessageConsole().newMessageStream();
output.print(line);
try {
output.close();
@@ -146,7 +150,7 @@ public class ConsoleManager
}
public void println(String line) {
- final MessageConsoleStream output = getConsole().newMessageStream();
+ final MessageConsoleStream output = getMessageConsole().newMessageStream();
output.println(line);
try {
output.close();
@@ -155,11 +159,29 @@ public class ConsoleManager
ConsolePlugin.log(e);
}
}
+ public void printlnStreams(Process process) {
+
+ MessageConsoleStream stdoutStream = getMessageConsole().newMessageStream();
+ MessageConsoleStream stderrStream = getMessageConsole().newMessageStream();
+
+ clear();
+ // waitAndRead while process is running
+ ProcessClosure closure = new ProcessClosure(process, stdoutStream, stderrStream);
+ closure.runBlocking(); // a blocking cal
+
+ try {
+ stdoutStream.close();
+ stderrStream.close();
+ }
+ catch( IOException e ) {
+ // ignore.
+ }
+ }
public void clear()
{
Runnable runnable = new Runnable() {
public void run() {
- IDocument document = getConsole().getDocument();
+ IDocument document = getMessageConsole().getDocument();
if (document != null) {
document.set("");
}