/*
* ACEForcedLogoffActionImpl
*
* 07/18/2003
*
* Copyright:
* Licensed Materials - Property of IBM
* "Restricted Materials of IBM"
* 5724-AEF
* (C) Copyright IBM Corp. 2003.
*
* %W% %E%
*/
package com.ibm.retail.AEF.action;
import com.ibm.retail.AEF.automation.*;
import com.ibm.retail.AEF.util.*;
import com.ibm.retail.si.util.*;
import com.ibm.retail.si.Copyright;
import com.ibm.retail.AEF.factory.*;
import com.ibm.retail.AEF.thread.*;
import com.ibm.retail.AEF.data.*;
import com.ibm.retail.AEF.session.*;
import java.util.*;
import java.rmi.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* ACEForcedLogoffActionImpl is a class which the POSAutomationProvider
* uses to force a logoff on the ACE application.
*
*/
public class ACEForcedLogoffActionImpl extends ACEActionImpl
{
static String copyright()
{ return com.ibm.retail.si.Copyright.IBM_COPYRIGHT_SHORT; }
private static AEFPerfTrace perfTrace = AEFPerfTrace.getInstance();
/**
* Constructor
*
* @param request The ActionRequest which contains a HashMap of arguments.
*
* @exception com.ibm.retail.AEF.util.AEFException
* Among the possible AEFException error codes are:
*
AEFConst.CONFIG_ERROR, AEFConst.FACTORY_ERROR
*
Common Errors
*/
public ACEForcedLogoffActionImpl(ActionRequest request) throws AEFException
{
super(request);
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter/-Exit constructor of ACEForcedLogoffActionImpl.");
log.trace(tempAEFMessage);
}
}
/**
* Tries to void the current transaction (if any) and return the application
* to the ID state
*
* @return Object N/A (null).
* @exception com.ibm.retail.AEF.util.AEFException
* Among the possible AEFException error codes are:
*
AEFConst.APPLICATION_NOT_IN_PROPER_STATE
*
AEFConst.OPERATION_TIMEOUT
*
AEFConst.WAIT_INTERRUPTED
*
Common Errors
*/
public Object performAction() throws AEFException
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter ACEForcedLogoffActionImpl.performAction()");
log.trace(tempAEFMessage);
}
// Call super to perform any common processing and clear any errors before we start.
super.performAction();
boolean salesTranInProgress = false;
boolean nonSalesTranInProgress = false;
Transaction trans = null;
ObjectDetector detector = null;
// If app is in secured state, and options are set to automatically do a special
// signon, then do a special signon first.
checkForSpecialSignon();
try
{
// Check for a "partial" transaction which was started, but no items have been sold.
trans = automationProvider.getTransaction();
// Check if we are in the middle of a transaction.
salesTranInProgress = getBooleanProviderProperty(WorkstationStatusProperties.CATEGORY,
WorkstationStatusProperties.SALES_TRANSACTION_IN_PROGRESS);
nonSalesTranInProgress = getBooleanProviderProperty(WorkstationStatusProperties.CATEGORY,
WorkstationStatusProperties.NONSALES_TRANSACTION_IN_PROGRESS);
if(salesTranInProgress || nonSalesTranInProgress || trans != null)
{
// We are in the middle of the transaction so void it.
automationProvider.voidCurrentTransaction();
}
// Now try to return the application to the "ID" State.
// First get all the states and sub-states from the config files.
initializeStates();
// Loop several times through the state test to ensure that we do not miss an escape route.
for (int i = 0; i < 2; i++)
{
// If in "REPEAT SIGNOFF" substate send
if (getCurrentSubstate().equalsIgnoreCase(theRepeatSignoffSubstate))
{
try
{
// We are in the middle of the transaction so void it.
sendSignoffSequence();
}
catch (AEFException e)
{
// Check to see if we timed out. If so log the error but continue,
// we may be in a state which we can fix below.
if (e.getErrorCode() != AEFConst.OPERATION_TIMEOUT)
{
throw(e);
}
else
{
if (log.isDebugEnabled())
{
log.debug( new AEFMessage( sessionID, "ACEForcedLogoffActionImpl.performAction timeout during sendSignoffSequence().")) ;
}
}
}
}
// If in Main state send
if (getCurrentState().equalsIgnoreCase(theMainState))
{
try
{
// We are in the middle of the transaction so void it.
automationProvider.logoff();
}
catch (AEFException e)
{
// Check to see if we timed out. If so log the error but continue,
// we may be in a state which we can fix below.
if (e.getErrorCode() != AEFConst.OPERATION_TIMEOUT)
{
throw(e);
}
else
{
if (log.isDebugEnabled())
{
log.debug(new AEFMessage( sessionID, "ACEForcedLogoffActionImpl.performAction timeout during sendLogoffSequence().") );
}
}
}
}
// If in state enter, wait to get out of the state .
if (getCurrentState().equalsIgnoreCase(theEnterState))
{
try
{
waitForStateChange(theEnterState);
}
catch (AEFException e)
{
// Check to see if we timed out. If so log the error but continue,
// we may be in a state which we can fix below.
if (e.getErrorCode() != AEFConst.OPERATION_TIMEOUT)
{
throw(e);
}
else
{
if (log.isDebugEnabled())
{
log.debug( new AEFMessage( sessionID, "ACEForcedLogoffActionImpl.performAction timeout during waitForStateChange()."));
}
}
}
}
// If in state clear then call the error handler.
if (getCurrentState().equalsIgnoreCase(theClearState))
{
try
{
handleError();
}
catch (AEFException e)
{
// Check to see if we timed out. If so log the error but continue,
// we may be in a state which we can fix below.
if (e.getErrorCode() != AEFConst.OPERATION_TIMEOUT)
{
throw(e);
}
else
{
if (log.isDebugEnabled())
{
log.debug( new AEFMessage( sessionID, "ACEForcedLogoffActionImpl.performAction timeout during handleError().")) ;
}
}
}
}
// If in ID state then stop
if (getCurrentState().equalsIgnoreCase(theIdState))
{
break; // We are at the desired state.
}
} // End of For Loop
// If we are out of the loop with an error condition, lets try to clear it one last time.
if (getCurrentState().equalsIgnoreCase(theClearState))
{
try
{
handleError();
}
catch (AEFException e)
{
// Check to see if we timed out. If so log the error but continue,
// we may be in a state which we can fix below.
if (e.getErrorCode() != AEFConst.OPERATION_TIMEOUT)
{
throw(e);
}
else
{
if (log.isDebugEnabled())
{
log.debug( new AEFMessage(sessionID, "ACEForcedLogoffActionImpl.performAction timeout during handleError()."));
}
}
}
}
// Wait to get into the ID state.
String[] states =
{
theIdState
};
waitForStates(states);
}
catch (RemoteException re)
{
// Not expected to get here since we are calling locally.
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit ACEForcedLogoffActionImpl.performAction()");
log.trace(tempAEFMessage);
}
return null;
}
/**
* Sends the clear key sequence.
*
* @param wait True to wait for a state transition to state Main.
* @return int Integer value representing the result of the key sequence.
* @exception com.ibm.retail.AEF.util.AEFException
* Among the possible AEFException error codes are:
*
AEFConst.OPERATION_TIMEOUT
*
AEFConst.WAIT_INTERRUPTED
*
Common Errors
*/
public int sendClearSequence(boolean wait) throws AEFException
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter ACEForcedLogoffActionImpl.sendClearSequence()");
log.trace(tempAEFMessage);
}
int retVal = -1;
AEFErrorHandler errorHandler = null;
args.clear();
args.put("SEQUENCE_ID", "clear-error");
theKeySequenceAction = (AEFAction)(actionFactory.makeAction(new ActionRequest("SimpleKeySequenceAction", args)));
if (wait)
{
AbstractPropertyCondition[] conditions =
{
new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_STATE, theMainState),
new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_STATE, theIdState),
new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_STATE, theOverrideState)
};
theLock = new ConditionLock();
if (perfTrace.isEnabled(AEFPerfTrace. COARSE))
{
perfTrace.reportTimer(AEFPerfTrace. COARSE,
sessionID,
"forceLogoff",
">>>Sending clear key to application.");
}
retVal = theLock.performActionAndWait("wait-for-state-main",theKeySequenceAction, conditions, BadConditionsImpl.getInstance().getBadConditions(), getTimeout());
if (retVal < 0)
{
errorHandler = new AEFErrorHandler("There was an error in SAForcedLogoffActionImpl.sendClearSequence()");
retVal = errorHandler.handleError(theLock,
theKeySequenceAction,
conditions,
BadConditionsImpl.getInstance().getBadConditions(),
getTimeout(),
retVal);
if (retVal < 0)
{
throw errorHandler.getAllExceptions();
}
}
}
else
{
theKeySequenceAction.performAction();
}
if (perfTrace.isEnabled(AEFPerfTrace. COARSE))
{
perfTrace.reportTimer(AEFPerfTrace. COARSE,
sessionID,
"forceLogoff",
"<<AEFConst.OPERATION_TIMEOUT
*
AEFConst.WAIT_INTERRUPTED
*
Common Errors
*/
public int sendSignoffSequence() throws AEFException
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter ACEForcedLogoffActionImpl.sendSignoffSequence()");
log.trace(tempAEFMessage);
}
int retVal = -1;
AEFErrorHandler errorHandler = null;
args.clear();
args.put("SEQUENCE_ID", "logoff2");
theKeySequenceAction = (AEFAction)(actionFactory.makeAction(new ActionRequest("SimpleKeySequenceAction", args)));
Condition[] goodConditions =
{
new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_STATE, theIdState)
};
theLock = new ConditionLock();
retVal = theLock.performActionAndWait("wait-for-id-state",
theKeySequenceAction,
goodConditions,
BadConditionsImpl.getInstance().getBadConditions(),
getTimeout());
if (retVal < 0)
{
errorHandler = new AEFErrorHandler("Send Repeat Logoff Sequence Error");
retVal = errorHandler.handleError(theLock,
theKeySequenceAction,
goodConditions,
BadConditionsImpl.getInstance().getBadConditions(),
getTimeout(),
retVal);
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit ACEForcedLogoffActionImpl.sendSignoffSequence()");
log.trace(tempAEFMessage);
}
return retVal;
}
/**
* Initialize the state variables for ACE.
*
* @result void
*/
private void initializeStates()
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter ACEForcedLogoffActionImpl.initializeStates()");
log.trace(tempAEFMessage);
}
// Get the values for all the ACE application states.
theClearState = State.getState("CLEAR");
theIdState = State.getState("ID");
thePasswordState = State.getState("PASSWORD");
theSoPasswordState = State.getState("SO_PASSWORD");
theSecuredState = State.getState("SECURED");
theOverrideState = State.getState("OVERRIDE");
theMainState = State.getState("MAIN");
theStandaloneState = State.getState("STANDALONE");
theAutoSignState = State.getState("AUTOSIGN");
theEnterState = State.getState("ENTER");
theRepeatSignoffSubstate = Substate.getSubstate("REPEAT_SIGNOFF");
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit ACEForcedLogoffActionImpl.initializeStates()");
log.trace(tempAEFMessage);
}
}
/**
* Calls the Error Handler to try to clear an error.
*
* @return int Integer value representing the result of the key sequence.
* @exception com.ibm.retail.AEF.util.AEFException
* Among the possible AEFException error codes are:
*
AEFConst.APPLICATION_NOT_IN_PROPER_STATE
*
AEFConst.OPERATION_TIMEOUT
*
AEFConst.WAIT_INTERRUPTED
*
Common Errors
*/
public int handleError() throws AEFException
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter ACEForcedLogoffActionImpl.handleError()");
log.trace(tempAEFMessage);
}
int retVal = -1;
AEFErrorHandler errorHandler = null;
args.clear();
args.put("SEQUENCE_ID", "clear-error");
theKeySequenceAction = (AEFAction)(actionFactory.makeAction(new ActionRequest("SimpleKeySequenceAction", args)));
AbstractPropertyCondition[] conditions =
{
new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_STATE, theMainState),
new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_STATE, theIdState),
new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_STATE, theOverrideState)
};
theLock = new ConditionLock();
errorHandler = new AEFErrorHandler("There was an error in ACEForcedLogoffActionImpl.handleError()");
retVal = errorHandler.handleError(theLock,
theKeySequenceAction,
conditions,
BadConditionsImpl.getInstance().getBadConditions(),
getTimeout(),
retVal);
if (retVal < 0)
{
throw errorHandler.getAllExceptions();
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit ACEForcedLogoffActionImpl.handleError()");
log.trace(tempAEFMessage);
}
return retVal;
}
// Instance Variables
protected AEFAction theKeySequenceAction = null;
protected ConditionLock theLock = null;
protected String theIdState = null;
protected String theClearState = null;
protected String thePasswordState = null;
protected String theSoPasswordState = null;
protected String theSecuredState = null;
protected String theOverrideState = null;
protected String theMainState = null;
protected String theStandaloneState = null;
protected String theAutoSignState = null;
protected String theEnterState = null;
protected String theRepeatSignoffSubstate = null;
private static Log log = LogFactory.getLog(ACEForcedLogoffActionImpl.class);
}