package org.tanukisoftware.wrapper.test;
/*
* Copyright (c) 1999, 2009 Tanuki Software, Ltd.
* http://www.tanukisoftware.com
* All rights reserved.
*
* This software is the proprietary information of Tanuki Software.
* You shall use it only in accordance with the terms of the
* license agreement you entered into with Tanuki Software.
* http://wrapper.tanukisoftware.org/doc/english/licenseOverview.html
*
*
* Portions of the Software have been derived from source code
* developed by Silver Egg Technology under the following license:
*
* Copyright (c) 2001 Silver Egg Technology
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sub-license, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*/
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Component;
import java.awt.Container;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Label;
import java.awt.List;
import java.awt.Panel;
import java.awt.ScrollPane;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import org.tanukisoftware.wrapper.WrapperActionServer;
import org.tanukisoftware.wrapper.WrapperManager;
import org.tanukisoftware.wrapper.WrapperListener;
import org.tanukisoftware.wrapper.event.WrapperEventListener;
/**
* This is a Test / Example program which can be used to test the
* main features of the Wrapper.
* <p>
* It is also an example of Integration Method #3, where you implement
* the WrapperListener interface manually.
* <p>
* <b>NOTE</b> that in most cases you will want to use Method #1, using the
* WrapperSimpleApp helper class to integrate your application. Please
* see the <a href="http://wrapper.tanukisoftware.org/doc/english/integrate.html">integration</a>
* section of the documentation for more details.
*
* @author Leif Mortenson <leif@tanukisoftware.com>
*/
public class Main
extends AbstractActionApp
implements WrapperListener
{
private WrapperActionServer m_actionServer;
private MainFrame m_frame;
private ActionRunner m_actionRunner;
private List m_listenerFlags;
private TextField m_serviceName;
/*---------------------------------------------------------------
* Constructors
*-------------------------------------------------------------*/
private Main() {
}
/*---------------------------------------------------------------
* Inner Classes
*-------------------------------------------------------------*/
private class MainFrame extends Frame implements ActionListener, WindowListener
{
/**
* Serial Version UID.
*/
private static final long serialVersionUID = -3847376282833547574L;
MainFrame()
{
super( "Wrapper Test Application" );
init();
setLocation( 10, 10 );
setSize( 750, 480 );
setResizable( true );
}
private void init()
{
GridBagLayout gridBag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
Panel panel = new Panel();
panel.setLayout( gridBag );
ScrollPane scrollPane = new ScrollPane();
scrollPane.add( panel );
scrollPane.getHAdjustable().setUnitIncrement( 20 );
scrollPane.getVAdjustable().setUnitIncrement( 20 );
setLayout( new BorderLayout() );
add( scrollPane, BorderLayout.CENTER );
buildCommand( panel, gridBag, c, "Stop(0)", "stop0",
"Calls WrapperManager.stop( 0 ) to shutdown the JVM and Wrapper with a success exit code." );
buildCommand( panel, gridBag, c, "Stop(1)", "stop1",
"Calls WrapperManager.stop( 1 ) to shutdown the JVM and Wrapper with a failure exit code." );
buildCommand( panel, gridBag, c, "Exit(0)", "exit0",
"Calls System.exit( 0 ) to shutdown the JVM and Wrapper with a success exit code." );
buildCommand( panel, gridBag, c, "Exit(1)", "exit1",
"Calls System.exit( 1 ) to shutdown the JVM and Wrapper with a failure exit code." );
buildCommand( panel, gridBag, c, "StopImmediate(0)", "stopimmediate0",
"Calls WrapperManager.stopImmediate( 0 ) to immediately shutdown the JVM and Wrapper with a success exit code." );
buildCommand( panel, gridBag, c, "StopImmediate(1)", "stopimmediate1",
"Calls WrapperManager.stopImmediate( 1 ) to immediately shutdown the JVM and Wrapper with a failure exir code." );
buildCommand( panel, gridBag, c, "StopAndReturn(0)", "stopandreturn0",
"Calls WrapperManager.stopAndReturn( 0 ) to shutdown the JVM and Wrapper with a success exit code." );
buildCommand( panel, gridBag, c, "Nested Exit(1)", "nestedexit1",
"Calls System.exit(1) within WrapperListener.stop(1) callback." );
buildCommand( panel, gridBag, c, "Halt(0)", "halt0",
"Calls Runtime.getRuntime().halt(0) to kill the JVM, the Wrapper will restart it." );
buildCommand( panel, gridBag, c, "Halt(1)", "halt1",
"Calls Runtime.getRuntime().halt(1) to kill the JVM, the Wrapper will restart it." );
buildCommand( panel, gridBag, c, "Restart()", "restart",
"Calls WrapperManager.restart() to shutdown the current JVM and start a new one." );
buildCommand( panel, gridBag, c, "RestartAndReturn()", "restartandreturn",
"Calls WrapperManager.restartAndReturn() to shutdown the current JVM and start a new one." );
buildCommand( panel, gridBag, c, "Access Violation", "access_violation",
"Attempts to cause an access violation within the JVM, relies on a JVM bug and may not work." );
buildCommand( panel, gridBag, c, "Native Access Violation", "access_violation_native",
"Causes an access violation using native code, the JVM will crash and be restarted." );
buildCommand( panel, gridBag, c, "Simulate JVM Hang", "appear_hung",
"Makes the JVM appear to be hung as viewed from the Wrapper, it will be killed and restarted." );
buildCommand( panel, gridBag, c, "Ignore Control Events", "ignore_events",
"Makes this application ignore control events. It will not shutdown in response to CTRL-C. The Wrapper will still respond." );
buildCommand( panel, gridBag, c, "Request Thread Dump", "dump",
"Calls WrapperManager.requestThreadDump() to cause the JVM to dump its current thread state." );
buildCommand( panel, gridBag, c, "System.out Deadlock", "deadlock_out",
"Simulates a failure mode where the System.out object has become deadlocked." );
buildCommand( panel, gridBag, c, "Poll Users", "users",
"Begins calling WrapperManager.getUser() and getInteractiveUser() to monitor the current and interactive users." );
buildCommand( panel, gridBag, c, "Poll Users with Groups", "groups",
"Same as above, but includes information about the user's groups." );
buildCommand( panel, gridBag, c, "Console", "console", "Prompt for Actions in the console." );
buildCommand( panel, gridBag, c, "Idle", "idle", "Run idly." );
buildCommand( panel, gridBag, c, "Dump Properties", "properties",
"Dumps all System Properties to the console." );
buildCommand( panel, gridBag, c, "Dump Configuration", "configuration",
"Dumps all Wrapper Configuration Properties to the console." );
m_listenerFlags = new List( 2, true );
m_listenerFlags.add( "Service" );
m_listenerFlags.add( "Control" );
m_listenerFlags.add( "Logging" );
m_listenerFlags.add( "Core" );
Panel flagPanel = new Panel();
flagPanel.setLayout( new BorderLayout() );
flagPanel.add( new Label( "Event Flags: " ), BorderLayout.WEST );
flagPanel.add( m_listenerFlags, BorderLayout.CENTER );
flagPanel.setSize( 100, 10 );
Panel flagPanel2 = new Panel();
flagPanel2.setLayout( new BorderLayout() );
flagPanel2.add( flagPanel, BorderLayout.WEST );
buildCommand( panel, gridBag, c, "Update Event Listener", "listener", flagPanel2 );
buildCommand( panel, gridBag, c, "Service List", "service_list", "Displays a list of registered services on Windows." );
m_serviceName = new TextField( "testwrapper" );
Panel servicePanel = new Panel();
servicePanel.setLayout( new BorderLayout() );
servicePanel.add( new Label( "Interrogate Service. Service name: " ), BorderLayout.WEST );
servicePanel.add( m_serviceName, BorderLayout.CENTER );
Panel servicePanel2 = new Panel();
servicePanel2.setLayout( new BorderLayout() );
servicePanel2.add( servicePanel, BorderLayout.WEST );
buildCommand( panel, gridBag, c, "Service Interrogate", "service_interrogate", servicePanel2 );
buildCommand( panel, gridBag, c, "Service Start", "service_start", "Starts the above service." );
buildCommand( panel, gridBag, c, "Service Stop", "service_stop", "Stops the above service." );
buildCommand( panel, gridBag, c, "Service User Code", "service_user", "Sends a series of user codes to the above service." );
buildCommand( panel, gridBag, c, "GC", "gc", "Performs a GC sweep." );
buildCommand( panel, gridBag, c, "Is Professional?", "is_professional", "Prints true if this is a Professional Edition." );
buildCommand( panel, gridBag, c, "Is Standard?", "is_standard", "Prints true if this is a Standard Edition." );
addWindowListener( this );
}
private void buildCommand( Container container,
GridBagLayout gridBag,
GridBagConstraints c,
String label,
String command,
Object description )
{
Button button = new Button( label );
button.setActionCommand( command );
c.fill = GridBagConstraints.BOTH;
c.gridwidth = 1;
gridBag.setConstraints( button, c );
container.add( button );
button.addActionListener(this);
c.gridwidth = GridBagConstraints.REMAINDER;
Component desc;
if ( description instanceof String )
{
desc = new Label( (String)description );
}
else if ( description instanceof Component )
{
desc = (Component)description;
}
else
{
desc = new Label( description.toString() );
}
gridBag.setConstraints( desc, c );
container.add( desc );
}
/**************************************************************************
* ActionListener Methods
*************************************************************************/
public void actionPerformed( ActionEvent event )
{
String action = event.getActionCommand();
if ( action.equals( "listener" ) )
{
// Create the mask.
long mask = 0;
String[] flags = m_listenerFlags.getSelectedItems();
for ( int i = 0; i < flags.length; i++ )
{
String flag = flags[i];
if ( flag.equals( "Service" ) )
{
mask |= WrapperEventListener.EVENT_FLAG_SERVICE;
}
else if ( flag.equals( "Control" ) )
{
mask |= WrapperEventListener.EVENT_FLAG_CONTROL;
}
else if ( flag.equals( "Logging" ) )
{
mask |= WrapperEventListener.EVENT_FLAG_LOGGING;
}
else if ( flag.equals( "Core" ) )
{
mask |= WrapperEventListener.EVENT_FLAG_CORE;
}
}
setEventMask( mask );
}
setServiceName( m_serviceName.getText() );
Main.this.doAction( action );
}
/**************************************************************************
* WindowListener Methods
*************************************************************************/
public void windowOpened( WindowEvent e )
{
}
public void windowClosing( WindowEvent e )
{
WrapperManager.stopAndReturn( 0 );
}
public void windowClosed( WindowEvent e )
{
}
public void windowIconified( WindowEvent e )
{
}
public void windowDeiconified( WindowEvent e )
{
}
public void windowActivated( WindowEvent e )
{
}
public void windowDeactivated( WindowEvent e )
{
}
}
private class ActionRunner implements Runnable {
private String m_action;
private boolean m_alive;
public ActionRunner(String action) {
m_action = action;
m_alive = true;
}
public void run() {
// Wait for a second so that the startup will complete.
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
if (!Main.this.doAction(m_action)) {
printHelp("\"" + m_action + "\" is an unknown action.");
WrapperManager.stop(0);
return;
}
while (m_alive) {
// Idle some
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void endThread( ) {
m_alive = false;
}
}
/*---------------------------------------------------------------
* WrapperListener Methods
*-------------------------------------------------------------*/
public Integer start( String[] args )
{
String command;
System.out.println( "TestWrapper: start()" );
prepareSystemOutErr();
if ( args.length <= 0 )
{
System.out.println( "TestWrapper: An action was not specified. Default to \"dialog\". Use \"help\" for list of actions." );
command = "dialog";
}
else
{
command = args[0];
}
if ( command.equals( "help" ) ) {
printHelp( null );
return null;
}
try
{
int port = 9999;
m_actionServer = new WrapperActionServer( port );
m_actionServer.enableShutdownAction( true );
m_actionServer.enableHaltExpectedAction( true );
m_actionServer.enableRestartAction( true );
m_actionServer.enableThreadDumpAction( true );
m_actionServer.enableHaltUnexpectedAction( true );
m_actionServer.enableAccessViolationAction( true );
m_actionServer.enableAppearHungAction( true );
m_actionServer.start();
System.out.println( "TestWrapper: ActionServer Enabled. " );
System.out.println( "TestWrapper: Telnet localhost 9999" );
System.out.println( "TestWrapper: Commands: " );
System.out.println( "TestWrapper: S: Shutdown" );
System.out.println( "TestWrapper: H: Expected Halt" );
System.out.println( "TestWrapper: R: Restart" );
System.out.println( "TestWrapper: D: Thread Dump" );
System.out.println( "TestWrapper: U: Unexpected Halt (Simulate crash)" );
System.out.println( "TestWrapper: V: Access Violation (Actual crash)" );
System.out.println( "TestWrapper: G: Make the JVM appear to be hung." );
System.out.println( "TestWrapper:" );
}
catch ( java.io.IOException e )
{
System.out.println( "TestWrapper: Unable to open the action server socket: " + e.getMessage() );
System.out.println( "TestWrapper:" );
}
if ( command.equals( "dialog" ) )
{
System.out.println( "TestWrapper: Showing dialog..." );
try
{
m_frame = new MainFrame();
m_frame.setVisible( true );
}
catch ( java.lang.InternalError e )
{
System.out.println( "TestWrapper: " );
System.out.println( "TestWrapper: ERROR - Unable to display the GUI:" );
System.out.println( "TestWrapper: " + e.toString() );
System.out.println( "TestWrapper: " );
System.out.println( "TestWrapper: Fall back to the \"console\" action." );
command = "console";
}
catch ( java.awt.AWTError e )
{
System.out.println( "TestWrapper: " );
System.out.println( "TestWrapper: ERROR - Unable to display the GUI:" );
System.out.println( "TestWrapper: " + e.toString() );
System.out.println( "TestWrapper: " );
System.out.println( "TestWrapper: Fall back to the \"console\" action." );
command = "console";
}
catch ( java.lang.UnsupportedOperationException e )
{
// java.awt.HeadlessException does not exist in Java versions prior to 1.4
if ( e.getClass().getName().equals( "java.awt.HeadlessException" ) )
{
System.out.println( "TestWrapper: " );
System.out.println( "TestWrapper: ERROR - Unable to display the GUI:" );
System.out.println( "TestWrapper: " + e.toString() );
System.out.println( "TestWrapper: " );
System.out.println( "TestWrapper: Fall back to the \"console\" action." );
command = "console";
}
else
{
throw e;
}
}
}
if ( !command.equals( "dialog" ) )
{
// * * Start the action thread
m_actionRunner = new ActionRunner( command );
Thread actionThread = new Thread( m_actionRunner );
actionThread.start();
}
return null;
}
public int stop( int exitCode )
{
System.out.println( "TestWrapper: stop(" + exitCode + ")" );
if ( m_actionServer != null )
{
try
{
m_actionServer.stop();
}
catch ( Exception e )
{
System.out.println( "TestWrapper: Unable to stop the action server: " + e.getMessage() );
}
}
if ( m_frame != null )
{
if ( !WrapperManager.hasShutdownHookBeenTriggered() )
{
m_frame.setVisible( false );
m_frame.dispose();
}
m_frame = null;
}
if ( isNestedExit() )
{
System.out.println( "TestWrapper: calling System.exit(" + exitCode + ") within stop." );
System.exit( exitCode );
}
return exitCode;
}
public void controlEvent( int event )
{
System.out.println( "TestWrapper: controlEvent(" + event + ")" );
if ( event == WrapperManager.WRAPPER_CTRL_LOGOFF_EVENT )
{
if ( WrapperManager.isLaunchedAsService() || WrapperManager.isIgnoreUserLogoffs() )
{
System.out.println( "TestWrapper: Ignoring logoff event" );
// Ignore
}
else if ( !ignoreControlEvents() )
{
WrapperManager.stop( 0 );
}
}
else if ( event == WrapperManager.WRAPPER_CTRL_C_EVENT )
{
if ( !ignoreControlEvents() ) {
//WrapperManager.stop(0);
// May be called before the runner is started.
if (m_actionRunner != null) {
m_actionRunner.endThread();
}
}
}
else
{
if ( !ignoreControlEvents() )
{
WrapperManager.stop( 0 );
}
}
}
/*---------------------------------------------------------------
* Static Methods
*-------------------------------------------------------------*/
/**
* Prints the usage text.
*
* @param error_msg Error message to write with usage text
*/
private static void printHelp( String errorMsg )
{
System.err.println( "USAGE" );
System.err.println( "" );
System.err.println( "TestWrapper <action>" );
printActions();
System.err.println( " Interactive:" );
System.err.println( " dialog : Shows the dialog interface" );
System.err.println( "[EXAMPLE]" );
System.err.println( " TestAction access_violation_native " );
System.err.println( "" );
if ( errorMsg != null )
{
System.err.println( "ERROR: " + errorMsg );
System.err.println( "" );
}
System.exit( 1 );
}
/*---------------------------------------------------------------
* Main Method
*-------------------------------------------------------------*/
/**
* IMPORTANT: Please read the Javadocs for this class at the top of the
* page before you start to use this class as a template for integrating
* your own application. This will save you a lot of time.
*/
public static void main( String[] args )
{
System.out.println( "TestWrapper: Initializing..." );
// Start the application. If the JVM was launched from the native
// Wrapper then the application will wait for the native Wrapper to
// call the application's start method. Otherwise the start method
// will be called immediately.
WrapperManager.start( new Main(), args );
}
}