/* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* <p/>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.rzo.yajsw.tray;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;
import javax.swing.AbstractAction;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JTextArea;
import javax.swing.WindowConstants;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import org.rzo.yajsw.util.DaemonThreadFactory;
/**
* The YAJSW System Tray Console User interface
*/
public class Console extends JFrame
{
/** The _tray icon. */
WrapperTrayIconImpl _trayIcon;
/** true if the console has been shut down */
boolean stop;
protected static final Executor executor = Executors.newCachedThreadPool(new DaemonThreadFactory("console"));
/** The max lines in the output window */
int maxLines = 1500;
/** The console UI. */
ConsoleForm _consoleForm = new ConsoleForm();
/** The date time format. */
SimpleDateFormat _dateTimeFormat = new SimpleDateFormat();
/** The byte format. */
ByteFormat _byteFormat = new ByteFormat();
/** The ok icon. */
Icon _okIcon;
JMenuItem _startOutputItem = new JMenuItem();
JMenuItem _pauseOutputItem = new JMenuItem();
JMenuItem _clearOutputItem = new JMenuItem();
volatile boolean _outputPaused = false;
volatile String _outputFilter = null;
volatile LinkedList<String> _outputLines = new LinkedList<String>();
ReentrantLock _outputLock = new ReentrantLock();
/**
* Instantiates a new console.
*
* @param trayIcon
* the tray icon
*/
public Console(WrapperTrayIconImpl trayIcon)
{
_trayIcon = trayIcon;
this.setTitle(_trayIcon.toolTipPrefix + "Console");
this.addWindowListener(new WindowEventHandler());
this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
_okIcon = _trayIcon.createImageIcon("/resources/tick.png");
_clearOutputItem.setAction(new AbstractAction(null, WrapperTrayIconImpl.createImageIcon("/resources/edit-clear.png"))
{
public void actionPerformed(ActionEvent e)
{
clearOutput();
}
});
_pauseOutputItem.setAction(new AbstractAction(null, WrapperTrayIconImpl.createImageIcon("/resources/pause.png"))
{
public void actionPerformed(ActionEvent e)
{
_outputPaused = true;
_consoleForm._START_OUTPUT_BUTTON.setEnabled(true);
_consoleForm._PAUSE_OUTPUT_BUTTON.setEnabled(false);
}
});
_startOutputItem.setAction(new AbstractAction(null, WrapperTrayIconImpl.createImageIcon("/resources/start.png"))
{
public void actionPerformed(ActionEvent e)
{
_outputPaused = false;
_consoleForm._START_OUTPUT_BUTTON.setEnabled(false);
_consoleForm._PAUSE_OUTPUT_BUTTON.setEnabled(true);
}
});
_consoleForm.__OUTPUT_FILTER.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String txt = _consoleForm.__OUTPUT_FILTER.getText();
_outputFilter = "".equals(txt) ? null : txt;
filterOutput();
}
});
initOutput();
initInput();
initPerformance();
initButtons();
_consoleForm._START_OUTPUT_BUTTON.setEnabled(false);
this.getContentPane().add(_consoleForm);
this.pack();
this.setVisible(true);
stop = false;
}
private void initButtons()
{
initButton(_consoleForm._EXIT_TRAY_ICON_BUTTON, _trayIcon._exitItem);
initButton(_consoleForm._EXIT_WRAPPER_BUTTON, _trayIcon._exitWrapperItem);
initButton(_consoleForm._THREAD_DUMP_WRAPPER_BUTTON, _trayIcon._threadDumpWrapperItem);
initButton(_consoleForm._RESTART_BUTTON, _trayIcon._restartItem);
initButton(_consoleForm._START_BUTTON, _trayIcon._startItem);
initButton(_consoleForm._STOP_BUTTON, _trayIcon._stopItem);
initButton(_consoleForm._STOP_TIMER_BUTTON, _trayIcon._stopTimerItem);
initButton(_consoleForm._THREAD_DUMP_BUTTON, _trayIcon._threadDumpItem);
initButton(_consoleForm._jbutton1, _trayIcon._closeConsoleItem);
initButton(_consoleForm._PAUSE_OUTPUT_BUTTON, _pauseOutputItem);
initButton(_consoleForm._START_OUTPUT_BUTTON, _startOutputItem);
initButton(_consoleForm._CLEAR_OUTPUT_BUTTON, _clearOutputItem);
}
private void initButton(JButton button, JMenuItem item)
{
button.setAction(item.getAction());
}
private void initPerformance()
{
executor.execute(new Runnable()
{
public void run()
{
while (!stop)
{
setAppCpu(_trayIcon._process.getAppCpu());
setAppHandles(_trayIcon._process.getAppHandles());
setAppMemory(_trayIcon._process.getAppMemory());
setAppThreads(_trayIcon._process.getAppThreads());
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
});
}
/**
* Sets the state.
*
* @param state
* the new state
*/
void setState(String state)
{
if (state != null)
_consoleForm._state.setText(state);
_consoleForm._state.repaint();
}
/**
* Sets the app pid.
*
* @param pid
* the new app pid
*/
void setAppPid(int pid)
{
if (pid > 0)
_consoleForm._appPid.setText("" + pid);
else
_consoleForm._appPid.setText("-");
}
/**
* Sets the wrapper pid.
*
* @param pid
* the new wrapper pid
*/
void setWrapperPid(int pid)
{
if (pid > 0)
_consoleForm._wPid.setText("" + pid);
else
_consoleForm._wPid.setText("-");
}
/**
* Sets the trigger.
*
* @param trigger
* the new trigger
*/
void setTrigger(String trigger)
{
if (trigger != null)
_consoleForm._trigger.setText(trigger);
}
/**
* Sets the app started.
*
* @param time
* the new app started
*/
void setAppStarted(Date time)
{
if (time != null)
_consoleForm._appStartTime.setText(_dateTimeFormat.format(time));
}
/**
* Sets the app stopped.
*
* @param time
* the new app stopped
*/
void setAppStopped(Date time)
{
if (time != null)
_consoleForm._appStopTime.setText(_dateTimeFormat.format(time));
}
/**
* Sets the app restart count.
*
* @param total
* the total
* @param count
* the count
*/
void setAppRestartCount(int total, int count)
{
if (count > 0)
_consoleForm._count.setText(total + "[" + count + "]");
}
/**
* Sets the wrapper started.
*
* @param time
* the new wrapper started
*/
void setWrapperStarted(Date time)
{
if (time != null)
_consoleForm._wStartTime.setText(_dateTimeFormat.format(time));
}
/**
* Sets the app threads.
*
* @param count
* the new app threads
*/
void setAppThreads(int count)
{
if (count > 0)
_consoleForm._threads.setText("" + count);
else
_consoleForm._threads.setText("-");
}
/**
* Sets the app handles.
*
* @param count
* the new app handles
*/
void setAppHandles(int count)
{
if (count > 0)
_consoleForm._handles.setText("" + count);
else
_consoleForm._handles.setText("-");
}
/**
* Sets the app memory.
*
* @param bytes
* the new app memory
*/
void setAppMemory(long bytes)
{
if (bytes > 0)
_consoleForm._memory.setText(_byteFormat.format(bytes));
else
_consoleForm._memory.setText("-");
}
/**
* Sets the app cpu.
*
* @param count
* the new app cpu
*/
void setAppCpu(int count)
{
if (count >= 0)
_consoleForm._cpu.setText("" + count);
else
_consoleForm._cpu.setText("-");
}
/**
* Sets the exit code.
*
* @param code
* the new exit code
*/
void setExitCode(int code)
{
if (code >= 0)
_consoleForm._exitCode.setText("" + code);
}
/**
* Sets the wrapper type.
*
* @param type
* the new wrapper type
*/
void setWrapperType(String type)
{
_consoleForm._wrapperType.setText(type);
}
/**
* Sets the condition.
*
* @param active
* the new condition
*/
void setCondition(boolean active)
{
if (active)
{
_consoleForm._condition.setText("");
_consoleForm._condition.setIcon(_okIcon);
}
else
{
_consoleForm._condition.setText("-");
_consoleForm._condition.setIcon(null);
}
}
/**
* Sets the timer.
*
* @param active
* the new timer
*/
void setTimer(boolean active)
{
if (active)
{
_consoleForm._timer.setText("");
_consoleForm._timer.setIcon(_okIcon);
}
else
{
_consoleForm._timer.setText("-");
_consoleForm._timer.setIcon(null);
}
}
private void initInput()
{
_consoleForm._input.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
// process may have not yet been started or it may have been
// stopped
try
{
if (_trayIcon._process == null || !_trayIcon._process.hasOutput())
{
_consoleForm._input.setText("No input possible");
_consoleForm._input.selectAll();
return;
}
String txt = _consoleForm._input.getText();
_trayIcon._process.writeOutput(txt);
_consoleForm._input.selectAll();
}
catch (Throwable ex)
{
ex.printStackTrace();
}
}
});
}
private void initOutput()
{
executor.execute(new Runnable()
{
public void run()
{
_trayIcon._process.startDrain();
while (!stop)
{
if (!_outputPaused)
{
_trayIcon.showState(_trayIcon._process.getState());
String line;
while ((line = _trayIcon._process.readDrainLine()) != null)
addLine(line);
}
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
_trayIcon._process.stopDrain();
}
});
}
private void filterOutput()
{
executor.execute(new Runnable()
{
public void run()
{
_outputLock.lock();
try
{
_consoleForm._output.getDocument().remove(0, _consoleForm._output.getDocument().getLength());
}
catch (BadLocationException e)
{
e.printStackTrace();
}
for (String line : _outputLines)
if (_outputFilter == null || line.contains(_outputFilter))
addToTextArea(line);
_outputLock.unlock();
}
});
}
private void clearOutput()
{
_outputLock.lock();
_outputLines.clear();
filterOutput();
_outputLock.unlock();
}
private void addLine(String line)
{
_outputLock.lock();
_outputLines.addLast(line);
if (_outputLines.size() > maxLines)
_outputLines.removeFirst();
if (_outputFilter == null || line.contains(_outputFilter))
addToTextArea(line);
_outputLock.unlock();
}
private void addToTextArea(String line)
{
JTextArea textArea = _consoleForm._output;
textArea.append(line + "\n");
if (textArea.getLineCount() > maxLines)
{
Element root = textArea.getDocument().getDefaultRootElement();
Element firstLine = root.getElement(0);
try
{
textArea.getDocument().remove(0, firstLine.getEndOffset());
}
catch (Exception ble)
{
System.out.println(ble.getMessage());
}
}
textArea.setCaretPosition(textArea.getDocument().getLength());
}
/**
* Close.
*/
public void close()
{
stop = true;
this.setVisible(false);
this.dispose();
}
/**
* The Class WindowEventHandler.
*/
class WindowEventHandler extends WindowAdapter
{
/*
* (non-Javadoc)
*
* @see
* java.awt.event.WindowAdapter#windowClosing(java.awt.event.WindowEvent
* )
*/
public void windowClosing(WindowEvent evt)
{
close();
_trayIcon.closeConsole();
}
}
}