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