ee.ioc.cs.vsle.util.Console.java Source code

Java tutorial

Introduction

Here is the source code for ee.ioc.cs.vsle.util.Console.java

Source

package ee.ioc.cs.vsle.util;

/*-
 * #%L
 * CoCoViLa
 * %%
 * Copyright (C) 2003 - 2017 Institute of Cybernetics at Tallinn University of Technology
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

/*
 * Java Console showing System.out and System.err
 * 
 * Initially taken from
 * http://www.comweb.nl/java/Console/Console.html
 */
import org.apache.commons.io.output.TeeOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Console extends WindowAdapter implements ActionListener {
    private static final Logger logger = LoggerFactory.getLogger(StreamFollower.class);

    private JFrame frame;
    private JTextArea textArea;
    private Thread sysOutFollower;
    private Thread sysErrFollower;
    private volatile boolean quit;

    //backup
    private final static PrintStream systemOut = System.out;
    private final static PrintStream systemErr = System.err;

    private static Console instance;

    public static void show() {
        if (instance == null) {
            instance = new Console();
        }
        instance.frame.toFront();
    }

    private Console() {
        // create all components and add them
        frame = new JFrame("Java Console");
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension frameSize = new Dimension((screenSize.width / 2), (screenSize.height / 2));
        int x = (frameSize.width / 2);
        int y = (frameSize.height / 2);
        frame.setBounds(x, y, frameSize.width, frameSize.height);

        textArea = new JTextArea();
        textArea.setEditable(false);
        JButton button = new JButton("clear");

        frame.getContentPane().setLayout(new BorderLayout());
        frame.getContentPane().add(new JScrollPane(textArea), BorderLayout.CENTER);
        frame.getContentPane().add(button, BorderLayout.SOUTH);
        frame.setVisible(true);

        frame.addWindowListener(this);
        button.addActionListener(this);

        final PipedInputStream pin = new PipedInputStream();
        try {
            PipedOutputStream pout = new PipedOutputStream(pin);
            System.setOut(new PrintStream(new TeeOutputStream(systemOut, pout), true));
        } catch (java.io.IOException io) {
            textArea.append("Couldn't redirect STDOUT to this console\n" + io.getMessage());
        } catch (SecurityException se) {
            textArea.append("Couldn't redirect STDOUT to this console\n" + se.getMessage());
        }

        final PipedInputStream pin2 = new PipedInputStream();
        try {
            PipedOutputStream pout2 = new PipedOutputStream(pin2);
            System.setErr(new PrintStream(new TeeOutputStream(systemErr, pout2), true));
        } catch (java.io.IOException io) {
            textArea.append("Couldn't redirect STDERR to this console\n" + io.getMessage());
        } catch (SecurityException se) {
            textArea.append("Couldn't redirect STDERR to this console\n" + se.getMessage());
        }

        quit = false; // signals the Threads that they should exit

        sysOutFollower = new StreamFollower(pin, StreamRestorer.SYS_OUT, "Console_out");
        sysOutFollower.start();
        //
        sysErrFollower = new StreamFollower(pin2, StreamRestorer.SYS_ERR, "Console_err");
        sysErrFollower.start();
    }

    @Override
    public void windowClosed(WindowEvent evt) {
        quit = true;
        try {
            sysOutFollower.interrupt();
            sysOutFollower.join(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            sysErrFollower.interrupt();
            sysErrFollower.join(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        instance = null;
    }

    @Override
    public void windowClosing(WindowEvent evt) {
        frame.setVisible(false); // default behaviour of JFrame   
        frame.dispose();
    }

    @Override
    public void actionPerformed(ActionEvent evt) {
        textArea.setText("");
    }

    private void scrollToBottom() {
        if (textArea != null) {
            textArea.setCaretPosition(textArea.getDocument().getLength());
        }
    }

    public String readLine(PipedInputStream in) throws IOException {
        String input = "";
        do {
            int available = in.available();
            if (available == 0)
                break;
            byte b[] = new byte[available];
            in.read(b);
            input = input + new String(b, 0, b.length);
        } while (!input.endsWith("\n") && !input.endsWith("\r\n") && !quit);
        return input;
    }

    private void appendToConsole(final String s) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                textArea.append(s);
                scrollToBottom();
            }
        });
    }

    private class StreamFollower extends Thread {

        private final PipedInputStream pin;
        private final StreamRestorer restorer;

        StreamFollower(PipedInputStream pin, StreamRestorer restorer, String name) {
            super(name);
            setDaemon(true);
            this.pin = pin;
            this.restorer = restorer;
        }

        @Override
        public void run() {
            try {
                while (!quit) {
                    sleep(1);
                    if (pin.available() != 0) {
                        String input = readLine(pin);
                        appendToConsole(input);
                    }
                }
            } catch (InterruptedException ie) {
                //quit
            } catch (Exception e) {
                appendToConsole("\nConsole reports an Internal error.");
                appendToConsole("The error is: " + e);
            } finally {
                try {
                    pin.close();
                } catch (IOException e) {
                    logger.error("Error closing stream", e);
                }
                restorer.restore();
            }
        }
    }

    interface StreamRestorer {
        void restore();

        StreamRestorer SYS_OUT = new StreamRestorer() {

            @Override
            public void restore() {
                System.setOut(systemOut);
            }
        };

        StreamRestorer SYS_ERR = new StreamRestorer() {

            @Override
            public void restore() {
                System.setErr(systemErr);
            }
        };
    }
}