Use an interconnected pair of piped streams and a
Thread
to read from the input half, and write it
to the text area. You may also want to redirect
System.out
and System.err
to
the stream; see Section 9.7.
The
PipedInputStream
and
PipedOutputStream
provide two streams (see Chapter 9) that are connected together by
a buffer and are designed to provide communication between multiple
threads (see Section 24.1).
As you’ll see in Chapter 19, I am fairly
aggressive in the pursuit of SPAM perpetrators. I have a program
called TestOpenMailRelay
, derived from the mail sender in Section 19.3, that I use to test whether remote servers are
willing to accept mail from unknown third parties and forward it as
their own. This gives these bastard messages a parent, just as many
birds will glibly nest on a cuckoo’s egg that has been snuck
into their nest. This is the GUI for that program; both this and the
main program are online in the email directory.
In the constructor, I arrange for the main class to write to the
PipedOutputStream
; the call to
TestOpenMailRelay.process( )
passing the
ps argument arranges this. That method will
write its own output to the stream in addition to assigning standard
output and standard error, so we should see anything it tries to
print. To avoid long (possibly infinitely long!) delays, I start an
additional thread to read from the pipe buffer. Figure 13-7 shows three windows: the program output window
(the goal of this whole exercise), a terminal window from which I
copied the IP address (some parts of the text in this window have
been deliberately obfuscated), and another command window in which I
started the GUI program running.
The code is shown in Example 13-4. Note that
there’s a problem that causes an IOException
at the end of the first file; hopefully this will be corrected by the
time you download the source code.
Example 13-4. TestOpenMailRelayGUI.java
import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; /** GUI for TestOpenMailRelay, lets you run it multiple times in one JVM * to avoid startup delay. * * Starts each in its own Thread for faster return to ready state. * * Uses PipedI/OStreams to capture system.out/err into a window. */ public class TestOpenMailRelayGUI extends JFrame { /** The one-line textfield for the user to type Host name/IP */ JTextField hostTextField; /** Multi-line text area for results. */ JTextArea results; /** The piped stream for the main class to write into "results" */ PrintStream ps; /** The piped stream to read from "ps" into "results" */ DataInputStream iis; /** This inner class is the action handler both for pressing * the "Try" button and also for pressing <ENTER> in the text * field. It gets the IP name/address from the text field * and passes it to process( ) in the main class. */ ActionListener runner = new ActionListener( ) { public void actionPerformed(ActionEvent evt) { new Thread(new Runnable( ) { public void run( ) { String host = hostTextField.getText().trim( ); ps.println("Trying " + host); TestOpenMailRelay.process(host, ps); } }).start( ); } }; /** Construct a GUI and some I/O plumbing to get the output * of "TestOpenMailRelay" into the "results" textfield. */ public TestOpenMailRelayGUI( ) throws IOException { super("Tests for Open Mail Relays"); PipedInputStream is; PipedOutputStream os; JPanel p; Container cp = getContentPane( ); cp.add(BorderLayout.NORTH, p = new JPanel( )); // The entry label and text field. p.add(new JLabel("Host:")); p.add(hostTextField = new JTextField(10)); hostTextField.addActionListener(runner); JButton b; p.add(b = new JButton("Try")); b.addActionListener(runner); results = new JTextArea(20, 60); // Add the text area to the main part of the window (CENTER). // Wrap it in a JScrollPane to make it scroll automatically. cp.add(BorderLayout.CENTER, new JScrollPane(results)); pack( ); // end of GUI portion // Create a pair of Piped Streams. is = new PipedInputStream( ); os = new PipedOutputStream(is); iis = new DataInputStream(is); ps = new PrintStream(os); // Construct and start a Thread to copy data from "is" to "os". new Thread( ) { public void run( ) { try { String line; while ((line = iis.readLine( )) != null) { results.append(line); results.append(" "); } } catch(IOException ex) { results.append(" "); results.append("*** Input or Output error *** "); results.append(ex.toString( )); return; } } }.start( ); } }
3.129.194.123