/* * 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: * <br>AEFConst.CONFIG_ERROR, AEFConst.FACTORY_ERROR * <br><a href="../commonerrorcodes.html">Common Errors</a> */ 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: * <br>AEFConst.APPLICATION_NOT_IN_PROPER_STATE * <br>AEFConst.OPERATION_TIMEOUT * <br>AEFConst.WAIT_INTERRUPTED * <br><a href="../commonerrorcodes.html">Common Errors</a> */ 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 <SO> 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 <SO><SO> 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: * <br>AEFConst.OPERATION_TIMEOUT * <br>AEFConst.WAIT_INTERRUPTED * <br><a href="../commonerrorcodes.html">Common Errors</a> */ 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", "<<<Clear key processed by application."); } if (log.isTraceEnabled()) { tempAEFMessage.setMessage("-Exit ACEForcedLogoffActionImpl.sendClearSequence()"); log.trace(tempAEFMessage); } return retVal; } /** * Sends the signoff key sequence. This method is called if the application * was sitting at the "REPEAT SIGNOFF" prompt when the force logoff was called. * * @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: * <br>AEFConst.OPERATION_TIMEOUT * <br>AEFConst.WAIT_INTERRUPTED * <br><a href="../commonerrorcodes.html">Common Errors</a> */ 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: * <br>AEFConst.APPLICATION_NOT_IN_PROPER_STATE * <br>AEFConst.OPERATION_TIMEOUT * <br>AEFConst.WAIT_INTERRUPTED * <br><a href="../commonerrorcodes.html">Common Errors</a> */ 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); }