001
014
015 package com.liferay.portal.tools.seleniumbuilder;
016
017 import com.liferay.portal.freemarker.FreeMarkerUtil;
018 import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
019 import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
020 import com.liferay.portal.kernel.util.ArrayUtil;
021 import com.liferay.portal.kernel.util.CharPool;
022 import com.liferay.portal.kernel.util.FileUtil;
023 import com.liferay.portal.kernel.util.ListUtil;
024 import com.liferay.portal.kernel.util.StringBundler;
025 import com.liferay.portal.kernel.util.StringPool;
026 import com.liferay.portal.kernel.util.StringUtil;
027 import com.liferay.portal.kernel.util.TextFormatter;
028 import com.liferay.portal.kernel.util.Validator;
029 import com.liferay.portal.kernel.xml.Attribute;
030 import com.liferay.portal.kernel.xml.Document;
031 import com.liferay.portal.kernel.xml.DocumentException;
032 import com.liferay.portal.kernel.xml.Element;
033 import com.liferay.portal.kernel.xml.UnsecureSAXReaderUtil;
034 import com.liferay.portal.tools.ToolsUtil;
035
036 import java.io.ByteArrayInputStream;
037 import java.io.File;
038 import java.io.InputStream;
039
040 import java.util.ArrayList;
041 import java.util.HashMap;
042 import java.util.HashSet;
043 import java.util.List;
044 import java.util.Map;
045 import java.util.Properties;
046 import java.util.Set;
047 import java.util.TreeSet;
048 import java.util.regex.Matcher;
049 import java.util.regex.Pattern;
050
051 import javax.xml.xpath.XPath;
052 import javax.xml.xpath.XPathFactory;
053
054 import org.apache.commons.lang.StringEscapeUtils;
055
056
059 public class SeleniumBuilderFileUtil {
060
061 public SeleniumBuilderFileUtil(String baseDirName, String projectDirName) {
062 _baseDirName = baseDirName;
063
064 try {
065 String content = FileUtil.read(projectDirName + "/test.properties");
066
067 InputStream inputStream = new ByteArrayInputStream(
068 content.getBytes());
069
070 _properties.load(inputStream);
071 }
072 catch (Exception e) {
073 e.printStackTrace();
074 }
075
076 _componentNames = ListUtil.fromArray(
077 StringUtil.split(getProperty("component.names")));
078 _testCaseAvailablePropertyNames = ListUtil.fromArray(
079 StringUtil.split(
080 getProperty("test.case.available.property.names")));
081 _testrayAvailableComponentNames = ListUtil.fromArray(
082 StringUtil.split(getProperty("testray.available.component.names")));
083 }
084
085 public String escapeHtml(String input) {
086 return StringEscapeUtils.escapeHtml(input);
087 }
088
089 public String escapeJava(String input) {
090 return StringEscapeUtils.escapeJava(input);
091 }
092
093 public List<Element> getAllChildElements(
094 Element element, String elementName) {
095
096 List<Element> allChildElements = new ArrayList<>();
097
098 List<Element> childElements = element.elements();
099
100 if (childElements.isEmpty()) {
101 return allChildElements;
102 }
103
104 for (Element childElement : childElements) {
105 String childElementName = childElement.getName();
106
107 if (childElementName.equals(elementName)) {
108 allChildElements.add(childElement);
109 }
110
111 allChildElements.addAll(
112 getAllChildElements(childElement, elementName));
113 }
114
115 return allChildElements;
116 }
117
118 public String getBaseDirName() {
119 return _baseDirName;
120 }
121
122 public Set<String> getChildElementAttributeValues(
123 Element element, String attributeName) {
124
125 Set<String> childElementAttributeValues = new TreeSet<>();
126
127 List<Element> childElements = element.elements();
128
129 if (childElements.isEmpty()) {
130 return childElementAttributeValues;
131 }
132
133 for (Element childElement : childElements) {
134 String childElementName = childElement.attributeValue(
135 attributeName);
136
137 if (childElementName != null) {
138 int x = childElementName.lastIndexOf(StringPool.POUND);
139
140 if (x != -1) {
141 childElementAttributeValues.add(
142 childElementName.substring(0, x));
143 }
144 else if (attributeName.equals("function")) {
145 childElementAttributeValues.add(childElementName);
146 }
147 }
148
149 childElementAttributeValues.addAll(
150 getChildElementAttributeValues(childElement, attributeName));
151 }
152
153 return childElementAttributeValues;
154 }
155
156 public Set<String> getChildElementLineNumbers(Element element) {
157 Set<String> childElementLineNumbers = new TreeSet<>();
158
159 List<Element> childElements = element.elements();
160
161 if (childElements.isEmpty()) {
162 return childElementLineNumbers;
163 }
164
165 for (Element childElement : childElements) {
166 String childElementLineNumber = childElement.attributeValue(
167 "line-number");
168
169 if (childElementLineNumber != null) {
170 childElementLineNumbers.add(childElementLineNumber);
171 }
172
173 childElementLineNumbers.addAll(
174 getChildElementLineNumbers(childElement));
175 }
176
177 return childElementLineNumbers;
178 }
179
180 public String getClassName(String fileName) {
181 String classSuffix = getClassSuffix(fileName);
182
183 return getClassName(fileName, classSuffix);
184 }
185
186 public String getClassName(String fileName, String classSuffix) {
187 return
188 getPackageName(fileName) + "." +
189 getSimpleClassName(fileName, classSuffix);
190 }
191
192 public String getClassSimpleClassName(String className) {
193 int x = className.lastIndexOf(CharPool.PERIOD);
194
195 return className.substring(x + 1);
196 }
197
198 public String getClassSuffix(String fileName) {
199 int x = fileName.indexOf(CharPool.PERIOD);
200
201 String classSuffix = StringUtil.upperCaseFirstLetter(
202 fileName.substring(x + 1));
203
204 if (classSuffix.equals("Testcase")) {
205 classSuffix = "TestCase";
206 }
207
208 return classSuffix;
209 }
210
211 public List<String> getComponentNames() {
212 return _componentNames;
213 }
214
215 public String getDefaultCommandName(Element rootElement) {
216 return rootElement.attributeValue("default");
217 }
218
219 public String getHTMLFileName(String fileName) {
220 String javaFileName = getJavaFileName(fileName);
221
222 return StringUtil.replace(javaFileName, ".java", ".html");
223 }
224
225 public String getJavaFileName(String fileName) {
226 String classSuffix = getClassSuffix(fileName);
227
228 return getJavaFileName(fileName, classSuffix);
229 }
230
231 public String getJavaFileName(String fileName, String classSuffix) {
232 return
233 getPackagePath(fileName) + "/" +
234 getSimpleClassName(fileName, classSuffix) + ".java";
235 }
236
237 public int getLocatorCount(Element rootElement) {
238 String xml = rootElement.asXML();
239
240 for (int i = 1;; i++) {
241 if (xml.contains("${locator" + i + "}")) {
242 continue;
243 }
244
245 if (i > 1) {
246 i--;
247 }
248
249 return i;
250 }
251 }
252
253 public String getName(String fileName) {
254 int x = fileName.lastIndexOf(StringPool.SLASH);
255 int y = fileName.lastIndexOf(CharPool.PERIOD);
256
257 return fileName.substring(x + 1, y);
258 }
259
260 public String getNormalizedContent(String fileName) throws Exception {
261 String content = readFile(fileName);
262
263 if (fileName.endsWith(".path")) {
264 int x = content.indexOf("<tbody>");
265 int y = content.indexOf("</tbody>");
266
267 if ((x == -1) || (y == -1)) {
268 throwValidationException(1002, fileName, "tbody");
269 }
270
271 String pathTbody = content.substring(x, y + 8);
272
273 Map<String, Object> context = new HashMap<>();
274
275 context.put("pathName", getName(fileName));
276 context.put("pathTbody", pathTbody);
277
278 String newContent = processTemplate("path_xml.ftl", context);
279
280 if (!content.equals(newContent)) {
281 content = newContent;
282
283 writeFile(getBaseDirName(), fileName, newContent, false);
284 }
285 }
286
287 StringBundler sb = new StringBundler();
288
289 int lineNumber = 1;
290
291 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
292 new UnsyncStringReader(content));
293
294 String line = null;
295
296 while ((line = unsyncBufferedReader.readLine()) != null) {
297 Matcher matcher = _tagPattern.matcher(line);
298
299 if (matcher.find()) {
300 for (String reservedTag : _reservedTags) {
301 if (line.contains("<" + reservedTag)) {
302 line = StringUtil.replace(
303 line, matcher.group(),
304 matcher.group() + " line-number=\"" + lineNumber +
305 "\"");
306
307 break;
308 }
309 }
310 }
311
312 sb.append(line);
313
314 lineNumber++;
315 }
316
317 content = sb.toString();
318
319 if (content != null) {
320 content = content.trim();
321 content = StringUtil.replace(content, "\n", "");
322 content = StringUtil.replace(content, "\r\n", "");
323 content = StringUtil.replace(content, "\t", " ");
324 content = content.replaceAll(" +", " ");
325 }
326
327 return content;
328 }
329
330 public String getObjectName(String name) {
331 return StringUtil.upperCaseFirstLetter(name);
332 }
333
334 public String getPackageName(String fileName) {
335 String packagePath = getPackagePath(fileName);
336
337 return StringUtil.replace(
338 packagePath, StringPool.SLASH, StringPool.PERIOD);
339 }
340
341 public String getPackagePath(String fileName) {
342 int x = fileName.lastIndexOf(StringPool.SLASH);
343
344 return fileName.substring(0, x);
345 }
346
347 public String getReturnType(String name) {
348 if (name.startsWith("Is")) {
349 return "boolean";
350 }
351
352 return "void";
353 }
354
355 public Element getRootElement(String fileName) throws Exception {
356 String content = getNormalizedContent(fileName);
357
358 try {
359 Document document = UnsecureSAXReaderUtil.read(content, true);
360
361 Element rootElement = document.getRootElement();
362
363 validate(fileName, rootElement);
364
365 return rootElement;
366 }
367 catch (DocumentException de) {
368 throwValidationException(1007, fileName, de);
369 }
370
371 return null;
372 }
373
374 public String getSimpleClassName(String fileName) {
375 String classSuffix = getClassSuffix(fileName);
376
377 return getSimpleClassName(fileName, classSuffix);
378 }
379
380 public String getSimpleClassName(String fileName, String classSuffix) {
381 return getName(fileName) + classSuffix;
382 }
383
384 public String getVariableName(String name) {
385 return TextFormatter.format(name, TextFormatter.I);
386 }
387
388 public String normalizeFileName(String fileName) {
389 return StringUtil.replace(
390 fileName, StringPool.BACK_SLASH, StringPool.SLASH);
391 }
392
393 public String readFile(String fileName) throws Exception {
394 return FileUtil.read(getBaseDirName() + "/" + fileName);
395 }
396
397 public void writeFile(String fileName, String content, boolean format)
398 throws Exception {
399
400 writeFile(getBaseDirName() + "-generated", fileName, content, format);
401 }
402
403 public void writeFile(
404 String baseDirName, String fileName, String content, boolean format)
405 throws Exception {
406
407 File file = new File(baseDirName + "/" + fileName);
408
409 if (format) {
410 ToolsUtil.writeFile(file, content, null);
411 }
412 else {
413 System.out.println("Writing " + file);
414
415 FileUtil.write(file, content);
416 }
417 }
418
419 protected String getProperty(String propertyName) {
420 String propertyValue = _properties.getProperty(propertyName);
421
422 if (Validator.isNotNull(propertyValue)) {
423 Matcher matcher = _varElementPattern.matcher(propertyValue);
424
425 while (matcher.find()) {
426 propertyValue = propertyValue.replace(
427 matcher.group(), getProperty(matcher.group(1)));
428 }
429 }
430
431 return propertyValue;
432 }
433
434 protected String processTemplate(String name, Map<String, Object> context)
435 throws Exception {
436
437 return StringUtil.strip(
438 FreeMarkerUtil.process(_TPL_ROOT + name, context), '\r');
439 }
440
441 protected void throwValidationException(int errorCode, String fileName) {
442 throwValidationException(
443 errorCode, fileName, null, null, null, null, null);
444 }
445
446 protected void throwValidationException(
447 int errorCode, String fileName, Element element) {
448
449 throwValidationException(
450 errorCode, fileName, element, null, null, null, null);
451 }
452
453 protected void throwValidationException(
454 int errorCode, String fileName, Element element, String string1) {
455
456 throwValidationException(
457 errorCode, fileName, element, null, string1, null, null);
458 }
459
460 protected void throwValidationException(
461 int errorCode, String fileName, Element element, String string1,
462 String string2) {
463
464 throwValidationException(
465 errorCode, fileName, element, null, string1, string2, null);
466 }
467
468 protected void throwValidationException(
469 int errorCode, String fileName, Element element, String[] array) {
470
471 throwValidationException(
472 errorCode, fileName, element, array, null, null, null);
473 }
474
475 protected void throwValidationException(
476 int errorCode, String fileName, Element element, String[] array,
477 String string1) {
478
479 throwValidationException(
480 errorCode, fileName, element, array, string1, null, null);
481 }
482
483 protected void throwValidationException(
484 int errorCode, String fileName, Element element, String[] array,
485 String string1, String string2, Exception e) {
486
487 String prefix = "Error " + errorCode + ": ";
488 String suffix = fileName;
489
490 if (element != null) {
491 suffix += ":" + element.attributeValue("line-number");
492 }
493
494 if (errorCode == 1000) {
495 throw new IllegalArgumentException(
496 prefix + "Invalid root element in " + suffix);
497 }
498 else if (errorCode == 1001) {
499 throw new IllegalArgumentException(
500 prefix + "Missing (" + StringUtil.merge(array, "|") +
501 ") child element in " + suffix);
502 }
503 else if (errorCode == 1002) {
504 throw new IllegalArgumentException(
505 prefix + "Invalid " + string1 + " element in " + suffix);
506 }
507 else if (errorCode == 1003) {
508 throw new IllegalArgumentException(
509 prefix + "Missing " + string1 + " attribute in " + suffix);
510 }
511 else if (errorCode == 1004) {
512 throw new IllegalArgumentException(
513 prefix + "Missing (" + StringUtil.merge(array, "|") +
514 ") attribute in " + suffix);
515 }
516 else if (errorCode == 1005) {
517 throw new IllegalArgumentException(
518 prefix + "Invalid " + string1 + " attribute in " + suffix);
519 }
520 else if (errorCode == 1006) {
521 throw new IllegalArgumentException(
522 prefix + "Invalid " + string1 + " attribute value in " +
523 suffix);
524 }
525 else if (errorCode == 1007) {
526 throw new IllegalArgumentException(
527 prefix + "Poorly formed XML in " + suffix, e);
528 }
529 else if (errorCode == 1008) {
530 throw new IllegalArgumentException(
531 prefix + "Duplicate file name " + string1 + " at " + suffix);
532 }
533 else if (errorCode == 1009) {
534 throw new IllegalArgumentException(
535 prefix + "Duplicate command name " + string1 + " at " + suffix);
536 }
537 else if (errorCode == 1010) {
538 throw new IllegalArgumentException(
539 prefix + "Invalid locator-key " + string1 + " at " + suffix);
540 }
541 else if (errorCode == 1011) {
542 throw new IllegalArgumentException(
543 prefix + "Invalid " + string1 + " name " + string2 + " at " +
544 suffix);
545 }
546 else if (errorCode == 1012) {
547 throw new IllegalArgumentException(
548 prefix + "Invalid " + string1 + " command " + string2 + " at " +
549 suffix);
550 }
551 else if (errorCode == 1013) {
552 throw new IllegalArgumentException(
553 prefix + "Invalid method " + string1 + " at " + suffix);
554 }
555 else if (errorCode == 1014) {
556 throw new IllegalArgumentException(
557 prefix + "Invalid path " + string1 + " at " + suffix);
558 }
559 else if (errorCode == 1015) {
560 throw new IllegalArgumentException(
561 prefix + "Poorly formed test case command " + string1 + " at " +
562 suffix);
563 }
564 else if (errorCode == 1016) {
565 throw new IllegalArgumentException(
566 prefix + "Invalid " + string1 + " attribute value " + string2 +
567 " in " + suffix);
568 }
569 else if (errorCode == 1017) {
570 throw new IllegalArgumentException(
571 prefix + "Description '" + string1 +
572 "' must end with a '.' in " + suffix);
573 }
574 else if (errorCode == 1018) {
575 throw new IllegalArgumentException(
576 prefix + "Missing (" + StringUtil.merge(array, "|") +
577 ") in attribute " + string1 + " at " + suffix);
578 }
579 else if (errorCode == 2000) {
580 throw new IllegalArgumentException(
581 prefix + "Too many child elements in the " + string1 +
582 " element in " + suffix);
583 }
584 else if (errorCode == 2001) {
585 throw new IllegalArgumentException(
586 prefix + "Action command " + string1 +
587 " does not match a function name at " + suffix);
588 }
589 else if (errorCode == 2002) {
590 throw new IllegalArgumentException(
591 prefix + "Missing matching " + string1 + ".path for " + suffix);
592 }
593 else if (errorCode == 2003) {
594 throw new IllegalArgumentException(
595 prefix + "Illegal XPath " + string1 + " in " + suffix);
596 }
597 else if (errorCode == 2004) {
598 throw new IllegalArgumentException(
599 prefix + "Description '" + string1 +
600 "' must title convention in " + suffix);
601 }
602 else if (errorCode == 3001) {
603 throw new IllegalArgumentException(
604 prefix + "The property '" + string1 +
605 "' has an invalid component name '" + string2 + "' in " +
606 suffix);
607 }
608 else if (errorCode == 3002) {
609 throw new IllegalArgumentException(
610 prefix + "Missing property '" + string1 + "' for " + suffix);
611 }
612 else if (errorCode == 3003) {
613 throw new IllegalArgumentException(
614 prefix + "Invalid property " + string1 + " at " + suffix);
615 }
616 else {
617 throw new IllegalArgumentException(prefix + suffix);
618 }
619 }
620
621 protected void throwValidationException(
622 int errorCode, String fileName, Exception e) {
623
624 throwValidationException(
625 errorCode, fileName, null, null, null, null, e);
626 }
627
628 protected void throwValidationException(
629 int errorCode, String fileName, String string1) {
630
631 throwValidationException(
632 errorCode, fileName, null, null, string1, null, null);
633 }
634
635 protected void validate(String fileName, Element rootElement)
636 throws Exception {
637
638 if (fileName.endsWith(".action")) {
639 validateActionDocument(fileName, rootElement);
640 }
641 else if (fileName.endsWith(".function")) {
642 validateFunctionDocument(fileName, rootElement);
643 }
644 else if (fileName.endsWith(".macro")) {
645 validateMacroDocument(fileName, rootElement);
646 }
647 else if (fileName.endsWith(".path")) {
648 validatePathDocument(fileName, rootElement);
649 }
650 else if (fileName.endsWith(".testcase")) {
651 validateTestCaseDocument(fileName, rootElement);
652 }
653 }
654
655 protected void validateActionCommandElement(
656 String fileName, Element commandElement,
657 String[] allowedBlockChildElementNames,
658 String[] allowedExecuteAttributeNames,
659 String[] allowedExecuteChildElementNames) {
660
661 List<Element> elements = commandElement.elements();
662
663 if (elements.isEmpty()) {
664 throwValidationException(
665 1001, fileName, commandElement,
666 new String[] {"case", "default"});
667 }
668
669 for (Element element : elements) {
670 List<Element> descriptionElements = element.elements("description");
671
672 String elementName = element.getName();
673
674 if (descriptionElements.size() > 1) {
675 throwValidationException(
676 2000, fileName, descriptionElements.get(1), elementName);
677 }
678
679 List<Element> executeChildElements = element.elements("execute");
680
681 if (executeChildElements.size() > 1) {
682 throwValidationException(
683 2000, fileName, executeChildElements.get(1), elementName);
684 }
685
686 if (elementName.equals("case")) {
687 List<Attribute> attributes = element.attributes();
688
689 boolean hasNeededAttributeName = false;
690
691 for (Attribute attribute : attributes) {
692 String attributeName = attribute.getName();
693
694 if (attributeName.equals("comparator")) {
695 String attributeValue = attribute.getValue();
696
697 if (!attributeValue.equals("contains") &&
698 !attributeValue.equals("endsWith") &&
699 !attributeValue.equals("equals") &&
700 !attributeValue.equals("startsWith")) {
701
702 throwValidationException(
703 1006, fileName, element, attributeName);
704 }
705 }
706 else if (attributeName.equals("locator1") ||
707 attributeName.equals("locator2") ||
708 attributeName.equals("locator-key1") ||
709 attributeName.equals("locator-key2") ||
710 attributeName.equals("value1") ||
711 attributeName.equals("value2")) {
712
713 String attributeValue = attribute.getValue();
714
715 if (Validator.isNull(attributeValue)) {
716 throwValidationException(
717 1006, fileName, element, attributeName);
718 }
719
720 hasNeededAttributeName = true;
721 }
722
723 if (!attributeName.equals("comparator") &&
724 !attributeName.equals("line-number") &&
725 !attributeName.equals("locator1") &&
726 !attributeName.equals("locator2") &&
727 !attributeName.equals("locator-key1") &&
728 !attributeName.equals("locator-key2") &&
729 !attributeName.equals("value1") &&
730 !attributeName.equals("value2")) {
731
732 throwValidationException(
733 1005, fileName, element, attributeName);
734 }
735
736 if (attributeName.equals("locator") ||
737 attributeName.equals("locator-key") ||
738 attributeName.equals("value")) {
739
740 throwValidationException(
741 1005, fileName, element, attributeName);
742 }
743 }
744
745 if (!hasNeededAttributeName) {
746 throwValidationException(
747 1004, fileName, element,
748 new String[] {"locator1", "locator-key1", "value1"});
749 }
750
751 validateBlockElement(
752 fileName, element, new String[] {"execute"},
753 new String[] {"function"}, new String[0], new String[0]);
754 }
755 else if (elementName.equals("default")) {
756 List<Attribute> attributes = element.attributes();
757
758 if (attributes.size() != 1) {
759 Attribute attribute = attributes.get(1);
760
761 String attributeName = attribute.getName();
762
763 throwValidationException(
764 1005, fileName, element, attributeName);
765 }
766
767 validateBlockElement(
768 fileName, element, new String[] {"description", "execute"},
769 new String[] {"function"}, new String[0], new String[0]);
770 }
771 else {
772 throwValidationException(1002, fileName, element, elementName);
773 }
774 }
775 }
776
777 protected void validateActionDocument(
778 String fileName, Element rootElement) {
779
780 if (!Validator.equals(rootElement.getName(), "definition")) {
781 throwValidationException(1000, fileName, rootElement);
782 }
783
784 List<Element> elements = rootElement.elements();
785
786 if (elements.isEmpty()) {
787 throwValidationException(
788 1001, fileName, rootElement, new String[] {"command"});
789 }
790
791 for (Element element : elements) {
792 String elementName = element.getName();
793
794 if (elementName.equals("command")) {
795 String attributeValue = element.attributeValue("name");
796
797 if (attributeValue == null) {
798 throwValidationException(1003, fileName, element, "name");
799 }
800 else if (Validator.isNull(attributeValue)) {
801 throwValidationException(1006, fileName, element, "name");
802 }
803
804 validateActionCommandElement(
805 fileName, element, new String[] {"execute"},
806 new String[] {"function"}, new String[0]);
807 }
808 else {
809 throwValidationException(1002, fileName, element, elementName);
810 }
811 }
812 }
813
814 protected void validateBlockElement(
815 String fileName, Element commandElement,
816 String[] allowedBlockChildElementNames,
817 String[] allowedExecuteAttributeNames,
818 String[] allowedExecuteChildElementNames,
819 String[] allowedIfConditionElementNames) {
820
821 List<Element> elements = commandElement.elements();
822
823 if (elements.isEmpty()) {
824 throwValidationException(
825 1001, fileName, commandElement, allowedBlockChildElementNames);
826 }
827
828 for (Element element : elements) {
829 String elementName = element.getName();
830
831 if (!ArrayUtil.contains(
832 allowedBlockChildElementNames, elementName)) {
833
834 throwValidationException(1002, fileName, element, elementName);
835 }
836
837 if (elementName.equals("description")) {
838 validateSimpleElement(
839 fileName, element, new String[] {"message"});
840
841 String message = element.attributeValue("message");
842
843 if (!message.endsWith(".")) {
844 throwValidationException(
845 1017, fileName, commandElement, message);
846 }
847 }
848 else if (elementName.equals("echo") || elementName.equals("fail")) {
849 validateSimpleElement(
850 fileName, element, new String[] {"message"});
851 }
852 else if (elementName.equals("execute")) {
853 validateExecuteElement(
854 fileName, element, allowedExecuteAttributeNames, ".+",
855 allowedExecuteChildElementNames);
856 }
857 else if (elementName.equals("for")) {
858 validateForElement(
859 fileName, element, new String[] {"list", "param"},
860 allowedBlockChildElementNames, allowedExecuteAttributeNames,
861 allowedExecuteChildElementNames,
862 allowedIfConditionElementNames);
863 }
864 else if (elementName.equals("if") || elementName.equals("while")) {
865 validateIfElement(
866 fileName, element, allowedBlockChildElementNames,
867 allowedExecuteAttributeNames,
868 allowedExecuteChildElementNames,
869 allowedIfConditionElementNames);
870 }
871 else if (elementName.equals("property")) {
872 validatePropertyElement(fileName, element);
873 }
874 else if (elementName.equals("take-screenshot")) {
875 validateSimpleElement(fileName, element, new String[0]);
876 }
877 else if (elementName.equals("task")) {
878 validateBlockElement(
879 fileName, element, allowedBlockChildElementNames,
880 allowedExecuteAttributeNames,
881 allowedExecuteChildElementNames,
882 allowedIfConditionElementNames);
883 }
884 else if (elementName.equals("var")) {
885 validateVarElement(fileName, element);
886 }
887 else {
888 throwValidationException(1002, fileName, element, elementName);
889 }
890 }
891 }
892
893 protected void validateExecuteElement(
894 String fileName, Element executeElement,
895 String[] allowedExecuteAttributeNames,
896 String allowedExecuteAttributeValuesRegex,
897 String[] allowedExecuteChildElementNames) {
898
899 boolean hasAllowedAttributeName = false;
900
901 List<Attribute> attributes = executeElement.attributes();
902
903 for (Attribute attribute : attributes) {
904 String attributeName = attribute.getName();
905
906 if (ArrayUtil.contains(
907 allowedExecuteAttributeNames, attributeName)) {
908
909 hasAllowedAttributeName = true;
910
911 break;
912 }
913 }
914
915 if (!hasAllowedAttributeName) {
916 throwValidationException(
917 1004, fileName, executeElement, allowedExecuteAttributeNames);
918 }
919
920 String action = executeElement.attributeValue("action");
921 String function = executeElement.attributeValue("function");
922 String macro = executeElement.attributeValue("macro");
923 String macroDesktop = executeElement.attributeValue("macro-desktop");
924 String macroMobile = executeElement.attributeValue("macro-mobile");
925 String selenium = executeElement.attributeValue("selenium");
926 String testCase = executeElement.attributeValue("test-case");
927 String testCaseCommand = executeElement.attributeValue(
928 "test-case-command");
929 String testClass = executeElement.attributeValue("test-class");
930
931 if (action != null) {
932 if (Validator.isNull(action) ||
933 !action.matches(allowedExecuteAttributeValuesRegex)) {
934
935 throwValidationException(
936 1006, fileName, executeElement, "action");
937 }
938
939 for (Attribute attribute : attributes) {
940 String attributeName = attribute.getName();
941
942 if (!attributeName.equals("action") &&
943 !attributeName.equals("line-number") &&
944 !attributeName.equals("locator1") &&
945 !attributeName.equals("locator2") &&
946 !attributeName.equals("locator-key1") &&
947 !attributeName.equals("locator-key2") &&
948 !attributeName.equals("value1") &&
949 !attributeName.equals("value2")) {
950
951 throwValidationException(
952 1005, fileName, executeElement, attributeName);
953 }
954
955 if (attributeName.equals("locator") ||
956 attributeName.equals("locator-key") ||
957 attributeName.equals("value")) {
958
959 throwValidationException(
960 1005, fileName, executeElement, attributeName);
961 }
962
963 String attributeValue = attribute.getValue();
964
965 if (attributeName.equals("value1") &&
966 attributeValue.contains("move-file")) {
967
968 if (!attributeValue.contains("-Dfile") ||
969 !attributeValue.contains("-Dtofile")) {
970
971 throwValidationException(
972 1018, fileName, executeElement,
973 new String[] {"-Dfile", "-Dtofile"}, "value1");
974 }
975 }
976
977 if (attributeName.equals("value1") &&
978 attributeValue.contains("replace-file")) {
979
980 if (!attributeValue.contains("-Dfile") ||
981 !attributeValue.contains("-Dtoken") ||
982 !attributeValue.contains("-Dvalue")) {
983
984 throwValidationException(
985 1018, fileName, executeElement,
986 new String[] {"-Dfile", "-Dtoken", "-Dvalue"},
987 "value1");
988 }
989 }
990 }
991 }
992 else if (function != null) {
993 if (Validator.isNull(function) ||
994 !function.matches(allowedExecuteAttributeValuesRegex)) {
995
996 throwValidationException(
997 1006, fileName, executeElement, "function");
998 }
999
1000 for (Attribute attribute : attributes) {
1001 String attributeName = attribute.getName();
1002
1003 if (!attributeName.equals("function") &&
1004 !attributeName.equals("ignore-javascript-error") &&
1005 !attributeName.equals("line-number") &&
1006 !attributeName.startsWith("locator") &&
1007 !attributeName.startsWith("value")) {
1008
1009 throwValidationException(
1010 1005, fileName, executeElement, attributeName);
1011 }
1012
1013 if (attributeName.equals("locator") ||
1014 attributeName.equals("value") ||
1015 attributeName.startsWith("locator-key")) {
1016
1017 throwValidationException(
1018 1005, fileName, executeElement, attributeName);
1019 }
1020 }
1021 }
1022 else if (macro != null) {
1023 if (Validator.isNull(macro) ||
1024 !macro.matches(allowedExecuteAttributeValuesRegex)) {
1025
1026 throwValidationException(
1027 1006, fileName, executeElement, "macro");
1028 }
1029
1030 for (Attribute attribute : attributes) {
1031 String attributeName = attribute.getName();
1032
1033 if (!attributeName.equals("line-number") &&
1034 !attributeName.equals("macro")) {
1035
1036 throwValidationException(
1037 1005, fileName, executeElement, attributeName);
1038 }
1039 }
1040 }
1041 else if (macroDesktop != null) {
1042 if (Validator.isNull(macroDesktop) ||
1043 !macroDesktop.matches(allowedExecuteAttributeValuesRegex)) {
1044
1045 throwValidationException(
1046 1006, fileName, executeElement, "macro-desktop");
1047 }
1048
1049 for (Attribute attribute : attributes) {
1050 String attributeName = attribute.getName();
1051
1052 if (!attributeName.equals("line-number") &&
1053 !attributeName.equals("macro-desktop") &&
1054 !attributeName.equals("macro-mobile")) {
1055
1056 throwValidationException(
1057 1005, fileName, executeElement, attributeName);
1058 }
1059 }
1060 }
1061 else if (macroMobile != null) {
1062 if (Validator.isNull(macroMobile) ||
1063 !macroMobile.matches(allowedExecuteAttributeValuesRegex)) {
1064
1065 throwValidationException(
1066 1006, fileName, executeElement, "macro-mobile");
1067 }
1068
1069 for (Attribute attribute : attributes) {
1070 String attributeName = attribute.getName();
1071
1072 if (!attributeName.equals("line-number") &&
1073 !attributeName.equals("macro")) {
1074
1075 throwValidationException(
1076 1005, fileName, executeElement, attributeName);
1077 }
1078 }
1079 }
1080 else if (selenium != null) {
1081 if (Validator.isNull(selenium) ||
1082 !selenium.matches(allowedExecuteAttributeValuesRegex)) {
1083
1084 throwValidationException(
1085 1006, fileName, executeElement, "selenium");
1086 }
1087
1088 for (Attribute attribute : attributes) {
1089 String attributeName = attribute.getName();
1090
1091 if (!attributeName.equals("argument1") &&
1092 !attributeName.equals("argument2") &&
1093 !attributeName.equals("line-number") &&
1094 !attributeName.equals("selenium")) {
1095
1096 throwValidationException(
1097 1005, fileName, executeElement, attributeName);
1098 }
1099 }
1100 }
1101 else if (testCase != null) {
1102 if (Validator.isNull(testCase) ||
1103 !testCase.matches(allowedExecuteAttributeValuesRegex)) {
1104
1105 throwValidationException(
1106 1006, fileName, executeElement, "test-case");
1107 }
1108
1109 if (testCase.contains("#")) {
1110 int x = testCase.lastIndexOf("#");
1111
1112 if (x == -1) {
1113 throwValidationException(
1114 1015, fileName, executeElement, testCaseCommand);
1115 }
1116
1117 String testCaseName = testCase.substring(0, x);
1118
1119 String testCaseCommandName = testCase.substring(x + 1);
1120
1121 if (Validator.isNull(testCaseCommandName) ||
1122 Validator.isNull(testCaseName) ||
1123 !testCaseName.equals("super")) {
1124
1125 throwValidationException(
1126 1015, fileName, executeElement, testCase);
1127 }
1128 }
1129 else {
1130 throwValidationException(
1131 1015, fileName, executeElement, testCase);
1132 }
1133
1134 for (Attribute attribute : attributes) {
1135 String attributeName = attribute.getName();
1136
1137 if (!attributeName.equals("line-number") &&
1138 !attributeName.equals("test-case")) {
1139
1140 throwValidationException(
1141 1005, fileName, executeElement, attributeName);
1142 }
1143 }
1144 }
1145 else if (testCaseCommand != null) {
1146 if (Validator.isNull(testCaseCommand) ||
1147 !testCaseCommand.matches(allowedExecuteAttributeValuesRegex)) {
1148
1149 throwValidationException(
1150 1006, fileName, executeElement, "test-case-command");
1151 }
1152
1153 if (testCaseCommand.contains("#")) {
1154 int x = testCaseCommand.lastIndexOf("#");
1155
1156 String testCaseName = testCaseCommand.substring(0, x);
1157
1158 String testCaseCommandName = testCaseCommand.substring(x + 1);
1159
1160 if (Validator.isNull(testCaseCommandName) ||
1161 Validator.isNull(testCaseName)) {
1162
1163 throwValidationException(
1164 1015, fileName, executeElement, testCaseCommand);
1165 }
1166 }
1167 else {
1168 throwValidationException(
1169 1015, fileName, executeElement, testCaseCommand);
1170 }
1171
1172 for (Attribute attribute : attributes) {
1173 String attributeName = attribute.getName();
1174
1175 if (!attributeName.equals("line-number") &&
1176 !attributeName.equals("test-case-command")) {
1177
1178 throwValidationException(
1179 1005, fileName, executeElement, attributeName);
1180 }
1181 }
1182 }
1183 else if (testClass != null) {
1184 if (Validator.isNull(testClass) ||
1185 !testClass.matches(allowedExecuteAttributeValuesRegex)) {
1186
1187 throwValidationException(
1188 1006, fileName, executeElement, "test-class");
1189 }
1190
1191 for (Attribute attribute : attributes) {
1192 String attributeName = attribute.getName();
1193
1194 if (!attributeName.equals("line-number") &&
1195 !attributeName.equals("test-class")) {
1196
1197 throwValidationException(
1198 1005, fileName, executeElement, attributeName);
1199 }
1200 }
1201 }
1202 else {
1203 throwValidationException(0, fileName);
1204 }
1205
1206 List<Element> elements = executeElement.elements();
1207
1208 if (allowedExecuteChildElementNames.length == 0) {
1209 if (!elements.isEmpty()) {
1210 Element element = elements.get(0);
1211
1212 String elementName = element.getName();
1213
1214 throwValidationException(1002, fileName, element, elementName);
1215 }
1216 }
1217 else {
1218 String executeElementName = executeElement.getName();
1219
1220 for (Element element : elements) {
1221 String elementName = element.getName();
1222
1223 if (executeElementName.equals("condition")) {
1224 throwValidationException(
1225 1002, fileName, element, elementName);
1226 }
1227
1228 if (elementName.equals("var")) {
1229 validateVarElement(fileName, element);
1230 }
1231 else {
1232 throwValidationException(
1233 1002, fileName, element, elementName);
1234 }
1235 }
1236 }
1237 }
1238
1239 protected void validateForElement(
1240 String fileName, Element forElement, String[] neededAttributes,
1241 String[] allowedBlockChildElementNames,
1242 String[] allowedExecuteAttributeNames,
1243 String[] allowedExecuteChildElementNames,
1244 String[] allowedIfConditionElementNames) {
1245
1246 Map<String, Boolean> hasNeededAttributes = new HashMap<>();
1247
1248 for (String neededAttribute : neededAttributes) {
1249 hasNeededAttributes.put(neededAttribute, false);
1250 }
1251
1252 List<Attribute> attributes = forElement.attributes();
1253
1254 for (Attribute attribute : attributes) {
1255 String attributeName = attribute.getName();
1256 String attributeValue = attribute.getValue();
1257
1258 if (!_allowedNullAttributes.contains(attributeName) &&
1259 Validator.isNull(attributeValue)) {
1260
1261 throwValidationException(
1262 1006, fileName, forElement, attributeName);
1263 }
1264
1265 if (hasNeededAttributes.containsKey(attributeName)) {
1266 hasNeededAttributes.put(attributeName, true);
1267 }
1268
1269 if (!attributeName.equals("line-number") &&
1270 !hasNeededAttributes.containsKey(attributeName)) {
1271
1272 throwValidationException(
1273 1005, fileName, forElement, attributeName);
1274 }
1275 }
1276
1277 for (String neededAttribute : neededAttributes) {
1278 if (!hasNeededAttributes.get(neededAttribute)) {
1279 throwValidationException(
1280 1004, fileName, forElement, neededAttributes);
1281 }
1282 }
1283
1284 validateBlockElement(
1285 fileName, forElement, allowedBlockChildElementNames,
1286 allowedExecuteAttributeNames, allowedExecuteChildElementNames,
1287 allowedIfConditionElementNames);
1288 }
1289
1290 protected void validateFunctionDocument(
1291 String fileName, Element rootElement) {
1292
1293 if (!Validator.equals(rootElement.getName(), "definition")) {
1294 throwValidationException(1000, fileName, rootElement);
1295 }
1296
1297 String defaultCommandName = getDefaultCommandName(rootElement);
1298
1299 if (defaultCommandName == null) {
1300 throwValidationException(1003, fileName, rootElement, "default");
1301 }
1302
1303 List<Element> elements = rootElement.elements();
1304
1305 if (elements.isEmpty()) {
1306 throwValidationException(
1307 1001, fileName, rootElement, new String[] {"command"});
1308 }
1309
1310 for (Element element : elements) {
1311 String elementName = element.getName();
1312
1313 if (elementName.equals("command")) {
1314 String attributeValue = element.attributeValue("name");
1315
1316 if (attributeValue == null) {
1317 throwValidationException(1003, fileName, element, "name");
1318 }
1319 else if (Validator.isNull(attributeValue)) {
1320 throwValidationException(1006, fileName, element, "name");
1321 }
1322
1323 validateBlockElement(
1324 fileName, element, new String[] {"execute", "if"},
1325 new String[] {"function", "selenium"}, new String[0],
1326 new String[] {"condition", "contains"});
1327 }
1328 else {
1329 throwValidationException(1002, fileName, element, elementName);
1330 }
1331 }
1332 }
1333
1334 protected void validateIfElement(
1335 String fileName, Element ifElement,
1336 String[] allowedBlockChildElementNames,
1337 String[] allowedExecuteAttributeNames,
1338 String[] allowedExecuteChildElementNames,
1339 String[] allowedIfConditionElementNames) {
1340
1341 List<Element> elements = ifElement.elements();
1342
1343 Set<String> elementNames = new HashSet<>();
1344
1345 boolean hasAllowedIfConditionElementNames = false;
1346
1347 for (Element element : elements) {
1348 String elementName = element.getName();
1349
1350 elementNames.add(elementName);
1351
1352 if (ArrayUtil.contains(
1353 allowedIfConditionElementNames, elementName)) {
1354
1355 hasAllowedIfConditionElementNames = true;
1356 }
1357
1358 String ifElementName = ifElement.getName();
1359
1360 if (elementName.equals("and") || elementName.equals("not") ||
1361 elementName.equals("or")) {
1362
1363 validateIfElement(
1364 fileName, element, allowedBlockChildElementNames,
1365 allowedExecuteAttributeNames,
1366 allowedExecuteChildElementNames,
1367 allowedIfConditionElementNames);
1368 }
1369 else if (elementName.equals("condition")) {
1370 validateExecuteElement(
1371 fileName, element, allowedExecuteAttributeNames,
1372 ".*(is|Is).+", allowedExecuteChildElementNames);
1373 }
1374 else if (elementName.equals("contains")) {
1375 validateSimpleElement(
1376 fileName, element, new String[] {"string", "substring"});
1377
1378 if (fileName.endsWith(".function")) {
1379 List<Attribute> attributes = element.attributes();
1380
1381 for (Attribute attribute : attributes) {
1382 String attributeValue = attribute.getValue();
1383
1384 Matcher varElementMatcher = _varElementPattern.matcher(
1385 attributeValue);
1386
1387 Matcher varElementFunctionMatcher =
1388 _varElementFunctionPattern.matcher(attributeValue);
1389
1390 if (varElementMatcher.find() &&
1391 !varElementFunctionMatcher.find()) {
1392
1393 throwValidationException(
1394 1006, fileName, element, attribute.getName());
1395 }
1396 }
1397 }
1398 }
1399 else if (elementName.equals("else")) {
1400 if (ifElementName.equals("while")) {
1401 throwValidationException(
1402 1002, fileName, element, elementName);
1403 }
1404
1405 validateBlockElement(
1406 fileName, element, allowedBlockChildElementNames,
1407 allowedExecuteAttributeNames,
1408 allowedExecuteChildElementNames,
1409 allowedIfConditionElementNames);
1410 }
1411 else if (elementName.equals("elseif")) {
1412 if (ifElementName.equals("while")) {
1413 throwValidationException(
1414 1002, fileName, element, elementName);
1415 }
1416
1417 validateIfElement(
1418 fileName, element, allowedBlockChildElementNames,
1419 allowedExecuteAttributeNames,
1420 allowedExecuteChildElementNames,
1421 allowedIfConditionElementNames);
1422 }
1423 else if (elementName.equals("equals")) {
1424 validateSimpleElement(
1425 fileName, element, new String[] {"arg1", "arg2"});
1426 }
1427 else if (elementName.equals("isset")) {
1428 validateSimpleElement(fileName, element, new String[] {"var"});
1429 }
1430 else if (elementName.equals("then")) {
1431 validateBlockElement(
1432 fileName, element, allowedBlockChildElementNames,
1433 allowedExecuteAttributeNames,
1434 allowedExecuteChildElementNames,
1435 allowedIfConditionElementNames);
1436 }
1437 else {
1438 throwValidationException(1002, fileName, element, elementName);
1439 }
1440 }
1441
1442 if (!hasAllowedIfConditionElementNames) {
1443 throwValidationException(
1444 1001, fileName, ifElement, allowedIfConditionElementNames);
1445 }
1446
1447 if (Validator.equals(ifElement.getName(), "and") ||
1448 Validator.equals(ifElement.getName(), "not") ||
1449 Validator.equals(ifElement.getName(), "or")) {
1450
1451 return;
1452 }
1453
1454 if (!elementNames.contains("then")) {
1455 throwValidationException(
1456 1001, fileName, ifElement, new String[] {"then"});
1457 }
1458 }
1459
1460 protected void validateMacroDocument(String fileName, Element rootElement) {
1461 if (!Validator.equals(rootElement.getName(), "definition")) {
1462 throwValidationException(1000, fileName, rootElement);
1463 }
1464
1465 List<Element> elements = rootElement.elements();
1466
1467 String extendsName = rootElement.attributeValue("extends");
1468
1469 if (elements.isEmpty() && (extendsName == null)) {
1470 throwValidationException(
1471 1001, fileName, rootElement, new String[] {"command", "var"});
1472 }
1473 else if (extendsName != null) {
1474 if (Validator.isNull(extendsName)) {
1475 throwValidationException(
1476 1006, fileName, rootElement, "extends");
1477 }
1478 }
1479
1480 for (Element element : elements) {
1481 String elementName = element.getName();
1482
1483 if (elementName.equals("command")) {
1484 String attributeValue = element.attributeValue("name");
1485
1486 if (attributeValue == null) {
1487 throwValidationException(1003, fileName, element, "name");
1488 }
1489 else if (Validator.isNull(attributeValue)) {
1490 throwValidationException(1006, fileName, element, "name");
1491 }
1492
1493 validateBlockElement(
1494 fileName, element,
1495 new String[] {
1496 "description", "echo", "execute", "fail", "for", "if",
1497 "take-screenshot", "task", "var", "while"
1498 },
1499 new String[] {
1500 "action", "function", "macro", "macro-desktop",
1501 "macro-mobile"
1502 },
1503 new String[] {"var"},
1504 new String[] {
1505 "and", "condition", "contains", "equals", "isset",
1506 "not", "or"
1507 });
1508 }
1509 else if (elementName.equals("var")) {
1510 validateVarElement(fileName, element);
1511 }
1512 else {
1513 throwValidationException(1002, fileName, element, elementName);
1514 }
1515 }
1516 }
1517
1518 protected void validatePathDocument(String fileName, Element rootElement) {
1519 Element headElement = rootElement.element("head");
1520
1521 Element titleElement = headElement.element("title");
1522
1523 String title = titleElement.getText();
1524
1525 int x = fileName.lastIndexOf(StringPool.SLASH);
1526 int y = fileName.lastIndexOf(CharPool.PERIOD);
1527
1528 String shortFileName = fileName.substring(x + 1, y);
1529
1530 if ((title == null) || !shortFileName.equals(title)) {
1531 throwValidationException(0, fileName);
1532 }
1533
1534 Element bodyElement = rootElement.element("body");
1535
1536 Element tableElement = bodyElement.element("table");
1537
1538 Element theadElement = tableElement.element("thead");
1539
1540 Element trElement = theadElement.element("tr");
1541
1542 Element tdElement = trElement.element("td");
1543
1544 String tdText = tdElement.getText();
1545
1546 if ((tdText == null) || !shortFileName.equals(tdText)) {
1547 throwValidationException(0, fileName);
1548 }
1549
1550 Element tbodyElement = tableElement.element("tbody");
1551
1552 List<Element> elements = tbodyElement.elements();
1553
1554 for (Element element : elements) {
1555 String elementName = element.getName();
1556
1557 if (elementName.equals("tr")) {
1558 validatePathTrElement(fileName, element);
1559 }
1560 else {
1561 throwValidationException(1002, fileName, element, elementName);
1562 }
1563 }
1564 }
1565
1566 protected void validatePathTrElement(String fileName, Element trElement) {
1567 List<Element> elements = trElement.elements();
1568
1569 for (Element element : elements) {
1570 String elementName = element.getName();
1571
1572 if (!elementName.equals("td")) {
1573 throwValidationException(1002, fileName, element, elementName);
1574 }
1575 }
1576
1577 if (elements.size() < 3) {
1578 throwValidationException(
1579 1001, fileName, trElement, new String[] {"td"});
1580 }
1581
1582 if (elements.size() > 3) {
1583 Element element = elements.get(3);
1584
1585 String elementName = element.getName();
1586
1587 throwValidationException(1002, fileName, element, elementName);
1588 }
1589
1590 Element locatorElement = elements.get(1);
1591
1592 String locator = locatorElement.getText();
1593
1594 locator = locator.replace("${", "");
1595 locator = locator.replace("}", "");
1596 locator = locator.replace("/-/", "/");
1597
1598 if (locator.endsWith("/")) {
1599 locator = locator.substring(0, locator.length() - 1);
1600 }
1601
1602 if (!locator.equals("") && !locator.startsWith("link=") &&
1603 !locator.startsWith("title=") && !locator.contains(".png")) {
1604
1605 try {
1606 XPathFactory xPathFactory = XPathFactory.newInstance();
1607
1608 XPath xPath = xPathFactory.newXPath();
1609
1610 xPath.compile(locator);
1611 }
1612 catch (Exception e) {
1613 throwValidationException(2003, fileName, locator);
1614 }
1615 }
1616
1617 Element keyElement = elements.get(0);
1618
1619 String key = keyElement.getText();
1620
1621 Element descriptionElement = elements.get(2);
1622
1623 String description = descriptionElement.getText();
1624
1625 if (!key.equals("") && !key.equals("EXTEND_ACTION_PATH") &&
1626 !key.equals("PAGE_NAME") && !description.equals("")) {
1627
1628 if (description.endsWith(".")) {
1629 throwValidationException(2004, fileName, description);
1630 }
1631
1632 Matcher statmentMatcher = _pathTrElementStatementPattern.matcher(
1633 description);
1634
1635 if (!statmentMatcher.find()) {
1636 throwValidationException(2004, fileName, description);
1637 }
1638
1639 Matcher wordMatcher1 = _pathTrElementWordPattern1.matcher(
1640 description);
1641
1642 while (wordMatcher1.find()) {
1643 String word = wordMatcher1.group();
1644
1645 if (word.equals("a") || word.equals("and") ||
1646 word.equals("as") || word.equals("at") ||
1647 word.equals("by") || word.equals("for") ||
1648 word.equals("from") || word.equals("in") ||
1649 word.equals("of") || word.equals("the") ||
1650 word.equals("to")) {
1651
1652 continue;
1653 }
1654
1655 Matcher wordMatcher2 = _pathTrElementWordPattern2.matcher(word);
1656
1657 if (!wordMatcher2.find()) {
1658 throwValidationException(2004, fileName, description);
1659 }
1660 }
1661 }
1662 }
1663
1664 protected void validatePropertyElement(
1665 String fileName, Element propertyElement) {
1666
1667 List<Attribute> attributes = propertyElement.attributes();
1668
1669 String propertyName = propertyElement.attributeValue("name");
1670
1671 if (!_testCaseAvailablePropertyNames.contains(propertyName)) {
1672 throwValidationException(
1673 3003, fileName, propertyElement, propertyName);
1674 }
1675
1676 if (propertyName.equals("ignore.errors")) {
1677 String propertyDelimiter = propertyElement.attributeValue(
1678 "delimiter");
1679
1680 String propertyValue = propertyElement.attributeValue("value");
1681
1682 if (propertyDelimiter != null) {
1683 if (!propertyValue.contains(propertyDelimiter)) {
1684 throwValidationException(
1685 1006, fileName, propertyElement, "delimiter");
1686 }
1687 }
1688
1689 if (Validator.isNull(propertyValue)) {
1690 throwValidationException(
1691 1006, fileName, propertyElement, "value");
1692 }
1693 }
1694
1695 for (Attribute attribute : attributes) {
1696 String attributeName = attribute.getName();
1697
1698 if (attributeName.equals("delimiter") &&
1699 propertyName.equals("ignore.errors")) {
1700
1701 continue;
1702 }
1703 else if (attributeName.equals("line-number") ||
1704 attributeName.equals("name") ||
1705 attributeName.equals("value")) {
1706
1707 continue;
1708 }
1709 else {
1710 throwValidationException(
1711 1005, fileName, propertyElement, attributeName);
1712 }
1713 }
1714 }
1715
1716 protected void validateSimpleElement(
1717 String fileName, Element element, String[] neededAttributes) {
1718
1719 Map<String, Boolean> hasNeededAttributes = new HashMap<>();
1720
1721 for (String neededAttribute : neededAttributes) {
1722 hasNeededAttributes.put(neededAttribute, false);
1723 }
1724
1725 List<Attribute> attributes = element.attributes();
1726
1727 for (Attribute attribute : attributes) {
1728 String attributeName = attribute.getName();
1729 String attributeValue = attribute.getValue();
1730
1731 if (!_allowedNullAttributes.contains(attributeName) &&
1732 Validator.isNull(attributeValue)) {
1733
1734 throwValidationException(
1735 1006, fileName, element, attributeName);
1736 }
1737
1738 if (hasNeededAttributes.containsKey(attributeName)) {
1739 hasNeededAttributes.put(attributeName, true);
1740 }
1741
1742 if (!attributeName.equals("line-number") &&
1743 !hasNeededAttributes.containsKey(attributeName)) {
1744
1745 throwValidationException(
1746 1005, fileName, element, attributeName);
1747 }
1748 }
1749
1750 for (String neededAttribute : neededAttributes) {
1751 if (!hasNeededAttributes.get(neededAttribute)) {
1752 throwValidationException(
1753 1004, fileName, element, neededAttributes);
1754 }
1755 }
1756
1757 List<Element> childElements = element.elements();
1758
1759 if (!childElements.isEmpty()) {
1760 Element childElement = childElements.get(0);
1761
1762 String childElementName = childElement.getName();
1763
1764 throwValidationException(
1765 1002, fileName, childElement, childElementName);
1766 }
1767 }
1768
1769 protected void validateTestCaseDocument(
1770 String fileName, Element rootElement) {
1771
1772 if (!Validator.equals(rootElement.getName(), "definition")) {
1773 throwValidationException(1000, fileName, rootElement);
1774 }
1775
1776 String extendedTestCase = rootElement.attributeValue("extends");
1777
1778 if (extendedTestCase != null) {
1779 if (Validator.isNull(extendedTestCase)) {
1780 throwValidationException(
1781 1006, fileName, rootElement, "extends");
1782 }
1783 }
1784
1785 String componentName = rootElement.attributeValue("component-name");
1786
1787 if (componentName == null) {
1788 throwValidationException(
1789 1003, fileName, rootElement, "component-name");
1790 }
1791
1792 if ((componentName != null) &&
1793 !_componentNames.contains(componentName)) {
1794
1795 throwValidationException(
1796 1006, fileName, rootElement, "component-name");
1797 }
1798
1799 List<Element> elements = rootElement.elements();
1800
1801 if (Validator.isNull(extendedTestCase)) {
1802 if (elements.isEmpty()) {
1803 throwValidationException(
1804 1001, fileName, rootElement, new String[] {"command"});
1805 }
1806 }
1807
1808 for (Element element : elements) {
1809 String elementName = element.getName();
1810
1811 if (elementName.equals("command")) {
1812 String attributeValue = element.attributeValue("name");
1813
1814 if (attributeValue == null) {
1815 throwValidationException(1003, fileName, element, "name");
1816 }
1817 else if (Validator.isNull(attributeValue)) {
1818 throwValidationException(1006, fileName, element, "name");
1819 }
1820
1821 String priorityValue = element.attributeValue("priority");
1822
1823 if (priorityValue == null) {
1824 throwValidationException(
1825 1003, fileName, element, "priority");
1826 }
1827 else if (!(priorityValue.equals("1") ||
1828 priorityValue.equals("2") ||
1829 priorityValue.equals("3") ||
1830 priorityValue.equals("4") ||
1831 priorityValue.equals("5"))) {
1832
1833 throwValidationException(
1834 1006, fileName, element, "priority");
1835 }
1836
1837 validateBlockElement(
1838 fileName, element,
1839 new String[] {
1840 "description", "echo", "execute", "fail", "for", "if",
1841 "property", "take-screenshot", "task", "var", "while"
1842 },
1843 new String[] {
1844 "action", "function", "macro", "macro-desktop",
1845 "macro-mobile", "test-case"
1846 },
1847 new String[] {"var"},
1848 new String[] {
1849 "and", "condition", "contains", "equals", "isset",
1850 "not", "or"
1851 });
1852 }
1853 else if (elementName.equals("property")) {
1854 validatePropertyElement(fileName, element);
1855 }
1856 else if (elementName.equals("set-up") ||
1857 elementName.equals("tear-down")) {
1858
1859 List<Attribute> attributes = element.attributes();
1860
1861 for (Attribute attribute : attributes) {
1862 String attributeName = attribute.getName();
1863
1864 if (!attributeName.equals("line-number")) {
1865 throwValidationException(
1866 1005, fileName, element, attributeName);
1867 }
1868 }
1869
1870 validateBlockElement(
1871 fileName, element,
1872 new String[] {
1873 "description", "echo", "execute", "fail", "if",
1874 "take-screenshot", "task", "var", "while"
1875 },
1876 new String[] {
1877 "action", "function", "macro", "macro-desktop",
1878 "macro-mobile", "test-case"
1879 },
1880 new String[] {"var"},
1881 new String[] {
1882 "and", "condition", "contains", "equals", "isset",
1883 "not", "or"
1884 });
1885 }
1886 else if (elementName.equals("var")) {
1887 validateVarElement(fileName, element);
1888 }
1889 else {
1890 throwValidationException(1002, fileName, element, elementName);
1891 }
1892 }
1893
1894 elements = getAllChildElements(rootElement, "property");
1895
1896 for (Element element : elements) {
1897 String name = element.attributeValue("name");
1898 String value = element.attributeValue("value");
1899
1900 if (name.equals("testray.component.names")) {
1901 List<String> testrayComponentNames = ListUtil.fromArray(
1902 StringUtil.split(value));
1903
1904 for (String testrayComponentName : testrayComponentNames) {
1905 if (!_testrayAvailableComponentNames.contains(
1906 testrayComponentName)) {
1907
1908 throwValidationException(
1909 3001, fileName, element, name,
1910 testrayComponentName);
1911 }
1912 }
1913 }
1914 else if (name.equals("testray.main.component.name")) {
1915 if (!_testrayAvailableComponentNames.contains(value)) {
1916 throwValidationException(
1917 3001, fileName, element, name, value);
1918 }
1919 }
1920 }
1921
1922 elements = rootElement.elements("property");
1923
1924 boolean rootTestrayMainComponentNameFound = false;
1925
1926 for (Element element : elements) {
1927 String name = element.attributeValue("name");
1928
1929 if (name.equals("testray.main.component.name")) {
1930 rootTestrayMainComponentNameFound = true;
1931
1932 break;
1933 }
1934 }
1935
1936 if (!rootTestrayMainComponentNameFound) {
1937 elements = rootElement.elements("command");
1938
1939 for (Element element : elements) {
1940 List<Element> propertyElements = getAllChildElements(
1941 element, "property");
1942
1943 boolean commandTestrayMainComponentNameFound = false;
1944
1945 for (Element propertyElement : propertyElements) {
1946 String propertyName = propertyElement.attributeValue(
1947 "name");
1948
1949 if (propertyName.equals("testray.main.component.name")) {
1950 commandTestrayMainComponentNameFound = true;
1951
1952 break;
1953 }
1954 }
1955
1956 if (!commandTestrayMainComponentNameFound) {
1957 throwValidationException(
1958 3002, fileName, element, "testray.main.component.name");
1959 }
1960 }
1961 }
1962 }
1963
1964 protected void validateVarElement(String fileName, Element element) {
1965 List<Attribute> attributes = element.attributes();
1966
1967 Map<String, String> attributeMap = new HashMap<>();
1968
1969 for (Attribute attribute : attributes) {
1970 String attributeName = attribute.getName();
1971 String attributeValue = attribute.getValue();
1972
1973 if (!attributeName.equals("value") &&
1974 Validator.isNull(attributeValue)) {
1975
1976 throwValidationException(
1977 1006, fileName, element, attributeName);
1978 }
1979
1980 if (!_allowedVarAttributes.contains(attributeName)) {
1981 throwValidationException(
1982 1005, fileName, element, attributeName);
1983 }
1984
1985 attributeMap.put(attributeName, attributeValue);
1986 }
1987
1988 if (!attributeMap.containsKey("name")) {
1989 throwValidationException(
1990 1004, fileName, element, new String[] {"name"});
1991 }
1992 else {
1993 String nameValue = attributeMap.get("name");
1994
1995 if (Validator.isNull(nameValue)) {
1996 throwValidationException(1006, fileName, element, "name");
1997 }
1998 }
1999
2000 if (attributeMap.containsKey("locator")) {
2001 String[] disallowedAttributes = {"locator-key", "path", "value"};
2002
2003 for (String disallowedAttribute : disallowedAttributes) {
2004 if (attributeMap.containsKey(disallowedAttribute)) {
2005 throwValidationException(
2006 1005, fileName, element, disallowedAttribute);
2007 }
2008 }
2009 }
2010 else if (attributeMap.containsKey("locator-key") &&
2011 attributeMap.containsKey("path")) {
2012
2013 if (attributeMap.containsKey("value")) {
2014 throwValidationException(1005, fileName, element, "value");
2015 }
2016 }
2017 else if (attributeMap.containsKey("locator-key")) {
2018 throwValidationException(
2019 1004, fileName, element, new String[] {"path"});
2020 }
2021 else if (attributeMap.containsKey("path")) {
2022 throwValidationException(
2023 1004, fileName, element, new String[] {"locator-key"});
2024 }
2025
2026 String varText = element.getText();
2027
2028 if (attributeMap.containsKey("locator") ||
2029 attributeMap.containsKey("locator-key") ||
2030 attributeMap.containsKey("path")) {
2031
2032 if (!Validator.isNull(varText)) {
2033 throwValidationException(1005, fileName, element, "value");
2034 }
2035 }
2036
2037 if (attributeMap.containsKey("method")) {
2038 String methodValue = attributeMap.get("method");
2039
2040 if (!methodValue.startsWith("MathUtil") &&
2041 !methodValue.startsWith("selenium") &&
2042 !methodValue.startsWith("StringUtil") &&
2043 !methodValue.startsWith("TestPropsUtil")) {
2044
2045 throwValidationException(1005, fileName, element, "method");
2046 }
2047
2048 if (!methodValue.contains("#")) {
2049 throwValidationException(1005, fileName, element, "method");
2050 }
2051 }
2052
2053 if (!attributeMap.containsKey("property-value") &&
2054 !attributeMap.containsKey("value") && Validator.isNull(varText)) {
2055
2056 if (!attributeMap.containsKey("group") &&
2057 !attributeMap.containsKey("input") &&
2058 !attributeMap.containsKey("locator") &&
2059 !attributeMap.containsKey("locator-key") &&
2060 !attributeMap.containsKey("method") &&
2061 !attributeMap.containsKey("path") &&
2062 !attributeMap.containsKey("pattern")) {
2063
2064 throwValidationException(
2065 1004, fileName, element, new String[] {"value"});
2066 }
2067 }
2068 else {
2069 String varValue = attributeMap.get("value");
2070
2071 if (Validator.isNull(varValue)) {
2072 varValue = varText;
2073 }
2074
2075 Matcher matcher = _varElementPattern.matcher(varValue);
2076
2077 while (matcher.find()) {
2078 String statement = matcher.group(1);
2079
2080 Matcher statementMatcher = _varElementStatementPattern.matcher(
2081 statement);
2082
2083 if (statementMatcher.find()) {
2084 String operand = statementMatcher.group(1);
2085
2086 String method = statementMatcher.group(2);
2087
2088 if (operand.equals("") || method.equals("")) {
2089 throwValidationException(
2090 1006, fileName, element, "value");
2091 }
2092
2093 if (!_methodNames.contains(method)) {
2094 throwValidationException(
2095 1013, fileName, element, method);
2096 }
2097 }
2098 }
2099 }
2100
2101 List<Element> childElements = element.elements();
2102
2103 if (!childElements.isEmpty()) {
2104 Element childElement = childElements.get(0);
2105
2106 String childElementName = childElement.getName();
2107
2108 throwValidationException(
2109 1002, fileName, childElement, childElementName);
2110 }
2111 }
2112
2113 private static final String _TPL_ROOT =
2114 "com/liferay/portal/tools/seleniumbuilder/dependencies/";
2115
2116 private static final List<String> _allowedNullAttributes =
2117 ListUtil.fromArray(
2118 new String[] {
2119 "arg1", "arg2", "delimiter", "message", "string", "substring",
2120 "value"
2121 });
2122 private static final List<String> _allowedVarAttributes =
2123 ListUtil.fromArray(
2124 new String[] {
2125 "attribute", "group", "input", "line-number", "locator",
2126 "locator-key", "method", "name", "path", "pattern",
2127 "property-value", "value"
2128 });
2129 private static final List<String> _methodNames = ListUtil.fromArray(
2130 new String[] {
2131 "getFirstNumber", "getIPAddress", "increment", "length",
2132 "lowercase", "replace", "uppercase"
2133 });
2134 private static final List<String> _reservedTags = ListUtil.fromArray(
2135 new String[] {
2136 "and", "case", "command", "condition", "contains", "default",
2137 "definition", "delimiter", "description", "echo", "else", "elseif",
2138 "equals", "execute", "fail", "for", "if", "isset", "not", "or",
2139 "property", "set-up", "take-screenshot", "task", "td", "tear-down",
2140 "then", "tr", "while", "var"
2141 });
2142
2143 private final String _baseDirName;
2144 private final List<String> _componentNames;
2145 private final Pattern _pathTrElementStatementPattern = Pattern.compile(
2146 "[A-Z0-9].*");
2147 private final Pattern _pathTrElementWordPattern1 = Pattern.compile(
2148 "[A-Za-z0-9\\-]+");
2149 private final Pattern _pathTrElementWordPattern2 = Pattern.compile(
2150 "[A-Z0-9][A-Za-z0-9\\-]*");
2151 private final Properties _properties = new Properties();
2152 private final Pattern _tagPattern = Pattern.compile("<[a-z\\-]+");
2153 private final List<String> _testCaseAvailablePropertyNames;
2154 private final List<String> _testrayAvailableComponentNames;
2155 private final Pattern _varElementFunctionPattern = Pattern.compile(
2156 "\\$\\{(locator|value)[0-9]+\\}");
2157 private final Pattern _varElementPattern = Pattern.compile(
2158 "\\$\\{([^\\}]*?)\\}");
2159 private final Pattern _varElementStatementPattern = Pattern.compile(
2160 "(.*)\\?(.*)\\(([^\\)]*?)\\)");
2161
2162 }