/*
* GSAForcedLogoffActionImpl
*
* 07/01/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;
/**
* GSAForcedLogoffActionImpl is a class which the POSAutomationProvider
* uses to accomplish a forced logoff within the GSA application.
*
*/
public class GSAForcedLogoffActionImpl extends GSAActionImpl
{
static String copyright()
{ return com.ibm.retail.si.Copyright.IBM_COPYRIGHT_SHORT; }
/**
* 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 GSAForcedLogoffActionImpl(ActionRequest request) throws AEFException
{
super(request);
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter GSAForcedLogoffActionImpl.GSAForcedLogoffActionImpl().");
log.trace(tempAEFMessage);
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit GSAForcedLogoffActionImpl.GSAForcedLogoffActionImpl().");
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.PROCEDURE_NOT_ALLOWED, AEFConst.TRANSACTION_CANNOT_BE_VOIDED
*
Common Errors
*/
public Object performAction() throws AEFException
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter GSAForcedLogoffActionImpl.performAction().");
log.trace(tempAEFMessage);
}
super.performAction(); // Call super to perform any common processing and clear any errors before we start.
boolean salesTranInProgress = false;
boolean nonSalesTranInProgress = false;
Transaction trans = null;
ObjectDetector detector = null;
try
{
// Check for a "partial" transaction which was started, but no items have been sold.
trans = automationProvider.getTransaction();
if (trans != null)
{
if (trans.getTransactionInfo().getTransactionID() == null)
{
// Clear the partial transaction object.
detector = ((DetectorAccess)(SessionContext.getSession())).getTransactionDetector();
detector.reset();
automationProvider.setTransaction(null);
}
}
// Check the condition that 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)
{
// We are in the middle of the transaction so lets void it.
automationProvider.voidCurrentTransaction();
}
// Now try to return the application to the "ID" State.
// First get all the 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 state clear then call the error handler.
if (getCurrentState().equalsIgnoreCase(clearState))
{
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.isInfoEnabled())
{
tempAEFMessage.setMessage("GSAForcedLogoffActionImpl.performAction timeout after handleError().");
log.info(tempAEFMessage);
}
}
}
}
// If in state SIGNOFF then send ENTER key.
if (getCurrentState().equalsIgnoreCase(signOffState))
{
try
{
sendEnterSequence();
}
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.isInfoEnabled())
{
tempAEFMessage.setMessage("GSAForcedLogoffActionImpl.performAction timeout after sendEnterSequence().");
log.info(tempAEFMessage);
}
}
}
}
// If in ID state then stop
if (getCurrentState().equalsIgnoreCase(idState))
{
break; // We are at the desired state.
}
else // try to log off!
{
try
{
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.isInfoEnabled())
{
tempAEFMessage.setMessage("GSAForcedLogoffActionImpl.performAction timeout after sendLogoffSequence().");
log.info(tempAEFMessage);
}
}
}
}
} // 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(clearState))
{
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.isInfoEnabled())
{
tempAEFMessage.setMessage("GSAForcedLogoffActionImpl.performAction timeout after handleError().");
log.info(tempAEFMessage);
}
}
}
}
// Wait to get into the ID state.
String[] states =
{
idState
};
waitForStates(states);
}
catch (AEFException e)
{
tempAEFMessage.setMessage("There was an AEF exception thrown in performAction of GSAForcedLogoffActionImpl.");
log.error(tempAEFMessage, e);
throw e;
}
catch (RemoteException re)
{
// Not expected to get here since we are calling locally.
tempAEFMessage.setMessage("There was a remote exception thrown in performAction of GSAForcedLogoffActionImpl.");
log.error(tempAEFMessage, re);
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit GSAForcedLogoffActionImpl.performAction().");
log.trace(tempAEFMessage);
}
return null;
}
/**
* Sends the Enter key sequence.
*
* @return int Integer value representing the result of the key sequence.
* 0 = Were are in the ID State.
* <0 = There was an error.
* @exception com.ibm.retail.AEF.util.AEFException
* Among the possible AEFException error codes are:
*
Common Errors
*/
private int sendEnterSequence() throws AEFException
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter GSAForcedLogoffActionImpl.sendEnterSequence().");
log.trace(tempAEFMessage);
}
int retVal = -1;
AEFAction keySequenceAction = null;
ConditionLock lock = new ConditionLock();
// Send the second part of the logoff sequence and check for errors.
args.clear();
args.put("SEQUENCE_ID", "logoff2");
keySequenceAction = (AEFAction)(actionFactory.makeAction(new ActionRequest("SimpleKeySequenceAction", args)));
Condition[] goodConditions2 =
{
new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_STATE, State.getState("ID"))
};
if (log.isDebugEnabled())
{
tempAEFMessage.setMessage("GSAForcedLogoffActionImpl.sendEnterSequence() about to call performActionAndWait for part two of Signoff.");
log.debug(tempAEFMessage);
}
retVal = lock.performActionAndWait("wait-for-id-state", keySequenceAction, goodConditions2, BadConditionsImpl.getInstance().getBadConditions(), getTimeout());
if (retVal < 0)
{
AEFErrorHandler errorHandler = new AEFErrorHandler("Send Logoff Sequence Error Part 2");
retVal = errorHandler.handleError(lock, keySequenceAction, goodConditions2, BadConditionsImpl.getInstance().getBadConditions(), getTimeout(), retVal);
if (retVal < 0)
{
tempAEFMessage.setMessage("An AEF exception was thrown in GSAForcedLogoffActionImpl.sendEnterSequence()");
log.trace(tempAEFMessage, errorHandler.getAllExceptions());
throw errorHandler.getAllExceptions();
}
}
if (log.isDebugEnabled())
{
tempAEFMessage.setMessage("GSAForcedLogoffActionImpl.sendEnterSequence() retVal=" + retVal);
log.debug(tempAEFMessage);
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit GSAForcedLogoffActionImpl.sendEnterSequence().");
log.trace(tempAEFMessage);
}
return retVal;
}
/**
* Initialize the state variables for GSA.
*
*/
private void initializeStates()
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter GSAForcedLogoffActionImpl.initializeStates().");
log.trace(tempAEFMessage);
}
clearState = State.getState("CLEAR");
idState = State.getState("ID");
signOffState = State.getState("SIGNOFF");
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit GSAForcedLogoffActionImpl.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.PROCEDURE_NOT_ALLOWED, AEFConst.TRANSACTION_CANNOT_BE_VOIDED
*
AEFConst.WAIT_INTERRUPTED
*
Common Errors
*/
public int handleError() throws AEFException
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter GSAForcedLogoffActionImpl.handleError().");
log.trace(tempAEFMessage);
}
int retVal = -1;
AEFErrorHandler errorHandler = null;
args.clear();
args.put("SEQUENCE_ID", "clear-error");
keySequenceAction = (AEFAction)(actionFactory.makeAction(new ActionRequest("SimpleKeySequenceAction", args)));
lock = new ConditionLock();
errorHandler = new AEFErrorHandler("There was an error in GSAForcedLogoffActionImpl.handleError()");
retVal = errorHandler.handleError(lock,
keySequenceAction,
BadConditionsImpl.getInstance().getLogicalOpposite(),
BadConditionsImpl.getInstance().getBadConditions(),
getTimeout(),
retVal);
if (retVal < 0)
{
tempAEFMessage.setMessage("An AEF exception was thrown in GSAForcedLogoffActionImpl.handleError()");
log.trace(tempAEFMessage, errorHandler.getAllExceptions());
throw errorHandler.getAllExceptions();
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit GSAForcedLogoffActionImpl.handleError().");
log.trace(tempAEFMessage);
}
return retVal;
}
// Instance Variables
protected AEFAction keySequenceAction = null;
protected ConditionLock lock = null;
protected String idState = null;
protected String clearState = null;
protected String signOffState = null;
private static Log log = LogFactory.getLog(GSAForcedLogoffActionImpl.class);
}