upload tizen1.0 source
[sdk/ide/common-eplugin.git] / org.tizen.common / src / org / tizen / common / console / ConsoleProcessClosure.java
1 /*
2 *  Common
3 *
4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5 *
6 * Contact: 
7 * Changhyun Lee <changhyun1.lee@samsung.com>
8 * Kangho Kim <kh5325.kim@samsung.com>
9
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 * Contributors:
23 * - S-Core Co., Ltd
24 *
25 */
26 package org.tizen.common.console;
27
28 import java.io.BufferedReader;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.io.InputStreamReader;
32 import java.util.List;
33
34 import org.eclipse.swt.SWT;
35
36
37 /**
38  * Bundled state of a launched process including the threads linking the process
39  * in/output to console documents.
40  */
41 public class ConsoleProcessClosure {
42
43         /**
44          * Thread which continuously reads from a input stream and pushes the read
45          * data to an output stream which is immediately flushed afterwards.
46          */
47         protected static class ReaderThread extends Thread {
48
49                 private InputStream fInputStream;
50                 private ConsoleManager fConsole;
51                 private boolean fFinished = false;
52                 private String lineSeparator;
53                 /*
54                  * outputStream can be null
55                  */
56                 public ReaderThread(ThreadGroup group, String name, InputStream in, ConsoleManager out) {
57                         super(group, name);
58                         fConsole = out;
59                         fInputStream = in;
60                         setDaemon(true);
61                         lineSeparator = System.getProperty("line.separator"); //$NON-NLS-1$
62                 }
63
64                 @Override
65                 public void run() {
66                         try {
67                                 try {
68                                         BufferedReader reader = new BufferedReader(new InputStreamReader(fInputStream));
69                                         String line;
70                                         while ((line = reader.readLine()) != null) {
71                                                 List<TextStyle> ts = AnsicodeAdapter.getStringStyles(line);
72                                                 
73                                                 if (ts != null) {
74                                                         for (int i=0 ; i< ts.size() ; i++) {
75                                                                 fConsole.print(ts.get(i).getStripString(),SWT.NORMAL,ts.get(i).getForeground());
76                                                         }
77                                                 } else {
78                                                         fConsole.print(line,SWT.NORMAL,AnsicodeAdapter.BLACK);
79                                                 }
80                                                 fConsole.print(lineSeparator,SWT.NORMAL,AnsicodeAdapter.BLACK);
81                                         }
82                                 } catch (IOException x) {
83                                         // ignore
84                                 } finally {
85                                         try {
86                                                 fInputStream.close();
87                                         } catch (IOException e) {
88                                                 // ignore
89                                         }
90                                 }
91                         } finally {
92                                 complete();
93                         }
94                 }
95                 
96                 public synchronized boolean finished() {
97                         return fFinished;
98                 }
99
100                 public synchronized void waitFor() {
101                         while (!fFinished) {
102                                 try {
103                                         wait();
104                                 } catch (InterruptedException e) {
105                                 }
106                         }
107                 }
108
109                 public synchronized void complete() {
110                         fFinished = true;
111                         notify();
112                 }
113
114                 public void close() {
115                         //TODO : fix me!
116                         /*try {
117                                 fOutputStream.close();
118                         } catch (IOException e) {
119                                 // ignore
120                         }*/
121                 }
122         }
123
124         protected static int fCounter = 0;
125
126         protected Process fProcess;
127         protected ConsoleManager fConsole;
128
129         protected ReaderThread fOutputReader;
130         protected ReaderThread fErrorReader;
131
132         /**
133          * Creates a process closure and connects the launched process with a
134          * console document.
135          * 
136          * @param outputStream
137          *            prcess stdout is written to this stream. Can be
138          *            <code>null</code>, if not interested in reading the output
139          * @param errorStream
140          *            prcess stderr is written to this stream. Can be
141          *            <code>null</code>, if not interested in reading the output
142          */
143         public ConsoleProcessClosure(Process process, ConsoleManager console) {
144                 fProcess = process;
145                 fConsole = console;
146         }
147
148         /**
149          * Live links the launched process with the configured in/out streams using
150          * reader threads.
151          */
152         public void runNonBlocking() {
153                 ThreadGroup group = new ThreadGroup("SRuncher" + fCounter++); //$NON-NLS-1$
154
155                 InputStream stdin = fProcess.getInputStream();
156                 InputStream stderr = fProcess.getErrorStream();
157
158                 fOutputReader = new ReaderThread(group, "OutputReader", stdin, fConsole); //$NON-NLS-1$
159                 fErrorReader = new ReaderThread(group, "ErrorReader", stderr, fConsole); //$NON-NLS-1$
160
161                 fOutputReader.start();
162                 fErrorReader.start();
163         }
164
165         public void runBlocking() {
166                 runNonBlocking();
167
168                 boolean finished = false;
169                 while (!finished) {
170                         try {
171                                 fProcess.waitFor();
172                         } catch (InterruptedException e) {
173                                 //System.err.println("Closure exception " +e);
174                         }
175                         try {
176                                 fProcess.exitValue();
177                                 finished = true;
178                         } catch (IllegalThreadStateException e) {
179                                 //System.err.println("Closure exception " +e);
180                         }
181                 }
182
183                 // @@@FIXME: Windows 2000 is screwed; double-check using output threads
184                 if (!fOutputReader.finished()) {
185                         fOutputReader.waitFor();
186                 }
187
188                 if (!fErrorReader.finished()) {
189                         fErrorReader.waitFor();
190                 }
191
192                 fOutputReader.close();
193                 fErrorReader.close();
194                 // it seems that thread termination and stream closing is working
195                 // without
196                 // any help
197                 fProcess = null;
198                 fOutputReader = null;
199                 fErrorReader = null;
200         }
201
202         public boolean isAlive() {
203                 if (fProcess != null) {
204                         if (fOutputReader.isAlive() || fErrorReader.isAlive()) {
205                                 return true;
206                         }
207                         fProcess = null;
208                         fOutputReader.close();
209                         fErrorReader.close();
210                         fOutputReader = null;
211                         fErrorReader = null;
212                 }
213                 return false;
214         }
215
216         /**
217          * The same functionality as "isAlive()"
218          * but does not affect out streams,
219          * because they can be shared among processes
220          */
221         public boolean isRunning() {
222                 if (fProcess != null) {
223                         if (fOutputReader.isAlive() || fErrorReader.isAlive()) {
224                                 return true;
225                         }
226                         fProcess = null;
227                 }
228                 return false;
229         }
230         /**
231          * Forces the termination the launched process
232          */
233         public void terminate() {
234                 if (fProcess != null) {
235                         fProcess.destroy();
236                         fProcess = null;
237                 }
238                 if (!fOutputReader.finished()) {
239                         fOutputReader.waitFor();
240                 }
241                 if (!fErrorReader.finished()) {
242                         fErrorReader.waitFor();
243                 }
244                 fOutputReader.close();
245                 fErrorReader.close();
246                 fOutputReader = null;
247                 fErrorReader = null;
248         }
249 }
250