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.SAXReaderUtil;
034 import com.liferay.portal.tools.servicebuilder.ServiceBuilder;
035
036 import java.io.File;
037
038 import java.util.ArrayList;
039 import java.util.HashMap;
040 import java.util.HashSet;
041 import java.util.List;
042 import java.util.Map;
043 import java.util.Set;
044 import java.util.TreeSet;
045 import java.util.regex.Matcher;
046 import java.util.regex.Pattern;
047
048 import org.apache.commons.lang.StringEscapeUtils;
049
050
053 public class SeleniumBuilderFileUtil {
054
055 public SeleniumBuilderFileUtil(String baseDir) {
056 _baseDir = baseDir;
057 }
058
059 public String escapeHtml(String input) {
060 return StringEscapeUtils.escapeHtml(input);
061 }
062
063 public String escapeJava(String input) {
064 return StringEscapeUtils.escapeJava(input);
065 }
066
067 public List<Element> getAllChildElements(
068 Element element, String elementName) {
069
070 List<Element> allChildElements = new ArrayList<Element>();
071
072 List<Element> childElements = element.elements();
073
074 if (childElements.isEmpty()) {
075 return allChildElements;
076 }
077
078 for (Element childElement : childElements) {
079 String childElementName = childElement.getName();
080
081 if (childElementName.equals(elementName)) {
082 allChildElements.add(childElement);
083 }
084
085 allChildElements.addAll(
086 getAllChildElements(childElement, elementName));
087 }
088
089 return allChildElements;
090 }
091
092 public String getBaseDir() {
093 return _baseDir;
094 }
095
096 public Set<String> getChildElementAttributeValues(
097 Element element, String attributeName) {
098
099 Set<String> childElementAttributeValues = new TreeSet<String>();
100
101 List<Element> childElements = element.elements();
102
103 if (childElements.isEmpty()) {
104 return childElementAttributeValues;
105 }
106
107 for (Element childElement : childElements) {
108 String childElementName = childElement.attributeValue(
109 attributeName);
110
111 if (childElementName != null) {
112 int x = childElementName.lastIndexOf(StringPool.POUND);
113
114 if (x != -1) {
115 childElementAttributeValues.add(
116 childElementName.substring(0, x));
117 }
118 }
119
120 childElementAttributeValues.addAll(
121 getChildElementAttributeValues(childElement, attributeName));
122 }
123
124 return childElementAttributeValues;
125 }
126
127 public String getClassName(String fileName) {
128 String classSuffix = getClassSuffix(fileName);
129
130 return getClassName(fileName, classSuffix);
131 }
132
133 public String getClassName(String fileName, String classSuffix) {
134 return
135 getPackageName(fileName) + "." +
136 getSimpleClassName(fileName, classSuffix);
137 }
138
139 public String getClassSimpleClassName(String className) {
140 int x = className.lastIndexOf(CharPool.PERIOD);
141
142 return className.substring(x + 1);
143 }
144
145 public String getClassSuffix(String fileName) {
146 int x = fileName.indexOf(CharPool.PERIOD);
147
148 String classSuffix = StringUtil.upperCaseFirstLetter(
149 fileName.substring(x + 1));
150
151 if (classSuffix.equals("Testcase")) {
152 classSuffix = "TestCase";
153 }
154 else if (classSuffix.equals("Testsuite")) {
155 classSuffix = "TestSuite";
156 }
157
158 return classSuffix;
159 }
160
161 public String getHTMLFileName(String fileName) {
162 String javaFileName = getJavaFileName(fileName);
163
164 return StringUtil.replace(javaFileName, ".java", ".html");
165 }
166
167 public String getJavaFileName(String fileName) {
168 String classSuffix = getClassSuffix(fileName);
169
170 return getJavaFileName(fileName, classSuffix);
171 }
172
173 public String getJavaFileName(String fileName, String classSuffix) {
174 return
175 getPackagePath(fileName) + "/" +
176 getSimpleClassName(fileName, classSuffix) + ".java";
177 }
178
179 public int getLocatorCount(Element rootElement) {
180 String xml = rootElement.asXML();
181
182 for (int i = 1;; i++) {
183 if (xml.contains("${locator" + i + "}")) {
184 continue;
185 }
186
187 if (i > 1) {
188 i--;
189 }
190
191 return i;
192 }
193 }
194
195 public String getName(String fileName) {
196 int x = fileName.lastIndexOf(StringPool.SLASH);
197 int y = fileName.lastIndexOf(CharPool.PERIOD);
198
199 return fileName.substring(x + 1, y);
200 }
201
202 public String getNormalizedContent(String fileName) throws Exception {
203 String content = readFile(fileName);
204
205 if (fileName.endsWith(".path")) {
206 int x = content.indexOf("<tbody>");
207 int y = content.indexOf("</tbody>");
208
209 if ((x == -1) || (y == -1)) {
210 throwValidationException(1002, fileName, "tbody");
211 }
212
213 String pathTbody = content.substring(x, y + 8);
214
215 Map<String, Object> context = new HashMap<String, Object>();
216
217 context.put("pathName", getName(fileName));
218 context.put("pathTbody", pathTbody);
219
220 String newContent = processTemplate("path_xml.ftl", context);
221
222 if (!content.equals(newContent)) {
223 content = newContent;
224
225 writeFile(getBaseDir(), fileName, newContent, false);
226 }
227 }
228
229 StringBundler sb = new StringBundler();
230
231 int lineNumber = 1;
232
233 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
234 new UnsyncStringReader(content));
235
236 String line = null;
237
238 while ((line = unsyncBufferedReader.readLine()) != null) {
239 Pattern pattern = Pattern.compile("<[a-z\\-]+");
240
241 Matcher matcher = pattern.matcher(line);
242
243 if (matcher.find()) {
244 for (String reservedTag : _reservedTags) {
245 if (line.contains("<" + reservedTag)) {
246 line = StringUtil.replace(
247 line, matcher.group(),
248 matcher.group() + " line-number=\"" + lineNumber +
249 "\"");
250
251 break;
252 }
253 }
254 }
255
256 sb.append(line);
257
258 lineNumber++;
259 }
260
261 content = sb.toString();
262
263 if (content != null) {
264 content = content.trim();
265 content = StringUtil.replace(content, "\n", "");
266 content = StringUtil.replace(content, "\r\n", "");
267 content = StringUtil.replace(content, "\t", " ");
268 content = content.replaceAll(" +", " ");
269 }
270
271 return content;
272 }
273
274 public String getObjectName(String name) {
275 return StringUtil.upperCaseFirstLetter(name);
276 }
277
278 public String getPackageName(String fileName) {
279 String packagePath = getPackagePath(fileName);
280
281 return StringUtil.replace(
282 packagePath, StringPool.SLASH, StringPool.PERIOD);
283 }
284
285 public String getPackagePath(String fileName) {
286 int x = fileName.lastIndexOf(StringPool.SLASH);
287
288 return fileName.substring(0, x);
289 }
290
291 public String getReturnType(String name) {
292 if (name.startsWith("Is")) {
293 return "boolean";
294 }
295
296 return "void";
297 }
298
299 public Element getRootElement(String fileName) throws Exception {
300 String content = getNormalizedContent(fileName);
301
302 try {
303 Document document = SAXReaderUtil.read(content, true);
304
305 Element rootElement = document.getRootElement();
306
307 validate(fileName, rootElement);
308
309 return rootElement;
310 }
311 catch (DocumentException de) {
312 throwValidationException(1007, fileName, de);
313 }
314
315 return null;
316 }
317
318 public String getSimpleClassName(String fileName) {
319 String classSuffix = getClassSuffix(fileName);
320
321 return getSimpleClassName(fileName, classSuffix);
322 }
323
324 public String getSimpleClassName(String fileName, String classSuffix) {
325 return getName(fileName) + classSuffix;
326 }
327
328 public String getVariableName(String name) {
329 return TextFormatter.format(name, TextFormatter.I);
330 }
331
332 public String normalizeFileName(String fileName) {
333 return StringUtil.replace(
334 fileName, StringPool.BACK_SLASH, StringPool.SLASH);
335 }
336
337 public String readFile(String fileName) throws Exception {
338 return FileUtil.read(getBaseDir() + "/" + fileName);
339 }
340
341 public void writeFile(String fileName, String content, boolean format)
342 throws Exception {
343
344 writeFile(getBaseDir() + "-generated", fileName, content, format);
345 }
346
347 public void writeFile(
348 String baseDir, String fileName, String content, boolean format)
349 throws Exception {
350
351 File file = new File(baseDir + "/" + fileName);
352
353 if (format) {
354 ServiceBuilder.writeFile(file, content);
355 }
356 else {
357 System.out.println("Writing " + file);
358
359 FileUtil.write(file, content);
360 }
361 }
362
363 protected String processTemplate(String name, Map<String, Object> context)
364 throws Exception {
365
366 return StringUtil.strip(
367 FreeMarkerUtil.process(_TPL_ROOT + name, context), '\r');
368 }
369
370 protected void throwValidationException(int errorCode, String fileName) {
371 throwValidationException(
372 errorCode, fileName, null, null, null, null, null);
373 }
374
375 protected void throwValidationException(
376 int errorCode, String fileName, Element element) {
377
378 throwValidationException(
379 errorCode, fileName, element, null, null, null, null);
380 }
381
382 protected void throwValidationException(
383 int errorCode, String fileName, Element element, String string1) {
384
385 throwValidationException(
386 errorCode, fileName, element, null, string1, null, null);
387 }
388
389 protected void throwValidationException(
390 int errorCode, String fileName, Element element, String string1,
391 String string2) {
392
393 throwValidationException(
394 errorCode, fileName, element, null, string1, string2, null);
395 }
396
397 protected void throwValidationException(
398 int errorCode, String fileName, Element element, String[] array) {
399
400 throwValidationException(
401 errorCode, fileName, element, array, null, null, null);
402 }
403
404 protected void throwValidationException(
405 int errorCode, String fileName, Element element, String[] array,
406 String string1, String string2, Exception e) {
407
408 String prefix = "Error " + errorCode + ": ";
409 String suffix = fileName;
410
411 if (element != null) {
412 suffix += ":" + element.attributeValue("line-number");
413 }
414
415 if (errorCode == 1000) {
416 throw new IllegalArgumentException(
417 prefix + "Invalid root element in " + suffix);
418 }
419 else if (errorCode == 1001) {
420 throw new IllegalArgumentException(
421 prefix + "Missing (" + StringUtil.merge(array, "|") +
422 ") child element in " + suffix);
423 }
424 else if (errorCode == 1002) {
425 throw new IllegalArgumentException(
426 prefix + "Invalid " + string1 + " element in " + suffix);
427 }
428 else if (errorCode == 1003) {
429 throw new IllegalArgumentException(
430 prefix + "Missing " + string1 + " attribute in " + suffix);
431 }
432 else if (errorCode == 1004) {
433 throw new IllegalArgumentException(
434 prefix + "Missing (" + StringUtil.merge(array, "|") +
435 ") attribute in " + suffix);
436 }
437 else if (errorCode == 1005) {
438 throw new IllegalArgumentException(
439 prefix + "Invalid " + string1 + " attribute in " + suffix);
440 }
441 else if (errorCode == 1006) {
442 throw new IllegalArgumentException(
443 prefix + "Invalid " + string1 + " attribute value in " +
444 suffix);
445 }
446 else if (errorCode == 1007) {
447 throw new IllegalArgumentException(
448 prefix + "Poorly formed XML in " + suffix, e);
449 }
450 else if (errorCode == 1008) {
451 throw new IllegalArgumentException(
452 prefix + "Duplicate file name " + string1 + " at " + suffix);
453 }
454 else if (errorCode == 1009) {
455 throw new IllegalArgumentException(
456 prefix + "Duplicate command name " + string1 + " at " + suffix);
457 }
458 else if (errorCode == 1010) {
459 throw new IllegalArgumentException(
460 prefix + "Invalid locator-key " + string1 + " at " + suffix);
461 }
462 else if (errorCode == 1011) {
463 throw new IllegalArgumentException(
464 prefix + "Invalid " + string1 + " name " + string2 + " at " +
465 suffix);
466 }
467 else if (errorCode == 1012) {
468 throw new IllegalArgumentException(
469 prefix + "Invalid " + string1 + " command " + string2 + " at " +
470 suffix);
471 }
472 else if (errorCode == 1013) {
473 throw new IllegalArgumentException(
474 prefix + "Invalid method " + string1 + " at " + suffix);
475 }
476 else if (errorCode == 1014) {
477 throw new IllegalArgumentException(
478 prefix + "Invalid path " + string1 + " at " + suffix);
479 }
480 else if (errorCode == 1015) {
481 throw new IllegalArgumentException(
482 prefix + "Poorly formed test case command " + string1 + " at " +
483 suffix);
484 }
485 else if (errorCode == 1016) {
486 throw new IllegalArgumentException(
487 prefix + "Invalid " + string1 + " attribute value " + string2 +
488 " in " + suffix);
489 }
490 else if (errorCode == 2000) {
491 throw new IllegalArgumentException(
492 prefix + "Too many child elements in the " + string1 +
493 " element in " + suffix);
494 }
495 else if (errorCode == 2001) {
496 throw new IllegalArgumentException(
497 prefix + "Action command " + string1 +
498 " does not match a function name at " + suffix);
499 }
500 else if (errorCode == 2002) {
501 throw new IllegalArgumentException(
502 prefix + "Missing matching " + string1 + ".path for " + suffix);
503 }
504 else {
505 throw new IllegalArgumentException(prefix + suffix);
506 }
507 }
508
509 protected void throwValidationException(
510 int errorCode, String fileName, Exception e) {
511
512 throwValidationException(
513 errorCode, fileName, null, null, null, null, e);
514 }
515
516 protected void throwValidationException(
517 int errorCode, String fileName, String string1) {
518
519 throwValidationException(
520 errorCode, fileName, null, null, string1, null, null);
521 }
522
523 protected void validate(String fileName, Element rootElement)
524 throws Exception {
525
526 if (fileName.endsWith(".action")) {
527 validateActionDocument(fileName, rootElement);
528 }
529 else if (fileName.endsWith(".function")) {
530 validateFunctionDocument(fileName, rootElement);
531 }
532 else if (fileName.endsWith(".macro")) {
533 validateMacroDocument(fileName, rootElement);
534 }
535 else if (fileName.endsWith(".path")) {
536 validatePathDocument(fileName, rootElement);
537 }
538 else if (fileName.endsWith(".testcase")) {
539 validateTestCaseDocument(fileName, rootElement);
540 }
541 else if (fileName.endsWith(".testsuite")) {
542 validateTestSuiteDocument(fileName, rootElement);
543 }
544 }
545
546 protected void validateActionCommandElement(
547 String fileName, Element commandElement,
548 String[] allowedBlockChildElementNames,
549 String[] allowedExecuteAttributeNames,
550 String[] allowedExecuteChildElementNames) {
551
552 List<Element> elements = commandElement.elements();
553
554 if (elements.isEmpty()) {
555 throwValidationException(
556 1001, fileName, commandElement,
557 new String[] {"case", "default"});
558 }
559
560 for (Element element : elements) {
561 List<Element> childElements = element.elements();
562
563 String elementName = element.getName();
564
565 if (childElements.size() > 1) {
566 throwValidationException(
567 2000, fileName, childElements.get(1), elementName);
568 }
569
570 if (elementName.equals("case")) {
571 List<Attribute> attributes = element.attributes();
572
573 boolean hasNeededAttributeName = false;
574
575 for (Attribute attribute : attributes) {
576 String attributeName = attribute.getName();
577
578 if (attributeName.equals("comparator")) {
579 String attributeValue = attribute.getValue();
580
581 if (!attributeValue.equals("contains") &&
582 !attributeValue.equals("endsWith") &&
583 !attributeValue.equals("equals") &&
584 !attributeValue.equals("startsWith")) {
585
586 throwValidationException(
587 1006, fileName, element, attributeName);
588 }
589 }
590 else if (attributeName.startsWith("locator") ||
591 attributeName.startsWith("locator-key")) {
592
593 String attributeValue = attribute.getValue();
594
595 if (Validator.isNull(attributeValue)) {
596 throwValidationException(
597 1006, fileName, element, attributeName);
598 }
599
600 hasNeededAttributeName = true;
601 }
602
603 if (!attributeName.equals("comparator") &&
604 !attributeName.equals("line-number") &&
605 !attributeName.startsWith("locator") &&
606 !attributeName.startsWith("locator-key")) {
607
608 throwValidationException(
609 1005, fileName, element, attributeName);
610 }
611
612 if (attributeName.equals("locator") ||
613 attributeName.equals("locator-key")) {
614
615 throwValidationException(
616 1005, fileName, element, attributeName);
617 }
618 }
619
620 if (!hasNeededAttributeName) {
621 throwValidationException(
622 1004, fileName, element,
623 new String[] {"locator1", "locator-key1"});
624 }
625
626 validateBlockElement(
627 fileName, element, new String[] {"execute"},
628 new String[] {"function"}, new String[0], new String[0]);
629 }
630 else if (elementName.equals("default")) {
631 List<Attribute> attributes = element.attributes();
632
633 if (attributes.size() != 1) {
634 Attribute attribute = attributes.get(1);
635
636 String attributeName = attribute.getName();
637
638 throwValidationException(
639 1005, fileName, element, attributeName);
640 }
641
642 validateBlockElement(
643 fileName, element, new String[] {"execute"},
644 new String[] {"function"}, new String[0], new String[0]);
645 }
646 else {
647 throwValidationException(1002, fileName, element, elementName);
648 }
649 }
650 }
651
652 protected void validateActionDocument(
653 String fileName, Element rootElement) {
654
655 if (!Validator.equals(rootElement.getName(), "definition")) {
656 throwValidationException(1000, fileName, rootElement);
657 }
658
659 List<Element> elements = rootElement.elements();
660
661 if (elements.isEmpty()) {
662 throwValidationException(
663 1001, fileName, rootElement, new String[] {"command"});
664 }
665
666 for (Element element : elements) {
667 String elementName = element.getName();
668
669 if (elementName.equals("command")) {
670 String attributeValue = element.attributeValue("name");
671
672 if (attributeValue == null) {
673 throwValidationException(1003, fileName, element, "name");
674 }
675 else if (Validator.isNull(attributeValue)) {
676 throwValidationException(1006, fileName, element, "name");
677 }
678
679 validateActionCommandElement(
680 fileName, element, new String[] {"execute"},
681 new String[] {"function"}, new String[0]);
682 }
683 else {
684 throwValidationException(1002, fileName, element, elementName);
685 }
686 }
687 }
688
689 protected void validateBlockElement(
690 String fileName, Element commandElement,
691 String[] allowedBlockChildElementNames,
692 String[] allowedExecuteAttributeNames,
693 String[] allowedExecuteChildElementNames,
694 String[] allowedIfConditionElementNames) {
695
696 List<Element> elements = commandElement.elements();
697
698 if (elements.isEmpty()) {
699 throwValidationException(
700 1001, fileName, commandElement, allowedBlockChildElementNames);
701 }
702
703 for (Element element : elements) {
704 String elementName = element.getName();
705
706 if (!ArrayUtil.contains(
707 allowedBlockChildElementNames, elementName)) {
708
709 throwValidationException(1002, fileName, element, elementName);
710 }
711
712 if (elementName.equals("echo") || elementName.equals("fail")) {
713 validateSimpleElement(
714 fileName, element, new String[] {"message"});
715 }
716 else if (elementName.equals("execute")) {
717 validateExecuteElement(
718 fileName, element, allowedExecuteAttributeNames, ".+",
719 allowedExecuteChildElementNames);
720 }
721 else if (elementName.equals("if")) {
722 validateIfElement(
723 fileName, element, allowedBlockChildElementNames,
724 allowedExecuteAttributeNames,
725 allowedExecuteChildElementNames,
726 allowedIfConditionElementNames);
727 }
728 else if (elementName.equals("var")) {
729 validateVarElement(fileName, element);
730 }
731 else if (elementName.equals("while")) {
732 validateWhileElement(
733 fileName, element, allowedBlockChildElementNames,
734 allowedExecuteAttributeNames,
735 allowedExecuteChildElementNames,
736 allowedIfConditionElementNames);
737 }
738 else {
739 throwValidationException(1002, fileName, element, elementName);
740 }
741 }
742 }
743
744 protected void validateExecuteElement(
745 String fileName, Element executeElement,
746 String[] allowedExecuteAttributeNames,
747 String allowedExecuteAttributeValuesRegex,
748 String[] allowedExecuteChildElementNames) {
749
750 boolean hasAllowedAttributeName = false;
751
752 List<Attribute> attributes = executeElement.attributes();
753
754 for (Attribute attribute : attributes) {
755 String attributeName = attribute.getName();
756
757 if (ArrayUtil.contains(
758 allowedExecuteAttributeNames, attributeName)) {
759
760 hasAllowedAttributeName = true;
761
762 break;
763 }
764 }
765
766 if (!hasAllowedAttributeName) {
767 throwValidationException(
768 1004, fileName, executeElement, allowedExecuteAttributeNames);
769 }
770
771 String action = executeElement.attributeValue("action");
772 String function = executeElement.attributeValue("function");
773 String macro = executeElement.attributeValue("macro");
774 String selenium = executeElement.attributeValue("selenium");
775 String testCase = executeElement.attributeValue("test-case");
776 String testCaseCommand = executeElement.attributeValue(
777 "test-case-command");
778 String testClass = executeElement.attributeValue("test-class");
779 String testSuite = executeElement.attributeValue("test-suite");
780
781 if (action != null) {
782 if (Validator.isNull(action) ||
783 !action.matches(allowedExecuteAttributeValuesRegex)) {
784
785 throwValidationException(
786 1006, fileName, executeElement, "action");
787 }
788
789 for (Attribute attribute : attributes) {
790 String attributeName = attribute.getName();
791
792 if (!attributeName.equals("action") &&
793 !attributeName.equals("line-number") &&
794 !attributeName.startsWith("locator") &&
795 !attributeName.startsWith("locator-key") &&
796 !attributeName.startsWith("value")) {
797
798 throwValidationException(
799 1005, fileName, executeElement, attributeName);
800 }
801
802 if (attributeName.equals("locator") ||
803 attributeName.equals("locator-key") ||
804 attributeName.equals("value")) {
805
806 throwValidationException(
807 1005, fileName, executeElement, attributeName);
808 }
809 }
810 }
811 else if (function != null) {
812 if (Validator.isNull(function) ||
813 !function.matches(allowedExecuteAttributeValuesRegex)) {
814
815 throwValidationException(
816 1006, fileName, executeElement, "function");
817 }
818
819 for (Attribute attribute : attributes) {
820 String attributeName = attribute.getName();
821
822 if (!attributeName.equals("function") &&
823 !attributeName.equals("line-number") &&
824 !attributeName.startsWith("locator") &&
825 !attributeName.startsWith("value")) {
826
827 throwValidationException(
828 1005, fileName, executeElement, attributeName);
829 }
830
831 if (attributeName.equals("locator") ||
832 attributeName.equals("value")) {
833
834 throwValidationException(
835 1005, fileName, executeElement, attributeName);
836 }
837 }
838 }
839 else if (macro != null) {
840 if (Validator.isNull(macro) ||
841 !macro.matches(allowedExecuteAttributeValuesRegex)) {
842
843 throwValidationException(
844 1006, fileName, executeElement, "macro");
845 }
846
847 for (Attribute attribute : attributes) {
848 String attributeName = attribute.getName();
849
850 if (!attributeName.equals("macro") &&
851 !attributeName.equals("line-number")) {
852
853 throwValidationException(
854 1005, fileName, executeElement, attributeName);
855 }
856 }
857 }
858 else if (selenium != null) {
859 if (Validator.isNull(selenium) ||
860 !selenium.matches(allowedExecuteAttributeValuesRegex)) {
861
862 throwValidationException(
863 1006, fileName, executeElement, "selenium");
864 }
865
866 for (Attribute attribute : attributes) {
867 String attributeName = attribute.getName();
868
869 if (!attributeName.equals("argument1") &&
870 !attributeName.equals("argument2") &&
871 !attributeName.equals("line-number") &&
872 !attributeName.equals("selenium")) {
873
874 throwValidationException(
875 1005, fileName, executeElement, attributeName);
876 }
877 }
878 }
879 else if (testCase != null) {
880 if (Validator.isNull(testCase) ||
881 !testCase.matches(allowedExecuteAttributeValuesRegex)) {
882
883 throwValidationException(
884 1006, fileName, executeElement, "test-case");
885 }
886
887 for (Attribute attribute : attributes) {
888 String attributeName = attribute.getName();
889
890 if (!attributeName.equals("line-number") &&
891 !attributeName.equals("test-case")) {
892
893 throwValidationException(
894 1005, fileName, executeElement, attributeName);
895 }
896 }
897 }
898 else if (testCaseCommand != null) {
899 if (Validator.isNull(testCaseCommand) ||
900 !testCaseCommand.matches(allowedExecuteAttributeValuesRegex)) {
901
902 throwValidationException(
903 1006, fileName, executeElement, "test-case-command");
904 }
905
906 if (testCaseCommand.contains("#")) {
907 int x = testCaseCommand.lastIndexOf("#");
908
909 String testCaseName = testCaseCommand.substring(0, x);
910
911 String testCaseCommandName = testCaseCommand.substring(x + 1);
912
913 if (Validator.isNull(testCaseCommandName) ||
914 Validator.isNull(testCaseName)) {
915
916 throwValidationException(
917 1015, fileName, executeElement, testCaseCommand);
918 }
919 }
920 else {
921 throwValidationException(
922 1015, fileName, executeElement, testCaseCommand);
923 }
924
925 for (Attribute attribute : attributes) {
926 String attributeName = attribute.getName();
927
928 if (!attributeName.equals("line-number") &&
929 !attributeName.equals("test-case-command")) {
930
931 throwValidationException(
932 1005, fileName, executeElement, attributeName);
933 }
934 }
935 }
936 else if (testClass != null) {
937 if (Validator.isNull(testClass) ||
938 !testClass.matches(allowedExecuteAttributeValuesRegex)) {
939
940 throwValidationException(
941 1006, fileName, executeElement, "test-class");
942 }
943
944 for (Attribute attribute : attributes) {
945 String attributeName = attribute.getName();
946
947 if (!attributeName.equals("line-number") &&
948 !attributeName.equals("test-class")) {
949
950 throwValidationException(
951 1005, fileName, executeElement, attributeName);
952 }
953 }
954 }
955 else if (testSuite != null) {
956 if (Validator.isNull(testSuite) ||
957 !testSuite.matches(allowedExecuteAttributeValuesRegex)) {
958
959 throwValidationException(
960 1006, fileName, executeElement, "test-suite");
961 }
962
963 for (Attribute attribute : attributes) {
964 String attributeName = attribute.getName();
965
966 if (!attributeName.equals("line-number") &&
967 !attributeName.equals("test-suite")) {
968
969 throwValidationException(
970 1005, fileName, executeElement, attributeName);
971 }
972 }
973 }
974 else {
975 throwValidationException(0, fileName);
976 }
977
978 List<Element> elements = executeElement.elements();
979
980 if (allowedExecuteChildElementNames.length == 0) {
981 if (!elements.isEmpty()) {
982 Element element = elements.get(0);
983
984 String elementName = element.getName();
985
986 throwValidationException(1002, fileName, element, elementName);
987 }
988 }
989 else {
990 String executeElementName = executeElement.getName();
991
992 for (Element element : elements) {
993 String elementName = element.getName();
994
995 if (executeElementName.equals("condition")) {
996 throwValidationException(
997 1002, fileName, element, elementName);
998 }
999
1000 if (elementName.equals("var")) {
1001 validateVarElement(fileName, element);
1002 }
1003 else {
1004 throwValidationException(
1005 1002, fileName, element, elementName);
1006 }
1007 }
1008 }
1009 }
1010
1011 protected void validateFunctionDocument(
1012 String fileName, Element rootElement) {
1013
1014 if (!Validator.equals(rootElement.getName(), "definition")) {
1015 throwValidationException(1000, fileName, rootElement);
1016 }
1017
1018 List<Element> elements = rootElement.elements();
1019
1020 if (elements.isEmpty()) {
1021 throwValidationException(
1022 1001, fileName, rootElement, new String[] {"command"});
1023 }
1024
1025 for (Element element : elements) {
1026 String elementName = element.getName();
1027
1028 if (elementName.equals("command")) {
1029 String attributeValue = element.attributeValue("name");
1030
1031 if (attributeValue == null) {
1032 throwValidationException(1003, fileName, element, "name");
1033 }
1034 else if (Validator.isNull(attributeValue)) {
1035 throwValidationException(1006, fileName, element, "name");
1036 }
1037
1038 validateBlockElement(
1039 fileName, element, new String[] {"execute", "if"},
1040 new String[] {"function", "selenium"}, new String[0],
1041 new String[] {"condition"});
1042 }
1043 else {
1044 throwValidationException(1002, fileName, element, elementName);
1045 }
1046 }
1047 }
1048
1049 protected void validateIfElement(
1050 String fileName, Element ifElement,
1051 String[] allowedBlockChildElementNames,
1052 String[] allowedExecuteAttributeNames,
1053 String[] allowedExecuteChildElementNames,
1054 String[] allowedIfConditionElementNames) {
1055
1056 List<Element> elements = ifElement.elements();
1057
1058 Set<String> elementNames = new HashSet<String>();
1059
1060 boolean hasAllowedIfConditionElementNames = false;
1061
1062 for (Element element : elements) {
1063 String elementName = element.getName();
1064
1065 elementNames.add(elementName);
1066
1067 if (ArrayUtil.contains(
1068 allowedIfConditionElementNames, elementName)) {
1069
1070 hasAllowedIfConditionElementNames = true;
1071 }
1072
1073 if (elementName.equals("condition")) {
1074 validateExecuteElement(
1075 fileName, element, allowedExecuteAttributeNames,
1076 ".*(is|Is).+", allowedExecuteChildElementNames);
1077 }
1078 else if (elementName.equals("contains")) {
1079 validateSimpleElement(
1080 fileName, element, new String[] {"string", "substring"});
1081 }
1082 else if (elementName.equals("else") || elementName.equals("then")) {
1083 validateBlockElement(
1084 fileName, element, allowedBlockChildElementNames,
1085 allowedExecuteAttributeNames,
1086 allowedExecuteChildElementNames,
1087 allowedIfConditionElementNames);
1088 }
1089 else if (elementName.equals("elseif")) {
1090 validateIfElement(
1091 fileName, element, allowedBlockChildElementNames,
1092 allowedExecuteAttributeNames,
1093 allowedExecuteChildElementNames,
1094 allowedIfConditionElementNames);
1095 }
1096 else if (elementName.equals("equals")) {
1097 validateSimpleElement(
1098 fileName, element, new String[] {"arg1", "arg2"});
1099 }
1100 else if (elementName.equals("isset")) {
1101 validateSimpleElement(fileName, element, new String[] {"var"});
1102 }
1103 else if (elementName.equals("and") || elementName.equals("not") ||
1104 elementName.equals("or")) {
1105
1106 validateIfElement(
1107 fileName, element, allowedBlockChildElementNames,
1108 allowedExecuteAttributeNames,
1109 allowedExecuteChildElementNames,
1110 allowedIfConditionElementNames);
1111 }
1112 else {
1113 throwValidationException(1002, fileName, element, elementName);
1114 }
1115 }
1116
1117 if (!hasAllowedIfConditionElementNames) {
1118 throwValidationException(
1119 1001, fileName, ifElement, allowedIfConditionElementNames);
1120 }
1121
1122 if (Validator.equals(ifElement.getName(), "and") ||
1123 Validator.equals(ifElement.getName(), "not") ||
1124 Validator.equals(ifElement.getName(), "or")) {
1125
1126 return;
1127 }
1128
1129 if (!elementNames.contains("then")) {
1130 throwValidationException(
1131 1001, fileName, ifElement, new String[] {"then"});
1132 }
1133 }
1134
1135 protected void validateMacroDocument(String fileName, Element rootElement) {
1136 if (!Validator.equals(rootElement.getName(), "definition")) {
1137 throwValidationException(1000, fileName, rootElement);
1138 }
1139
1140 List<Element> elements = rootElement.elements();
1141
1142 if (elements.isEmpty()) {
1143 throwValidationException(
1144 1001, fileName, rootElement, new String[] {"command", "var"});
1145 }
1146
1147 for (Element element : elements) {
1148 String elementName = element.getName();
1149
1150 if (elementName.equals("command")) {
1151 String attributeValue = element.attributeValue("name");
1152
1153 if (attributeValue == null) {
1154 throwValidationException(1003, fileName, element, "name");
1155 }
1156 else if (Validator.isNull(attributeValue)) {
1157 throwValidationException(1006, fileName, element, "name");
1158 }
1159
1160 validateBlockElement(
1161 fileName, element,
1162 new String[] {
1163 "echo", "execute", "fail", "if", "var","while"
1164 },
1165 new String[] {"action", "macro"}, new String[] {"var"},
1166 new String[] {
1167 "and", "condition", "contains", "equals", "isset",
1168 "not", "or"
1169 });
1170 }
1171 else if (elementName.equals("var")) {
1172 validateVarElement(fileName, element);
1173 }
1174 else {
1175 throwValidationException(1002, fileName, element, elementName);
1176 }
1177 }
1178 }
1179
1180 protected void validatePathDocument(String fileName, Element rootElement) {
1181 Element headElement = rootElement.element("head");
1182
1183 Element titleElement = headElement.element("title");
1184
1185 String title = titleElement.getText();
1186
1187 int x = fileName.lastIndexOf(StringPool.SLASH);
1188 int y = fileName.lastIndexOf(CharPool.PERIOD);
1189
1190 String shortFileName = fileName.substring(x + 1, y);
1191
1192 if ((title == null) || !shortFileName.equals(title)) {
1193 throwValidationException(0, fileName);
1194 }
1195
1196 Element bodyElement = rootElement.element("body");
1197
1198 Element tableElement = bodyElement.element("table");
1199
1200 Element theadElement = tableElement.element("thead");
1201
1202 Element trElement = theadElement.element("tr");
1203
1204 Element tdElement = trElement.element("td");
1205
1206 String tdText = tdElement.getText();
1207
1208 if ((tdText == null) || !shortFileName.equals(tdText)) {
1209 throwValidationException(0, fileName);
1210 }
1211
1212 Element tbodyElement = tableElement.element("tbody");
1213
1214 List<Element> elements = tbodyElement.elements();
1215
1216 for (Element element : elements) {
1217 String elementName = element.getName();
1218
1219 if (elementName.equals("tr")) {
1220 validatePathTrElement(fileName, element);
1221 }
1222 else {
1223 throwValidationException(1002, fileName, element, elementName);
1224 }
1225 }
1226 }
1227
1228 protected void validatePathTrElement(String fileName, Element trElement) {
1229 List<Element> elements = trElement.elements();
1230
1231 for (Element element : elements) {
1232 String elementName = element.getName();
1233
1234 if (!elementName.equals("td")) {
1235 throwValidationException(1002, fileName, element, elementName);
1236 }
1237 }
1238
1239 if (elements.size() < 3) {
1240 throwValidationException(
1241 1001, fileName, trElement, new String[] {"td"});
1242 }
1243
1244 if (elements.size() > 3) {
1245 Element element = elements.get(3);
1246
1247 String elementName = element.getName();
1248
1249 throwValidationException(1002, fileName, element, elementName);
1250 }
1251 }
1252
1253 protected void validateSimpleElement(
1254 String fileName, Element element, String[] neededAttributes) {
1255
1256 Map<String, Boolean> hasNeededAttributes =
1257 new HashMap<String, Boolean>();
1258
1259 for (String neededAttribute : neededAttributes) {
1260 hasNeededAttributes.put(neededAttribute, false);
1261 }
1262
1263 List<Attribute> attributes = element.attributes();
1264
1265 for (Attribute attribute : attributes) {
1266 String attributeName = attribute.getName();
1267 String attributeValue = attribute.getValue();
1268
1269 if (!_allowedNullAttributes.contains(attributeName) &&
1270 Validator.isNull(attributeValue)) {
1271
1272 throwValidationException(
1273 1006, fileName, element, attributeName);
1274 }
1275
1276 if (hasNeededAttributes.containsKey(attributeName)) {
1277 hasNeededAttributes.put(attributeName, true);
1278 }
1279
1280 if (!attributeName.equals("line-number") &&
1281 !hasNeededAttributes.containsKey(attributeName)) {
1282
1283 throwValidationException(
1284 1005, fileName, element, attributeName);
1285 }
1286 }
1287
1288 for (String neededAttribute : neededAttributes) {
1289 if (!hasNeededAttributes.get(neededAttribute)) {
1290 throwValidationException(
1291 1004, fileName, element, neededAttributes);
1292 }
1293 }
1294
1295 List<Element> childElements = element.elements();
1296
1297 if (!childElements.isEmpty()) {
1298 Element childElement = childElements.get(0);
1299
1300 String childElementName = childElement.getName();
1301
1302 throwValidationException(
1303 1002, fileName, childElement, childElementName);
1304 }
1305 }
1306
1307 protected void validateTestCaseDocument(
1308 String fileName, Element rootElement) {
1309
1310 if (!Validator.equals(rootElement.getName(), "definition")) {
1311 throwValidationException(1000, fileName, rootElement);
1312 }
1313
1314 List<Element> elements = rootElement.elements();
1315
1316 if (elements.isEmpty()) {
1317 throwValidationException(
1318 1001, fileName, rootElement, new String[] {"command"});
1319 }
1320
1321 for (Element element : elements) {
1322 String elementName = element.getName();
1323
1324 if (elementName.equals("command")) {
1325 String attributeValue = element.attributeValue("name");
1326
1327 if (attributeValue == null) {
1328 throwValidationException(1003, fileName, element, "name");
1329 }
1330 else if (Validator.isNull(attributeValue)) {
1331 throwValidationException(1006, fileName, element, "name");
1332 }
1333
1334 validateBlockElement(
1335 fileName, element, new String[] {"execute", "var"},
1336 new String[] {"action", "macro"}, new String[] {"var"},
1337 new String[0]);
1338 }
1339 else if (elementName.equals("set-up") ||
1340 elementName.equals("tear-down")) {
1341
1342 List<Attribute> attributes = element.attributes();
1343
1344 for (Attribute attribute : attributes) {
1345 String attributeName = attribute.getName();
1346
1347 if (!attributeName.equals("line-number")) {
1348 throwValidationException(
1349 1005, fileName, element, attributeName);
1350 }
1351 }
1352
1353 validateBlockElement(
1354 fileName, element, new String[] {"execute", "var"},
1355 new String[] {"action", "macro"}, new String[] {"var"},
1356 new String[0]);
1357 }
1358 else if (elementName.equals("var")) {
1359 validateVarElement(fileName, element);
1360 }
1361 else {
1362 throwValidationException(1002, fileName, element, elementName);
1363 }
1364 }
1365 }
1366
1367 protected void validateTestSuiteDocument(
1368 String fileName, Element rootElement) {
1369
1370 if (!Validator.equals(rootElement.getName(), "definition")) {
1371 throwValidationException(1000, fileName, rootElement);
1372 }
1373
1374 List<Element> elements = rootElement.elements();
1375
1376 if (elements.isEmpty()) {
1377 throwValidationException(
1378 1001, fileName, rootElement, new String[] {"execute"});
1379 }
1380
1381 for (Element element : elements) {
1382 String elementName = element.getName();
1383
1384 if (elementName.equals("execute")) {
1385 validateExecuteElement(
1386 fileName, element,
1387 new String[] {
1388 "test-case", "test-case-command", "test-class",
1389 "test-suite"
1390 },
1391 ".+", new String[0]);
1392 }
1393 else {
1394 throwValidationException(1002, fileName, element, elementName);
1395 }
1396 }
1397 }
1398
1399 protected void validateVarElement(String fileName, Element element) {
1400 List<Attribute> attributes = element.attributes();
1401
1402 Map<String, String> attributeMap = new HashMap<String, String>();
1403
1404 for (Attribute attribute : attributes) {
1405 String attributeName = attribute.getName();
1406 String attributeValue = attribute.getValue();
1407
1408 if (!attributeName.equals("value") &&
1409 Validator.isNull(attributeValue)) {
1410
1411 throwValidationException(
1412 1006, fileName, element, attributeName);
1413 }
1414
1415 if (!_allowedVarAttributes.contains(attributeName)) {
1416 throwValidationException(
1417 1005, fileName, element, attributeName);
1418 }
1419
1420 attributeMap.put(attributeName, attributeValue);
1421 }
1422
1423 if (!attributeMap.containsKey("name")) {
1424 throwValidationException(
1425 1004, fileName, element, new String[] {"name"});
1426 }
1427 else {
1428 String nameValue = attributeMap.get("name");
1429
1430 if (Validator.isNull(nameValue)) {
1431 throwValidationException(1006, fileName, element, "name");
1432 }
1433 }
1434
1435 if (!element.hasContent() &&
1436 !attributeMap.containsKey("locator-key") &&
1437 !attributeMap.containsKey("path") &&
1438 !attributeMap.containsKey("value")) {
1439
1440 throwValidationException(
1441 1004, fileName, element, new String [] {"value"});
1442 }
1443
1444 if (!attributeMap.containsKey("value")) {
1445 String locatorKeyValue = attributeMap.get("locator-key");
1446 String pathValue = attributeMap.get("path");
1447
1448 if (Validator.isNull(locatorKeyValue) &&
1449 Validator.isNotNull(pathValue)) {
1450
1451 throwValidationException(
1452 1004, fileName, element, new String [] {"locator-key"});
1453 }
1454
1455 if (Validator.isNotNull(locatorKeyValue) &&
1456 Validator.isNull(pathValue)) {
1457
1458 throwValidationException(
1459 1004, fileName, element, new String [] {"path"});
1460 }
1461 }
1462 else {
1463 String varValue = attributeMap.get("value");
1464
1465 if (element.hasContent()) {
1466 varValue = element.getText();
1467 }
1468
1469 Pattern pattern = Pattern.compile("\\$\\{([^\\}]*?)\\}");
1470
1471 Matcher matcher = pattern.matcher(varValue);
1472
1473 while (matcher.find()) {
1474 String statement = matcher.group(1);
1475
1476 Pattern statementPattern = Pattern.compile(
1477 "(.*)\\?(.*)\\(([^\\)]*?)\\)");
1478
1479 Matcher statementMatcher = statementPattern.matcher(statement);
1480
1481 if (statementMatcher.find()) {
1482 String operand = statementMatcher.group(1);
1483
1484 String method = statementMatcher.group(2);
1485
1486 if (operand.equals("") || method.equals("")) {
1487 throwValidationException(
1488 1006, fileName, element, "value");
1489 }
1490
1491 if (!_methodNames.contains(method)) {
1492 throwValidationException(
1493 1013, fileName, element, method);
1494 }
1495 }
1496 else {
1497 if (statement.matches(".*[\\?\\(\\)\\}\\{].*")) {
1498 throwValidationException(
1499 1006, fileName, element, "value");
1500 }
1501 }
1502 }
1503 }
1504
1505 List<Element> childElements = element.elements();
1506
1507 if (!childElements.isEmpty()) {
1508 Element childElement = childElements.get(0);
1509
1510 String childElementName = childElement.getName();
1511
1512 throwValidationException(
1513 1002, fileName, childElement, childElementName);
1514 }
1515 }
1516
1517 protected void validateWhileElement(
1518 String fileName, Element whileElement,
1519 String[] allowedBlockChildElementNames,
1520 String[] allowedExecuteAttributeNames,
1521 String[] allowedExecuteChildElementNames,
1522 String[] allowedIfConditionElementNames) {
1523
1524 List<Element> elements = whileElement.elements();
1525
1526 Set<String> elementNames = new HashSet<String>();
1527
1528 for (Element element : elements) {
1529 String elementName = element.getName();
1530
1531 elementNames.add(elementName);
1532
1533 if (elementName.equals("condition")) {
1534 validateExecuteElement(
1535 fileName, element, allowedExecuteAttributeNames,
1536 ".*(is|Is).+", allowedExecuteChildElementNames);
1537 }
1538 else if (elementName.equals("then")) {
1539 validateBlockElement(
1540 fileName, element, allowedBlockChildElementNames,
1541 allowedExecuteAttributeNames,
1542 allowedExecuteChildElementNames,
1543 allowedIfConditionElementNames);
1544 }
1545 else {
1546 throwValidationException(1002, fileName, element, elementName);
1547 }
1548 }
1549
1550 if (!elementNames.contains("condition") ||
1551 !elementNames.contains("then")) {
1552
1553 throwValidationException(
1554 1001, fileName, whileElement,
1555 new String[] {"condition", "then"});
1556 }
1557 }
1558
1559 private static final String _TPL_ROOT =
1560 "com/liferay/portal/tools/seleniumbuilder/dependencies/";
1561
1562 private static List<String> _allowedNullAttributes = ListUtil.fromArray(
1563 new String[] {
1564 "arg1", "arg2", "message", "string", "substring", "value"
1565 });
1566 private static List<String> _allowedVarAttributes = ListUtil.fromArray(
1567 new String[] {"line-number", "locator-key", "name", "path", "value"});
1568 private static List<String> _methodNames = ListUtil.fromArray(
1569 new String[] {
1570 "getFirstNumber", "increment", "length", "lowercase", "replace"
1571 });
1572 private static List<String> _reservedTags = ListUtil.fromArray(
1573 new String[] {
1574 "and", "case", "command", "condition", "contains", "default",
1575 "definition", "echo", "else", "elseif", "equals", "execute", "fail",
1576 "if", "isset", "not", "or", "set-up", "td", "tear-down", "then",
1577 "tr", "while", "var"
1578 });
1579
1580 private String _baseDir;
1581
1582 }