use of org.openecard.gui.ResultStatus in project open-ecard by ecsec.
the class ExecutionEngine method process.
/**
* Processes the user consent associated with this instance. <br>
* The following algorithm is used to process the dialog.
* <ol>
* <li>Display the first step.</li>
* <li>Evaluate step result. Break execution on CANCEL.</li>
* <li>Execute step action. Break execution on CANCEL.</li>
* <li>Display either next previous or current step, or a replacement according to result.</li>
* <li>Proceed with point 2.</li>
* </ol>
*
* @return Overall result of the execution.
* @throws ThreadTerminateException Thrown in case the GUI has been closed externally (interrupted).
*/
public ResultStatus process() throws ThreadTerminateException {
// get first step
StepResult next = navigator.next();
// loop over steps. break inside loop
while (true) {
ResultStatus result = next.getStatus();
// close dialog on cancel and interrupt
if (result == ResultStatus.INTERRUPTED || Thread.currentThread().isInterrupted()) {
navigator.close();
throw new ThreadTerminateException("GUI has been interrupted.");
} else if (result == ResultStatus.CANCEL) {
navigator.close();
return result;
}
// get result and put it in resultmap
List<OutputInfoUnit> stepResults = next.getResults();
Map<String, ExecutionResults> oldResults = Collections.unmodifiableMap(results);
results.put(next.getStepID(), new ExecutionResults(next.getStepID(), stepResults));
// replace InfoInputUnit values in live list
if (!next.getStep().isResetOnLoad()) {
Step s = next.getStep();
List<InputInfoUnit> inputInfo = s.getInputInfoUnits();
Map<String, InputInfoUnit> infoMap = new HashMap<>();
// create index over infos
for (InputInfoUnit nextInfo : inputInfo) {
infoMap.put(nextInfo.getID(), nextInfo);
}
for (OutputInfoUnit nextOut : stepResults) {
InputInfoUnit matchingInfo = infoMap.get(nextOut.getID());
// an entry must exist, otherwise this is an error in the GUI implementation
// this type of error should be found in tests
matchingInfo.copyContentFrom(nextOut);
}
}
// replace step if told by result value
if (next.getReplacement() != null) {
switch(next.getStatus()) {
case BACK:
next = navigator.replacePrevious(next.getReplacement());
break;
case OK:
if (navigator.hasNext()) {
next = navigator.replaceNext(next.getReplacement());
} else {
navigator.close();
return convertStatus(StepActionResultStatus.NEXT);
}
break;
case RELOAD:
next = navigator.replaceCurrent(next.getReplacement());
break;
default:
// fallthrough because CANCEL and INTERRUPTED are already handled
break;
}
} else {
// step replacement did not happen, so we can execute the action
StepAction action = next.getStep().getAction();
StepActionCallable actionCallable = new StepActionCallable(action, oldResults, next);
// use separate thread or tasks running outside the JVM context, like PCSC calls, won't stop on cancellation
ExecutorService execService = Executors.newSingleThreadExecutor();
Future<StepActionResult> actionFuture = execService.submit(actionCallable);
navigator.setRunningAction(actionFuture);
StepActionResult actionResult;
try {
actionResult = actionFuture.get();
} catch (CancellationException ex) {
LOG.info("StepAction was canceled.", ex);
navigator.close();
return ResultStatus.CANCEL;
} catch (InterruptedException ex) {
LOG.info("StepAction was interrupted.", ex);
navigator.close();
throw new ThreadTerminateException("GUI has been interrupted.");
} catch (ExecutionException ex) {
// there are some special kinds we need to handle here
if (ex.getCause() instanceof InvocationTargetExceptionUnchecked) {
InvocationTargetExceptionUnchecked iex = (InvocationTargetExceptionUnchecked) ex.getCause();
if (iex.getCause() instanceof ThreadTerminateException) {
LOG.info("StepAction was interrupted.", ex);
navigator.close();
throw new ThreadTerminateException("GUI has been interrupted.");
}
}
// all other types
LOG.error("StepAction failed with error.", ex.getCause());
navigator.close();
return ResultStatus.CANCEL;
}
// break out if cancel was returned
if (actionResult.getStatus() == StepActionResultStatus.CANCEL) {
LOG.info("StepAction was canceled.");
navigator.close();
return ResultStatus.CANCEL;
}
// replace step if told by result value
if (actionResult.getReplacement() != null) {
switch(actionResult.getStatus()) {
case BACK:
next = navigator.replacePrevious(actionResult.getReplacement());
break;
case NEXT:
if (navigator.hasNext()) {
next = navigator.replaceNext(actionResult.getReplacement());
} else {
navigator.close();
return convertStatus(StepActionResultStatus.NEXT);
}
break;
case REPEAT:
next = navigator.replaceCurrent(actionResult.getReplacement());
break;
default:
// fallthrough because CANCEL is already handled
break;
}
} else {
// no replacement just proceed
switch(actionResult.getStatus()) {
case BACK:
next = navigator.previous();
break;
case NEXT:
if (navigator.hasNext()) {
next = navigator.next();
} else {
navigator.close();
return convertStatus(StepActionResultStatus.NEXT);
}
break;
case REPEAT:
next = navigator.current();
break;
default:
// fallthrough because CANCEL is already handled
break;
}
}
}
}
}
use of org.openecard.gui.ResultStatus in project open-ecard by ecsec.
the class TCTokenRequest method findCard.
/**
* Finds a card which matches one of the give types.
*
* @param types String array containing valid card types.
* @param disp Dispatcher used to query cards and terminals.
* @param gui User consent to display messages to the user.
* @return ConnectionHandleType object of the chosen card.
*/
private static ConnectionHandleType findCard(@Nonnull String[] types, @Nonnull Context ctx) throws MissingActivationParameterException, UserCancellationException {
CardRecognition rec = ctx.getRecognition();
Map<String, String> namesAndType = new HashMap<>();
for (String type : types) {
namesAndType.put(rec.getTranslatedCardName(type), type);
}
InsertCardDialog insCardDiag = new InsertCardDialog(ctx.getUserConsent(), ctx.getCardStates(), namesAndType, ctx.getEventDispatcher());
List<ConnectionHandleType> usableCards = insCardDiag.show();
if (usableCards == null) {
// user aborted the card insertion dialog
throw new UserCancellationException(null, LANG.translationForKey(CARD_INSERTION_ABORT));
}
ConnectionHandleType handle;
if (usableCards.size() > 1) {
UserConsentDescription ucd = new UserConsentDescription(LANG.translationForKey("card.selection.heading.uc", AppVersion.getName()));
String stepTitle = LANG.translationForKey("card.selection.heading.step");
CardSelectionStep step = new CardSelectionStep(stepTitle, usableCards, ctx.getRecognition());
ArrayList<String> types2 = new ArrayList<>();
types2.addAll(namesAndType.values());
CardMonitorTask task = new CardMonitorTask(types2, step);
ctx.getEventDispatcher().add(task, EventType.CARD_REMOVED, EventType.CARD_RECOGNIZED);
step.setBackgroundTask(task);
CardSelectionAction action = new CardSelectionAction(step, usableCards, types2, ctx);
step.setAction(action);
ucd.getSteps().add(step);
UserConsent uc = ctx.getUserConsent();
UserConsentNavigator ucNav = uc.obtainNavigator(ucd);
ExecutionEngine exec = new ExecutionEngine(ucNav);
ResultStatus resStatus = exec.process();
if (resStatus != ResultStatus.OK) {
throw new MissingActivationParameterException(CARD_SELECTION_ABORT);
}
handle = action.getResult();
ctx.getEventDispatcher().del(task);
} else {
handle = usableCards.get(0);
}
return handle;
}
Aggregations