/**************************************************************************
*
* Class : Daemon.Manager
*
* Purpose : Generic NT service that runs MTS/COM+ objects as a service.
*
**************************************************************************
* Revision History
*
* V1.0.0 03/07/2000 James Bischoff
* Created
*
*************************************************************************/
/**************************************************************************
* System Classes
*************************************************************************/
import com.ms.service.*; // Service
import com.ms.wfc.app.*; // Registry
/**************************************************************************
* Custom Classes
*************************************************************************/
import com.upperbay.Message; // Custom Galaxy Local Messenger wrapper
/**************************************************************************
* Class : Manager
* Purpose : The main service class.
*************************************************************************/
public class Manager extends Service
{
/***********************************************************************
* Class Constants
**********************************************************************/
private final static String gcstrClassName = new String("Daemon.Manager");
private final static String gcstrRegistryRoot = "Software\\UpperBay\\DaemonManager\\1.0\\";
/***********************************************************************
* Class Globals
***********************************************************************/
private static com.upperbay.Message gobjMessage = null;
private static int gintTraceLevel = 1;
private static int gintWaitHintSec = 5;
private static String[] gastrProgIDs = null;
private static int gintServiceAction = ServiceAction.STOP;
private static Monitor gobjMonitor = null;
/***********************************************************************
* Method : Class Constructor
* Purpose : Called when the class is instantiated (service started)
**********************************************************************/
public Manager (String[] args) throws Throwable {
final String cstrMethodName = new String("Manager Constructor");
try {
gobjMessage = new com.upperbay.Message();
gobjMessage.SetTraceLevel(gintTraceLevel);
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Start");
LoadRegistryValues();
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Sending updated pending status");
CheckPoint(1000);
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Sending running status with all controls");
setRunning(ACCEPT_SHUTDOWN | ACCEPT_PAUSE_CONTINUE | ACCEPT_STOP);
gobjMonitor = new Monitor();
gintServiceAction = ServiceAction.START;
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Start COM Object Threads");
for (int i = 0; i < gastrProgIDs.length; i++) {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Start [" + gastrProgIDs[i] + "]");
com.ms.com.ComLib.startMTAThread(new Thread(new COMThread(this, gobjMonitor, gobjMessage, gastrProgIDs[i])));
}
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "DaemonManager Service Started");
}
catch (Throwable exc) {
gobjMessage.SendError(gcstrClassName, cstrMethodName, exc.toString());
throw exc;
}
finally {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "End");
}
}
/***********************************************************************
* Method : handleStop
* Purpose : Handles stop events.
**********************************************************************/
protected boolean handleStop () {
final String cstrMethodName = new String("handleStop");
try {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Start");
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Notify COMThreads");
gintServiceAction = ServiceAction.STOP;
gobjMonitor.Unlock();
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Wait for COMThreads to stop");
synchronized (this) {
wait(gintWaitHintSec * 1000);
}
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Dying");
setStopping(gintWaitHintSec * 1000);
}
catch (Throwable exc) {
gobjMessage.SendError(gcstrClassName, cstrMethodName, exc.toString());
}
finally {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "End");
return true;
}
}
/***********************************************************************
* Method : handlePause
* Purpose : Handles pause events.
**********************************************************************/
protected boolean handlePause () {
final String cstrMethodName = new String("handlePause");
try {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Start");
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Pausing");
setPausing(gintWaitHintSec * 1000);
gintServiceAction = ServiceAction.PAUSE;
gobjMonitor.Unlock();
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Paused");
setPaused();
}
catch (Throwable exc) {
gobjMessage.SendError(gcstrClassName, cstrMethodName, exc.toString());
}
finally {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "End");
return false;
}
}
/***********************************************************************
* Method : handleContinue
* Purpose : Handles continue events.
**********************************************************************/
protected boolean handleContinue () {
final String cstrMethodName = new String("handleContinue");
try {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Start");
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Continuing");
setContinuing(gintWaitHintSec * 1000);
gintServiceAction = ServiceAction.CONTINUE;
gobjMonitor.Unlock();
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Running");
setRunning();
}
catch (Throwable exc) {
gobjMessage.SendError(gcstrClassName, cstrMethodName, exc.toString());
}
finally {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "End");
return false;
}
}
/***********************************************************************
* Method : handleShutdown
* Purpose : Handles system shutdown events.
**********************************************************************/
protected boolean handleShutdown () {
final String cstrMethodName = new String("handleShutdown");
boolean blnStatus = false;
try {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Start");
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Treat As Stop");
blnStatus = handleStop();
}
catch (Throwable exc) {
gobjMessage.SendError(gcstrClassName, cstrMethodName, exc.toString());
}
finally {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "End");
return blnStatus;
}
}
/***********************************************************************
* Method : handleInterrogate
* Purpose : Handles interrogate events.
**********************************************************************/
protected boolean handleInterrogate () {
final String cstrMethodName = new String("handleInterrogate");
try {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Start");
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Sent Status For Interrogate");
setServiceStatus(getServiceStatus());
}
catch (Throwable exc) {
gobjMessage.SendError(gcstrClassName, cstrMethodName, exc.toString());
}
finally {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "End");
return false;
}
}
/***********************************************************************
* Method : GetServiceAction
* Purpose : Obtain the last service action.
**********************************************************************/
public static int GetServiceAction() {
return gintServiceAction;
}
/***********************************************************************
* Method : LoadRegistryValues
* Purpose : Load all class cconfiguration values from the registry.
**********************************************************************/
private void LoadRegistryValues() throws Throwable {
final String cstrMethodName = new String("LoadRegistryValues");
String strTemp = null;
com.ms.wfc.app.RegistryKey hKey = null;
try {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Start");
if ((hKey = Registry.LOCAL_MACHINE.getSubKey(gcstrRegistryRoot)) == null)
gobjMessage.SendError(gcstrClassName, cstrMethodName,
"Unable to open registry key [" + gcstrRegistryRoot + "]");
else {
if ((strTemp = (String) hKey.getValue("TRACE_LEVEL")) != null)
gintTraceLevel = Integer.parseInt(strTemp);
if ((strTemp = (String) hKey.getValue("WAIT_HINT_SECONDS")) != null)
gintWaitHintSec = Integer.parseInt(strTemp);
gastrProgIDs = hKey.getSubKeyNames();
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Found [" + hKey.getSubKeyCount() + "] Service Objects");
hKey.close();
}
}
catch (Throwable exc) {
gobjMessage.SendError(gcstrClassName, cstrMethodName, exc.toString());
throw exc;
}
finally {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName,
"TRACE_LEVEL = [" + gintTraceLevel + "]");
gobjMessage.SendDebug(gcstrClassName, cstrMethodName,
"WAIT_HINT_SECONDS = [" + gintWaitHintSec + "]");
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "End");
}
}
}
/**************************************************************************
*
* Class : Daemon.COMThread
*
* Purpose : Thread that hosts a single COM object
*
**************************************************************************
* Revision History
*
* V1.0.0 03/07/2000 James Bischoff
* Created
*
*************************************************************************/
/**************************************************************************
* System Classes
*************************************************************************/
import com.ms.com.*;
import com.ms.win32.*;
/**************************************************************************
* Custom Classes
*************************************************************************/
import com.upperbay.Message; // Custom Galaxy Local Messenger wrapper
/**************************************************************************
* Class : COMThread
* Purpose : The main thread class.
*************************************************************************/
public class COMThread implements Runnable
{
/***********************************************************************
* Class Constants
**********************************************************************/
private final static String gcstrClassName = new String("Daemon.COMThread");
/***********************************************************************
* Class Globals
***********************************************************************/
private static Message gobjMessage = null;
private static _Guid IID_IUnknown = new _Guid("{00000000-0000-0000-C000-000000000046}");
private String gstrProgID;
private Monitor gobjMonitor;
private Manager gobjManager;
/***********************************************************************
* Native Functions
***********************************************************************/
/** @dll.import("ole32", ole) */
private static native IUnknown CoCreateInstance(_Guid clsid,
IUnknown punkOuter,
int context,
_Guid riid);
/** @dll.import("ole32", ole) */
private static native _Guid CLSIDFromString(String str);
/**************************************************************************
* Class : COMThread
* Purpose : COMThread Constructor.
*************************************************************************/
COMThread(Manager objManager,
Monitor objMonitor,
String strProgID) throws Throwable {
final String cstrMethodName = new String("COMThread Constructor");
try {
gobjMessage = new Message();
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Start");
gstrProgID = strProgID;
gobjMonitor = objMonitor;
gobjManager = objManager;
}
catch (Throwable exc) {
gobjMessage.SendError(gcstrClassName, cstrMethodName, exc.toString());
throw exc;
}
finally {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "End");
}
}
/**************************************************************************
* Class : COMThread
* Purpose : COMThread Constructor with Message object.
*************************************************************************/
COMThread(Manager objManager,
Monitor objMonitor,
Message objMessage,
String strProgID) throws Throwable {
final String cstrMethodName = new String("COMThread Constructor");
try {
gobjMessage = objMessage;
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Start");
gstrProgID = strProgID;
gobjMonitor = objMonitor;
gobjManager = objManager;
}
catch (Throwable exc) {
gobjMessage.SendError(gcstrClassName, cstrMethodName, exc.toString());
throw exc;
}
finally {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "End");
}
}
/***********************************************************************
* Method : SetUpMessenger
* Purpose : Use parent's messenger.
**********************************************************************/
public void SetUpMessenger(Message objMessage) {
final String cstrMethodName = new String("SetUpMessenger");
try {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Start");
gobjMessage = null;
gobjMessage = objMessage;
}
catch (Throwable exc) {
gobjMessage.SendError(gcstrClassName, cstrMethodName, exc.toString());
}
finally {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "End");
}
}
/***********************************************************************
* Method : run
* Purpose : Start the forever loop.
**********************************************************************/
public void run() {
final String cstrMethodName = new String("COMThread run");
Object objCOMObject = null;
int intServiceAction;
boolean blnRun = true;
try {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Start");
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Create COM Object");
objCOMObject = CreateObject(gstrProgID);
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Call COM Object SvcStart");
Dispatch.callSub(objCOMObject,"SvcStart");
while(blnRun) {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Wait For Service State Change");
gobjMonitor.Lock();
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Get New Service State");
intServiceAction = gobjManager.GetServiceAction();
switch (intServiceAction) {
case ServiceAction.STOP:
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Call COM Object SvcStop");
Dispatch.callSub(objCOMObject,"SvcStop");
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Wait For COM Object Release");
com.ms.com.ComLib.release(objCOMObject);
synchronized (this) {
wait(500);
}
blnRun = false;
break;
case ServiceAction.START:
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Call COM Object SvcStart");
Dispatch.callSub(objCOMObject,"SvcStart");
break;
case ServiceAction.PAUSE:
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Call COM Object SvcPause");
Dispatch.callSub(objCOMObject,"SvcPause");
break;
case ServiceAction.CONTINUE:
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Call COM Object SvcContinue");
Dispatch.callSub(objCOMObject,"SvcContinue");
break;
}
}
}
catch (Throwable exc) {
gobjMessage.SendError(gcstrClassName, cstrMethodName, exc.toString());
}
finally {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "End");
}
}
/***********************************************************************
* Method : CreateObject
* Purpose : Create a COM object from its Prog ID.
**********************************************************************/
private Object CreateObject(String strProgID) throws Throwable {
final String cstrMethodName = new String("CreateObject");
Object objObject = null;
_Guid guidClassID = null;
int intContext;
try {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "Start");
guidClassID = com.ms.win32.Ole32.CLSIDFromProgID(strProgID);
intContext = ComContext.INPROC_SERVER | com.ms.win32.win.CLSCTX_LOCAL_SERVER;
objObject = com.ms.win32.Ole32.CoCreateInstance(
guidClassID,
null,
intContext,
IID_IUnknown);
return objObject;
}
catch (Throwable exc) {
gobjMessage.SendError(gcstrClassName, cstrMethodName, exc.toString());
throw exc;
}
finally {
gobjMessage.SendDebug(gcstrClassName, cstrMethodName, "End");
}
}
}
/**************************************************************************
*
* Class : Daemon.Monitor
*
* Purpose : Generic object monitor used to stop and start threads.
*
**************************************************************************
* Revision History
*
* V1.0.0 03/07/2000 James Bischoff
* Created
*
*************************************************************************/
public class Monitor
{
public Monitor() {}
public synchronized void Unlock() {
notifyAll();
}
public synchronized void Lock() {
try {
wait();
}
catch (InterruptedException ex) {
}
}
}
/**************************************************************************
*
* Class : Daemon.ServiceAction
*
* Purpose : Service action enum constants.
*
**************************************************************************
* Revision History
*
* V1.0.0 03/07/2000 James Bischoff
* Created
*
*************************************************************************/
public class ServiceAction extends com.ms.wfc.core.Enum {
public static final int STOP = 0;
public static final int START = 1;
public static final int PAUSE = 2;
public static final int CONTINUE = 3;
public static boolean valid(int value) {
if (value < 0 || value > 3)
return false;
return true;
}
}
|