/*
* 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:
*
AEFConst.CONFIG_ERROR, AEFConst.NO_DEFAULT_ID_CONFIGURED
*
AEFConst.INVALID_ARGUMENT, AEFConst.ID_REQUIRED
*
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:
*
AEFConst.INVALID_ARGUMENT, AEFConst.NEW_PASSWORD_PROHIBITED
*
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",
"<<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);
}