Merge branch 'releases/Release_2_11_4_Branch'
[jalview.git] / 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 public class AWTConsole extends WindowAdapter implements WindowListener,
52         ActionListener, Runnable
53 {
54   private Frame frame;
55
56   private TextArea textArea;
57
58   private Thread reader;
59
60   private Thread reader2;
61
62   private boolean quit;
63
64   private final PipedInputStream pin = new PipedInputStream();
65
66   private final PipedInputStream pin2 = new PipedInputStream();
67
68   Thread errorThrower; // just for testing (Throws an Exception at this Console
69
70   public AWTConsole()
71   {
72     // create all components and add them
73     frame = new Frame("Java Console");
74     Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
75     Dimension frameSize = new Dimension((int) (screenSize.width / 2),
76             (int) (screenSize.height / 2));
77     int x = (int) (frameSize.width / 2);
78     int y = (int) (frameSize.height / 2);
79     frame.setBounds(x, y, frameSize.width, frameSize.height);
80
81     textArea = new TextArea();
82     textArea.setEditable(false);
83     Button button = new Button("clear");
84
85     Panel panel = new Panel();
86     panel.setLayout(new BorderLayout());
87     panel.add(textArea, BorderLayout.CENTER);
88     panel.add(button, BorderLayout.SOUTH);
89     frame.add(panel);
90
91     frame.setVisible(true);
92
93     frame.addWindowListener(this);
94     button.addActionListener(this);
95
96     try
97     {
98       PipedOutputStream pout = new PipedOutputStream(this.pin);
99       System.setOut(new PrintStream(pout, true));
100     } catch (java.io.IOException io)
101     {
102       textArea.append("Couldn't redirect STDOUT to this console\n"
103               + io.getMessage());
104     } catch (SecurityException se)
105     {
106       textArea.append("Couldn't redirect STDOUT to this console\n"
107               + se.getMessage());
108     }
109
110     try
111     {
112       PipedOutputStream pout2 = new PipedOutputStream(this.pin2);
113       System.setErr(new PrintStream(pout2, true));
114     } catch (java.io.IOException io)
115     {
116       textArea.append("Couldn't redirect STDERR to this console\n"
117               + io.getMessage());
118     } catch (SecurityException se)
119     {
120       textArea.append("Couldn't redirect STDERR to this console\n"
121               + se.getMessage());
122     }
123
124     quit = false; // signals the Threads that they should exit
125
126     // Starting two seperate threads to read from the PipedInputStreams
127     //
128     reader = new Thread(this);
129     reader.setDaemon(true);
130     reader.start();
131     //
132     reader2 = new Thread(this);
133     reader2.setDaemon(true);
134     reader2.start();
135
136     // testing part
137     // you may omit this part for your application
138     //
139     System.out.println("Hello World 2");
140     System.out.println("All fonts available to Graphic2D:\n");
141     GraphicsEnvironment ge = GraphicsEnvironment
142             .getLocalGraphicsEnvironment();
143     String[] fontNames = ge.getAvailableFontFamilyNames();
144     for (int n = 0; n < fontNames.length; n++)
145       System.out.println(fontNames[n]);
146     // Testing part: simple an error thrown anywhere in this JVM will be printed
147     // on the Console
148     // We do it with a seperate Thread becasue we don't wan't to break a Thread
149     // used by the Console.
150     System.out.println("\nLets throw an error on this console");
151     errorThrower = new Thread(this);
152     errorThrower.setDaemon(true);
153     errorThrower.start();
154   }
155
156   public synchronized void windowClosed(WindowEvent evt)
157   {
158     quit = true;
159     this.notifyAll(); // stop all threads
160     try
161     {
162       reader.join(1000);
163       pin.close();
164     } catch (Exception e)
165     {
166     }
167     try
168     {
169       reader2.join(1000);
170       pin2.close();
171     } catch (Exception e)
172     {
173     }
174     System.exit(0);
175   }
176
177   public synchronized void windowClosing(WindowEvent evt)
178   {
179     frame.setVisible(false); // default behaviour of JFrame
180     frame.dispose();
181   }
182
183   public synchronized void actionPerformed(ActionEvent evt)
184   {
185     textArea.setText("");
186   }
187
188   public synchronized void run()
189   {
190     try
191     {
192       while (Thread.currentThread() == reader)
193       {
194         try
195         {
196           this.wait(100);
197         } catch (InterruptedException ie)
198         {
199         }
200         if (pin.available() != 0)
201         {
202           String input = this.readLine(pin);
203           textArea.append(input);
204         }
205         if (quit)
206           return;
207       }
208
209       while (Thread.currentThread() == reader2)
210       {
211         try
212         {
213           this.wait(100);
214         } catch (InterruptedException ie)
215         {
216         }
217         if (pin2.available() != 0)
218         {
219           String input = this.readLine(pin2);
220           textArea.append(input);
221         }
222         if (quit)
223           return;
224       }
225     } catch (Exception e)
226     {
227       textArea.append("\nConsole reports an Internal error.");
228       textArea.append("The error is: " + e);
229     }
230
231     // just for testing (Throw a Nullpointer after 1 second)
232     if (Thread.currentThread() == errorThrower)
233     {
234       try
235       {
236         this.wait(1000);
237       } catch (InterruptedException ie)
238       {
239       }
240       throw new NullPointerException(
241               MessageManager.getString("exception.application_test_npe"));
242     }
243
244   }
245
246   public synchronized String readLine(PipedInputStream in)
247           throws IOException
248   {
249     String input = "";
250     do
251     {
252       int available = in.available();
253       if (available == 0)
254         break;
255       byte b[] = new byte[available];
256       in.read(b);
257       input = input + new String(b, 0, b.length);
258     } while (!input.endsWith("\n") && !input.endsWith("\r\n") && !quit);
259     return input;
260   }
261
262   public static void main(String[] arg)
263   {
264     new AWTConsole(); // create console with not reference
265   }
266 }