001package com.ganteater.ae.processor; 002 003import java.io.BufferedReader; 004import java.io.ByteArrayOutputStream; 005import java.io.File; 006import java.io.FileInputStream; 007import java.io.FileNotFoundException; 008import java.io.FileOutputStream; 009import java.io.FileReader; 010import java.io.IOException; 011import java.io.InputStream; 012import java.io.InputStreamReader; 013import java.io.OutputStream; 014import java.io.StringReader; 015import java.io.StringWriter; 016import java.io.UnsupportedEncodingException; 017import java.net.Inet4Address; 018import java.net.InetAddress; 019import java.net.NetworkInterface; 020import java.net.Socket; 021import java.net.SocketException; 022import java.net.SocketTimeoutException; 023import java.net.URL; 024import java.net.URLConnection; 025import java.net.UnknownHostException; 026import java.security.NoSuchAlgorithmException; 027import java.security.SecureRandom; 028import java.text.DateFormat; 029import java.text.ParsePosition; 030import java.text.SimpleDateFormat; 031import java.util.ArrayList; 032import java.util.Arrays; 033import java.util.Base64; 034import java.util.Calendar; 035import java.util.Collection; 036import java.util.Date; 037import java.util.Enumeration; 038import java.util.HashMap; 039import java.util.HashSet; 040import java.util.Iterator; 041import java.util.LinkedHashMap; 042import java.util.LinkedHashSet; 043import java.util.List; 044import java.util.Map; 045import java.util.Map.Entry; 046import java.util.Properties; 047import java.util.Random; 048import java.util.Set; 049import java.util.StringTokenizer; 050import java.util.TimeZone; 051import java.util.UUID; 052import java.util.concurrent.Executors; 053import java.util.concurrent.ThreadPoolExecutor; 054import java.util.concurrent.TimeUnit; 055import java.util.regex.Matcher; 056import java.util.regex.Pattern; 057import java.util.stream.Collectors; 058import java.util.stream.IntStream; 059 060import javax.swing.JOptionPane; 061import javax.xml.transform.Source; 062import javax.xml.transform.Transformer; 063import javax.xml.transform.TransformerFactory; 064import javax.xml.transform.stream.StreamResult; 065import javax.xml.transform.stream.StreamSource; 066 067import org.apache.commons.beanutils.ConvertUtils; 068import org.apache.commons.collections.CollectionUtils; 069import org.apache.commons.collections.MapUtils; 070import org.apache.commons.io.FileUtils; 071import org.apache.commons.io.IOUtils; 072import org.apache.commons.io.filefilter.TrueFileFilter; 073import org.apache.commons.jexl3.JexlBuilder; 074import org.apache.commons.jexl3.JexlContext; 075import org.apache.commons.jexl3.JexlEngine; 076import org.apache.commons.jexl3.JexlExpression; 077import org.apache.commons.jexl3.MapContext; 078import org.apache.commons.lang.ArrayUtils; 079import org.apache.commons.lang.BooleanUtils; 080import org.apache.commons.lang.ObjectUtils; 081import org.apache.commons.lang.StringEscapeUtils; 082import org.apache.commons.lang.StringUtils; 083import org.apache.commons.lang.math.NumberUtils; 084import org.apache.commons.lang3.SystemUtils; 085import org.apache.http.auth.AuthScope; 086import org.apache.http.auth.UsernamePasswordCredentials; 087import org.apache.http.client.CredentialsProvider; 088import org.apache.http.client.config.RequestConfig; 089import org.apache.http.client.methods.CloseableHttpResponse; 090import org.apache.http.client.methods.HttpGet; 091import org.apache.http.client.methods.HttpPost; 092import org.apache.http.client.methods.HttpRequestBase; 093import org.apache.http.client.protocol.HttpClientContext; 094import org.apache.http.client.utils.URLEncodedUtils; 095import org.apache.http.entity.ByteArrayEntity; 096import org.apache.http.impl.client.BasicCredentialsProvider; 097import org.apache.http.impl.client.CloseableHttpClient; 098import org.apache.http.impl.client.HttpClients; 099import org.apache.sling.commons.json.JSONArray; 100import org.apache.sling.commons.json.JSONException; 101import org.apache.sling.commons.json.JSONObject; 102 103import com.ganteater.ae.AEManager; 104import com.ganteater.ae.AEWorkspace; 105import com.ganteater.ae.ChoiceTaskRunner; 106import com.ganteater.ae.CommandException; 107import com.ganteater.ae.ILogger; 108import com.ganteater.ae.MultiTaskRunDialog; 109import com.ganteater.ae.OperationHolder; 110import com.ganteater.ae.RecipeListener; 111import com.ganteater.ae.RecipeRunner; 112import com.ganteater.ae.TaskCancelingException; 113import com.ganteater.ae.processor.annotation.CommandDescription; 114import com.ganteater.ae.processor.annotation.CommandExamples; 115import com.ganteater.ae.util.AEUtils; 116import com.ganteater.ae.util.AssertionFailedError; 117import com.ganteater.ae.util.NameValuePairImplementation; 118import com.ganteater.ae.util.TestCase; 119import com.ganteater.ae.util.xml.easyparser.EasyParser; 120import com.ganteater.ae.util.xml.easyparser.EasyUtils; 121import com.ganteater.ae.util.xml.easyparser.Node; 122import com.opencsv.CSVReader; 123 124import okhttp3.MediaType; 125import okhttp3.OkHttpClient; 126import okhttp3.Request.Builder; 127import okhttp3.Response; 128 129public class BaseProcessor extends Processor { 130 131 private Random random; 132 133 protected BaseProcessor() { 134 } 135 136 public BaseProcessor(Processor parent) throws CommandException { 137 init(parent); 138 } 139 140 public BaseProcessor(AEManager manager, ILogger log, File baseDir) { 141 super(manager, log, baseDir); 142 } 143 144 public BaseProcessor(Map<String, Object> hashMap, Node node, File baseDir) { 145 super(hashMap, node, baseDir); 146 } 147 148 public BaseProcessor(Node configNode, Map<String, Object> startVariables, RecipeListener listener, File startDir, 149 ILogger aLog, Processor parent) throws CommandException { 150 super(configNode, startVariables, listener, startDir, aLog, parent); 151 } 152 153 @CommandExamples({ "<Regexp name='type:property' source='type:property' regex='type:string' />" }) 154 public void runCommandRegexp(final Node aCurrentAction) throws Throwable { 155 final String theName = replaceProperties(aCurrentAction.getAttribute("name")); 156 final String source = replaceProperties(aCurrentAction.getAttribute("source")); 157 String variableValue = (String) getVariableValue(source); 158 159 String theText = null; 160 String regex = replaceProperties(aCurrentAction.getAttribute("regex")); 161 Pattern pattern = Pattern.compile(regex); 162 Matcher matcher = pattern.matcher(variableValue); 163 if (matcher.find()) { 164 theText = matcher.group(1); 165 } 166 167 setVariableValue(theName, theText); 168 } 169 170 @CommandExamples({ "<Replace name='type:property' oldChar='type:integer' newChar='type:integer'/>", 171 "<Replace name='type:property' regex='' replacement=''/>", 172 "<Replace name='type:property' unescape='enum:java|csv|html|javascript|xml' />", 173 "<Replace name='type:property' escape='enum:java|csv|html|javascript|xml|sql' />" }) 174 public void runCommandReplace(final Node command) throws Throwable { 175 String name = replaceProperties(command.getAttribute("name")); 176 177 Object variableValue = getVariableValue(name); 178 String value = null; 179 if (variableValue instanceof String) { 180 value = (String) variableValue; 181 } else if (variableValue instanceof byte[]) { 182 value = new String((byte[]) variableValue); 183 } else { 184 value = ObjectUtils.toString(variableValue); 185 } 186 value = replaceProperties(value); 187 188 final String theOldChar = replaceProperties(command.getAttribute("oldChar")); 189 final String theNewChar = replaceProperties(command.getAttribute("newChar")); 190 if (theOldChar != null) { 191 value = value.replace(theOldChar, theNewChar); 192 } 193 194 final String regex = replaceProperties(command.getAttribute("regex")); 195 final String replacement = replaceProperties(command.getAttribute("replacement")); 196 if (regex != null && value != null) { 197 value = value.replaceAll(regex, replacement); 198 } 199 200 String unescape = attr(command, "unescape"); 201 if (unescape != null) { 202 unescape = unescape.toLowerCase(); 203 switch (unescape) { 204 case "csv": { 205 value = StringEscapeUtils.unescapeCsv(value); 206 break; 207 } 208 case "html": { 209 value = StringEscapeUtils.unescapeHtml(value); 210 break; 211 } 212 case "java": { 213 value = StringEscapeUtils.unescapeJava(value); 214 break; 215 } 216 case "javascript": { 217 value = StringEscapeUtils.unescapeJavaScript(value); 218 break; 219 } 220 case "xml": { 221 value = StringEscapeUtils.unescapeXml(value); 222 break; 223 } 224 } 225 } 226 227 String escape = attr(command, "escape"); 228 if (escape != null) { 229 escape = escape.toLowerCase(); 230 switch (escape) { 231 case "csv": { 232 value = StringEscapeUtils.escapeCsv(value); 233 break; 234 } 235 case "html": { 236 value = StringEscapeUtils.escapeHtml(value); 237 break; 238 } 239 case "java": { 240 value = StringEscapeUtils.escapeJava(value); 241 break; 242 } 243 case "javascript": { 244 value = StringEscapeUtils.escapeJavaScript(value); 245 break; 246 } 247 case "sql": { 248 value = StringEscapeUtils.escapeSql(value); 249 break; 250 } 251 case "xml": { 252 value = StringEscapeUtils.escapeXml(value); 253 break; 254 } 255 } 256 } 257 258 setVariableValue(name, value); 259 } 260 261 @CommandExamples({ 262 "<CheckValue actual='type:string' expected='type:string' mode='enum:normal|trimLines' condition='enum:unequal|equal' onErrorMsg='type:string'/>", 263 "<CheckValue value='type:string' regex='type:string' onErrorMsg='type:string'/>" }) 264 public void runCommandCheckValue(final Node aCurrentAction) throws Throwable { 265 266 final String theErrorMsg = replaceProperties(aCurrentAction.getAttribute("onErrorMsg")); 267 268 final String theRegex = replaceProperties(aCurrentAction.getAttribute("regex")); 269 270 if (theRegex == null) { 271 final boolean theTrimLines = "trimLines".equals(replaceProperties(aCurrentAction.getAttribute("mode"))); 272 try { 273 String actual = replaceProperties(aCurrentAction.getAttribute("actual")); 274 String expected = replaceProperties(aCurrentAction.getAttribute("expected")); 275 if (theTrimLines) { 276 actual = getTrimmedLines(actual); 277 expected = getTrimmedLines(expected); 278 } 279 280 final boolean unequal = "unequal".equals(replaceProperties(aCurrentAction.getAttribute("condition"))); 281 if (unequal) { 282 boolean equals = StringUtils.equals(expected, actual); 283 TestCase.assertFalse(theErrorMsg, equals); 284 } else { 285 TestCase.assertEquals(theErrorMsg, expected, actual); 286 } 287 } catch (final Throwable e) { 288 taskNode(aCurrentAction, false); 289 throw e; 290 } 291 } else { 292 final String theValue = replaceProperties(aCurrentAction.getAttribute("value")); 293 final Pattern p = Pattern.compile(theRegex); 294 final Matcher m = p.matcher(theValue); 295 if (m.find() == false) { 296 taskNode(aCurrentAction, false); 297 TestCase.fail("Regex validation failed. Regex:" + theRegex + ", value:" + theValue); 298 } 299 } 300 301 } 302 303 @CommandExamples({ "<CheckNotNull name='type:property' onErrorMsg='type:string'/>" }) 304 public void runCommandCheckNotNull(final Node aCurrentAction) throws Throwable { 305 final String theName = replaceProperties(aCurrentAction.getAttribute("name")); 306 final String theErrorMsg = replaceProperties(aCurrentAction.getAttribute("onErrorMsg")); 307 Object theValue = getVariableValue(theName); 308 if (theValue != null && theValue instanceof String[] && ((String[]) theValue).length == 0) { 309 theValue = null; 310 } 311 try { 312 TestCase.assertNotNull(theErrorMsg, theValue); 313 } catch (final Throwable e) { 314 taskNode(aCurrentAction, false); 315 throw e; 316 } 317 } 318 319 @CommandExamples({ "<Choice name='type:property'>" + "<Task name='type:string'>...</Task></Choice>", 320 "<Choice name='type:property' mode='enum:default|table'>" + "<Task name='type:string'>...</Task></Choice>", 321 "<Choice name='type:property' mode='enum:default|table' type='setup'>" 322 + "<Task name='type:string'/></Choice>", 323 "<Choice name='type:property' mode='enum:default|table' type='call-task'>" 324 + "<Task name='type:task'/></Choice>", 325 "<Choice name='type:property'><Task name='type:string'>...</Task><Started>...</Started></Choice>", 326 "<Choice name='type:property' runAllTaskName='type:string' mode='enum:default|table' type='enum:default|call-task'>" 327 + "<Task name='type:string'>...</Task><Started>...</Started></Choice>" }) 328 public void runCommandChoice(final Node aCurrentAction) throws Throwable { 329 330 final String nameOfChoice = replaceProperties(aCurrentAction.getAttribute("name")); 331 Object preset = getVariableValue(nameOfChoice); 332 333 String description = replaceProperties(aCurrentAction.getAttribute("description")); 334 335 final String theRunAllTaskName = replaceProperties(aCurrentAction.getAttribute("runAllTaskName")); 336 String type = replaceProperties(aCurrentAction.getAttribute("type")); 337 final boolean callType = "call-task".equals(type); 338 339 final Map<String, Node> tablesNodes = new LinkedHashMap<>(); 340 341 final String theMode = replaceProperties(aCurrentAction.getAttribute("mode")); 342 343 final Node[] taskNodes = aCurrentAction.getNodes("Task"); 344 for (int i = 0; i < taskNodes.length; i++) { 345 final String name = replaceProperties(taskNodes[i].getAttribute("name")); 346 347 if ("table".equals(theMode) && name != null && name.equals(theRunAllTaskName)) { 348 continue; 349 } 350 351 if (!callType || getListener().getManager().getTestPath(name) != null) { 352 tablesNodes.put(name, taskNodes[i]); 353 } 354 } 355 356 final String[] names = tablesNodes.keySet().toArray(new String[tablesNodes.size()]); 357 358 debug("Task list: " + nameOfChoice); 359 360 final List<String> activeNodes = new ArrayList<>(); 361 362 if ("table".equals(theMode) || "hidden".equals(theMode)) { 363 364 final String exceptionIgnore = replaceProperties(aCurrentAction.getAttribute("exception")); 365 boolean startsWith = false; 366 if (exceptionIgnore != null) { 367 startsWith = exceptionIgnore.startsWith("ignore"); 368 } 369 370 ChoiceTaskRunner choiceRunner = new ChoiceTaskRunner(nameOfChoice, preset == null); 371 boolean visible = !"hidden".equals(theMode); 372 final MultiTaskRunDialog inputSelectChoice = this.recipeListener.getManager().tasksChoice(choiceRunner, 373 names, startsWith, preset, this, visible); 374 375 try { 376 final Iterator<String> selectedTasks = inputSelectChoice.getSelectedTasks(); 377 378 List<String> selectedTaskNames = new ArrayList<>(); 379 while (selectedTasks.hasNext()) { 380 String selectedTask = selectedTasks.next(); 381 activeNodes.add(selectedTask); 382 383 selectedTaskNames.add(selectedTask); 384 inputSelectChoice.begin(selectedTask); 385 386 try { 387 Node action = tablesNodes.get(selectedTask); 388 startCommandInformation(action); 389 390 if (callType) { 391 runCommandTask(action); 392 } else { 393 taskNode(action, false); 394 } 395 inputSelectChoice.end(selectedTask, true); 396 397 } catch (final Throwable e) { 398 inputSelectChoice.end(selectedTask, false); 399 if (inputSelectChoice.isExceptionIgnore() == false) { 400 throw e; 401 } 402 } 403 } 404 405 if ("setup".equals(type)) { 406 setVariableValue(nameOfChoice, selectedTaskNames.toArray(new String[selectedTaskNames.size()])); 407 } 408 } finally { 409 inputSelectChoice.done(); 410 if (inputSelectChoice.isStarted()) { 411 Node[] nodes = aCurrentAction.getNodes("Started"); 412 for (Node node : nodes) { 413 taskNode(node); 414 } 415 } 416 } 417 418 } else { 419 if (this.recipeListener.getManager() != null) { 420 boolean notifyMe = this.recipeListener.isNotifyMe(); 421 description = StringUtils.defaultString(description, nameOfChoice); 422 final String inputSelectChoice = this.recipeListener.getManager().inputChoice(nameOfChoice, description, 423 names, ObjectUtils.toString(preset, null), this, notifyMe); 424 if (inputSelectChoice != null) { 425 activeNodes.add(inputSelectChoice); 426 } 427 } 428 429 debug("Select task: " + (activeNodes != null ? activeNodes : "<not chosen>")); 430 431 if (!activeNodes.isEmpty()) { 432 if (activeNodes.get(0).equals(theRunAllTaskName) == false) { 433 434 if (callType) { 435 runCommandTask(tablesNodes.get(activeNodes.get(0))); 436 } else { 437 taskNode(tablesNodes.get(activeNodes.get(0))); 438 } 439 440 } else { 441 for (int i = 0; i < names.length; i++) { 442 final String theActiveNode = names[i]; 443 if (theActiveNode.equals(theRunAllTaskName) == false) { 444 if (callType) { 445 runCommandTask(tablesNodes.get(theActiveNode)); 446 } else { 447 taskNode(tablesNodes.get(theActiveNode)); 448 } 449 } 450 } 451 } 452 } 453 } 454 455 setVariableValue(nameOfChoice, activeNodes); 456 } 457 458 @CommandExamples({ "<Runnable name='type:property' threadLog='type:boolean'>...</Runnable>" }) 459 public void runCommandRunnable(final Node aCurrentAction) throws CommandException { 460 final String theName = replaceProperties(aCurrentAction.getAttribute("name")); 461 String theNameThreads = getTestName(aCurrentAction); 462 if (theNameThreads == null) { 463 theNameThreads = "Thread"; 464 } 465 466 boolean threadLog = Boolean.valueOf(StringUtils.defaultIfBlank(attr(aCurrentAction, "threadLog"), "false")); 467 ILogger theLog = this.log; 468 if (threadLog) { 469 theLog = this.recipeListener.createLog(theNameThreads, false); 470 } 471 472 Node task = new Node("Task"); 473 task.setAttribute("description", aCurrentAction.getAttribute("name")); 474 task.addAll(aCurrentAction); 475 final TaskProcessorThread runnable = new TaskProcessorThread(this, task, getBaseDir(), theLog); 476 setVariableValue(theName, runnable); 477 } 478 479 @CommandExamples({ "<Sort name='type:property' type='enum:natural|random' />" }) 480 public void runCommandSort(final Node aCurrentAction) { 481 final String theName = replaceProperties(aCurrentAction.getAttribute("name")); 482 String theType = replaceProperties(aCurrentAction.getAttribute("type")); 483 if (theType == null) { 484 theType = "natural"; 485 } 486 487 final Object theObject = getVariableValue(theName); 488 if (theObject instanceof String[]) { 489 String[] theArray = (String[]) theObject; 490 if ("natural".equals(theType)) { 491 Arrays.sort(theArray); 492 } else if ("random".equals(theType)) { 493 theArray = randomSort(theArray); 494 } else { 495 throw new IllegalArgumentException("Sort type should be following value: natural, random."); 496 } 497 setVariableValue(theName, theArray); 498 } 499 } 500 501 @CommandExamples({ "<CheckInArray value='type:string' array='type:property' onErrorMsg='type:string'/>" }) 502 public void runCommandCheckInArray(final Node aCurrentAction) throws Throwable { 503 final String theValue = replaceProperties(aCurrentAction.getAttribute("value")); 504 final String theArrayName = replaceProperties(aCurrentAction.getAttribute("array")); 505 final String theErrorMsg = replaceProperties(aCurrentAction.getAttribute("onErrorMsg")); 506 final Object theObject = getVariableValue(theArrayName); 507 if (theObject != null && theObject instanceof String[]) { 508 final String[] theValues = (String[]) theObject; 509 Arrays.sort(theValues); 510 try { 511 TestCase.assertTrue(theErrorMsg, Arrays.binarySearch(theValues, theValue) >= 0); 512 } catch (final Throwable e) { 513 taskNode(aCurrentAction, false); 514 throw e; 515 } 516 } 517 } 518 519 @CommandExamples({ "<Tokenizer name='type:property' delim='type:string'/>" }) 520 public void runCommandTokenizer(final Node aCurrentVar) { 521 final String theAttribut = aCurrentVar.getAttribute("name"); 522 String theDelimAttribut = aCurrentVar.getAttribute("delim"); 523 if (theDelimAttribut == null) { 524 theDelimAttribut = ";"; 525 } 526 final Object theObjectValue = getVariableValue(theAttribut); 527 if (theObjectValue == null) { 528 return; 529 } 530 String theLine = null; 531 if (theObjectValue instanceof String) { 532 theLine = (String) getVariableValue(theAttribut); 533 } else if (theObjectValue instanceof String[] && ((String[]) getVariableValue(theAttribut)).length == 1) { 534 theLine = ((String[]) getVariableValue(theAttribut))[0]; 535 } 536 final ArrayList<String> theArrayList = new ArrayList<String>(); 537 if (theLine != null) { 538 final StringTokenizer theStringTokenizer = new StringTokenizer(theLine, theDelimAttribut); 539 while (theStringTokenizer.hasMoreTokens()) { 540 theArrayList.add(theStringTokenizer.nextToken()); 541 } 542 final String[] theArray = new String[theArrayList.size()]; 543 for (int i = 0; i < theArrayList.size(); i++) { 544 if (isStopped()) { 545 break; 546 } 547 theArray[i] = theArrayList.get(i); 548 } 549 setVariableValue(theAttribut, theArray); 550 } else { 551 debug("Tokenized empty string is ignored."); 552 } 553 } 554 555 @CommandExamples({ "<Date name='type:string' format='type:string' />", 556 "<Date name='type:string' format='type:string' source='type:property' sformat='type:string' />", 557 "<Date name='type:string' format='type:string' shift='1s|1m|1h|1M|1Y' />" }) 558 public void runCommandDate(final Node aCurrentAction) throws Throwable { 559 final String name = replaceProperties(aCurrentAction.getAttribute("name")); 560 String value = replaceProperties(aCurrentAction.getAttribute("value")); 561 if (value == null) { 562 String source = aCurrentAction.getAttribute("source"); 563 if (source != null) { 564 value = (String) getVariableValue(replaceProperties(source)); 565 } 566 } 567 568 if (value == null) { 569 Object variableValue = getVariableValue(name); 570 if (variableValue != null) { 571 value = ObjectUtils.toString(variableValue); 572 } 573 } 574 575 String format = replaceProperties(aCurrentAction.getAttribute("format")); 576 String sformat = StringUtils.defaultString(replaceProperties(aCurrentAction.getAttribute("sformat")), format); 577 578 SimpleDateFormat dateFor = null; 579 if (sformat != null && !"ms".equals(sformat)) { 580 dateFor = new SimpleDateFormat(sformat); 581 dateFor.setTimeZone(TimeZone.getTimeZone("UTC")); 582 } 583 String stringDate = null; 584 if (value == null) { 585 if (dateFor != null) { 586 stringDate = dateFor.format(new Date()); 587 } else { 588 stringDate = Long.toString(new Date().getTime()); 589 } 590 value = stringDate; 591 } 592 593 final String shift = replaceProperties(StringUtils.trim(aCurrentAction.getAttribute("shift"))); 594 595 Date date; 596 if (dateFor != null) { 597 date = dateFor.parse(value); 598 } else { 599 date = new Date(Long.parseLong(value)); 600 } 601 602 if (shift != null) { 603 Calendar c = Calendar.getInstance(); 604 c.setTime(date); 605 String substring = StringUtils.substring(shift, 0, shift.length() - 1); 606 int shiftValue = Integer.parseInt(substring); 607 switch (shift.charAt(shift.length() - 1)) { 608 case 's': 609 c.add(Calendar.SECOND, shiftValue); 610 break; 611 case 'm': 612 c.add(Calendar.MINUTE, shiftValue); 613 break; 614 case 'h': 615 c.add(Calendar.HOUR, shiftValue); 616 break; 617 case 'd': 618 c.add(Calendar.DAY_OF_MONTH, shiftValue); 619 break; 620 case 'w': 621 c.add(Calendar.WEEK_OF_MONTH, shiftValue); 622 break; 623 case 'M': 624 c.add(Calendar.MONTH, shiftValue); 625 break; 626 case 'Y': 627 c.add(Calendar.YEAR, shiftValue); 628 break; 629 } 630 631 date = c.getTime(); 632 } 633 634 if (format != null && !"ms".equals(format)) { 635 dateFor = new SimpleDateFormat(format); 636 dateFor.setTimeZone(TimeZone.getTimeZone("UTC")); 637 stringDate = dateFor.format(date); 638 } else { 639 stringDate = Long.toString(date.getTime()); 640 } 641 642 setVariableValue(name, stringDate); 643 } 644 645 @CommandExamples({ "<Wait delay='type:integer'/>", "<Wait/>" }) 646 public void runCommandWait(final Node aCurrentAction) { 647 final String theValue = replaceProperties(aCurrentAction.getAttribute("delay")); 648 if (theValue != null) { 649 wait(theValue); 650 } else { 651 pause(); 652 } 653 } 654 655 @CommandExamples({ 656 "<View id='type:string' reuse='type:boolean' type='Text'/><Out id='type:string' level='debug'/>", 657 "<View id='type:string' reuse='type:boolean' type='HTML'/><Out id='type:string' level='debug'/>", 658 "<View id='type:string' reuse='type:boolean' type='XYLineChart' title='type:string' xAxisLabel='type:string' yAxisLabel='type:string'/><Out id='type:string' series='type:string' x='type:integer' level='debug'>...</Out>", 659 "<View id='type:string' reuse='type:boolean' type='BarChart' title='type:string' xAxisLabel='type:string' yAxisLabel='type:string'/><Out id='type:string' row='type:string' column='type:string' level='debug'>...</Out>", 660 "<View id='type:string' reuse='type:boolean' type='PieChart' title='type:string' /><Out id='type:string' key='type:string' level='debug'/>", 661 "<View id='type:string' reuse='type:boolean' type='DialScale' title='type:string' label='type:string' lower='type:double' upper='type:double' increment='type:double' count='type:integer'/><Out id='type:string' level='debug'/>" }) 662 public void runCommandView(final Node aCurrentAction) throws Throwable { 663 this.recipeListener.runCommandView(replaceAttributes(aCurrentAction)); 664 } 665 666 @CommandExamples({ "<Formater name='type:property' type='enum:xml|http-get-request'/>" }) 667 public void runCommandFormater(final Node aCurrentAction) throws Throwable { 668 final String theNameAttribut = replaceProperties(aCurrentAction.getAttribute("name")); 669 final String theTypeAttribut = replaceProperties(aCurrentAction.getAttribute("type")); 670 Object theValue = getVariableValue(theNameAttribut); 671 if (theValue instanceof String) { 672 if ("json".equals(theTypeAttribut)) { 673 theValue = AEUtils.format(ObjectUtils.toString(theValue)); 674 } else { 675 theValue = new String[] { (String) theValue }; 676 } 677 678 setVariableValue(theNameAttribut, theValue); 679 } 680 if (theValue instanceof String[]) { 681 final String[] theValueArray = (String[]) theValue; 682 for (int i = 0; i < theValueArray.length; i++) { 683 if (isStopped()) { 684 break; 685 } 686 if ("xml".equals(theTypeAttribut)) { 687 final EasyParser theParser = new EasyParser(); 688 String theCurrentValue = theValueArray[i]; 689 theCurrentValue = prepareXml(theCurrentValue); 690 final Node object = theParser.getObject(theCurrentValue); 691 theValueArray[i] = object.getXMLText(); 692 } 693 } 694 if (theValueArray.length > 2) { 695 setVariableValue(theNameAttribut, theValueArray); 696 } else if (theValueArray.length == 1) { 697 setVariableValue(theNameAttribut, theValueArray[0]); 698 } else { 699 setVariableValue(theNameAttribut, null); 700 } 701 } 702 } 703 704 @CommandExamples({ "<Trim name='type:property'/>" }) 705 public void runCommandTrim(final Node aCurrentAction) throws Throwable { 706 String name = replaceProperties(aCurrentAction.getAttribute("name")); 707 Object value = getVariableValue(name); 708 if (value instanceof String) { 709 value = StringUtils.trimToNull(ObjectUtils.toString(value)); 710 } else if (value instanceof String[]) { 711 String[] array = (String[]) value; 712 if (array.length == 0) { 713 value = null; 714 } else { 715 List<String> list = new ArrayList<>(); 716 for (String object : array) { 717 String val = ObjectUtils.toString(object); 718 if (StringUtils.isNotBlank(val)) { 719 list.add(object); 720 } 721 } 722 value = list.toArray(new String[list.size()]); 723 } 724 } else if (value instanceof List) { 725 @SuppressWarnings("unchecked") 726 List<String> array = (List<String>) value; 727 if (array.size() == 0) { 728 value = null; 729 } else { 730 List<String> list = new ArrayList<>(); 731 for (String object : array) { 732 String val = ObjectUtils.toString(object); 733 if (StringUtils.isNotBlank(val)) { 734 list.add(object); 735 } 736 } 737 value = list.toArray(new String[list.size()]); 738 } 739 } 740 applyResult(aCurrentAction, name, value); 741 } 742 743 @CommandExamples({ "<Xslt name='type:property' xml='type:string' xsl='type:string'/>" }) 744 public void runCommandXslt(final Node aCurrentAction) throws Throwable { 745 final String theNameAttribut = replaceProperties(aCurrentAction.getAttribute("name")); 746 final String theXmlAttribut = replaceProperties(aCurrentAction.getAttribute("xml")); 747 final String theXslAttribut = replaceProperties(aCurrentAction.getAttribute("xsl")); 748 final StringWriter theStringWriter = new StringWriter(); 749 750 if (theXmlAttribut == null || theXmlAttribut.trim().length() == 0 || "null".equals(theXmlAttribut)) { 751 debug("Xml document is empty, transform disable."); 752 return; 753 } 754 755 if (theXslAttribut == null || theXslAttribut.trim().length() == 0 || "null".equals(theXslAttribut)) { 756 debug("Xsl document is empty, transform disable."); 757 return; 758 } 759 760 try { 761 final Source xslSource = new StreamSource(new StringReader(theXslAttribut)); 762 final Transformer transformer = TransformerFactory.newInstance().newTransformer(xslSource); 763 final Source xmlSource = new StreamSource(new StringReader(theXmlAttribut)); 764 765 transformer.transform(xmlSource, new StreamResult(theStringWriter)); 766 767 } catch (final Throwable e) { 768 debug("XML Data to transformation:\n" + theXmlAttribut); 769 debug("XSL:\n" + theXslAttribut); 770 this.log.error("Xsl transformation is failed.", e); 771 throw e; 772 } 773 774 setVariableValue(theNameAttribut, theStringWriter.toString()); 775 } 776 777 @CommandExamples({ "Output a property by name: <Out name='type:property' />", 778 "Output with a type: <Out name='type:property' type='enum:txt|html|xml|json|~json|url|path|uri|csv'/>", 779 "Outputs the value of the specified view id: <Out id='type:string'/>", 780 "Outputs a property value with a specified log level: <Out name='type:property' level='enum:info|debug|warn|error'/>", 781 "Outputs a property value with a message at a specified log level: <Out name='type:property' level='enum:info|debug|warn|error'> ... </Out>", 782 "Outputs a property value at specified log level: <Out level='enum:info|debug|warn|error'>... $var{...}</Out>", 783 "Writes output to a file with options to append content and specify encoding: <Out file='type:path' append='enum:true|false' encoding='UTF-8'/>" }) 784 public void runCommandOut(final Node command) throws UnsupportedEncodingException, IOException { 785 final String name = replaceProperties(command.getAttribute("name")); 786 final String description = replaceProperties(command.getAttribute("description")); 787 String theOutFileNameAttribut = replaceProperties(command.getAttribute("file")); 788 789 String logLevel = command.getAttribute("level"); 790 logLevel = replaceProperties(logLevel); 791 792 if (logLevel == null) { 793 logLevel = StringUtils.defaultIfBlank(getVariableString(DEFAULT_LOG_LEVEL_NAME), "info"); 794 } 795 796 String type = replaceProperties(command.getAttribute("type")); 797 798 FileOutputStream theFileOutputStream = null; 799 try { 800 if (theOutFileNameAttribut != null) { 801 String theAppendAttribut = replaceProperties(command.getAttribute("append")); 802 if (theAppendAttribut == null) { 803 theAppendAttribut = "true"; 804 } 805 theOutFileNameAttribut = replaceProperties(theOutFileNameAttribut); 806 final File file = getFile(theOutFileNameAttribut); 807 file.getParentFile().mkdirs(); 808 theFileOutputStream = new FileOutputStream(file, "true".equals(theAppendAttribut)); 809 } 810 String theEncoding = replaceProperties(command.getAttribute("encoding")); 811 if (theEncoding == null) { 812 theEncoding = "UTF-8"; 813 } 814 815 String theTextOut = null; 816 String varName = name; 817 final Node[] nodes = command.getTextNodes(); 818 819 if (nodes.length > 0) { 820 Node node = nodes[0]; 821 theTextOut = replaceProperties(node.getText()); 822 } else if (command.size() > 0) { 823 String innerXMLText = command.getInnerXMLText(); 824 Node node = new EasyParser().getObject(innerXMLText); 825 EasyUtils.removeTagId(node); 826 theTextOut = replaceProperties(node.toString()); 827 } 828 829 if (theTextOut != null) { 830 if (name != null) { 831 varName = theTextOut + ": " + varName; 832 } 833 if (theFileOutputStream != null) { 834 theFileOutputStream.write(theTextOut.getBytes(theEncoding)); 835 } 836 837 Properties attributes = replaceAttributes(command); 838 this.recipeListener.outToFrame(this, attributes, theTextOut); 839 } 840 841 if (name != null) { 842 Object theValue = getVariableValue(name); 843 844 if (theValue instanceof byte[]) { 845 if (theFileOutputStream != null) { 846 final byte[] value = (byte[]) theValue; 847 theFileOutputStream.write(value); 848 theFileOutputStream.close(); 849 return; 850 } else { 851 outputLog(StringUtils.defaultIfEmpty(description, varName), logLevel, theValue, type); 852 return; 853 } 854 } 855 856 if (theValue == null) { 857 outputLog(StringUtils.defaultIfEmpty(description, varName), logLevel, null, type); 858 859 } else if (theValue instanceof String) { 860 if (theFileOutputStream == null) { 861 outputLog(StringUtils.defaultIfEmpty(description, varName), logLevel, theValue.toString(), 862 type); 863 } else { 864 theFileOutputStream.write(theValue.toString().getBytes(theEncoding)); 865 } 866 867 this.recipeListener.outToFrame(this, replaceAttributes(command), theValue); 868 869 } else if (theValue instanceof String[]) { 870 final StringBuffer theBuffer = new StringBuffer(); 871 872 final String[] theValueArray = (String[]) theValue; 873 for (int i = 0; i < theValueArray.length; i++) { 874 if (isStopped()) { 875 break; 876 } 877 878 if (theBuffer.length() > 0) { 879 theBuffer.append("\n"); 880 } 881 theBuffer.append(theValueArray[i]); 882 883 Properties params = replaceAttributes(command); 884 String msg = theValueArray[i]; 885 this.recipeListener.outToFrame(this, params, msg); 886 } 887 if (theFileOutputStream == null) { 888 outputLog(StringUtils.defaultIfEmpty(description, varName), logLevel, theBuffer.toString(), 889 type); 890 } else { 891 theFileOutputStream.write(theBuffer.toString().getBytes(theEncoding)); 892 } 893 } else { 894 outputLog(StringUtils.defaultIfEmpty(description, varName), logLevel, theValue, type); 895 this.recipeListener.outToFrame(this, replaceAttributes(command), theValue); 896 } 897 } else { 898 outputLog(StringUtils.defaultIfEmpty(description, varName), logLevel, theTextOut, type); 899 } 900 } finally { 901 if (theFileOutputStream != null) { 902 theFileOutputStream.flush(); 903 theFileOutputStream.close(); 904 } 905 } 906 } 907 908 @CommandDescription("The <About> information tag is used to display details about the recipe. This tag contains a <description> element, " 909 + "which provides the recipe's description.\r\n" 910 + "The description can be written in plain text or markdown format and is displayed as additional information on the menu page. " 911 + "For optimal readability in the recipe editor. Text strings must be formatted and less than 120 characters long.") 912 @CommandExamples({ "<About><description>...</description></About>", 913 "<About><attach><file name='' /></attach></About>", 914 "<About><author name='' email='' messager='' phone=''/><attach><file name='' width='' height=''/></attach></About>" }) 915 public void runCommandAbout(final Node aCurrentAction) throws Throwable { 916 } 917 918 @CommandExamples({ "<Exist name='type:property' text='' value=''/>", 919 "<Exist name='type:property' array='type:property' value=''/>" }) 920 public void runCommandExist(final Node aCurrentAction) throws Throwable { 921 final String theName = replaceProperties(aCurrentAction.getAttribute("name")); 922 final String theText = replaceProperties(aCurrentAction.getAttribute("text")); 923 final String theArrayName = replaceProperties(aCurrentAction.getAttribute("array")); 924 final String theValue = replaceProperties(aCurrentAction.getAttribute("value")); 925 926 if (theArrayName != null) { 927 final Object variableValue = getVariableValue(theArrayName); 928 if (variableValue instanceof String[]) { 929 final String[] variableValueArray = (String[]) variableValue; 930 for (int i = 0; i < variableValueArray.length; i++) { 931 if (theValue.equals(variableValueArray[i])) { 932 setVariableValue(theName, "true"); 933 return; 934 } 935 } 936 } 937 938 if (variableValue instanceof String) { 939 final String value = (String) variableValue; 940 if (theValue.equals(value)) { 941 setVariableValue(theName, "true"); 942 return; 943 } 944 } 945 setVariableValue(theName, "false"); 946 } else { 947 if (theText == null || theValue == null || theName == null) { 948 return; 949 } 950 final int indexOf = theText.indexOf(theValue); 951 setVariableValue(theName, indexOf >= 0 ? "true" : "false"); 952 } 953 } 954 955 @CommandExamples({ "<Load name='type:property' init='console'/>", 956 "<Load name='type:property' init='console'/>...</Load>", "<Load name='type:property' file='type:path'/>", 957 "<Load name='type:property' file='type:path' timeout='type:time' mode='enum:default|noreplace|escapeJS|bytes'/>", 958 "<Load name='type:property' url='' timeout='type:time' mode='enum:default|noreplace|escapeJS|bytes'/>", 959 "<Load name='type:property' xml='' timeout='type:time' mode='enum:default|noreplace|escapeJS|bytes|array'/>" }) 960 public void runCommandLoad(final Node action) throws Throwable { 961 final boolean noreplace = "noreplace".equals(action.getAttribute("mode")); 962 final boolean isArray = "array".equals(action.getAttribute("mode")); 963 final boolean defaultMode = "default".equals(action.getAttribute("mode")); 964 final boolean escapeJSValue = "escapeJS".equals(action.getAttribute("mode")); 965 final boolean bytes = "bytes".equals(action.getAttribute("mode")); 966 final boolean base64 = "base64".equals(action.getAttribute("mode")); 967 968 String theEncoding = replaceProperties(action.getAttribute("encoding")); 969 if (theEncoding == null) { 970 theEncoding = "UTF-8"; 971 } 972 973 final String name = replaceProperties(action.getAttribute("name")); 974 int timeout = (int) parseTime(action, "timeout", "0"); 975 976 final String theUrl = replaceProperties(action.getAttribute("url")); 977 if (theUrl != null) { 978 URL url = new URL(theUrl); 979 long startTime = System.currentTimeMillis(); 980 while (timeout == 0 || System.currentTimeMillis() < startTime + timeout) { 981 if (isStopped()) { 982 break; 983 } 984 try { 985 URLConnection openConnection = url.openConnection(); 986 openConnection.setReadTimeout(timeout); 987 byte[] byteArray = IOUtils.toByteArray(openConnection.getInputStream()); 988 if (escapeJSValue) { 989 String data = StringEscapeUtils.escapeJavaScript(new String(byteArray)); 990 setVariableValue(name, data); 991 } else { 992 setVariableValue(name, new String(byteArray, theEncoding)); 993 } 994 return; 995 996 } catch (IOException e) { 997 if (timeout == 0) { 998 throw e; 999 } 1000 wait("200"); 1001 } 1002 } 1003 } 1004 1005 String filePath = (String) attr(action, "file"); 1006 final boolean theDialog = isActiveInitFor(action, "console"); 1007 1008 if (theDialog) { 1009 File theFile = null; 1010 if (filePath != null) { 1011 theFile = getFile(filePath); 1012 } 1013 filePath = this.recipeListener.getManager().inputFile(name, null, theFile, log, this); 1014 } 1015 1016 if (filePath != null) { 1017 if (base64 || bytes) { 1018 File file = getFile(filePath); 1019 debug("Loading file: " + file); 1020 if (file.exists()) { 1021 try (FileInputStream input = new FileInputStream(file)) { 1022 Object byteArray = IOUtils.toByteArray(input); 1023 if (base64) { 1024 byteArray = Base64.getEncoder().encodeToString((byte[]) byteArray); 1025 } 1026 setVariableValue(name, byteArray); 1027 } 1028 } else { 1029 throw new FileNotFoundException(file.getAbsolutePath()); 1030 } 1031 return; 1032 } 1033 1034 int iterations = timeout / 1000; 1035 if (iterations == 0) { 1036 iterations = 1; 1037 } 1038 for (int i = 0; i < iterations; i++) { 1039 if (isStopped()) { 1040 break; 1041 } 1042 try { 1043 1044 if (!action.isEmpty()) { 1045 File file = getFile(filePath); 1046 try (BufferedReader reader = new BufferedReader(new FileReader(file))) { 1047 String line; 1048 while ((line = reader.readLine()) != null) { 1049 if (this.breakFlag > 0) { 1050 break; 1051 } 1052 setVariableValue(name, line); 1053 taskNode(action, false); 1054 } 1055 } finally { 1056 if (this.breakFlag > 0) { 1057 breakFlag--; 1058 } 1059 } 1060 1061 } else { 1062 1063 String text = AEUtils.loadResource(filePath, getBaseDir(), theEncoding); 1064 if (!noreplace) { 1065 text = replaceProperties(text, defaultMode); 1066 } 1067 1068 if (escapeJSValue) { 1069 String data = StringEscapeUtils.escapeJavaScript(text); 1070 setVariableValue(name, data); 1071 } else { 1072 Object val = text; 1073 if (isArray) { 1074 val = StringUtils.split(text, "\n\r"); 1075 } 1076 1077 setVariableValue(name, val); 1078 } 1079 } 1080 1081 break; 1082 1083 } catch (final FileNotFoundException e) { 1084 if (timeout == 0) { 1085 throw e; 1086 } 1087 wait("1000"); 1088 } catch (final Exception e) { 1089 throw e; 1090 } 1091 } 1092 } else { 1093 if (isActiveInitFor(action, "mandatory")) { 1094 stop(); 1095 } 1096 } 1097 1098 } 1099 1100 @CommandExamples({ "<Remove name='type:property'/>", "<Remove file=''/>", 1101 "<Remove name='type:property' history='type:boolean'/>" }) 1102 public void runCommandRemove(final Node aCurrentAction) throws Throwable { 1103 String theFileName = aCurrentAction.getAttribute("file"); 1104 if (theFileName != null) { 1105 theFileName = replaceProperties(theFileName); 1106 final File theFile = getFile(theFileName); 1107 if (theFile.isDirectory()) { 1108 FileUtils.deleteDirectory(theFile); 1109 } else { 1110 if (theFile.delete() == false) { 1111 new Exception("File '" + theFile.getAbsolutePath() + "' is not deleted."); 1112 } 1113 } 1114 } 1115 String theVarName = aCurrentAction.getAttribute("name"); 1116 if (theVarName != null) { 1117 theVarName = replaceProperties(theVarName); 1118 setVariableValue(theVarName, null); 1119 if (Boolean.parseBoolean((attr(aCurrentAction, "history")))) { 1120 AEWorkspace.getInstance().setDefaultUserConfiguration(".inputValue." + theVarName, null); 1121 } 1122 } 1123 } 1124 1125 @CommandExamples({ 1126 "<Get name='type:property' url='type:string' auth='type:string' mediaType='type:string' retries='1' timeout='type:time'/> " }) 1127 public void runCommandGet(final Node aCurrentAction) throws Throwable { 1128 1129 String mediaTypeStr = attr(aCurrentAction, "mediaType"); 1130 mediaTypeStr = StringUtils.defaultIfEmpty(mediaTypeStr, "application/json"); 1131 1132 String url = attr(aCurrentAction, "url"); 1133 String auth = attr(aCurrentAction, "auth"); 1134 int retries = Integer.parseInt(attr(aCurrentAction, "retries", "1")); 1135 1136 Builder builder = new okhttp3.Request.Builder().url(url).get(); 1137 1138 if (mediaTypeStr != null) { 1139 builder.addHeader("Content-Type", mediaTypeStr); 1140 } 1141 if (auth != null) { 1142 builder.addHeader("Authorization", auth); 1143 } 1144 1145 okhttp3.Request request = builder.build(); 1146 1147 for (int i = 0; i < retries; i++) { 1148 if (isStopped()) { 1149 break; 1150 } 1151 1152 try { 1153 okhttp3.OkHttpClient.Builder newBuilder = new OkHttpClient().newBuilder(); 1154 long timeout = parseTime(aCurrentAction, "timeout", "0"); 1155 if (timeout > 0) { 1156 newBuilder.connectTimeout(timeout, TimeUnit.MILLISECONDS); 1157 newBuilder.readTimeout(timeout, TimeUnit.MILLISECONDS); 1158 newBuilder.writeTimeout(timeout, TimeUnit.MILLISECONDS); 1159 } 1160 OkHttpClient client = newBuilder.build(); 1161 1162 try (Response response = client.newCall(request).execute()) { 1163 String value = new String(response.body().bytes(), "UTF-8"); 1164 String name = attr(aCurrentAction, "name"); 1165 if (name != null) { 1166 setVariableValue(name, value); 1167 } 1168 } 1169 1170 break; 1171 } catch (SocketTimeoutException e) { 1172 if (i == 2) { 1173 throw e; 1174 } 1175 } 1176 } 1177 } 1178 1179 @CommandExamples({ 1180 "<Post name='type:property' url='type:string' auth='type:string' body='type:string' mediaType='type:string' timeout='type:time'/> " }) 1181 public void runCommandPost(final Node aCurrentAction) throws Throwable { 1182 String mediaTypeStr = attr(aCurrentAction, "mediaType"); 1183 mediaTypeStr = StringUtils.defaultIfEmpty(mediaTypeStr, "application/json"); 1184 1185 String url = attr(aCurrentAction, "url"); 1186 String auth = attr(aCurrentAction, "auth"); 1187 String bodyStr = StringUtils.defaultIfEmpty(replaceProperties(aCurrentAction.getAttribute("body")), ""); 1188 1189 MediaType mediaType = MediaType.parse(mediaTypeStr); 1190 okhttp3.RequestBody body = okhttp3.RequestBody.create(mediaType, bodyStr); 1191 1192 Builder addHeader = new okhttp3.Request.Builder().url(url).method("POST", body).addHeader("Content-Type", 1193 mediaTypeStr); 1194 if (auth != null) { 1195 addHeader = addHeader.addHeader("Authorization", auth); 1196 } 1197 okhttp3.Request request = addHeader.addHeader("Accept", "*/*").build(); 1198 okhttp3.OkHttpClient.Builder newBuilder = new OkHttpClient().newBuilder(); 1199 1200 long timeout = parseTime(aCurrentAction, "timeout", "0"); 1201 if (timeout > 0) { 1202 newBuilder.connectTimeout(timeout, TimeUnit.MILLISECONDS); 1203 newBuilder.readTimeout(timeout, TimeUnit.MILLISECONDS); 1204 newBuilder.writeTimeout(timeout, TimeUnit.MILLISECONDS); 1205 } 1206 OkHttpClient client = newBuilder.build(); 1207 try (Response response = client.newCall(request).execute()) { 1208 String value = new String(response.body().bytes(), "UTF-8"); 1209 1210// if(response.code() == 404) { 1211// 1212// } 1213 1214 String name = attr(aCurrentAction, "name"); 1215 if (name != null) { 1216 setVariableValue(name, value); 1217 } 1218 } 1219 } 1220 1221 @CommandExamples({ 1222 "<Request method='value:get|post|[socket]' request='type:property[Map{header;body}]' response='type:property[Map{status;body}]' host='http://...' timeout='type:time'/>", 1223 "<Request method='get' response='type:property[Map{status;body}]' host='http://...' userName='' password=''><param name='' value=''/></Request>" }) 1224 public void runCommandRequest(final Node aCurrentAction) throws Throwable { 1225 Object request = attrValue(aCurrentAction, "request"); 1226 final String responseName = attr(aCurrentAction, "response"); 1227 final String method = StringUtils.defaultIfEmpty(attr(aCurrentAction, "method"), "socket"); 1228 String theUrl = attr(aCurrentAction, "host"); 1229 1230 String userName = attr(aCurrentAction, "userName"); 1231 String password = attr(aCurrentAction, "password"); 1232 HttpClientContext localContext = null; 1233 if (userName != null && password != null) { 1234 CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); 1235 credentialsProvider.setCredentials(AuthScope.ANY, 1236 new UsernamePasswordCredentials(userName + ":" + password)); 1237 localContext = HttpClientContext.create(); 1238 localContext.setCredentialsProvider(credentialsProvider); 1239 } 1240 1241 HttpRequestBase httpRequest = null; 1242 1243 final Node[] paramNodes = aCurrentAction.getNodes("param"); 1244 if (paramNodes != null && paramNodes.length > 0) { 1245 List<NameValuePairImplementation> parameters = new ArrayList<>(); 1246 for (Node node : paramNodes) { 1247 String name = attr(node, "name"); 1248 String value = attr(node, "value"); 1249 1250 NameValuePairImplementation nameValuePair = new NameValuePairImplementation(name, value); 1251 parameters.add(nameValuePair); 1252 } 1253 1254 String query = URLEncodedUtils.format(parameters, "UTF-8"); 1255 theUrl = theUrl + "?" + query; 1256 } 1257 1258 if (theUrl.toLowerCase().startsWith("http")) { 1259 if ("get".equalsIgnoreCase(method)) { 1260 httpRequest = new HttpGet(theUrl); 1261 1262 } else if ("post".equalsIgnoreCase(method)) { 1263 HttpPost httpPost = new HttpPost(theUrl); 1264 if (request != null) { 1265 @SuppressWarnings("unchecked") 1266 final Map<String, Object> requestMap = (Map<String, Object>) request; 1267 Object bodyObject = requestMap.get("body"); 1268 byte[] body = null; 1269 if (bodyObject instanceof byte[]) { 1270 body = (byte[]) bodyObject; 1271 } else if (bodyObject instanceof String) { 1272 body = ((String) bodyObject).getBytes(); 1273 } 1274 httpPost.setEntity(new ByteArrayEntity(body)); 1275 } 1276 httpRequest = httpPost; 1277 1278 } 1279 int timeout = (int) parseTime(aCurrentAction, "timeout", "5000"); 1280 1281 RequestConfig config = RequestConfig.custom().setConnectTimeout(timeout) 1282 .setConnectionRequestTimeout(timeout).setSocketTimeout(timeout).build(); 1283 httpRequest.setConfig(config); 1284 if (request != null) { 1285 @SuppressWarnings("unchecked") 1286 Map<String, String> header = (Map<String, String>) ((Map<String, Object>) request).get("header"); 1287 if (header != null) { 1288 Set<Entry<String, String>> entrySet = header.entrySet(); 1289 for (Entry<String, String> entry : entrySet) { 1290 httpRequest.setHeader(entry.getKey(), entry.getValue()); 1291 } 1292 } 1293 } 1294 1295 CloseableHttpResponse response; 1296 CloseableHttpClient httpclient = HttpClients.createDefault(); 1297 1298 long duration = System.currentTimeMillis(); 1299 if (localContext == null) { 1300 response = httpclient.execute(httpRequest); 1301 } else { 1302 response = httpclient.execute(httpRequest, localContext); 1303 } 1304 ByteArrayOutputStream body = new ByteArrayOutputStream(); 1305 response.getEntity().writeTo(body); 1306 1307 HashMap<String, Object> aValue = new HashMap<String, Object>(); 1308 aValue.put("body", body.toByteArray()); 1309 aValue.put("status", response.getStatusLine().getStatusCode()); 1310 aValue.put("header", response.getAllHeaders()); 1311 aValue.put("duration", Long.toString(System.currentTimeMillis() - duration)); 1312 setVariableValue(responseName, aValue); 1313 1314 } else { 1315 1316 Socket socket = null; 1317 try { 1318 String host = StringUtils.substringBefore(theUrl, ":"); 1319 int port = Integer.parseInt(StringUtils.defaultIfBlank(StringUtils.substringAfter(theUrl, ":"), "80")); 1320 socket = new Socket(host, port); 1321 OutputStream outputStream = socket.getOutputStream(); 1322 if (request instanceof byte[]) { 1323 IOUtils.write((byte[]) request, outputStream); 1324 } else if (request instanceof String) { 1325 IOUtils.write(((String) request).getBytes(), outputStream); 1326 } 1327 InputStream inputStream = socket.getInputStream(); 1328 byte[] response = IOUtils.toByteArray(inputStream); 1329 setVariableValue(responseName, response); 1330 } finally { 1331 if (socket != null) { 1332 socket.close(); 1333 } 1334 } 1335 1336 } 1337 1338 } 1339 1340 @CommandExamples({ "<Operation method='type:operation' />" }) 1341 public void runCommandOperation(final Node aCurrentAction) throws Throwable { 1342 String method = replaceProperties(aCurrentAction.getAttribute("method")); 1343 OperationHolder operationsMethod = AEWorkspace.getInstance().getOperationsMethod(method); 1344 1345 if (operationsMethod == null) { 1346 throw new IllegalArgumentException("Operation method is not found: " + method); 1347 } 1348 1349 Class<?>[] typeParameters = operationsMethod.getMethod().getParameterTypes(); 1350 1351 Object[] args = new Object[typeParameters.length]; 1352 for (int i = 0; i < args.length; i++) { 1353 String replaceProperties = aCurrentAction.getAttribute("arg" + (i + 1)); 1354 if (replaceProperties != null) { 1355 boolean varInjection = replaceProperties.startsWith("$var{") && replaceProperties.endsWith("}"); 1356 String varName = ""; 1357 if (varInjection) { 1358 varName = StringUtils.substring(replaceProperties, 5, replaceProperties.length() - 1); 1359 varInjection = !StringUtils.contains(varName, "{"); 1360 } 1361 1362 if (varInjection) { 1363 args[i] = ConvertUtils.convert(getVariableValue(varName), typeParameters[i]); 1364 } else { 1365 args[i] = ConvertUtils.convert(replaceProperties, typeParameters[i]); 1366 } 1367 } else { 1368 args[i] = null; 1369 } 1370 } 1371 1372 Class<?> operationClass = operationsMethod.getOperationClass(); 1373 Object operation = operationObjects.get(operationClass); 1374 if (operation == null) { 1375 operation = operationsMethod.newInstance(); 1376 operationObjects.put(operationClass, operation); 1377 } 1378 Object value = operationsMethod.invoke(operation, args); 1379 1380 String name = replaceProperties(aCurrentAction.getAttribute("name")); 1381 if (name != null) { 1382 setVariableValue(name, value); 1383 } 1384 } 1385 1386 @CommandExamples({ "<Table name='The table of variables'><var name='' value=''/></Table>", 1387 "<Table name='The table of variables' file='type:path'><var name='' value=''/></Table>" }) 1388 public void runCommandTable(final Node aCurrentVar) throws Throwable { 1389 AEManager manager = this.recipeListener.getManager(); 1390 boolean notifyMe = this.recipeListener.isNotifyMe(); 1391 1392 manager.inputDataTable(this, aCurrentVar, notifyMe); 1393 } 1394 1395 @SuppressWarnings({ "unchecked" }) 1396 @CommandExamples({ "<Loop name='type:property' source='type:property' numbers='type:integer'> ... </Loop>", 1397 "<Loop numbers='type:integer'> ... </Loop>", 1398 "<Loop name='type:property' query='select * from ...' maxCount='type:integer'> ... </Loop>" }) 1399 public void runCommandLoop(final Node aCurrentVar) throws Throwable { 1400 String theDescript = replaceProperties(aCurrentVar.getAttribute("description")); 1401 final String theNameAttribut = attr(aCurrentVar, "name"); 1402 boolean mainLoopCommand = false; 1403 1404 final String theNumbers = StringUtils.trimToNull(replaceProperties(aCurrentVar.getAttribute("numbers"))); 1405 if (theDescript == null) { 1406 theDescript = "Loop"; 1407 } 1408 String sourceAttribute = aCurrentVar.getAttribute("source"); 1409 final String theAttribut = replaceProperties(sourceAttribute); 1410 Object loopArrayVar = null; 1411 if (theAttribut != null) { 1412 loopArrayVar = getVariableValue(theAttribut); 1413 } 1414 List<Object> theLoopArray = new ArrayList<>(); 1415 if (loopArrayVar != null) { 1416 if (loopArrayVar instanceof String) { 1417 theLoopArray.add((String) loopArrayVar); 1418 } else if (loopArrayVar instanceof String[]) { 1419 List<String> asList = Arrays.asList((String[]) loopArrayVar); 1420 theLoopArray.addAll(asList); 1421 } else if (loopArrayVar instanceof List) { 1422 theLoopArray = (List<Object>) loopArrayVar; 1423 } else if (loopArrayVar instanceof Map) { 1424 Map map = (Map) loopArrayVar; 1425 theLoopArray.addAll(map.keySet()); 1426 } else if (loopArrayVar instanceof JSONArray) { 1427 JSONArray array = (JSONArray) loopArrayVar; 1428 theLoopArray = array.toList(); 1429 } else { 1430 return; 1431 } 1432 } 1433 int theCount = 0; 1434 boolean infinityLoop = false; 1435 if (StringUtils.isNotBlank(theNumbers)) { 1436 theCount = (int) Double.parseDouble(theNumbers); 1437 } else { 1438 if (!theLoopArray.isEmpty()) { 1439 theCount = theLoopArray.size(); 1440 } else { 1441 infinityLoop = sourceAttribute == null; 1442 } 1443 } 1444 if (isLoopActivated() == false) { 1445 this.mainLoopCommand = true; 1446 mainLoopCommand = true; 1447 } 1448 1449 if (infinityLoop) { 1450 this.mainLoopCommand = false; 1451 } 1452 try { 1453 for (int i = 0; (i < theCount || infinityLoop) && isStopped() == false; i++) { 1454 if (isStopped()) { 1455 break; 1456 } 1457 if (this.breakFlag > 0) { 1458 break; 1459 } 1460 if ((mainLoopCommand && !infinityLoop) || theCount > 5) { 1461 this.recipeListener.setProgress(theDescript, theCount, i, false); 1462 } 1463 startCommandInformation(aCurrentVar); 1464 if (theLoopArray != null && theLoopArray.size() > 0) { 1465 if (i < theLoopArray.size()) { 1466 setVariableValue(theNameAttribut, theLoopArray.get(i)); 1467 } 1468 } else { 1469 setVariableValue(theNameAttribut, ObjectUtils.toString(i)); 1470 } 1471 taskNode(aCurrentVar, false); 1472 } 1473 } finally { 1474 if (this.breakFlag > 0) { 1475 breakFlag--; 1476 } 1477 if (mainLoopCommand) { 1478 this.mainLoopCommand = false; 1479 } 1480 } 1481 } 1482 1483 @CommandExamples({ "<Append name='type:property' value='' type='unique'/>", 1484 "<Append name='type:property'>...</Append>" }) 1485 public synchronized void runCommandAppend(final Node aCurrentVar) throws Throwable { 1486 final String name = aCurrentVar.getAttribute("name"); 1487 Object value = attr(aCurrentVar, "value"); 1488 if (value == null) { 1489 value = replaceProperties(aCurrentVar.getInnerText()); 1490 } 1491 1492 String source = aCurrentVar.getAttribute("source"); 1493 if (source != null) { 1494 value = getVariableValue(replaceProperties(source)); 1495 } 1496 1497 final Object theOldValue = getVariableValue(name, false); 1498 if (theOldValue == null) { 1499 return; 1500 } 1501 if (theOldValue instanceof String) { 1502 final String theValue1 = (String) theOldValue; 1503 value = theValue1 + value; 1504 setVariableValue(name, value); 1505 1506 } else if (theOldValue instanceof Object[]) { 1507 final boolean theUniqueTypeAttribut = "unique".equals(aCurrentVar.getAttribute("type")); 1508 1509 final String[] theValue1 = (String[]) theOldValue; 1510 String[] theValue2 = null; 1511 1512 if (theUniqueTypeAttribut) { 1513 Set<String> targetSet = new LinkedHashSet<>(Arrays.asList(theValue1)); 1514 if (value instanceof String) { 1515 targetSet.add((String) value); 1516 } else if (value instanceof String[]) { 1517 for (String val : (String[]) value) { 1518 targetSet.add(val); 1519 } 1520 } 1521 1522 String[] array = new String[targetSet.size()]; 1523 Iterator<String> iterator = targetSet.iterator(); 1524 int i = 0; 1525 while (iterator.hasNext()) { 1526 String object = (String) iterator.next(); 1527 array[i++] = object; 1528 } 1529 1530 theValue2 = array; 1531 1532 } else { 1533 List<String> targetList = new ArrayList<>(Arrays.asList(theValue1)); 1534 if (value instanceof String[]) { 1535 for (String val : (String[]) value) { 1536 targetList.add(val); 1537 } 1538 } else { 1539 targetList.add((String) value); 1540 } 1541 1542 String[] array = new String[targetList.size()]; 1543 int i = 0; 1544 for (Object val : targetList) { 1545 if (val instanceof String) { 1546 array[i++] = (String) val; 1547 } else { 1548 array[i++] = ObjectUtils.toString(val); 1549 } 1550 } 1551 1552 theValue2 = array; 1553 } 1554 1555 applyResult(aCurrentVar, name, theValue2); 1556 } 1557 } 1558 1559 @CommandExamples({ "<Rnd name='type:property' symbols='type:integer' type='enum:number|default'/>", 1560 "<Rnd name='type:property' type='uuid'/>", 1561 "<Rnd name='type:property' symbols='type:integer' startCode='type:integer' endCode='type:integer'/>", 1562 "<Rnd name='type:property' source='type:property'/>" }) 1563 public void runCommandRnd(final Node aCurrentVar) throws Throwable { 1564 final String theNameAttribut = replaceProperties(aCurrentVar.getAttribute("name")); 1565 String result = null; 1566 String type = replaceProperties(aCurrentVar.getAttribute("type")); 1567 1568 if ("uuid".equalsIgnoreCase(type)) { 1569 result = UUID.randomUUID().toString(); 1570 1571 } else { 1572 final String source = replaceProperties(aCurrentVar.getAttribute("source")); 1573 if (this.random == null) { 1574 this.random = SecureRandom.getInstance("SHA1PRNG"); 1575 } 1576 if (source != null) { 1577 Object value = getVariableValue(source); 1578 if (value instanceof String[]) { 1579 String[] strings = (String[]) value; 1580 int index = this.random.nextInt(strings.length); 1581 value = strings[index]; 1582 } 1583 setVariableValue(theNameAttribut, value); 1584 return; 1585 } 1586 1587 final String theSymbolsAttribut = replaceProperties(aCurrentVar.getAttribute("symbols")); 1588 1589 final long theBegNum = Long.parseLong(theSymbolsAttribut); 1590 int startCode = 0x41; 1591 final String startCodeStr = replaceProperties(aCurrentVar.getAttribute("startCode")); 1592 if (startCodeStr != null) { 1593 if (startCodeStr.indexOf('x') > 0) { 1594 startCode = Integer.parseInt(startCodeStr.substring(2), 16); 1595 } else { 1596 startCode = Integer.parseInt(startCodeStr); 1597 } 1598 type = "-number"; 1599 } 1600 1601 int endCode = 0x05A; 1602 final String endCodeStr = replaceProperties(aCurrentVar.getAttribute("endCode")); 1603 if (endCodeStr != null) { 1604 if (endCodeStr.indexOf('x') > 0) { 1605 endCode = Integer.parseInt(endCodeStr.substring(2), 16); 1606 } else { 1607 endCode = Integer.parseInt(endCodeStr); 1608 } 1609 type = "-number"; 1610 } 1611 1612 if ("number".equals(type) == false) { 1613 final StringBuffer theBuffer = new StringBuffer(); 1614 for (int i = 0; i < theBegNum; i++) { 1615 theBuffer.append((char) (this.random.nextInt(endCode - startCode) + startCode)); 1616 } 1617 result = theBuffer.toString(); 1618 } else { 1619 final StringBuffer theBuffer = new StringBuffer(); 1620 for (int i = 0; i < theBegNum; i++) { 1621 theBuffer.append(this.random.nextInt(9)); 1622 } 1623 result = theBuffer.toString(); 1624 } 1625 } 1626 1627 setVariableValue(theNameAttribut, result); 1628 } 1629 1630 @CommandExamples({ "<Inc name='type:property' increase=''/>" }) 1631 public void runCommandInc(final Node aCurrentVar) throws Throwable { 1632 String theValueAttribut = aCurrentVar.getAttribute("increase"); 1633 theValueAttribut = replaceProperties(theValueAttribut); 1634 long theIncLong = 1; 1635 if (theValueAttribut != null) { 1636 theIncLong = Long.parseLong(theValueAttribut); 1637 } 1638 final String theAttribut = aCurrentVar.getAttribute("name"); 1639 Object theOldValue = getVariableValue(theAttribut); 1640 1641 if (!(theOldValue instanceof Object[])) { 1642 theOldValue = ObjectUtils.toString(theOldValue, null); 1643 } 1644 1645 if (theOldValue instanceof String) { 1646 final long theLongValue = Long.parseLong((String) theOldValue) + theIncLong; 1647 setVariableValue(theAttribut, Long.toString(theLongValue)); 1648 } 1649 if (theOldValue instanceof String[] && ((String[]) theOldValue).length > 0) { 1650 final long theLongValue = Long.parseLong(((String[]) theOldValue)[0]) + theIncLong; 1651 setVariableValue(theAttribut, Long.toString(theLongValue)); 1652 } else { 1653 new ClassCastException("Tag <Inc> enabled only one number argument."); 1654 } 1655 } 1656 1657 @CommandExamples({ "<If name='' startsWith='' endsWith='' contains='' equals='' notEqual=''> ... </If>", 1658 "<If value='' startsWith='' endsWith='' contains='' equals='' notEqual=''> ... <Else> ... </Else></If>", 1659 "<If expression=''> ... </If>", "<If isNull=''> ... </If>", "<If isNotNull=''> ... </If>" }) 1660 public void runCommandIf(final Node action) throws Throwable { 1661 runIf(action); 1662 } 1663 1664 private boolean runIf(final Node action) throws CommandException, Throwable, ClassNotFoundException { 1665 String theExpressionAttribut = action.getAttribute("expression"); 1666 String isNull = action.getAttribute("isNull"); 1667 String isNotNull = action.getAttribute("isNotNull"); 1668 String nameAttr = attr(action, "name"); 1669 1670 String valueAttr = action.getAttribute("value"); 1671 1672 String theValue1Attribut = action.getAttribute("value1"); 1673 String theValue2Attribut = action.getAttribute("value2"); 1674 String theConditionAttribut = action.getAttribute("condition"); 1675 1676 boolean result = false; 1677 if (nameAttr != null || valueAttr != null) { 1678 Object variableValue = getVariableValue(nameAttr); 1679 String value; 1680 1681 if (variableValue == null) { 1682 value = replaceProperties(valueAttr); 1683 } else { 1684 if (variableValue instanceof String[]) { 1685 value = StringUtils.join((String[]) variableValue, "\n"); 1686 } else { 1687 value = ObjectUtils.toString(variableValue); 1688 } 1689 } 1690 1691 String startsWith = attr(action, "startsWith"); 1692 String endsWith = attr(action, "endsWith"); 1693 String contains = attr(action, "contains"); 1694 String equals = attr(action, "equals"); 1695 String regex = attr(action, "regex"); 1696 String notEqual = attr(action, "notEqual"); 1697 1698 boolean ignoreCase = Boolean.valueOf(attr(action, "ignoreCase", "false")); 1699 1700 boolean condition1 = startsWith == null || (ignoreCase ? StringUtils.startsWithIgnoreCase(value, startsWith) 1701 : StringUtils.startsWith(value, startsWith)); 1702 boolean condition2 = endsWith == null || (ignoreCase ? StringUtils.endsWithIgnoreCase(value, endsWith) 1703 : StringUtils.endsWith(value, endsWith)); 1704 boolean condition3 = contains == null || (ignoreCase ? StringUtils.containsIgnoreCase(value, contains) 1705 : StringUtils.contains(value, contains)); 1706 boolean condition4 = equals == null 1707 || (ignoreCase ? StringUtils.equalsIgnoreCase(value, equals) : StringUtils.equals(value, equals)); 1708 1709 boolean condition5 = true; 1710 if (regex != null) { 1711 final Pattern p = Pattern.compile(regex); 1712 final Matcher m = p.matcher(value); 1713 condition5 = m.find(); 1714 } 1715 1716 boolean condition6 = notEqual == null || (ignoreCase ? !StringUtils.equalsIgnoreCase(value, notEqual) 1717 : !StringUtils.equals(value, notEqual)); 1718 1719 result = condition1 && condition2 && condition3 && condition4 && condition5 && condition6; 1720 execIf(action, result); 1721 return result; 1722 } else if (isNull != null) { 1723 result = getVariableValue(replaceProperties(isNull)) == null; 1724 execIf(action, result); 1725 return result; 1726 } else if (isNotNull != null) { 1727 Object variableValue = getVariableValue(replaceProperties(isNotNull)); 1728 result = variableValue != null; 1729 execIf(action, result); 1730 return result; 1731 } else if (theExpressionAttribut != null) { 1732 theExpressionAttribut = replaceProperties(theExpressionAttribut); 1733 JexlEngine jexl = new JexlBuilder().create(); 1734 1735 JexlExpression expr_c = jexl.createExpression(theExpressionAttribut); 1736 JexlContext context = new MapContext(); 1737 1738 if (expr_c != null) { 1739 Object val = expr_c.evaluate(context); 1740 result = "true".equals(val.toString()); 1741 } 1742 1743 execIf(action, result); 1744 return result; 1745 } else if (theValue1Attribut != null || theValue2Attribut != null) { 1746 if (theConditionAttribut == null) { 1747 theConditionAttribut = "=="; 1748 } 1749 theValue1Attribut = replaceProperties(theValue1Attribut); 1750 theValue2Attribut = replaceProperties(theValue2Attribut); 1751 1752 if ("==".equals(theConditionAttribut) && theValue1Attribut.equals(theValue2Attribut)) { 1753 taskNode(action, false); 1754 result = true; 1755 } else if (("!=".equals(theConditionAttribut) || "unequal".equals(theConditionAttribut)) 1756 && (theValue1Attribut.equals(theValue2Attribut) == false)) { 1757 taskNode(action, false); 1758 result = true; 1759 } else if ("less".equals(theConditionAttribut) 1760 && (Long.parseLong(theValue1Attribut) < Long.parseLong(theValue2Attribut))) { 1761 taskNode(action, false); 1762 result = true; 1763 } else if ("bigger".equals(theConditionAttribut) 1764 && (Long.parseLong(theValue1Attribut) > Long.parseLong(theValue2Attribut))) { 1765 taskNode(action, false); 1766 result = true; 1767 } else { 1768 for (Node command : action.getNodes("Else")) { 1769 taskNode(command, false); 1770 } 1771 } 1772 } 1773 1774 return result; 1775 } 1776 1777 private void execIf(final Node action, boolean result) throws CommandException, Throwable { 1778 if (result) { 1779 taskNode(action, false); 1780 } else { 1781 for (Node command : action.getNodes("Else")) { 1782 if (command.getAttribute("name") == null && action.getAttribute("name") != null) { 1783 command.setAttribute("name", action.getAttribute("name")); 1784 } 1785 if (command.getAttribute("value") == null && action.getAttribute("value") != null) { 1786 command.setAttribute("value", action.getAttribute("value")); 1787 } 1788 if (command.getAttribute("name") != null || command.getAttribute("value") != null) { 1789 if (runIf(command)) { 1790 break; 1791 } 1792 } else { 1793 taskNode(command); 1794 } 1795 } 1796 } 1797 } 1798 1799 @CommandExamples({ "<While name='' startsWith='' endsWith='' contains='' equals='' notEqual=''> ... </While>", 1800 "<While value1='' value2='' condition='unequal'> ... <Else value1='' value2='' condition=''> ... </Else></While>", 1801 "<While expression=''> ... </While>", "<While isNull=''> ... </While>", 1802 "<While isNotNull=''> ... </While>" }) 1803 public void runCommandWhile(final Node aCurrentVar) throws Throwable { 1804 try { 1805 for (; runIf(aCurrentVar);) { 1806 if (this.breakFlag > 0) { 1807 break; 1808 } 1809 } 1810 } finally { 1811 if (this.breakFlag > 0) { 1812 breakFlag--; 1813 } 1814 } 1815 } 1816 1817 @CommandExamples({ "<Pragma event='console-input' action='default'/>", 1818 "<Pragma event='random-select' action='on'/>", "<Pragma event='log-window' action='single'/>" }) 1819 public void runCommandPragma(final Node aCurrentVar) throws Throwable { 1820 final String theEventAttribut = aCurrentVar.getAttribute("event"); 1821 final String theActionAttribut = aCurrentVar.getAttribute("action"); 1822 1823 if ("console-input".equals(theEventAttribut)) { 1824 boolean consoleDefaultInput = "default".equals(theActionAttribut); 1825 getListener().getManager().setConsoleDefaultInput(consoleDefaultInput); 1826 } else if ("random-select".equals(theEventAttribut)) { 1827 randomSelect = "on".equals(theActionAttribut); 1828 } else { 1829 this.log.error("Pragma ignored. Event: " + theEventAttribut); 1830 } 1831 } 1832 1833 @SuppressWarnings("unchecked") 1834 @CommandExamples({ 1835 "<Threads name='type:property' threadLog='type:boolean' numbers='type:integer' multi='enum:true|false' />", 1836 "<Threads numbers='type:integer' multi='enum:true|false' mode='enum:wait|nowait'><Out name='" 1837 + TaskProcessorThread.THREAD_ID + "'/></Threads>", 1838 "<Threads multi='enum:true|false'><Out name='" + TaskProcessorThread.THREAD_ID + "'/></Threads>" }) 1839 public void runCommandThreads(final Node aCurrentAction) throws InterruptedException, CommandException { 1840 1841 boolean threadLog = Boolean 1842 .parseBoolean(StringUtils.defaultIfBlank(attr(aCurrentAction, "threadLog"), "false")); 1843 int numbers = Integer.parseInt(StringUtils.defaultIfBlank(attr(aCurrentAction, "numbers"), "1")); 1844 boolean multi = Boolean.parseBoolean(StringUtils.defaultIfBlank(attr(aCurrentAction, "multi"), "true")); 1845 1846 ThreadPoolExecutor threadPool; 1847 if (multi) { 1848 if (numbers > 0) { 1849 threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(numbers); 1850 } else { 1851 threadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool(); 1852 } 1853 } else { 1854 threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(1); 1855 } 1856 1857 String callableListName = attr(aCurrentAction, "name"); 1858 if (callableListName == null) { 1859 final Iterator<?> theIterator = aCurrentAction.iterator(); 1860 1861 if (numbers == 0) { 1862 while (theIterator.hasNext()) { 1863 final Node theNode = (Node) theIterator.next(); 1864 1865 String theNameThreads = getTestName(theNode); 1866 if (theNameThreads == null) { 1867 theNameThreads = "Thread"; 1868 } 1869 1870 ILogger theLog = this.log; 1871 if (threadLog) { 1872 theLog = this.recipeListener.createLog(theNameThreads, false); 1873 } 1874 1875 final TaskProcessorThread runnable = new TaskProcessorThread(this, theNode, getBaseDir(), theLog); 1876 1877 threadPool.execute(runnable); 1878 1879 } 1880 } else { 1881 final Node theNode = (Node) aCurrentAction.clone(); 1882 theNode.setTag("Task"); 1883 theNode.removeAttribute(callableListName); 1884 1885 for (int i = 0; i < numbers; i++) { 1886 String theNameThreads = getTestName(theNode); 1887 String logName = "Thread #" + i; 1888 if (theNameThreads != null) { 1889 logName = theNameThreads + " #" + i; 1890 } 1891 1892 ILogger theLog = this.log; 1893 if (threadLog) { 1894 theLog = this.recipeListener.createLog(logName, false); 1895 } 1896 1897 final TaskProcessorThread runnable = new TaskProcessorThread(this, theNode, getBaseDir(), theLog); 1898 runnable.getVaribleValue(TaskProcessorThread.THREAD_ID, String.valueOf(i)); 1899 1900 threadPool.execute(runnable); 1901 } 1902 } 1903 1904 } else { 1905 Object callableList = getVariableValue(callableListName); 1906 if (callableList instanceof List) { 1907 for (Runnable runnable : (List<Runnable>) callableList) { 1908 threadPool.execute(runnable); 1909 } 1910 } else if (callableList instanceof Runnable) { 1911 for (int i = 0; i < numbers; i++) { 1912 if (callableList instanceof TaskProcessorThread) { 1913 threadPool.execute(((TaskProcessorThread) callableList).clone(i)); 1914 } else { 1915 threadPool.execute((Runnable) callableList); 1916 } 1917 } 1918 } else { 1919 throw new IllegalArgumentException( 1920 "Variable of type must be Runnable or List<Runnable>, actually: " + callableList); 1921 } 1922 } 1923 1924 String description = replaceProperties(aCurrentAction.getAttribute("description")); 1925 1926 long completedTaskCount = 0; 1927 long size = threadPool.getTaskCount(); 1928 1929 threadPoolList.add(threadPool); 1930 do { 1931 completedTaskCount = threadPool.getCompletedTaskCount(); 1932 progress(size, completedTaskCount, description, false); 1933 Thread.sleep(200); 1934 1935 } while (completedTaskCount < size); 1936 threadPoolList.remove(threadPool); 1937 } 1938 1939 @CommandExamples({ "<Task name='type:task' />", "<Task name='type:task' mode='async' optional='optional'/>", 1940 "<Task> ... </Task>", "<Task file='type:path' />" }) 1941 public void runCommandTask(final Node action) throws Throwable { 1942 1943 final boolean optional = Boolean.valueOf(attr(action, "optional", "false")); 1944 1945 final String taskName = replaceProperties(action.getAttribute("name")); 1946 String taskFile = replaceProperties(action.getAttribute("file")); 1947 1948 if (taskFile == null) { 1949 if (taskName != null) { 1950 taskFile = getListener().getManager().getTestPath(taskName); 1951 1952 if (taskFile == null) { 1953 if (optional) { 1954 return; 1955 } else { 1956 throw new Exception("Task with name: '" + taskName + "' not found."); 1957 } 1958 } 1959 } 1960 } else { 1961 if (!(new File(taskFile)).exists()) { 1962 if (optional) { 1963 return; 1964 } else { 1965 throw new Exception("Task with name: '" + taskFile + "' not found."); 1966 } 1967 } 1968 } 1969 1970 final File theBaseDir = getBaseDir(); 1971 try { 1972 if (taskName != null) { 1973 String mode = replaceProperties(action.getAttribute("mode")); 1974 if ("async".equals(mode)) { 1975 getListener().getManager().runTask(taskName, true); 1976 1977 } else { 1978 Properties taskParameters = MapUtils.toProperties(action.getAttributes()); 1979 Set<Entry<Object, Object>> entrySet = taskParameters.entrySet(); 1980 1981 String currentLogLevel = (String) this.variables.get(DEFAULT_LOG_LEVEL_NAME); 1982 String level = (String) taskParameters.get("level"); 1983 1984 for (Entry<Object, Object> entry : entrySet) { 1985 String name = (String) entry.getKey(); 1986 if (!"$ID".equals(name) && !"name".equals(name) && !"file".equals(name) 1987 && !"level".equals(name)) { 1988 String value = replaceProperties((String) entry.getValue()); 1989 this.variables.put(toUpperCaseName(name), value); 1990 } 1991 } 1992 1993 this.variables.put(DEFAULT_LOG_LEVEL_NAME, level); 1994 this.variables = processTesting(taskFile, this.variables, getBaseDir()); 1995 this.variables.put(DEFAULT_LOG_LEVEL_NAME, currentLogLevel); 1996 } 1997 } else { 1998 taskNode(action, false); 1999 } 2000 } finally { 2001 setBaseDir(theBaseDir); 2002 } 2003 } 2004 2005 @CommandExamples({ "<IterationRules name='type:property'><Out name='Iteration'/></IterationRules>", 2006 "<IterationRules name='type:property' timeLimit='type:time' start='type:integer'> ... </IterationRules>", 2007 "<Var name='rules'>#\n[multiple]\na=1\nb $enum=1;2\nc $inc=0;10\nd $file=file_name\n[single]\n...\n[concurrently]\n...\n[independent]\n...\n#</Var><IterationRules name='rules'><Out name='Iteration'/></IterationRules>", }) 2008 public void runCommandIterationRules(final Node action) throws IOException, CommandException { 2009 final String name = (String) attrValue(action, "name"); 2010 String theStartAttribut = action.getAttribute("start"); 2011 long theLimit = parseTime(action, "timeLimit", "180000"); 2012 2013 if (theStartAttribut == null) { 2014 theStartAttribut = "0"; 2015 } 2016 2017 final int theStart = Integer.parseInt(theStartAttribut); 2018 if (name == null) { 2019 throw new CommandException("In tag <IterationRules> variable rules is not defined.", this); 2020 } 2021 try { 2022 this.iteratorMode = true; 2023 final TestIterator theTestIterator = new TestIterator(this, name); 2024 final int theMax = theTestIterator.count(); 2025 progress(theMax, 0, "Iteration process", false); 2026 debug("Iteration block. Total count: " + theMax); 2027 final long theStertTime = System.currentTimeMillis(); 2028 for (int i = theStart; i < theMax; i++) { 2029 if (isStopped()) { 2030 break; 2031 } 2032 setVariableValue("Iteration", Integer.toString(i + 1)); 2033 theTestIterator.nextIteration(this); 2034 2035 taskNode(action, false); 2036 2037 progress(theMax, i, "Iteration process", false); 2038 if (i == 0) { 2039 long theTotalTime = ((System.currentTimeMillis() - theStertTime) * theMax) / 60000; 2040 debug("Total Iteration time: " + Long.toString(theTotalTime) + " min."); 2041 if (theTotalTime > theLimit) { 2042 int theConfirm = 0; 2043 if (this.recipeListener.getManager() != null) { 2044 if (this.recipeListener.getManager().isConsoleDefaultInput(attr(action, "name"), 2045 attr(action, "description")) == false) { 2046 if (theTotalTime < 60) { 2047 theConfirm = JOptionPane.showConfirmDialog( 2048 JOptionPane.getRootFrame(), "Total Iteration time: " 2049 + Long.toString(theTotalTime) + " min. \nContinue?", 2050 "Warning", JOptionPane.YES_NO_OPTION); 2051 } else { 2052 theTotalTime /= 60; 2053 theConfirm = JOptionPane.showConfirmDialog(JOptionPane.getRootFrame(), 2054 "Total Iteration time: " + Long.toString(theTotalTime) + " h. \nContinue?", 2055 "Warning", JOptionPane.YES_NO_OPTION); 2056 } 2057 } 2058 if (theConfirm != JOptionPane.YES_OPTION) { 2059 break; 2060 } 2061 } 2062 } 2063 } 2064 } 2065 } finally { 2066 this.iteratorMode = false; 2067 } 2068 } 2069 2070 @CommandExamples({ "<Listdir path='type:path' name='type:property'/>", 2071 "<Listdir path='type:path' name='type:property' tree='type:boolean'/>" }) 2072 public void runCommandListdir(final Node aCurrentVar) throws Throwable { 2073 final String thePathAttribut = replaceProperties(aCurrentVar.getAttribute("path")); 2074 final String theNameAttribut = replaceProperties(aCurrentVar.getAttribute("name")); 2075 File theFile = getFile(thePathAttribut); 2076 2077 if (isActiveInitFor(aCurrentVar, "console")) { 2078 String path = this.recipeListener.getManager().inputFile(theNameAttribut, null, theFile, log, this); 2079 if (path != null) { 2080 theFile = new File(path); 2081 } 2082 } 2083 2084 if (theFile != null) { 2085 debug("Listing of directory: " + theFile.getAbsolutePath()); 2086 2087 String[] theValue = null; 2088 if ("true".equals(attr(aCurrentVar, "tree"))) { 2089 @SuppressWarnings("unchecked") 2090 Collection<File> files = FileUtils.listFiles(theFile, TrueFileFilter.TRUE, TrueFileFilter.TRUE); 2091 if (files != null) { 2092 theValue = new String[files.size()]; 2093 int i = 0; 2094 for (File file : files) { 2095 theValue[i++] = file.getAbsolutePath(); 2096 } 2097 } 2098 } else { 2099 int i = 0; 2100 File[] listFiles = theFile.listFiles(); 2101 if (listFiles != null) { 2102 theValue = new String[listFiles.length]; 2103 for (File file : listFiles) { 2104 theValue[i++] = file.getAbsolutePath(); 2105 } 2106 } 2107 } 2108 2109 if (theValue != null) { 2110 Arrays.sort(theValue); 2111 setVariableValue(theNameAttribut, theValue); 2112 } 2113 } else { 2114 throw new TaskCancelingException(); 2115 } 2116 } 2117 2118 @CommandExamples({ "<Textparser text='' start='' end='' path='type:path' name='type:property'/>" }) 2119 public void runCommandTextparser(final Node aCurrentVar) throws Throwable { 2120 final String theTextAttribut = replaceProperties(aCurrentVar.getAttribute("text")); 2121 String theStartKey = replaceProperties(aCurrentVar.getAttribute("start")); 2122 String theEndKey = replaceProperties(aCurrentVar.getAttribute("end")); 2123 if (theStartKey == null) { 2124 theStartKey = "${"; 2125 } 2126 if (theEndKey == null) { 2127 theEndKey = "}$"; 2128 } 2129 int theBeginPos = 0; 2130 int theEndPos = 0; 2131 while (true) { 2132 theBeginPos = theTextAttribut.indexOf(theStartKey, theEndPos); 2133 if (theBeginPos < 0) { 2134 break; 2135 } 2136 theEndPos = theTextAttribut.indexOf(theEndKey, theBeginPos); 2137 if (theEndPos < 0) { 2138 throw new Exception("Source text is incorrect, absent symbol '" + theEndKey + "'."); 2139 } 2140 final String theLine = theTextAttribut.substring(theBeginPos + theStartKey.length(), theEndPos); 2141 final int thePbrk = theLine.indexOf('='); 2142 final String theName = replaceProperties(theLine.substring(0, thePbrk)); 2143 final String theValue = replaceProperties(theLine.substring(thePbrk + 1)); 2144 setVariableValue(theName, theValue); 2145 theEndPos += theEndKey.length(); 2146 } 2147 } 2148 2149 @CommandExamples({ "<NetworkInterfaces name='type:property' />", 2150 "<NetworkInterfaces name='type:property' host='' filterFor=''/>" }) 2151 public void runCommandNetworkInterfaces(final Node aCurrentAction) throws SocketException, UnknownHostException { 2152 final String name = replaceProperties(aCurrentAction.getAttribute("name")); 2153 String host = replaceProperties(aCurrentAction.getAttribute("host")); 2154 2155 if (host == null) { 2156 Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces(); 2157 Set<String> hostIps = new HashSet<>(); 2158 while (networkInterfaces.hasMoreElements()) { 2159 NetworkInterface nextElement = networkInterfaces.nextElement(); 2160 Enumeration<InetAddress> inetAddresses = nextElement.getInetAddresses(); 2161 while (inetAddresses.hasMoreElements()) { 2162 InetAddress nextElement2 = inetAddresses.nextElement(); 2163 if (nextElement2 instanceof Inet4Address) { 2164 Inet4Address address = (Inet4Address) nextElement2; 2165 String hostAddress = address.getHostAddress(); 2166 hostIps.add(hostAddress); 2167 } 2168 } 2169 } 2170 setVariableValue(name, new ArrayList<>(hostIps)); 2171 } else { 2172 try { 2173 URL url = new URL(host); 2174 host = url.getHost(); 2175 } catch (Exception e) { 2176 2177 } 2178 2179 InetAddress address1 = InetAddress.getByName(host); 2180 setVariableValue(name, address1.getHostAddress()); 2181 } 2182 } 2183 2184 @CommandExamples({ "<CheckProperties map='' type='' onErrorMsg='' caption='' columnsize='' mark=''/>" }) 2185 public void runCommandCheckProperties(final Node aCurrentVar) throws Throwable { 2186 final String theMapFileAttribut = replaceProperties(aCurrentVar.getAttribute("map")); 2187 final String theTypeAttribut = replaceProperties(aCurrentVar.getAttribute("type")); 2188 final String theErrorMsg = replaceProperties(aCurrentVar.getAttribute("onErrorMsg")); 2189 String theCommentAttribut = replaceProperties(aCurrentVar.getAttribute("caption")); 2190 if (theCommentAttribut == null) { 2191 theCommentAttribut = "Check;Left;Right;Left value;Right value;Rule"; 2192 } 2193 String theSizeAttribut = replaceProperties(aCurrentVar.getAttribute("columnsize")); 2194 if (theSizeAttribut == null) { 2195 theSizeAttribut = "6;24;24;20;64;40"; 2196 } 2197 String theMark = replaceProperties(aCurrentVar.getAttribute("mark")); 2198 if (theMark == null) { 2199 theMark = " "; 2200 } 2201 String theLine = null; 2202 final BufferedReader theFileReader = new BufferedReader( 2203 new FileReader(new File(getBaseDir(), theMapFileAttribut))); 2204 try { 2205 2206 final StringBuffer theBufferText = new StringBuffer(); 2207 theBufferText.append("Checking value of properties:\n"); 2208 boolean theResult = false; 2209 boolean theFirstIniResult = false; 2210 StringTokenizer theTokenizer = new StringTokenizer(theCommentAttribut, ";"); 2211 final int theNumberColumn = theTokenizer.countTokens(); 2212 final String[] theCaption = new String[theNumberColumn]; 2213 for (int i = 0; i < theNumberColumn; i++) { 2214 theCaption[i] = theTokenizer.nextToken(); 2215 } 2216 theTokenizer = new StringTokenizer(theSizeAttribut, ";"); 2217 final int theNumberColumnTable = theTokenizer.countTokens(); 2218 final int[] theSizeCaption = new int[theNumberColumnTable]; 2219 for (int i = 0; i < theNumberColumnTable; i++) { 2220 theSizeCaption[i] = Integer.parseInt(theTokenizer.nextToken()); 2221 } 2222 appendTableLine(theBufferText, theSizeCaption, theCaption, " "); 2223 Object theValue1 = null, theValue2 = null; 2224 2225 boolean theFailed = false; 2226 while ((theLine = theFileReader.readLine()) != null) { 2227 theLine = theLine.trim(); 2228 if (theLine.length() == 0) { 2229 continue; 2230 } 2231 if (theLine.charAt(0) == '#') { 2232 appendTableLine(theBufferText, theSizeCaption, new String[] { theLine.substring(1).trim() }, " "); 2233 continue; 2234 } 2235 final int thePbrk = theLine.indexOf('='); 2236 final String theRuleLitteral = "@rule:"; 2237 int thePbrkRule = theLine.indexOf(theRuleLitteral); 2238 String theRule = null; 2239 boolean theCasesensitive = false; 2240 String theOperationRule = null; 2241 String theParameterRule = null; 2242 if (thePbrkRule >= 0) { 2243 theRule = theLine.substring(thePbrkRule + theRuleLitteral.length()); 2244 final String theCasesensitiveLitteral = "casesensitive:"; 2245 final int thePbrkCasesensitive = theRule.indexOf(theCasesensitiveLitteral); 2246 String theRuleLine = theRule; 2247 if (thePbrkCasesensitive >= 0) { 2248 theRuleLine = theRule.substring(thePbrkCasesensitive + theCasesensitiveLitteral.length()); 2249 theCasesensitive = true; 2250 } 2251 final String theOperationRuleEndLitteral = ":"; 2252 final int thePbrkOperationRuleEnd = theRule.indexOf(theOperationRuleEndLitteral); 2253 if (thePbrkOperationRuleEnd >= 0) { 2254 theOperationRule = theRuleLine.substring(0, thePbrkOperationRuleEnd); 2255 theParameterRule = theRuleLine.substring(thePbrkOperationRuleEnd + 1); 2256 } 2257 } else { 2258 thePbrkRule = theLine.length(); 2259 } 2260 String theLeftLine = theLine.substring(0, thePbrk); 2261 final String thePropLeft = replaceProperties(theLeftLine); 2262 String theRightLine = theLine.substring(thePbrk + 1, thePbrkRule); 2263 final String thePropRight = replaceProperties(theRightLine); 2264 Object theValueLeftObject = thePropLeft; 2265 Object theValueRightObject = thePropRight; 2266 if ("name".equals(theTypeAttribut)) { 2267 String theData = thePropLeft.trim(); 2268 boolean theValueMode = thePropLeft != null && theData.length() >= 2 && theData.charAt(0) == '[' 2269 && theData.charAt(theData.length() - 1) == ']'; 2270 if (theValueMode == false) { 2271 theValueLeftObject = getVariableValue(theData); 2272 theLeftLine = thePropLeft; 2273 } else { 2274 theValueLeftObject = theData.substring(1, theData.length() - 1); 2275 } 2276 theData = thePropRight.trim(); 2277 theValueMode = thePropLeft != null && theData.length() >= 2 && theData.charAt(0) == '[' 2278 && theData.charAt(theData.length() - 1) == ']'; 2279 if (theValueMode == false) { 2280 theValueRightObject = getVariableValue(theData); 2281 theRightLine = thePropRight; 2282 } else { 2283 theValueRightObject = theData.substring(1, theData.length() - 1); 2284 } 2285 } 2286 if (theValueLeftObject == null) { 2287 theValueLeftObject = "null"; 2288 } 2289 if (theValueRightObject == null) { 2290 theValueRightObject = "null"; 2291 } 2292 if (theValueLeftObject instanceof String && theValueRightObject instanceof String) { 2293 // -- RULE -- 2294 theResult = ruleTranslate(theCasesensitive, (String) (theValueLeftObject), 2295 (String) theValueRightObject, theOperationRule, theParameterRule); 2296 if (theResult == false && theFirstIniResult == false) { 2297 theValue1 = theValueLeftObject; 2298 theValue2 = theValueRightObject; 2299 theFirstIniResult = true; 2300 } 2301 } else { 2302 throw new Exception("CheckProperties operation possible only String values."); 2303 } 2304 if (theResult == false) { 2305 theFailed = true; 2306 } 2307 appendTableLine(theBufferText, theSizeCaption, 2308 new Object[] { theResult ? "ok" : "failed", theLeftLine, theRightLine, theValueLeftObject, 2309 theValueRightObject, theRule != null ? theRule : new String() }, 2310 theMark); 2311 } 2312 debug(theBufferText); 2313 if (theFailed) { 2314 TestCase.assertEquals(theErrorMsg, theValue2, theValue1); 2315 throw new AssertionFailedError("Incorrect value:<" + theValue1 + ">"); 2316 } 2317 2318 } finally { 2319 theFileReader.close(); 2320 } 2321 2322 } 2323 2324 private boolean ruleTranslate(final boolean aCasesensitive, String aValue, final String aValueRightObject, 2325 final String aOperationRule, String aParameterRule) throws Exception { 2326 if ("date".equals(aOperationRule)) { 2327 final int thePbrk = aParameterRule.indexOf(';'); 2328 final String theLeft = aParameterRule.substring(0, thePbrk); 2329 final String theRight = aParameterRule.substring(thePbrk + 1); 2330 try { 2331 final DateFormat theLeftFormat = new SimpleDateFormat(theLeft); 2332 theLeftFormat.setTimeZone(TimeZone.getTimeZone("UTC")); 2333 final DateFormat theRightFormat = new SimpleDateFormat(theRight); 2334 theRightFormat.setTimeZone(TimeZone.getTimeZone("UTC")); 2335 ParsePosition theParsePosition = new ParsePosition(0); 2336 final Date theLeftDate = theLeftFormat.parse(aValue, theParsePosition); 2337 if (theParsePosition.getErrorIndex() > -1) { 2338 return false; 2339 } 2340 theParsePosition = new ParsePosition(0); 2341 final Date theRightDate = theRightFormat.parse(aValueRightObject, theParsePosition); 2342 if (theParsePosition.getErrorIndex() > -1) { 2343 return false; 2344 } 2345 if ((theLeftDate != null && theRightDate == null) || (theRightDate != null && theLeftDate == null)) { 2346 return true; 2347 } 2348 if (theRightDate == null || theLeftDate == null) { 2349 return false; 2350 } 2351 return theLeftDate.compareTo(theRightDate) <= 0; 2352 } catch (final Throwable e) { 2353 return false; 2354 } 2355 } 2356 if ("file".equals(aOperationRule)) { 2357 final Map<String, Object> theMapProperties = new HashMap<String, Object>(); 2358 loadProperties(getFile(aParameterRule), theMapProperties, aCasesensitive == false); 2359 if (aCasesensitive == false) { 2360 aValue = aValue.toUpperCase(); 2361 } 2362 aValue = (String) theMapProperties.get(aValue); 2363 if (aValue == null) { 2364 aValue = "null"; 2365 } 2366 } 2367 if ("map".equals(aOperationRule)) { 2368 if (aCasesensitive == false) { 2369 aParameterRule = aParameterRule.toUpperCase(); 2370 } 2371 final Map<String, Object> theMapProperties = new HashMap<String, Object>(); 2372 loadProperties(aParameterRule, ";", theMapProperties, aCasesensitive == false); 2373 if (aCasesensitive == false) { 2374 aValue = aValue.toUpperCase(); 2375 } 2376 aValue = (String) theMapProperties.get(aValue); 2377 if (aValue == null) { 2378 aValue = "null"; 2379 } 2380 } 2381 boolean theResult; 2382 if (aCasesensitive) { 2383 theResult = aValue.equals(aValueRightObject); 2384 } else { 2385 theResult = aValue.equalsIgnoreCase(aValueRightObject); 2386 } 2387 return theResult; 2388 } 2389 2390 private void appendTableLine(final StringBuffer aStringBuffer, final int[] aSizeCaption, final Object[] aStrings, 2391 final String theMark) { 2392 if (aSizeCaption.length != aStrings.length) { 2393 for (int i = 0; i < aStrings.length; i++) { 2394 aStringBuffer.append(aStrings[i]); 2395 } 2396 } else { 2397 for (int i = 0; i < aSizeCaption.length; i++) { 2398 String theString = new String("NULL"); 2399 if (aStrings[i] != null) { 2400 theString = aStrings[i].toString(); 2401 } 2402 if (theString.length() > aSizeCaption[i]) { 2403 aStringBuffer.append(theString.substring(0, aSizeCaption[i])); 2404 } else { 2405 aStringBuffer.append(theString); 2406 } 2407 final StringBuffer theSpaceBuffer = new StringBuffer(); 2408 for (int theSpace = aSizeCaption[i] - theString.length(); theSpace > 0; theSpace -= theMark.length()) { 2409 theSpaceBuffer.append(theMark); 2410 } 2411 if (aSizeCaption[i] - theString.length() > 0) { 2412 theSpaceBuffer.setLength(aSizeCaption[i] - theString.length()); 2413 aStringBuffer.append(theSpaceBuffer); 2414 } 2415 aStringBuffer.append('|'); 2416 } 2417 } 2418 aStringBuffer.append('\n'); 2419 } 2420 2421 @CommandExamples({ "<Command os=''>...</Command>", 2422 "<Command name='type:property' os='' exitValue='type:property' cmd='' noCommandLog='type:boolean' dir='~'/>", 2423 "<Command name='type:property' os='' exitValue='type:property' cmd='' noCommandLog='type:boolean' dir='~'/>...</Command>" }) 2424 public void runCommandCommand(final Node aCurrentNode) throws Throwable { 2425 2426 String command = replaceProperties(aCurrentNode.getAttribute("cmd")); 2427 final String name = replaceProperties(aCurrentNode.getAttribute("name")); 2428 final String dir = replaceProperties(aCurrentNode.getAttribute("dir")); 2429 final String os = replaceProperties(aCurrentNode.getAttribute("os")); 2430 2431 String osName = SystemUtils.OS_NAME; 2432 2433 if (os == null || Pattern.compile(os).matcher(osName).matches()) { 2434 if (command == null) { 2435 final Node[] theNodes = aCurrentNode.getTextNodes(); 2436 if (theNodes.length > 0) { 2437 command = replaceProperties(theNodes[0].getText()); 2438 } 2439 } 2440 2441 runSystemCommand(command, name, aCurrentNode, dir); 2442 } 2443 } 2444 2445 private void runSystemCommand(final String theCommandAttribut, final String theNameAttribut, 2446 final Node aCurrentNode, String dir) throws Throwable { 2447 final String prefix = "start "; 2448 if (theCommandAttribut.startsWith(prefix) == false) { 2449 2450 String regExp = "\"(\\\"|[^\"])*?\"|[^ ]+"; 2451 Pattern pattern = Pattern.compile(regExp, Pattern.MULTILINE | Pattern.CASE_INSENSITIVE); 2452 Matcher matcher = pattern.matcher(theCommandAttribut); 2453 List<String> matches = new ArrayList<String>(); 2454 while (matcher.find()) { 2455 matches.add(matcher.group()); 2456 } 2457 String[] parsedCommand = matches.toArray(new String[] {}); 2458 2459 ProcessBuilder builder = new ProcessBuilder(parsedCommand); 2460 2461 if (dir != null) { 2462 File directory; 2463 if (dir.startsWith("~/")) { 2464 dir = dir.substring(1); 2465 String recipeFile = this.recipeListener.getManager().getTestPath(testName); 2466 if (recipeFile != null) { 2467 directory = new File(new File(recipeFile).getParent(), dir); 2468 builder.directory(directory); 2469 } 2470 } else { 2471 directory = new File(dir); 2472 builder.directory(directory); 2473 } 2474 } 2475 2476 builder.redirectErrorStream(true); 2477 Process process = builder.start(); 2478 2479 final String stdin = replaceProperties(aCurrentNode.getAttribute("stdin")); 2480 if (stdin != null) { 2481 process.getOutputStream().write(stdin.getBytes()); 2482 process.getOutputStream().close(); 2483 } 2484 2485 processes.add(process); 2486 2487 final BufferedReader errorStream = new BufferedReader(new InputStreamReader(process.getInputStream())); 2488 boolean noCommandLog = Boolean.valueOf(attr(aCurrentNode, "noCommandLog")); 2489 if (!noCommandLog) { 2490 debug("Command: " + theCommandAttribut); 2491 } else { 2492 debug("Command: ****** **** *****"); 2493 } 2494 2495 try { 2496 final BufferedReader theOutputStream = new BufferedReader( 2497 new InputStreamReader(process.getInputStream())); 2498 String theLine; 2499 2500 boolean line_output = aCurrentNode.size() == 0; 2501 final StringBuffer theBuffer = new StringBuffer(); 2502 while ((theLine = theOutputStream.readLine()) != null && !isStoppedTest()) { 2503 if (breakFlag > 0) { 2504 break; 2505 } 2506 2507 if (line_output) { 2508 theBuffer.append(theLine); 2509 theBuffer.append('\n'); 2510 } else { 2511 setVariableValue(theNameAttribut, theLine); 2512 taskNode(aCurrentNode, false); 2513 } 2514 } 2515 2516 if (this.breakFlag > 0) { 2517 breakFlag--; 2518 } 2519 2520 String exitValueName = attr(aCurrentNode, "exitValue"); 2521 if (exitValueName != null) { 2522 int exitValue = 0; 2523 try { 2524 exitValue = process.exitValue(); 2525 if (exitValue > 0) { 2526 String error = IOUtils.toString(errorStream); 2527 if (StringUtils.isNotBlank(error)) { 2528 throw new RuntimeException(error); 2529 } 2530 } 2531 } catch (IllegalThreadStateException e) { 2532 // 2533 } 2534 setVariableValue(exitValueName, Integer.toString(exitValue)); 2535 } 2536 2537 if (line_output) { 2538 if (theNameAttribut == null) { 2539 debug("System output:" + theBuffer.toString()); 2540 } else { 2541 setVariableValue(theNameAttribut, theBuffer.toString()); 2542 } 2543 } 2544 } finally { 2545 processes.remove(process); 2546 process.destroyForcibly(); 2547 try { 2548 if (!process.waitFor(5, TimeUnit.SECONDS)) { 2549 process.destroyForcibly(); 2550 } 2551 } catch (InterruptedException e) { 2552 Thread.currentThread().interrupt(); 2553 process.destroyForcibly(); 2554 } 2555 } 2556 2557 } else { 2558 final Thread thread = new SystemCommandStart(theCommandAttribut.substring(prefix.length()), this.log); 2559 thread.start(); 2560 } 2561 } 2562 2563// public void runCommandParameters(final Node aCurrentVar) throws Throwable { 2564// if (RecipeRunner.RUN_MODE_WEB.equals(this.recipeListener.getRunMode())) { 2565// // todo: 2566// } 2567// } 2568 2569 @CommandExamples({ "<ArraySize name = '' array = ''/>" }) 2570 public void runCommandArraySize(final Node aCurrentVar) throws Throwable { 2571 final String theNameAttribut = replaceProperties(aCurrentVar.getAttribute("name")); 2572 final String theArrayNameAttribut = replaceProperties(aCurrentVar.getAttribute("array")); 2573 final Object theValue = getVariableValue(theArrayNameAttribut); 2574 2575 int theResult = 0; 2576 if (theValue instanceof String[]) { 2577 theResult = ((String[]) theValue).length; 2578 } else if (theValue instanceof List) { 2579 theResult = ((List<String>) theValue).size(); 2580 } else if (theValue instanceof byte[]) { 2581 theResult = ((byte[]) theValue).length; 2582 } else if (theValue instanceof String && StringUtils.isNotBlank((String) theValue)) { 2583 theResult = 1; 2584 } else { 2585 theResult = 0; 2586 } 2587 2588 setVariableValue(theNameAttribut, String.valueOf(theResult)); 2589 } 2590 2591 @CommandExamples({ "<Size name = '' source = ''/>" }) 2592 public void runCommandSize(final Node aCurrentVar) throws Throwable { 2593 final String theNameAttribut = replaceProperties(aCurrentVar.getAttribute("name")); 2594 final String theArrayNameAttribut = replaceProperties(aCurrentVar.getAttribute("source")); 2595 final Object theValue = getVariableValue(theArrayNameAttribut); 2596 2597 int theResult = 0; 2598 if (theValue instanceof String[]) { 2599 String[] theValue2 = (String[]) theValue; 2600 for (int i = 0; i < theValue2.length; i++) { 2601 theResult += theValue2[i].length(); 2602 } 2603 } else if (theValue instanceof byte[]) { 2604 theResult = ((byte[]) theValue).length; 2605 } else if (theValue instanceof Collection) { 2606 theResult = ((Collection) theValue).size(); 2607 } else if (theValue instanceof String && StringUtils.isNotBlank((String) theValue)) { 2608 theResult = ((String) theValue).length(); 2609 } else { 2610 theResult = 0; 2611 } 2612 2613 setVariableValue(theNameAttribut, String.valueOf(theResult)); 2614 } 2615 2616 @CommandExamples({ "<Time name = 'type:property' action = 'enum:start|continue|pause|stop'/>", 2617 "<Time name = 'type:property' action = 'format' format='mm:ss:SSS'/>", 2618 "<Time name = 'type:property' action = 'duration' >...</Time>" }) 2619 public void runCommandTime(final Node command) throws Throwable { 2620 final String theNameAttribut = replaceProperties(command.getAttribute("name")); 2621 final String format = replaceProperties(command.getAttribute("format")); 2622 final String theTimeCaption = "Time"; 2623 String action = replaceProperties(command.getAttribute("action")); 2624 2625 if ("duration".equals(action)) { 2626 long start = System.currentTimeMillis(); 2627 2628 taskNode(command, false); 2629 2630 long stop = System.currentTimeMillis(); 2631 final String[] variableValue = new String[] { theTimeCaption, String.valueOf(start), String.valueOf(stop), 2632 "" }; 2633 2634 String result = formatTime(format, variableValue); 2635 setVariableValue(theNameAttribut, result); 2636 return; 2637 } 2638 2639 if ("start".equals(action)) { 2640 final String[] theTime = new String[] { theTimeCaption, String.valueOf(System.currentTimeMillis()), "", 2641 "" }; 2642 setVariableValue(theNameAttribut, theTime); 2643 return; 2644 } 2645 2646 if ("continue".equals(action)) { 2647 String[] theTime = (String[]) getVariableValue(theNameAttribut); 2648 if (theTime == null) { 2649 theTime = new String[] { theTimeCaption, String.valueOf(System.currentTimeMillis()), "", 2650 String.valueOf(System.currentTimeMillis()) }; 2651 } 2652 2653 if (theTime == null || theTime[3] == null || theTime[3].length() == 0) { 2654 throw new Exception("Timer is not paused."); 2655 } 2656 2657 if (theTimeCaption.equals(theTime[0])) { 2658 final long theStart = Long.parseLong(theTime[1]); 2659 final long thePaused = Long.parseLong(theTime[3]); 2660 theTime[1] = String.valueOf(theStart - (System.currentTimeMillis() - thePaused)); 2661 theTime[3] = ""; 2662 setVariableValue(theNameAttribut, theTime); 2663 } else { 2664 throw new Exception("Incorrect type."); 2665 } 2666 return; 2667 } 2668 2669 if ("pause".equals(action)) { 2670 final String[] theTime = (String[]) getVariableValue(theNameAttribut); 2671 2672 if (theTime[3] != null && theTime[3].length() > 0) { 2673 throw new Exception("Timer is paused."); 2674 } 2675 if (theTimeCaption.equals(theTime[0])) { 2676 theTime[3] = String.valueOf(System.currentTimeMillis()); 2677 setVariableValue(theNameAttribut, theTime); 2678 } else { 2679 throw new Exception("Incorrect type."); 2680 } 2681 return; 2682 } 2683 2684 if ("stop".equals(action)) { 2685 final String[] theTime = (String[]) getVariableValue(theNameAttribut); 2686 2687 final long theStart = Long.parseLong(theTime[1]); 2688 2689 if (theTime[3] != null && theTime[3].length() > 0) { 2690 final long thePaused = Long.parseLong(theTime[3]); 2691 theTime[1] = String.valueOf(theStart + (System.currentTimeMillis() - thePaused)); 2692 theTime[3] = ""; 2693 } 2694 2695 if (theTimeCaption.equals(theTime[0])) { 2696 theTime[2] = String.valueOf(System.currentTimeMillis()); 2697 setVariableValue(theNameAttribut, theTime); 2698 } else { 2699 throw new Exception("Incorrect type."); 2700 } 2701 return; 2702 } 2703 2704 if ("format".equals(action)) { 2705 Object variableValue = getVariableValue(theNameAttribut); 2706 String theResult = formatTime(format, variableValue); 2707 setVariableValue(theNameAttribut, theResult); 2708 return; 2709 } 2710 } 2711 2712 private String formatTime(final String format, Object variableValue) throws Exception { 2713 final String[] theTime; 2714 if (variableValue instanceof String[]) { 2715 theTime = (String[]) variableValue; 2716 } else { 2717 theTime = new String[] { "", "0", (String) variableValue }; 2718 } 2719 2720 if (ArrayUtils.getLength(theTime) < 2) { 2721 throw new Exception("Timer is not defined."); 2722 } 2723 2724 if (ArrayUtils.getLength(theTime) < 3) { 2725 throw new Exception("Timer is not stoped."); 2726 } 2727 2728 String theResult = null; 2729 if (format == null) { 2730 theResult = String.valueOf(Long.parseLong(theTime[2]) - Long.parseLong(theTime[1])); 2731 } else { 2732 final DateFormat dateFormat = new SimpleDateFormat(format); 2733 dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); 2734 long date = Long.parseLong(theTime[2]) - Long.parseLong(theTime[1]); 2735 theResult = dateFormat.format(new Date(date)); 2736 } 2737 return theResult; 2738 } 2739 2740 @CommandExamples({ "<ArrayElement name='type:property' array='' elementId=''/>" }) 2741 public void runCommandArrayElement(final Node aCurrentVar) throws Throwable { 2742 final String theNameAttribut = replaceProperties(aCurrentVar.getAttribute("name")); 2743 final String theArrayNameAttribut = replaceProperties(aCurrentVar.getAttribute("array")); 2744 if (theArrayNameAttribut == null) { 2745 throw new IllegalArgumentException("'array' attribute required."); 2746 } 2747 2748 final String theElementAttribut = replaceProperties(aCurrentVar.getAttribute("elementId")); 2749 if (theElementAttribut == null) { 2750 throw new IllegalArgumentException("'elementId' attribute required."); 2751 } 2752 2753 final String type = replaceProperties(aCurrentVar.getAttribute("type")); 2754 Object theValue = getVariableValue(theArrayNameAttribut); 2755 2756 final int theElementId = Integer.parseInt(theElementAttribut); 2757 2758 theValue = convert(theValue, type); 2759 2760 Object theResult = null; 2761 if (theValue instanceof JSONArray) { 2762 JSONArray jsonArray = (JSONArray) theValue; 2763 theResult = jsonArray.get(theElementId); 2764 } else if (theValue instanceof String[]) { 2765 theResult = ((String[]) theValue)[theElementId]; 2766 } else if (theValue instanceof String) { 2767 if ("string".equalsIgnoreCase(type)) { 2768 theResult = new String(new char[] { ((String) theValue).charAt(theElementId) }); 2769 } else if (theElementId == 0) { 2770 theResult = theValue; 2771 } 2772 } else if (theElementId == 0) { 2773 theResult = theValue; 2774 } 2775 2776 setVariableValue(theNameAttribut, theResult); 2777 } 2778 2779 @CommandExamples({ "<Calculate name='type:property' expressions='type:string'/>", 2780 "<Calculate name='type:property'>...</Calculate>" }) 2781 public void runCommandCalculate(final Node command) throws Throwable { 2782 final String name = replaceProperties(command.getAttribute("name")); 2783 String expressions = replaceProperties(command.getAttribute("expressions")); 2784 if (expressions == null) { 2785 expressions = replaceProperties(command.getInnerText()); 2786 } 2787 2788 JexlEngine jexl = new JexlBuilder().create(); 2789 2790 JexlExpression expr_c = jexl.createExpression(expressions); 2791 JexlContext context = new MapContext(); 2792 2793 Map<String, String> attributes = command.getAttributes(); 2794 for (Map.Entry<String, String> entry : attributes.entrySet()) { 2795 String key = entry.getKey(); 2796 String val = entry.getValue(); 2797 2798 Object variableValue = getVariableValue(val); 2799 if (variableValue instanceof String) { 2800 try { 2801 variableValue = Double.parseDouble((String) variableValue); 2802 } catch (NumberFormatException e) { 2803 // DO NOTHING 2804 } 2805 } 2806 2807 context.set(key, variableValue); 2808 } 2809 2810 if (expr_c != null) { 2811 Object result = expr_c.evaluate(context); 2812 2813 if (result != null) { 2814 setVariableValue(name, result); 2815 } else { 2816 setVariableValue(name, null); 2817 } 2818 } 2819 } 2820 2821 @CommandExamples({ 2822 "<Parse name='type:property' source='type:property' type='enum:array|json|csv|fixed-length-line'/>", 2823 "<Parse name='type:property' source='type:property' type='fixed-length-line' length='type:integer'/>" }) 2824 public void runCommandParse(final Node command) throws Throwable { 2825 Object source = attrValue(command, "source"); 2826 final String theNameAttribut = replaceProperties(command.getAttribute("name")); 2827 final String type = replaceProperties(command.getAttribute("type")); 2828 2829 if ("json".equalsIgnoreCase(type)) { 2830 String theValue = ObjectUtils.toString(source); 2831 if (StringUtils.isNotBlank(theValue)) { 2832 Object obj = new JSONObject(theValue); 2833 if (obj instanceof JSONObject) { 2834 JSONObject result = new JSONObject(theValue); 2835 setVariableValue(theNameAttribut, result); 2836 } else if (obj instanceof JSONArray) { 2837 JSONArray result = new JSONArray(theValue); 2838 String[] array = new String[result.length()]; 2839 for (int i = 0; i < result.length(); i++) { 2840 array[i] = ObjectUtils.toString(result.get(i)); 2841 } 2842 setVariableValue(theNameAttribut, array); 2843 } 2844 } else { 2845 setVariableValue(theNameAttribut, theValue); 2846 } 2847 2848 } else if ("array".equalsIgnoreCase(type)) { 2849 String theValue = ObjectUtils.toString(source); 2850 2851 String[] array = StringUtils.split(theValue, "\r\n"); 2852 setVariableValue(theNameAttribut, array); 2853 } else if ("csv".equalsIgnoreCase(type)) { 2854 String theValue = ObjectUtils.toString(source); 2855 2856 CSVReader reader = new CSVReader(new StringReader(theValue)); 2857 List<String[]> r = reader.readAll(); 2858 2859 setVariableValue(theNameAttribut, r); 2860 } else if ("fixed-length-line".equalsIgnoreCase(type)) { 2861 if (source instanceof String) { 2862 String input = (String) source; 2863 int lineLength = Integer.parseInt(attr(command, "length")); 2864 List<Object> result = IntStream.range(0, (input.length() + lineLength - 1) / lineLength) 2865 .mapToObj(i -> input.substring(i * lineLength, Math.min((i + 1) * lineLength, input.length()))) 2866 .collect(Collectors.toList()); 2867 setVariableValue(theNameAttribut, result); 2868 } 2869 } 2870 } 2871 2872 @CommandExamples({ "<FindObject name='type:property' source='type:property' withValue=''/>" }) 2873 public void runCommandFindObject(final Node aCurrentNode) throws Throwable { 2874 Object json = getVariableValue(replaceProperties(aCurrentNode.getAttribute("source"))); 2875 String withValue = replaceProperties(aCurrentNode.getAttribute("withValue")); 2876 2877 if (json instanceof String) { 2878 String jsonStr = (String) json; 2879 if (StringUtils.startsWith(jsonStr, "{")) { 2880 json = new JSONObject(jsonStr); 2881 } else if (StringUtils.startsWith(jsonStr, "[")) { 2882 json = new JSONArray(jsonStr); 2883 } 2884 } else if (json instanceof String[]) { 2885 String[] jsonStrArray = (String[]) json; 2886 JSONArray array = new JSONArray(); 2887 for (int i = 0; i < jsonStrArray.length; i++) { 2888 String jsonStr = jsonStrArray[i]; 2889 array.put(new JSONObject(jsonStr)); 2890 } 2891 json = array; 2892 } 2893 2894 Object value = find(json, withValue); 2895 2896 final String name = replaceProperties(aCurrentNode.getAttribute("name")); 2897 applyResult(aCurrentNode, name, value); 2898 } 2899 2900 private JSONObject find(Object obj, String withValue) throws JSONException { 2901 if (obj instanceof JSONObject) { 2902 JSONObject json = (JSONObject) obj; 2903 2904 JSONArray names = json.names(); 2905 if (names != null) { 2906 for (int i = 0; i < names.length(); i++) { 2907 String name = names.getString(i); 2908 Object object = json.get(name); 2909 if (object instanceof String) { 2910 if (ObjectUtils.equals(object, withValue)) { 2911 return json; 2912 } 2913 } else { 2914 JSONObject find = find(object, withValue); 2915 if (find != null) { 2916 return find; 2917 } 2918 } 2919 } 2920 } 2921 } else if (obj instanceof JSONArray) { 2922 JSONArray array = (JSONArray) obj; 2923 2924 for (int j = 0; j < array.length(); j++) { 2925 Object item = array.get(j); 2926 2927 JSONObject find = find(item, withValue); 2928 if (find != null) { 2929 return find; 2930 } 2931 } 2932 } 2933 return null; 2934 } 2935 2936 @CommandExamples({ 2937 "<Var name='type:property' init='enum:console|mandatory|default' type='enum:text|password|path'/>", 2938 "<Var name='type:property' type='enum:array|number|map|json|string' />", 2939 "<Var name='type:property' source='type:property' start='' end=''/>", 2940 "<Var name='type:property' value='type:string' description='' init='enum:console|mandatory|default'/>", 2941 "<Var name='type:property'><item>...</item></Var>", 2942 "<Var name='type:property' type='map'><item key='type:string'>...</item></Var>", 2943 "<Var name='type:property' type='enum:array|number' file='type:path'/>", 2944 "<Var name='type:property' source='type:property' />" }) 2945 public void runCommandVar(final Node aCurrentVar) throws Throwable { 2946 final String name = replaceProperties(aCurrentVar.getAttribute("name")); 2947 String description = replaceProperties(aCurrentVar.getAttribute("description")); 2948 String theInit = replaceProperties(aCurrentVar.getAttribute("init")); 2949 2950 Object theOldValue = getVariableValue(name); 2951 if ("default".equals(theInit) && theOldValue != null) { 2952 if (theOldValue instanceof String) { 2953 if (StringUtils.isNotBlank((String) theOldValue)) { 2954 return; 2955 } 2956 } else if (theOldValue instanceof String[] && ((String[]) theOldValue).length > 0) { 2957 return; 2958 } 2959 } 2960 2961 if ("file".equals(theInit)) { 2962 loadProperties(getFile(name), this.variables, false); 2963 return; 2964 } 2965 String source = replaceProperties(aCurrentVar.getAttribute("source"), true); 2966 Object theValue = getVariableValue(name); 2967 if (source != null) { 2968 String sourceVarName = replaceProperties(source); 2969 theValue = getVariableValue(sourceVarName); 2970 theOldValue = theValue; 2971 setVariableValue(name, theValue); 2972 } 2973 2974 String value = aCurrentVar.getAttribute("value"); 2975 if (value != null) { 2976 theValue = replaceProperties(value); 2977 } 2978 2979 // Item setting 2980 String type = StringUtils.defaultIfEmpty(aCurrentVar.getAttribute("type"), ""); 2981 if (aCurrentVar.size() > 0) { 2982 if (Node.TEXT_TEAG_NAME.equals(aCurrentVar.getNode(0).getTag())) { 2983 final Node theTextNode = aCurrentVar.getNode(0); 2984 theValue = replaceProperties(theTextNode.getText()); 2985 2986 } else { 2987 switch (type) { 2988 case "map": 2989 Node[] nodes = aCurrentVar.getNodes("item"); 2990 theValue = new LinkedHashMap<String, String>(); 2991 for (Node node : nodes) { 2992 ((Map) theValue).put(node.getAttribute("key"), replaceProperties(node.getInnerText())); 2993 } 2994 break; 2995 2996 default: 2997 List<Object> theItemArray = new ArrayList<>(); 2998 for (int i = 0; i < aCurrentVar.size(); i++) { 2999 final Node theCurrentAction = (Node) aCurrentVar.get(i); 3000 Node[] theItemNodes = theCurrentAction.getTextNodes(); 3001 if (theItemNodes != null && theItemNodes.length == 1) { 3002 final String replaceProperties = replaceProperties(theItemNodes[0].getText(), true); 3003 theItemArray.add(replaceProperties); 3004 } else { 3005 if (theCurrentAction.size() == 1) { 3006 Node node = theCurrentAction.get(0); 3007 EasyUtils.removeAllAttributes(node, Node.TAG_ID); 3008 theItemArray.add(replaceProperties(node.getXMLText(), true)); 3009 } else { 3010 theItemArray = null; 3011 } 3012 break; 3013 } 3014 } 3015 theValue = theItemArray; 3016 } 3017 } 3018 } 3019 3020 boolean contains = StringUtils.contains(theInit, "mandatory"); 3021 boolean isConsoleInput = StringUtils.contains(theInit, "console"); 3022 boolean mandatory = StringUtils.contains(theInit, "mandatory"); 3023 if (mandatory) { 3024 if (!isEmpty(theOldValue)) { 3025 setVariableValue(name, theValue); 3026 } else { 3027 isConsoleInput = true; 3028 } 3029 } 3030 3031 final boolean theIntegerType = "number".equals(type); 3032 if (theIntegerType) { 3033 String string = ObjectUtils.toString(theValue); 3034 if (StringUtils.isNotBlank(string) && !NumberUtils.isNumber(string)) { 3035 setVariableValue(name, null); 3036 throw new NumberFormatException(string); 3037 } 3038 } 3039 3040 final boolean theArrayType = "array".equals(type); 3041 if (name != null && !(theValue == null && theArrayType == false)) { 3042 if (theArrayType) { 3043 char separatorChar = ','; 3044 if (theValue instanceof String) { 3045 String[] split = StringUtils.split((String) theValue, separatorChar); 3046 theValue = split != null ? Arrays.asList(split) : null; 3047 } 3048 } 3049 if (theArrayType && theValue == null) { 3050 theValue = new String[0]; 3051 } 3052 3053 String file = replaceProperties(aCurrentVar.getAttribute("file")); 3054 if (theArrayType && file != null) { 3055 ArrayList<String> buffer = new ArrayList<String>(); 3056 3057 if (theValue instanceof String[]) { 3058 for (String string : (String[]) theValue) { 3059 buffer.add(string); 3060 } 3061 } else if (theValue instanceof Collection) { 3062 buffer = new ArrayList<String>((Collection<String>) theValue); 3063 } 3064 3065 try (InputStream inputStream = AEUtils.getInputStream(file, getBaseDir())) { 3066 String encoding = replaceProperties(aCurrentVar.getAttribute("charset")); 3067 if (encoding == null) { 3068 encoding = "UTF-8"; 3069 } 3070 final BufferedReader theFileReader = new BufferedReader( 3071 new InputStreamReader(inputStream, encoding)); 3072 String readLine; 3073 while ((readLine = theFileReader.readLine()) != null) { 3074 buffer.add(readLine); 3075 } 3076 } 3077 theValue = buffer; 3078 } 3079 3080 theValue = convert(theValue, type); 3081 setVariableValue(name, theValue); 3082 } 3083 3084 if (isConsoleInput) { 3085 3086 if (theOldValue instanceof List && CollectionUtils.size(theOldValue) == 1) { 3087 theOldValue = ((List) theOldValue).get(0); 3088 } 3089 3090 if ((aCurrentVar.size() == 0 || !aCurrentVar.getInnerText().isEmpty()) 3091 && (isEmpty(theOldValue) || theOldValue instanceof String)) { 3092 Object theInitialSelectionValue = null; 3093 final Object o = getVariableValue(name); 3094 if (o instanceof String) { 3095 theInitialSelectionValue = o; 3096 } 3097 if (o instanceof String[] && ((String[]) o).length > 0) { 3098 if (this.random == null) { 3099 this.random = SecureRandom.getInstance("SHA1PRNG"); 3100 } 3101 theInitialSelectionValue = ((String[]) o)[this.random.nextInt(((String[]) o).length)]; 3102 } 3103 3104 String defaultValue = AEWorkspace.getInstance().getDefaultUserConfiguration(".inputValue." + name, 3105 (String) theInitialSelectionValue); 3106 if (this.recipeListener.getManager().isConsoleDefaultInput(name, description) 3107 && !(mandatory && defaultValue == null)) { 3108 3109 if ((o instanceof String[] && ArrayUtils.contains((String[]) o, defaultValue)) || o == null) { 3110 theInitialSelectionValue = defaultValue; 3111 } 3112 3113 setVariableValue(name, theInitialSelectionValue); 3114 } else { 3115 boolean notifyMe = this.recipeListener.isNotifyMe(); 3116 Object inputValue; 3117 3118 inputValue = this.recipeListener.getManager().inputValue(name, description, defaultValue, log, type, 3119 notifyMe, this); 3120 3121 setVariableValue(name, inputValue); 3122 } 3123 3124 } else { 3125 List possibleValues = null; 3126 if (theOldValue instanceof List) { 3127 final List theStringArray = (List) theOldValue; 3128 possibleValues = theStringArray; 3129 } else if (theOldValue instanceof String[]) { 3130 possibleValues = new ArrayList(); 3131 String[] array = (String[]) theOldValue; 3132 for (String item : array) { 3133 possibleValues.add(item); 3134 } 3135 } else { 3136 possibleValues = new ArrayList(); 3137 for (int i = 0; i < aCurrentVar.size(); i++) { 3138 final Node theCurrentAction = (Node) aCurrentVar.get(i); 3139 possibleValues.add(theCurrentAction.getInnerText()); 3140 } 3141 } 3142 3143 if (this.recipeListener.getManager().isConsoleDefaultInput(name, null)) { 3144 String theInitialSelectionValue = randomSelect(possibleValues); 3145 if (!randomSelect) { 3146 theInitialSelectionValue = AEWorkspace.getInstance() 3147 .getDefaultUserConfiguration(".choiceValue." + name, theInitialSelectionValue); 3148 3149 } 3150 setVariableValue(name, theInitialSelectionValue); 3151 } else { 3152 boolean notifyMe = this.recipeListener.isNotifyMe(); 3153 final Object theValueOut = this.recipeListener.getManager().choiceValue(name, description, 3154 possibleValues.toArray(), log, notifyMe, this); 3155 setVariableValue(name, theValueOut); 3156 } 3157 } 3158 } 3159 3160 theValue = getVariableValue(name); 3161 3162 String start = replaceProperties(aCurrentVar.getAttribute("start")); 3163 String end = replaceProperties(aCurrentVar.getAttribute("end")); 3164 3165 if (StringUtils.isNotEmpty(start)) { 3166 if (theValue instanceof byte[]) { 3167 theValue = new String((byte[]) theValue); 3168 } 3169 theValue = StringUtils.substringAfter(ObjectUtils.toString(theValue), start); 3170 if (StringUtils.isBlank((String) theValue)) { 3171 theValue = null; 3172 } 3173 } 3174 if (StringUtils.isNotEmpty(end)) { 3175 theValue = StringUtils.substringBefore((String) theValue, end); 3176 if (StringUtils.isBlank((String) theValue)) { 3177 theValue = null; 3178 } 3179 } 3180 3181 applyResult(aCurrentVar, name, theValue); 3182 3183 if (contains && theValue == null) { 3184 stop(); 3185 } 3186 } 3187 3188 private Object convert(Object theValue, String type) throws JSONException { 3189 if ("json".equals(type)) { 3190 Object parse = theValue; 3191 if (theValue instanceof String[]) { 3192 String[] array = (String[]) theValue; 3193 List<String> asList = Arrays.asList(array); 3194 theValue = new JSONArray(asList); 3195 } else if (theValue instanceof String) { 3196 if (StringUtils.startsWith((String) theValue, "{")) { 3197 parse = new JSONObject(theValue.toString()); 3198 } else if (StringUtils.startsWith((String) theValue, "[")) { 3199 parse = new JSONArray(theValue.toString()); 3200 } 3201 } 3202 theValue = parse; 3203 } else if ("string".equals(type) && theValue instanceof String[]) { 3204 theValue = StringUtils.join((String[]) theValue); 3205 } 3206 3207 return theValue; 3208 } 3209 3210 private String randomSelect(List possibleValues) throws NoSuchAlgorithmException { 3211 final String theInitialSelectionValue; 3212 if (this.random == null) { 3213 this.random = SecureRandom.getInstance("SHA1PRNG"); 3214 } 3215 theInitialSelectionValue = (String) possibleValues.get(this.random.nextInt(possibleValues.size())); 3216 return theInitialSelectionValue; 3217 } 3218 3219 @CommandExamples({ "<Note name='type:string' connection='type:string'>...</Note>" }) 3220 public void runCommandNote(final Node aCurrentAction) throws Throwable { 3221 } 3222 3223 @CommandExamples({ "<!-- ... -->" }) 3224 public void runCommandComment(final Node aCurrentAction) throws Throwable { 3225 } 3226 3227 @CommandExamples({ "<Extern class=''>\n...\n</Extern>" }) 3228 public void runCommandExtern(final Node command) throws Throwable { 3229 final Processor newInstance = makeProcessor(command); 3230 boolean success = false; 3231 try { 3232 this.externProcessor = newInstance; 3233 externProcessor.setTestName(getTestName()); 3234 newInstance.init(this, command); 3235 boolean rootRecipe = isRootRecipe(); 3236 newInstance.setRootContext(rootRecipe); 3237 newInstance.stackTask.addAll(this.stackTask); 3238 newInstance.taskNode(command, false); 3239 3240 this.variables = newInstance.variables; 3241 success = true; 3242 } finally { 3243 externProcessor.complete(success); 3244 externProcessor = null; 3245 } 3246 } 3247 3248 @CommandExamples({ "<Confirm message='type:string' name='type:string'/>", 3249 "<Confirm message='type:string' name='type:string'>...</Confirm>" }) 3250 public void runCommandConfirm(final Node aCurrentAction) throws Throwable { 3251 final String message = attr(aCurrentAction, "message"); 3252 final String name = attr(aCurrentAction, "name"); 3253 final Object nameVar = getVariableValue(name); 3254 3255 boolean confirmed = false; 3256 if (nameVar != null && nameVar instanceof String) { 3257 confirmed = BooleanUtils.toBoolean((String) nameVar); 3258 } else { 3259 AEManager manager = this.recipeListener.getManager(); 3260 confirmed = manager.confirmation(name, message, this, this.recipeListener.isNotifyMe()); 3261 } 3262 3263 if (aCurrentAction.size() > 0) { 3264 if (confirmed) { 3265 taskNode(aCurrentAction, false); 3266 } 3267 } else { 3268 if (!confirmed) { 3269 stop(); 3270 } 3271 } 3272 } 3273 3274 @CommandExamples({ "<WhileRun name='type:string' message='type:string'>...</WhileRun>" }) 3275 public void runCommandWhileRun(final Node aCurrentAction) throws Throwable { 3276 final String message = replaceProperties(aCurrentAction.getAttribute("message")); 3277 final String name = replaceProperties(aCurrentAction.getAttribute("name")); 3278 final Object nameVar = getVariableValue(name); 3279 3280 if (!(nameVar instanceof String) || BooleanUtils.toBoolean((String) nameVar)) { 3281 AEManager manager = this.recipeListener.getManager(); 3282 MessageHandler handler = manager.message(this, name, message, this.recipeListener.isNotifyMe()); 3283 taskNode(aCurrentAction, false); 3284 handler.close(); 3285 } 3286 }; 3287 3288 @CommandExamples({ "<Server port='type:integer' request='type:property' response='type:property' > ... </Server>", 3289 "<Server port='type:integer' numbers='type:integer' request='type:property' response='type:property' > ... </Server>" }) 3290 public void runCommandServer(final Node aCurrentAction) throws Throwable { 3291 3292 String encoding = replaceProperties(aCurrentAction.getAttribute("charset")); 3293 if (encoding == null) { 3294 encoding = "UTF-8"; 3295 } 3296 3297 final int thePort = Integer.parseInt(replaceProperties(aCurrentAction.getAttribute("port"))); 3298 int maxNumber = 0; 3299 3300 final String theMaxNumbers = replaceProperties(aCurrentAction.getAttribute("numbers")); 3301 if (theMaxNumbers != null) { 3302 maxNumber = Integer.parseInt(theMaxNumbers); 3303 } 3304 final String request = attr(aCurrentAction, "request"); 3305 final String response = attr(aCurrentAction, "response"); 3306 3307 ServerAction server = new ServerAction(this, aCurrentAction, thePort, request, response, encoding, maxNumber); 3308 server.perform(); 3309 } 3310 3311 @CommandExamples({ "<Restore/>", "<Restore name='type:property'> ... </Restore>", 3312 "<Restore except='type:property'> ... </Restore>" }) 3313 public void runCommandRestore(final Node command) throws Throwable { 3314 String name = attr(command, "name"); 3315 String except = attr(command, "except"); 3316 3317 if (CollectionUtils.isEmpty(command)) { 3318 final Map<String, Object> systemVariables = getListener().getManager().getSystemVariables(); 3319 this.variables.clear(); 3320 this.variables.putAll(systemVariables); 3321 debug("Task variables has been restored."); 3322 } else if (name != null) { 3323 Object savedVariable = getVariableValue(name); 3324 taskNode(command, false); 3325 setVariableValue(name, savedVariable); 3326 3327 } else if (except != null) { 3328 Map<String, Object> savedVariables = this.variables; 3329 this.variables = new HashMap<String, Object>(this.variables); 3330 3331 taskNode(command, false); 3332 3333 Object object = getVariableValue(except); 3334 this.variables.clear(); 3335 this.variables = savedVariables; 3336 setVariableValue(except, object); 3337 } 3338 3339 } 3340 3341 @CommandExamples({ "<Finally> ... </Finally>" }) 3342 public void runCommandFinally(final Node aCurrentAction) throws Throwable { 3343 } 3344 3345 @CommandExamples({ "<Break/>" }) 3346 public void runCommandBreak(final Node aCurrentAction) throws Throwable { 3347 } 3348 3349 @CommandExamples({ "<Stop/>", "<Stop ifNull='type:property'/>" }) 3350 public void runCommandStop(final Node aCurrentAction) throws Throwable { 3351 } 3352 3353 private boolean isEmpty(Object theOldValue) { 3354 boolean result = false; 3355 if (theOldValue == null) { 3356 result = true; 3357 } else if (theOldValue instanceof String[] && ((String[]) theOldValue).length == 0) { 3358 result = true; 3359 } else if (theOldValue instanceof Map && ((Map) theOldValue).size() == 0) { 3360 result = true; 3361 } 3362 return result; 3363 } 3364 3365 public void setVariableValue(String name, final Object value) { 3366 if (name != null) { 3367 super.setVariableValue(name, value); 3368 if (this.recipeListener != null && name.startsWith("!") == false) { 3369 this.recipeListener.changeVariable(name, value); 3370 } 3371 } 3372 } 3373 3374}