I have a simple task of capturing all System.out output; I am however failing:
public class Main {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
ArrayList<String> history = new ArrayList<>();
StringBuilder output = new StringBuilder();
StringBuilder input = new StringBuilder();
JPanel panel = new JPanel();
JTextArea txt = new JTextArea();
String PROMPT = "> ";
Runnable show = new Runnable() {
public void run() {
txt.setText("");
for (String line: history) txt.append(line + "\n");
txt.append(PROMPT);
txt.append(output.toString());
txt.setCaretPosition(txt.getText().length());
}
};
PrintStream os = new PrintStream(new OutputStream() {
#Override
public void write(int b) throws IOException {
if (b == 13) {
history.add(input.toString());
input = new StringBuilder();
SwingUtilities.invokeLater(show);
} else input.append((char)b);
}
});
void init(String title) {
panel.setLayout(new BorderLayout());
txt.setLineWrap(true);
txt.setFont(new Font("Courier", Font.PLAIN, 16));
txt.setBackground(Color.BLACK);
txt.setForeground(Color.GREEN);
txt.setCaretColor(Color.GREEN);
txt.setEditable(false);
txt.setText(PROMPT);
txt.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == '\n') {
System.setOut(os);
System.setErr(os);
String result = output.toString();
history.add(PROMPT + result);
try {
engine.eval(result);
} catch (ScriptException ex) {
history.add(ex.toString());
}
output = new StringBuilder();
} else {
output.append(e.getKeyChar());
}
SwingUtilities.invokeLater(show);
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
});
panel.add(txt, BorderLayout.CENTER);
JFrame frame = new JFrame(title);
frame.setSize(650, 425);
frame.setContentPane(panel);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String args[]) {
new Main().init("javascript");
}
}
I should note the output I am looking for comes from something like:
new ScriptEngineManager().getEngineByName("js").eval("print(\"test\");");
The output is not going anywhere other than normal STDOUT a.k.a. System.out. Why?
ScriptEngine output redirection:
To redirect the output of a script you first have to get its ScriptContext instance, that has a method called setWriter(Writer).
That sets the output of the ScriptEngine.
For that you first need a Writer. This can be simple like this one:
public class CaptureWriter extends Writer
{
private StringBuilder m_build;
public CaptureWriter(StringBuilder build)
{
m_build = build;
}
#Override
public void write(char[] cbuf, int off, int len) throws IOException
{
m_build.insert(m_build.length(), cbuf, off, len);
}
#Override
public void flush() throws IOException
{
}
#Override
public void close() throws IOException
{
}
}
This writes all input into a StringBuilder.
Then you register it into a ScriptContext
ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
engine.getContext().setWriter(new CaptureWriter(m_mess));
When running this simple program:
StringBuilder build = new StringBuilder();
ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
engine.getContext().setWriter(new CaptureWriter(build));
try
{
engine.eval("print(\"Hello\")");
engine.eval("print(\"World\")");
engine.eval("print(\"You\")");
engine.eval("print(\"There\")");
} catch(ScriptException e)
{
e.printStackTrace();
}
System.out.println(build);
The output is the buffered output of the script:
Hello
World
You
There
You can of course hook anything into the write method of the Writer implementation, this is just an example.
System.out redirection:
To capture the System.out output you have to make your own PrintStream implementation, it can be very simple like:
public class Capture extends PrintStream
{
private StringBuilder m_build;
public Capture(OutputStream out, StringBuilder build)
{
super(out);
m_build = build;
}
public void println(String s)
{
super.println(s);
m_build.append(s + "\n");
}
}
Then you need to register it in the runtime:
StringBuilder build = new StringBuilder();
System.setOut(new Capture(System.out, build));
Then every time System.out.println is called it works like the overriding PrintStream should and the message gets written into the provided StringBuilder.
To capture other messages you'll need to override other methods.
You can capture System.out be providing a PrintStream that you control ... try something like this
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
PrintStream old = System.out;
System.setOut(ps);
System.out.println("This will be captured :P");
System.out.flush();
System.setOut(old);
System.out.println("He is what was captured : " + baos.toString());
Related
I modified some code I found to display a local variable instead of set text inside of a JFrame, but I'm unable to find a way to change the size of the text. I keep reading about frameName.setFont(new Font(____)), but that doesn't seem to be working for the println. How would I modify the text size? Here's my current code. (P.S. I'm new, so I'm sorry that i don't know what I'm talking about.)
import java.util.*;
import java.io.*;
import java.awt.*;
import javax.swing.*;
import java.time.*;
import java.time.temporal.*;
public class Window {
LocalDate today = LocalDate.now();
// LocalDate bday = LocalDate.of(2018, Month.MAY, 13);
LocalDate bday = LocalDate.parse("2018-05-13");
Period until = Period.between(today, bday);
long untilDay = ChronoUnit.DAYS.between(today, bday);
String string = new String("There are " + until.getYears() + " years, " + until.getMonths() +
" months, and " + until.getDays() +
" days left! (" + untilDay + " days total)");
public static void main(String[] args) {
new Window();
}
public Window() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
CapturePane capturePane = new CapturePane();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(capturePane);
frame.setSize(1000, 1000);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
PrintStream ps = System.out;
System.setOut(new PrintStream(new StreamCapturer("STDOUT", capturePane, ps)));
// System.out.println("Hello, this is a test");
System.out.println(string);
}
});
}
public class CapturePane extends JPanel implements Consumer {
private JTextArea output;
public CapturePane() {
setLayout(new BorderLayout());
output = new JTextArea();
add(new JScrollPane(output));
}
#Override
public void appendText(final String text) {
if (EventQueue.isDispatchThread()) {
output.append(text);
output.setCaretPosition(output.getText().length());
} else {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
appendText(text);
}
});
}
}
}
public interface Consumer {
public void appendText(String text);
}
public class StreamCapturer extends OutputStream {
private StringBuilder buffer;
private String prefix;
private Consumer consumer;
private PrintStream old;
public StreamCapturer(String prefix, Consumer consumer, PrintStream old) {
this.prefix = prefix;
buffer = new StringBuilder(128);
buffer.append("[").append(prefix).append("] ");
this.old = old;
this.consumer = consumer;
}
#Override
public void write(int b) throws IOException {
char c = (char) b;
String value = Character.toString(c);
buffer.append(value);
if (value.equals("\n")) {
consumer.appendText(buffer.toString());
buffer.delete(0, buffer.length());
buffer.append("[").append(prefix).append("] ");
}
old.print(c);
}
}
}
In about Line 55:
output = new JTextArea();
output.setFont ((output.getFont()).deriveFont (24.0f));
you could modify the font size to a new float value.
See the doc for JTextArea for the method setFont, look where it is defined in the inheritance hierarchy. Look into the Font class, what to do with it.
Hi i am using Jsch to run my shell command. I want to make it interactive .I am using java textarea to display the output of a script.This script requires some user inputs also. How i can i make this textarea to accept user input and run the commands.
public void init(){
try{
JSch jsch=new JSch();
Panel panel = new Panel();
TextArea log = new TextArea();
panel.add(log);
add(panel);
PrintStream printStream = new PrintStream(new CustomOutputStream(log));
System.setOut(printStream);
System.setErr(printStream);
Session session=jsch.getSession("akumar", "banas", 22);
String passwd = "*****";
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword(passwd);
session.connect(30000); // making a connection with timeout.
Channel channel=session.openChannel("shell");
channel.setInputStream(System.in);
channel.setOutputStream(System.out);
channel.connect(3*1000);
printStream.println("sftp akumar#banas");
printStream.flush();
}
catch(Exception e){
System.out.println(e);
}
}
// This is the code for making textarea as output stream
public class CustomOutputStream extends OutputStream {
private TextArea textArea;
public CustomOutputStream(TextArea textArea) {
this.textArea = textArea;
}
#Override
public void write(int b) throws IOException {
// redirects data to the text area
textArea.append(String.valueOf((char)b));
// scrolls the text area to the end of data
textArea.setCaretPosition(textArea.getText().length());
}
}
Here is an approach using a BlockingQueue to pass data from a JTextField's actionListener to the CustomInputStream.
public class Main extends JFrame {
public Main() {
init();
}
public void init() {
try {
JSch jsch = new JSch();
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(200, 200));
JTextArea log = new JTextArea();
JTextField cmd = new JTextField();
panel.setLayout(new BorderLayout());
JScrollPane scrollPane = new JScrollPane(log);
panel.add(scrollPane, BorderLayout.CENTER);
panel.add(cmd, BorderLayout.SOUTH);
add(panel);
Session session = jsch.getSession("akumar", "banas", 22);
String passwd = "******";
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword(passwd);
session.connect(30000); // making a connection with timeout.
Channel channel = session.openChannel("shell");
channel.setInputStream(new CustomInputStream(cmd));
channel.setOutputStream(new CustomOutputStream(log));
channel.connect(3 * 1000);
pack();
} catch (Exception e) {
System.out.println(e);
}
}
public class CustomInputStream extends InputStream implements ActionListener {
final JTextField field;
final BlockingQueue<String> q;
public CustomInputStream(JTextField field) {
this.field = field;
q = new LinkedBlockingQueue<>();
field.addActionListener(this);
}
private String s;
int pos;
#Override
public int read() throws IOException {
while (null == s || s.length() <= pos) {
try {
s = q.take();
pos = 0;
} catch (InterruptedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
int ret = (int) s.charAt(pos);
pos++;
return ret;
}
#Override
public boolean markSupported() {
return false;
}
#Override
public int read(byte[] b, int off, int len) throws IOException {
int bytes_copied = 0;
while (bytes_copied < 1) {
while (null == s || s.length() <= pos) {
try {
s = q.take();
System.out.println("s = " + s);
pos = 0;
} catch (InterruptedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
int bytes_to_copy = len < s.length()-pos ? len : s.length()-pos;
System.arraycopy(s.getBytes(), pos, b, off, bytes_to_copy);
pos += bytes_to_copy;
bytes_copied += bytes_to_copy;
}
return bytes_copied;
}
#Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void actionPerformed(ActionEvent e) {
q.add(field.getText() + "\r\n");
field.setText("");
}
}
// This is the code for making textarea as output stream
public class CustomOutputStream extends OutputStream {
private JTextArea textArea;
public CustomOutputStream(JTextArea textArea) {
this.textArea = textArea;
}
#Override
public void write(int b) throws IOException {
// redirects data to the text area
textArea.append(String.valueOf((char) b));
// scrolls the text area to the end of data
textArea.setCaretPosition(textArea.getText().length());
}
#Override
public void write(byte[] b, int off, int len) throws IOException {
String s = new String(b,off,len);
textArea.append(s);
textArea.setCaretPosition(textArea.getText().length());
}
#Override
public void write(byte[] b) throws IOException {
this.write(b, 0, b.length);
}
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(() -> {
new Main().setVisible(true);
});
}
}
try {
project.fireBuildStarted();
project.init();
ProjectHelper projectHelper = ProjectHelper.getProjectHelper();
project.addReference("ant.projectHelper", projectHelper);
projectHelper.parse(project, buildFile);
// If no target specified then default target will be executed.
String targetToExecute = (target != null && target.trim().length() > 0) ? target
.trim() : project.getDefaultTarget();
project.executeTarget(targetToExecute);
project.fireBuildFinished(null);
success = true;
} catch (BuildException buildException) {
project.fireBuildFinished(buildException);
JOptionPane.showMessageDialog(null, buildException, "Warning",
JOptionPane.WARNING_MESSAGE);
throw new RuntimeException(
"!!! Unable to restart the IEHS App !!!", buildException);
}
Above methods are giving some output on the console, but I need them in the dialog boxes. How can I do that ?
I think you are trying to capture the console logs to a UI component, if that is the case, here is the sample which will create output stream and capture console output and show it in UI component. You can try this.
public class Console extends JDialog {
JTextArea textArea = null;
/**
* Launch the application.
*/
public static void main(String[] args) {
try {
Console dialog = new Console();
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
private void updateTextPane(final String text) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textArea.append(text);
}
});
}
/**
* Create the dialog.
*/
public Console() {
//Creating a stream to move consle output to anything else
OutputStream out = new OutputStream() {
#Override
public void write(final int b) throws IOException {
updateTextPane(String.valueOf((char) b));
}
#Override
public void write(byte[] b, int off, int len) throws IOException {
updateTextPane(new String(b, off, len));
}
#Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
};
System.setOut(new PrintStream(out, true));
System.setErr(new PrintStream(out, true));
setBounds(100, 100, 450, 300);
getContentPane().setLayout(null);
JButton btnNewButton = new JButton("New button");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("hello");
}
});
btnNewButton.setBounds(91, 192, 91, 23);
getContentPane().add(btnNewButton);
textArea = new JTextArea();
textArea.setBounds(30, 11, 241, 136);
getContentPane().add(textArea);
}
}
Maybe you need this snippet:
JOptionPane.showMessageDialog(null, "Your Text");
On the other Hand if project.fireBuildFinished(buildException); gives output to the console then you have to enter a return value of this output and enter this in the "Your Text" spot or enter this MessageDialog into your method.
I have problem about applied SwingWorker with FileReader and my point is I need to implement FileReader with SwingWorker to make my UI Show the text from the file and this is my code
class Read1 extends SwingWorker<String,String>{
protected Void doInBackground() throws Exception{
FileReader read = new FileReader("msg.txt");
BufferedReader in = new BufferedReader(read);
String s;
s=in.readLine();
System.out.println(s);
return s;
}
protected void done()
{
try{
String show;
show=get();
textArea.append(show);}catch(Exception e){}}
public static void main(String args[]) {
Read1 r = new Form().new Read1();
r.execute();
However it does not append anything on the UI textarea
anyone have solution? Thank you
Works just fine for me:
public class Reader extends SwingWorker<List<String>, String> {
protected List<String> doInBackground() throws Exception {
ArrayList<String> lstText = new ArrayList<String>(25);
BufferedReader in = null;
try {
FileReader read = new FileReader("Scanner.txt");
in = new BufferedReader(read);
String s = null;
while ((s = in.readLine()) != null) {
lstText.add(s);
publish(s);
}
} finally {
try {
in.close();
} catch (Exception e) {
}
}
return lstText;
}
#Override
protected void process(List<String> chunks) {
for (String text : chunks) {
fldText.append(text + "\n");
}
}
#Override
protected void done() {
}
}
I have a BufferedWriter to which I use to write characters into a PipedInputStream. Based on keyboard events. But I am implementing a backspace handler, but I can see no way of doing so without unputc.
I am almost falling back into using a string to buffer the current line.
Perhaps, I could do a better job using Canvas instead. (God how I hate java!)
public class Console extends JTextArea {
/**
*
*/
private static final long serialVersionUID = 6315506875930497268L;
private PipedInputStream stdin;
private PipedOutputStream stdout;
private PipedOutputStream stderr;
private boolean bounceKey = true;
private class Dispatcher implements Runnable {
InputStream in;
public Dispatcher(InputStream in) {
this.in = in;
}
#Override
public void run() {
Reader input = new BufferedReader(new InputStreamReader(in));
int c;
try {
try {
while ((c = input.read()) >= 0) {
append(String.valueOf((char) c));
}
} finally {
input.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public Console() throws IOException {
stdin = new PipedInputStream();
stdout = new PipedOutputStream();
stderr = new PipedOutputStream();
final Writer kbd = new BufferedWriter(new OutputStreamWriter(
new PipedOutputStream(stdin)));
new Thread(new Dispatcher(new PipedInputStream(stdout))).start();
new Thread(new Dispatcher(new PipedInputStream(stderr))).start();
addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
try {
char ch = e.getKeyChar();
kbd.write(ch);
append(String.valueOf(ch));
if(ch == '\n') kbd.flush();
} catch (IOException e1) {
e1.printStackTrace();
}
}
#Override
public void keyPressed(KeyEvent e) {
int keycode = e.getKeyCode();
switch(keycode) {
case KeyEvent.VK_BACK_SPACE:
// Erase the last char from buffer and the screen
}
}
#Override
public void keyReleased(KeyEvent e) {
} // DONOTHING
});
setEditable(false);
setFocusable(true);
setBackground(Color.black);
setForeground(Color.lightGray);
setFont(new Font("Monospace", Font.BOLD, 12));
setLineWrap(true);
}
public OutputStream getStderr() {
return stderr;
}
public OutputStream getStdout() {
return stdout;
}
public InputStream getStdin() {
return stdin;
}
public boolean isBounceKey() {
return bounceKey;
}
public void setBounceKey(boolean bounceKey) {
this.bounceKey = bounceKey;
}
}
Yes, see PushbackInputStream.
I am almost falling back into using a string to buffer the current line.
That is the correct way to do it: save up the whole line and don't do anything with it it until the user presses "enter". They might delete the whole thing - what if the process you are communicating with has already taken action?
I.e. what you should be doing is the thing you are for some reason trying to avoid doing! :-)