package jp.vmi.selenium.selenese.command; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import jp.vmi.selenium.selenese.Context; import jp.vmi.selenium.selenese.SeleneseCommandErrorException; import jp.vmi.selenium.selenese.inject.DoCommand; import jp.vmi.selenium.selenese.result.CommandResult; import jp.vmi.selenium.selenese.result.CommandResultList; import jp.vmi.selenium.selenese.result.Error; import jp.vmi.selenium.selenese.result.Result; /** * Command list. */ public class CommandList extends ArrayList<ICommand> { private static final long serialVersionUID = 1L; private final Map<Object, Integer> indexCache = new HashMap<>(); @Override public boolean add(ICommand command) { if (command instanceof ILabel) indexCache.put(((ILabel) command).getLabel(), size()); return super.add(command); } /** * Get index by label or command. * * @param key label string or ICommand object. * @return index or -1. */ @Override public int indexOf(Object key) { Integer index = indexCache.get(key); if (index == null) { index = super.indexOf(key); indexCache.put(key, index); } return index; } /** * Original list iterator. * * see {@link ArrayList#listIterator(int)} * * @param index start index. * @return ListIterator. */ protected ListIterator<ICommand> originalListIterator(int index) { return super.listIterator(index); } @Override public CommandListIterator iterator() { return iterator(null); } /** * Create the iterator of this command list. * * @param parentIterator parent iterator. * * @return iterator. */ public CommandListIterator iterator(CommandListIterator parentIterator) { return new CommandListIterator(this, parentIterator); } @DoCommand protected Result doCommand(Context context, ICommand command, String... curArgs) { try { if (context.isInteractive()) { System.out.println(">>> Press ENTER to continue <<<"); System.in.read(); } return command.execute(context, curArgs); } catch (SeleneseCommandErrorException e) { return e.getError(); } catch (Exception e) { return new Error(e); } } private static final Pattern JS_BLOCK_RE = Pattern.compile("javascript\\{(.*)\\}", Pattern.DOTALL); protected void evalCurArgs(Context context, String[] curArgs) { for (int i = 0; i < curArgs.length; i++) { Matcher matcher = JS_BLOCK_RE.matcher(curArgs[i]); if (matcher.matches()) { Object value = context.getEval().eval(context, matcher.group(1)); if (value == null) value = ""; curArgs[i] = value.toString(); } } } /** * Execute command list. * * @param context Selenese Runner context. * @param cresultList command result list for keeping all command results. * @return result of command list execution. */ public Result execute(Context context, CommandResultList cresultList) { CommandListIterator parentIterator = context.getCommandListIterator(); CommandListIterator commandListIterator = iterator(parentIterator); context.pushCommandListIterator(commandListIterator); CommandSequence sequence = commandListIterator.getCommandSequence(); boolean isContinued = true; try { while (isContinued && commandListIterator.hasNext()) { ICommand command = commandListIterator.next(); sequence.increment(command); List<Screenshot> ss = command.getScreenshots(); int prevSSIndex = (ss == null) ? 0 : ss.size(); String[] curArgs = context.getVarsMap().replaceVarsForArray(command.getArguments()); evalCurArgs(context, curArgs); Result result = doCommand(context, command, curArgs); if (result.isAborted()) isContinued = false; else context.waitSpeed(); ss = command.getScreenshots(); List<Screenshot> newSS; if (ss == null || prevSSIndex == ss.size()) newSS = null; else newSS = new ArrayList<>(ss.subList(prevSSIndex, ss.size())); CommandResult cresult = new CommandResult(sequence.toString(), command, newSS, result, cresultList.getEndTime(), System.currentTimeMillis()); cresultList.add(cresult); } } finally { context.popCommandListIterator(); } return cresultList.getResult(); } }