Article View: borland.public.jbuilder.java.api
Article #942Re: an idea to consider
From: Alan Shiers
Date: Mon, 08 Jul 2002 21:04
Date: Mon, 08 Jul 2002 21:04
469 lines
13480 bytes
13480 bytes
Hi John,
John McGrath [TeamB] wrote:
> As I said, the conditions under which the shutdown hooks are run are
> operating system dependent. If I run a Java program as a Console
> Application on Windows or from a RH Linux terminal window, Ctrl-C will
> run the shutdown hooks.
>
> What operating system are you running this on? What command do you use
> to run the Java application?
The sample application I sent on the previous post was obviously a GUI
based application. So I guess I'll try making it a non-GUI based
application and try once again.
My development computer happens to be Windows98. I do have RH Linux
running on another computer. I use it for testing as well.
Ultimately, I'm wanting to add this extra feature to my server-side app
of my client/server project. The server-side app, if run without
arguements, will produce a GUI. However, it can be run from the
commandline prompt with arguements which produce no interface
whatsoever. It just runs in the background. Without an interface, in
the console window, the user is prompted to type "stop" [Enter] whenever
he wants to terminate the program.
I realized, however, that this was not convenient when running the
server app on Linux because it forces you to log in and keep a session
open in order to keep the server app running. So, I wanted some other
convenient way to shut the program down.
I want to run the server app automatically when Linux boots up, and let
it run silently in the background. Then, if I want to shut it off, I
should have a way to simply log on as "root" and issue a command to shut
it off.
I'm thinking that the only way I'm going to pull this one off is to
simply encorportate another threaded class as part of the server app.
The class would contain a ServerSocket object listening only to the
loopback address.
Then, when I want to shut down the server app, all I got to do is log in
as "root" and execute another java program named Terminator. Terminator
will connect to the server app and issue the command to shutdown.
Both programs will then shut down.
I've taken the liberty of producing just such a test project today and
it appears to work.
The test project is only four classes. Well, there is one inner class,
so I guess technically its really five classes. Check it out:
Let me know what you think.
Alan
***********************************************************
package local_alert;
import javax.swing.UIManager;
import java.awt.*;
import local_alert.LocalSocketListener;
public class Application1
{
boolean packFrame = false;
Frame1 frame = null;
LocalSocketListener localListener = null;
protected final int SHUTDOWN = 99;
/**Construct the application*/
public Application1()
{
frame = new Frame1();
//Validate frames that have preset sizes
//Pack frames that have useful preferred size info, e.g. from their
layout
if (packFrame)
{
frame.pack();
}
else
{
frame.validate();
}
//Center the window
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = frame.getSize();
if (frameSize.height > screenSize.height)
{
frameSize.height = screenSize.height;
}
if (frameSize.width > screenSize.width)
{
frameSize.width = screenSize.width;
}
frame.setLocation((screenSize.width - frameSize.width) / 2,
(screenSize.height - frameSize.height) / 2);
frame.setVisible(true);
localListener = new LocalSocketListener("Application1", this, 2300);
localListener.start();
}
public void shutdown()
{
System.out.println("executing shutdown sequence");
System.exit(0);
}
public String getName()
{
return "Application1";
}
/**Main method*/
public static void main(String[] args)
{
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e)
{
e.printStackTrace();
}
new Application1();
}
}
****************************************************
package local_alert;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Frame1 extends JFrame
{
JPanel contentPane;
BorderLayout borderLayout1 = new BorderLayout();
JScrollPane jScrollPane1 = new JScrollPane();
JTextArea jTextArea1 = new JTextArea();
/**Construct the frame*/
public Frame1()
{
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try
{
jbInit();
}
catch(Exception e)
{
e.printStackTrace();
}
}
/**Component initialization*/
private void jbInit() throws Exception
{
//setIconImage(Toolkit.getDefaultToolkit().createImage(Frame1.class.getResource("[Your
Icon]")));
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(borderLayout1);
this.setSize(new Dimension(400, 300));
this.setTitle("Frame Title");
jTextArea1.setText("jTextArea1");
contentPane.add(jScrollPane1, BorderLayout.CENTER);
jScrollPane1.getViewport().add(jTextArea1, null);
}
/**Overridden so we can exit when window is closed*/
protected void processWindowEvent(WindowEvent e)
{
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING)
{
System.out.println("processing Window Closing event.");
System.exit(0);
}
}
}
********************************************************
package local_alert;
import java.net.*;
import java.io.*;
/**
* Title:
* Description:
* Copyright: Copyright (c) 2000
* Company:
* @author
* @version 1.0
*/
public class LocalSocketListener extends Thread
{
protected String ApplicationName = "";
private Application1 myApp = null;
private ServerSocket socket = null;
private SocketListener sl = null;
public LocalSocketListener(String appName, Application1 application,
int port)
{
ApplicationName = appName;
myApp = application;
//This class will only listen to the loopback address
//and allow only one logon.
String address = "127.0.0.1";
try
{
socket = new ServerSocket(port, 10,
InetAddress.getByName(address));
}
catch(UnknownHostException uhe)
{
uhe.printStackTrace();
}
catch(IOException io)
{
io.printStackTrace();
}
}
public void run()
{
//System.out.println("Waiting for external program to log on.");
while(true)
{
try
{
sl = new SocketListener(socket.accept(), this);
sl.start();
}
catch(SocketException se)
{
se.printStackTrace();
break;
}
catch(InterruptedIOException iioe)
{
iioe.printStackTrace();
break;
}
catch(IOException e)
{
//System.out.println("IOException in execute()");
e.printStackTrace();
break;
}
catch(Exception exc)
{
//System.out.println("Exception in execute()");
exc.printStackTrace();
break;
}
}
}
class SocketListener extends Thread
{
private Socket connection;
private LocalSocketListener lsl;
private DataInputStream input;
public SocketListener(Socket socket, LocalSocketListener listener)
{
connection = socket;
try
{
input = new DataInputStream(connection.getInputStream());
}
catch(IOException e)
{
e.printStackTrace();
System.exit(1);
}
lsl = listener;
}
public void run()
{
String name = "";
int command = 0;
while(true)
{
try
{
//Get the name of the application being addressed.
//If it is this application that is being addressed,
//then get the command sent by the calling program.
name = input.readUTF();
//System.out.println("Incoming app name: " + name);
if(name.equals(lsl.ApplicationName))
{
command = input.readInt();
//Now that we have the command, we need to tell
//the application that we have it so that it can
//decide what to do with it.
//System.out.println("command = " + command);
//lsl.myApp.frame.jTextArea1.setText("received command = " +
command);
if(command == lsl.myApp.SHUTDOWN)
{
lsl.myApp.shutdown();
input.close();
connection.close();
}
break;
}
else
{
//System.out.println("That other program can't be talking to
me.");
break;
}
}
catch(IOException ioe)
{
ioe.printStackTrace();
}
}
}
}
}
**********************************************************
package local_alert;
import java.net.*;
import java.io.*;
/**
* Title:
* Description:
* Copyright: Copyright (c) 2000
* Company:
* @author
* @version 1.0
*/
public class Terminator
{
static Socket connection;
static DataOutputStream output;
static String AppName = "";
static String command = "";
public Terminator()
{
//AppName = name;
//command = command;
try
{
makeConnection();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
//System.out.println("arguements: " + args[0] + " " + args[1]);
if(args[0].equals("/?") || args[0].equals("-h"))
{
displayHelp();
}
else if(!args[0].equals("") && !args[1].equals(""))
{
try
{
AppName = args[0];
command = args[1];
Terminator terminator1 = new Terminator();
}
catch(Exception e)
{
displayHelp();
e.printStackTrace();
}
}
else
{
displayHelp();
}
}
protected void makeConnection()
{
//System.out.println("Status: Attempting to connect to server
app.");
try
{
connection = new Socket("127.0.0.1", 2300);
if(connection == null)
{
System.out.println("Status: The socket could not be opened in
makeConnection() method.");
}
else
{
//System.out.println("We're connected");
output = new DataOutputStream(connection.getOutputStream());
//System.out.println("Sending data");
output.writeUTF(AppName);
//System.out.println("command = " + command);
output.writeInt(Integer.parseInt(command));
output.close();
connection.close();
}
}
catch(Exception e)
{
System.out.println("Status: Exception in makeConnection()
method.");
e.printStackTrace();
}
}
private static void displayHelp()
{
System.out.println("USAGE: java Terminator [ApplicationName]
[command as integer] [-h or /?]\n\n"
+ "OPTIONS:\n\n"
+ "ApplicationName: is the name of the running
application you wish to address.\n"
+ "command: is to be an integer value
associated with a 'shutdown' command defined by the running
application.\n"
+ "-h\t-help\n"
+ "/?\t-help\n\n"
+ "DEFINITIONS:\n\n"
+ "Terminator requires two commandline
arguements:\n\n"
+ "\t(1) The name of the application you intend
to address.\n"
+ "\t(2) The command you wish to send to the
application.\n"
+ "\t(3) Or one command line arguement asking
for this help screen: -h or /?\n\n"
+ "EXAMPLES:\n\n"
+ "1) java Terminator myApp 99\n"
+ "2) java Terminator -h\n"
+ "3) java Terminator /?\n");
}
}
Technical Details
Message-ID:
<3D29FE4E.C3EEF5B5@hfx.eastlink.ca>Path:
arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!sn-xit-02!sn-xit-03!sn-xit-06!supernews.com!iad-peer.news.verio.net!news.verio.net!fu-berlin.de!news.belwue.de!newsfeed01.sul.t-online.de!t-online.de!dnewsReferences:
<3D279D25.59AA52E@hfx.eastlink.ca> <3d27a0b2_2@dnews> <3D2861BB.63220DF5@hfx.eastlink.ca> <MPG.17923b35889aef9498b7f9@newsgroups.borland.com> <3D28A22A.89CB73DC@hfx.eastlink.ca> <MPG.1793793e26a87ab98b7fd@newsgroups.borland.com>Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 1089d0,4157c064c52214d4 X-Google-Attributes: gid1089d0,public X-Google-ArrivalTime: 2002-07-08 13:10:41 PST Message-ID: <3D29FE4E.C3EEF5B5@hfx.eastlink.ca> Date: Mon, 08 Jul 2002 17:04:14 -0400 From: Alan Shiers <ashiers@hfx.eastlink.ca> Organization: Mustard Seed Software X-Mailer: Mozilla 4.78 [en] (Win98; U) X-Accept-Language: en MIME-Version: 1.0 Newsgroups: borland.public.jbuilder.java.api Subject: Re: an idea to consider References: <3D279D25.59AA52E@hfx.eastlink.ca> <3d27a0b2_2@dnews> <3D2861BB.63220DF5@hfx.eastlink.ca> <MPG.17923b35889aef9498b7f9@newsgroups.borland.com> <3D28A22A.89CB73DC@hfx.eastlink.ca> <MPG.1793793e26a87ab98b7fd@newsgroups.borland.com> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit NNTP-Posting-Host: 24.222.101.2 X-Trace: dnews 1026158505 24.222.101.2 (8 Jul 2002 13:01:45 -0700) Lines: 469 Path: arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!sn-xit-02!sn-xit-03!sn-xit-06!supernews.com!iad-peer.news.verio.net!news.verio.net!fu-berlin.de!news.belwue.de!newsfeed01.sul.t-online.de!t-online.de!dnews