001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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    /**
051     * @author Michael Hashimoto
052     */
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    }