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