/* * ACELogonActionImpl * * 07/02/2003 * * Copyright: * Licensed Materials - Property of IBM * "Restricted Materials of IBM" * 5724-AEF * (C) Copyright IBM Corp. 2003. * * ace/com/ibm/retail/AEF/action/ACELogonActionImpl.java, aef.ace, aef.bravo 04/07/12 */ 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; /** * ACELogonActionImpl is a class which POSAutomationProvider uses to * log on to the ACE application. * */ public class ACELogonActionImpl 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 AEFException * Among the possible error codes are: * <br>AEFConst.CONFIG_ERROR, AEFConst.NO_DEFAULT_ID_CONFIGURED * <br>AEFConst.INVALID_ARGUMENT, AEFConst.ID_REQUIRED * <br>AEFConst.INVALID_ARGUMENT, AEFConst.PASSWORD_REQUIRED * */ public ACELogonActionImpl(ActionRequest request) throws AEFException { super(request); if (log.isTraceEnabled()) { tempAEFMessage.setMessage("+Enter constructor of ACELogonActionImpl."); log.trace(tempAEFMessage); } if (sessionID == null) { sessionID = "999"; } OperatorIdentifier opId = (OperatorIdentifier)(request.getArguments()); theId = opId.getID(); thePassword = opId.getPassword(); theNewPassword = opId.getNewPassword(); // If no password and no id, use defaults if (theId == null || theId.length() == 0) { if (thePassword == null || thePassword.length() == 0) { // Use defaults theId = AppLogons.getID(sessionID); thePassword = AppLogons.getPassword(sessionID); if (theId == null || theId.length() == 0) { // Error, unable to lookup default id for terminal number. String tempString = "ACELogonActionImpl: Default ID not configured for terminal " + sessionID + ", unable to perform logon.\nSee applogon.properties for id/password configuration."; AEFException tempException = new AEFException(AEFConst.CONFIG_ERROR, AEFConst.NO_DEFAULT_ID_CONFIGURED, tempString); tempAEFMessage.setMessage(tempString); log.error(tempAEFMessage, tempException); throw tempException; } if ( thePassword == null || thePassword.length() == 0) { // Error, unable to lookup default password for terminal number. String tempString = "ACELogonActionImpl: Default password not configured for terminal " + sessionID + ", unable to perform logon.\nSee applogon.properties for id/password configuration."; AEFException tempException = new AEFException(AEFConst.CONFIG_ERROR, AEFConst.NO_DEFAULT_ID_CONFIGURED, tempString); tempAEFMessage.setMessage(tempString); log.error(tempAEFMessage, tempException); throw tempException; } } else { // input bad, only password provided String tempString = "ACELogonActionImpl.performAction(): ID required, only password was provided.\n"; AEFException tempException = new AEFException(AEFConst.INVALID_ARGUMENT, AEFConst.ID_REQUIRED, tempString); tempAEFMessage.setMessage(tempString); log.error(tempAEFMessage, tempException); throw tempException; } } else { if (thePassword == null || thePassword.length() == 0) { //input bad, only id provided String tempString = "ACELogonActionImpl.performAction(): Password required, only ID was provided.\n"; AEFException tempException = new AEFException(AEFConst.INVALID_ARGUMENT, AEFConst.PASSWORD_REQUIRED, tempString); tempAEFMessage.setMessage(tempString); log.error(tempAEFMessage, tempException); throw tempException; } } if (log.isTraceEnabled()) { tempAEFMessage.setMessage("-Exit constructor of ACELogonActionImpl."); log.trace(tempAEFMessage); } } /** * Perform the action represented by the ActionRequest and return an ActionResult. * * * @param request The ActionRequest which contains the classname and arguments. * @return Object The Operator instance. * @exception AEFException * Among the possible error codes are: * <br>AEFConst.INVALID_ARGUMENT, AEFConst.NEW_PASSWORD_PROHIBITED * <br>AEFConst.APPLICATION_NOT_IN_PROPER_STATE */ public Object performAction() throws AEFException { if (log.isTraceEnabled()) { tempAEFMessage.setMessage("+Enter ACELogonActionImpl.performAction()"); log.trace(tempAEFMessage); } // Call super to perform any common processing and clear any errors before we start. super.performAction(); if (theNewPassword != null && theNewPassword.length() > 0) { String tempString = "ACELogonActionImpl.performAction(): Change password function not implemented."; AEFException tempException = new AEFException(AEFConst.INVALID_ARGUMENT, AEFConst.NEW_PASSWORD_PROHIBITED, tempString); tempAEFMessage.setMessage(tempString); log.error(tempAEFMessage, tempException); throw tempException; } Object retVal = null; int seqResult = -1; String currentState = getCurrentState(); theDetector = ((DetectorAccess)(SessionContext.getSession())).getOperatorDetector(); theIdState = State.getState("ID"); thePasswordState = State.getState("PASSWORD"); theItemEntryState = State.getState("ITEMENTRY"); theSecuredSignoffState = State.getState("SECURED"); // Check if we are in a clear state. If so, clear the error. // The state could be B014 NO TRANSACTION RECOVERY. if (currentState.equals(State.getState("CLEAR"))) { sendClearSequence(true); currentState = getCurrentState(); } if (currentState.equals(theSecuredSignoffState)) { // An operator is already signed on. retVal = doSecuredSignon(); } //Check precondition that POS_STATE is "ID" state (2). If not, throw exception. else if (!currentState.equals(theIdState)) { // Not in valid state for signon. String tempString = "ACELogonActionImpl.performAction(): POS application not in proper state to perform logon.\n Expected state " + theIdState + ", but application is in state " + currentState + "."; AEFException tempException = new AEFException(AEFConst.APPLICATION_NOT_IN_PROPER_STATE, 0, tempString); tempAEFMessage.setMessage(tempString); log.error(tempAEFMessage, tempException); throw tempException; } else { // Application is in correct state to start the logon. seqResult = sendIDSequence(); if (seqResult==0) { // Successfully got to password state, send the password sequence. seqResult = sendPasswordSequence(); if (seqResult == 0 || seqResult == 1) { Operator operator = null; operator = waitForOperator(); retVal = operator; try { operator.getInfo().setPassword(thePassword); } catch (RemoteException re) { // Can't get here. } } } } if (log.isTraceEnabled()) { tempAEFMessage.setMessage("-Exit ACELogonActionImpl.performAction()"); log.trace(tempAEFMessage); } return retVal; } /** * Sends the key sequence for entering the operator id. * * * @return int 0 = success, * @exception AEFException */ public int sendIDSequence() throws AEFException { if (log.isTraceEnabled()) { tempAEFMessage.setMessage("+Enter ACELogonActionImpl.sendIDSequence()"); log.trace(tempAEFMessage); } int retVal = -1; args.clear(); args.put("%0", theId); args.put("SEQUENCE_ID", "id"); theKeySequenceAction = (AEFAction) (actionFactory.makeAction(new ActionRequest("SimpleKeySequenceAction", args))); Condition[] goodConditions = { new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_STATE, thePasswordState), }; theLock = new ConditionLock(); // Save any current operator instance number so we are sure to only get an operator // created after this key sequence is sent. theInstanceNumber = theDetector.getInstanceNumber(); retVal = theLock.performActionAndWait("wait-for-password-state", theKeySequenceAction, goodConditions, BadConditionsImpl.getInstance().getBadConditions(), getTimeout()); if (retVal < 0) { AEFErrorHandler errorHandler = new AEFErrorHandler("Send Signon ID Sequence Error"); retVal = errorHandler.handleError(theLock, theKeySequenceAction, goodConditions, BadConditionsImpl.getInstance().getBadConditions(), getTimeout(), retVal); } if (log.isDebugEnabled()) { log.debug( new AEFMessage( sessionID, "ACELogonActionImpl.sendIDSequence() returning : " + retVal)) ; } if (log.isTraceEnabled()) { tempAEFMessage.setMessage("-Exit ACELogonActionImpl.sendIDSequence()"); log.trace(tempAEFMessage); } return retVal; } /** * Sends the key sequence for entering the operator password. * * * @return int 0,1 = success * @exception AEFException */ public int sendPasswordSequence() throws AEFException { if (log.isTraceEnabled()) { tempAEFMessage.setMessage("+Enter ACELogonActionImpl.sendPasswordSequence()"); log.trace(tempAEFMessage); } int retVal = -1; // We have a password which we can use to attempt the secure mode signon. args.clear(); args.put("%0", thePassword); args.put("SEQUENCE_ID", "password"); theKeySequenceAction = (AEFAction) (actionFactory.makeAction(new ActionRequest("SimpleKeySequenceAction", args))); // State at full signon Condition andConds1[] = { new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_STATE, State.getState("MAIN")), new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_SUB_STATE, // Substate.getSubstate("EXPECTING_PROCEDURE")) Substate.getSubstate("SELECT_PROCEDURE")) }; // For special sign on which only requires a password Condition andConds2[] = { new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_STATE, State.getState("MAIN")), new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_SUB_STATE, Substate.getSubstate("EXPECTING_TENDER")) }; // For special sign on in training mode Condition andConds3[] = { new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_STATE, State.getState("MAIN")), new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_SUB_STATE, Substate.getSubstate("ITEM_TRAINING")) }; // For a special signon when we were in the middle of a transaction - go to sstate 1001 Condition andConds4[] = { new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_STATE, State.getState("MAIN")), new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_SUB_STATE, Substate.getSubstate("EXPECTING_ITEM")) }; Condition goodConditions[] = { new AndCondition(andConds1), new AndCondition(andConds2), new AndCondition(andConds3), new AndCondition(andConds4), new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_SUB_STATE, Substate.getSubstate("REPEAT_SIGNOFF")) }; if (theLock == null) { theLock = new ConditionLock(); } if (log.isDebugEnabled()) { log.debug( new AEFMessage( sessionID, "About to wait on the perform action for 'password'")); } if (perfTrace.isEnabled(AEFPerfTrace. COARSE)) { perfTrace.reportTimer(AEFPerfTrace. COARSE, sessionID, "logon", ">>>Sending logon password key sequence to application."); } retVal= theLock.performActionAndWait("wait-for-successful-signon", theKeySequenceAction, goodConditions, BadConditionsImpl.getInstance().getBadConditions(), getTimeout()); if (retVal < 0) { AEFErrorHandler errorHandler = new AEFErrorHandler("Send Signon Password Sequence Error"); retVal = errorHandler.handleError(theLock, theKeySequenceAction, goodConditions, BadConditionsImpl.getInstance().getBadConditions(), getTimeout(), retVal); } if (log.isDebugEnabled()) { log.debug( new AEFMessage( sessionID, "Condition returned was " + retVal)); } if (log.isTraceEnabled()) { tempAEFMessage.setMessage("-Exit ACELogonActionImpl.sendPasswordSequence()"); log.trace(tempAEFMessage); } return retVal; } /** * Blocks the calling thread until a new operator object is created. * * * @exception AEFException */ public Operator waitForOperator() throws AEFException { if (log.isTraceEnabled()) { tempAEFMessage.setMessage("+Enter ACELogonActionImpl.waitForOperator()"); log.trace(tempAEFMessage); } Operator retVal = null; // Successfully got to item entry. Wait for the operator object to be created. ObjectDetectorLock objLock = new ObjectDetectorLock(); retVal = (Operator)(objLock.waitForNewObject("wait-for-operator",theDetector, theInstanceNumber, getTimeout())); if (perfTrace.isEnabled(AEFPerfTrace. COARSE)) { perfTrace.reportTimer(AEFPerfTrace. COARSE, sessionID, "logon", "<<<Detected operator logon from application."); } if (log.isTraceEnabled()) { tempAEFMessage.setMessage("-Exit ACELogonActionImpl.waitForOperator()"); log.trace(tempAEFMessage); } return retVal; } /** * Performs the logic required to sign an operator on from secured mode. * * * @exception AEFException * Among the possible error codes are: * <br>AEFConst.PROCEDURE_NOT_ALLOWED, AEFConst.ANOTHER_OPERATOR_SIGNED_ON */ public Operator doSecuredSignon() throws AEFException { if (log.isTraceEnabled()) { tempAEFMessage.setMessage("+Enter ACELogonActionImpl.doSecuredSignon()"); log.trace(tempAEFMessage); } if (log.isDebugEnabled()) { log.debug( new AEFMessage( sessionID, "App in secured signoff state.")) ; } Operator operator = null; // Somebody is already signed on, check to see if the id of the new signon request // matches the id of the already signed on operator. try { operator = automationProvider.getOperator(); if (operator!=null && !operator.getInfo().getID().equals(theId)) { // Currently signed on operator is a different operator. String tempString = "ACELogonActionImpl.performAction(): Can't perform logon for operator " + theId + " because operator " + operator.getInfo().getID() + " is already signed on."; AEFException tempException = new AEFException(AEFConst.PROCEDURE_NOT_ALLOWED, AEFConst.ANOTHER_OPERATOR_SIGNED_ON, tempString); tempAEFMessage.setMessage(tempString); log.error(tempAEFMessage, tempException); throw tempException; } else if (operator != null) { // The requested operator is already signed on, but app is in secured // signoff mode, just need to send password sequence. // Use the password that was entered with the command. int seqResult = sendPasswordSequence(); if (seqResult == 0 || seqResult == 1) { operator = waitForOperator(); try { operator.getInfo().setPassword(thePassword); } catch (RemoteException re) { // Can't get here. } } } } catch (RemoteException re) { // Not expected to get here since we are calling locally. } if (log.isTraceEnabled()) { tempAEFMessage.setMessage("-Exit ACELogonActionImpl.doSecuredSignon()"); log.trace(tempAEFMessage); } return operator; } /* Instance Variables */ protected AEFAction theKeySequenceAction; protected String theId; protected String thePassword; protected String theNewPassword; protected ConditionLock theLock; protected ObjectDetector theDetector; protected int theInstanceNumber; protected String theIdState; protected String thePasswordState; protected String theItemEntryState; protected String theSecuredSignoffState; private static Log log = LogFactory.getLog(ACELogonActionImpl.class); }