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