f6145c2dc3336588097c341a5782105a9423af60
[jalview.git] / src / jalview / util / AWTConsole.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.util;
22
23 //
24 // A simple Java Console for your application (Swing version)
25 // Requires Java 1.1.5 or higher
26 //
27 // Disclaimer the use of this source is at your own risk. 
28 //
29 // Permision to use and distribute into your own applications
30 //
31 // RJHM van den Bergh , rvdb@comweb.nl
32
33 import java.awt.BorderLayout;
34 import java.awt.Button;
35 import java.awt.Dimension;
36 import java.awt.Frame;
37 import java.awt.GraphicsEnvironment;
38 import java.awt.Panel;
39 import java.awt.TextArea;
40 import java.awt.Toolkit;
41 import java.awt.event.ActionEvent;
42 import java.awt.event.ActionListener;
43 import java.awt.event.WindowAdapter;
44 import java.awt.event.WindowEvent;
45 import java.awt.event.WindowListener;
46 import java.io.IOException;
47 import java.io.PipedInputStream;
48 import java.io.PipedOutputStream;
49 import java.io.PrintStream;
50
51 import jalview.bin.Jalview;
52
53 public class AWTConsole extends WindowAdapter
54         implements WindowListener, ActionListener, Runnable
55 {
56   private Frame frame;
57
58   private TextArea textArea;
59
60   private Thread reader;
61
62   private Thread reader2;
63
64   private boolean quit;
65
66   private final PipedInputStream pin = new PipedInputStream();
67
68   private final PipedInputStream pin2 = new PipedInputStream();
69
70   Thread errorThrower; // just for testing (Throws an Exception at this Console
71
72   public AWTConsole()
73   {
74     // create all components and add them
75     frame = new Frame("Java Console");
76     Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
77     Dimension frameSize = new Dimension(screenSize.width / 2,
78             screenSize.height / 2);
79     int x = frameSize.width / 2;
80     int y = frameSize.height / 2;
81     frame.setBounds(x, y, frameSize.width, frameSize.height);
82
83     textArea = new TextArea();
84     textArea.setEditable(false);
85     Button button = new Button("clear");
86
87     Panel panel = new Panel();
88     panel.setLayout(new BorderLayout());
89     panel.add(textArea, BorderLayout.CENTER);
90     panel.add(button, BorderLayout.SOUTH);
91     frame.add(panel);
92
93     frame.setVisible(true);
94
95     frame.addWindowListener(this);
96     button.addActionListener(this);
97
98     try
99     {
100       PipedOutputStream pout = new PipedOutputStream(this.pin);
101       System.setOut(new PrintStream(pout, true));
102     } catch (java.io.IOException io)
103     {
104       textArea.append("Couldn't redirect STDOUT to this console\n"
105               + io.getMessage());
106     } catch (SecurityException se)
107     {
108       textArea.append("Couldn't redirect STDOUT to this console\n"
109               + se.getMessage());
110     }
111
112     try
113     {
114       PipedOutputStream pout2 = new PipedOutputStream(this.pin2);
115       System.setErr(new PrintStream(pout2, true));
116     } catch (java.io.IOException io)
117     {
118       textArea.append("Couldn't redirect STDERR to this console\n"
119               + io.getMessage());
120     } catch (SecurityException se)
121     {
122       textArea.append("Couldn't redirect STDERR to this console\n"
123               + se.getMessage());
124     }
125
126     quit = false; // signals the Threads that they should exit
127
128     // Starting two seperate threads to read from the PipedInputStreams
129     //
130     reader = new Thread(this);
131     reader.setDaemon(true);
132     reader.start();
133     //
134     reader2 = new Thread(this);
135     reader2.setDaemon(true);
136     reader2.start();
137
138     // testing part
139     // you may omit this part for your application
140     //
141     jalview.bin.Console.outPrintln("Hello World 2");
142     jalview.bin.Console.outPrintln("All fonts available to Graphic2D:\n");
143     GraphicsEnvironment ge = GraphicsEnvironment
144             .getLocalGraphicsEnvironment();
145     String[] fontNames = ge.getAvailableFontFamilyNames();
146     for (int n = 0; n < fontNames.length; n++)
147     {
148       jalview.bin.Console.outPrintln(fontNames[n]);
149     }
150     // Testing part: simple an error thrown anywhere in this JVM will be printed
151     // on the Console
152     // We do it with a seperate Thread becasue we don't wan't to break a Thread
153     // used by the Console.
154     jalview.bin.Console.outPrintln("\nLets throw an error on this console");
155     errorThrower = new Thread(this);
156     errorThrower.setDaemon(true);
157     errorThrower.start();
158   }
159
160   @Override
161   public synchronized void windowClosed(WindowEvent evt)
162   {
163     quit = true;
164     this.notifyAll(); // stop all threads
165     try
166     {
167       reader.join(1000);
168       pin.close();
169     } catch (Exception e)
170     {
171     }
172     try
173     {
174       reader2.join(1000);
175       pin2.close();
176     } catch (Exception e)
177     {
178     }
179     Jalview.exit("Window closing. Bye!", 0);
180   }
181
182   @Override
183   public synchronized void windowClosing(WindowEvent evt)
184   {
185     frame.setVisible(false); // default behaviour of JFrame
186     frame.dispose();
187   }
188
189   @Override
190   public synchronized void actionPerformed(ActionEvent evt)
191   {
192     textArea.setText("");
193   }
194
195   @Override
196   public synchronized void run()
197   {
198     try
199     {
200       while (Thread.currentThread() == reader)
201       {
202         try
203         {
204           this.wait(100);
205         } catch (InterruptedException ie)
206         {
207         }
208         if (pin.available() != 0)
209         {
210           String input = this.readLine(pin);
211           textArea.append(input);
212         }
213         if (quit)
214         {
215           return;
216         }
217       }
218
219       while (Thread.currentThread() == reader2)
220       {
221         try
222         {
223           this.wait(100);
224         } catch (InterruptedException ie)
225         {
226         }
227         if (pin2.available() != 0)
228         {
229           String input = this.readLine(pin2);
230           textArea.append(input);
231         }
232         if (quit)
233         {
234           return;
235         }
236       }
237     } catch (Exception e)
238     {
239       textArea.append("\nConsole reports an Internal error.");
240       textArea.append("The error is: " + e);
241     }
242
243     // just for testing (Throw a Nullpointer after 1 second)
244     if (Thread.currentThread() == errorThrower)
245     {
246       try
247       {
248         this.wait(1000);
249       } catch (InterruptedException ie)
250       {
251       }
252       throw new NullPointerException(
253               MessageManager.getString("exception.application_test_npe"));
254     }
255
256   }
257
258   public synchronized String readLine(PipedInputStream in)
259           throws IOException
260   {
261     String input = "";
262     do
263     {
264       int available = in.available();
265       if (available == 0)
266       {
267         break;
268       }
269       byte b[] = new byte[available];
270       in.read(b);
271       input = input + new String(b, 0, b.length);
272     } while (!input.endsWith("\n") && !input.endsWith("\r\n") && !quit);
273     return input;
274   }
275
276   /**
277    * 
278    * @param arg
279    * @j2sIgnore
280    */
281   public static void main(String[] arg)
282   {
283     new AWTConsole(); // create console with not reference
284   }
285 }