001    /**
002     * Copyright (c) 2000-present 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.sourceformatter;
016    
017    import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
018    import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
019    import com.liferay.portal.kernel.util.CharPool;
020    import com.liferay.portal.kernel.util.GetterUtil;
021    import com.liferay.portal.kernel.util.SetUtil;
022    import com.liferay.portal.kernel.util.StringBundler;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.kernel.util.StringUtil;
025    import com.liferay.portal.kernel.util.TextFormatter;
026    import com.liferay.portal.kernel.util.Validator;
027    
028    import com.thoughtworks.qdox.JavaDocBuilder;
029    import com.thoughtworks.qdox.model.JavaClass;
030    import com.thoughtworks.qdox.model.JavaMethod;
031    import com.thoughtworks.qdox.model.Type;
032    
033    import java.io.File;
034    import java.io.IOException;
035    
036    import java.util.ArrayList;
037    import java.util.HashMap;
038    import java.util.HashSet;
039    import java.util.List;
040    import java.util.Map;
041    import java.util.Set;
042    import java.util.regex.Matcher;
043    import java.util.regex.Pattern;
044    
045    /**
046     * @author Hugo Huijser
047     */
048    public class JSPSourceProcessor extends BaseSourceProcessor {
049    
050            protected void addImportCounts(String content) {
051                    Matcher matcher = _importsPattern.matcher(content);
052    
053                    while (matcher.find()) {
054                            String importName = matcher.group(1);
055    
056                            int count = 0;
057    
058                            if (_importCountMap.containsKey(importName)) {
059                                    count = _importCountMap.get(importName);
060                            }
061                            else {
062                                    int pos = importName.lastIndexOf(StringPool.PERIOD);
063    
064                                    String importClassName = importName.substring(pos + 1);
065    
066                                    if (_importClassNames.contains(importClassName)) {
067                                            _duplicateImportClassNames.add(importClassName);
068                                    }
069                                    else {
070                                            _importClassNames.add(importClassName);
071                                    }
072                            }
073    
074                            _importCountMap.put(importName, count + 1);
075                    }
076            }
077    
078            protected void addJSPIncludeFileNames(String fileName) {
079                    String content = _jspContents.get(fileName);
080    
081                    if (Validator.isNull(content)) {
082                            return;
083                    }
084    
085                    for (int x = 0;;) {
086                            x = content.indexOf("<%@ include file=", x);
087    
088                            if (x == -1) {
089                                    break;
090                            }
091    
092                            x = content.indexOf(StringPool.QUOTE, x);
093    
094                            if (x == -1) {
095                                    break;
096                            }
097    
098                            int y = content.indexOf(StringPool.QUOTE, x + 1);
099    
100                            if (y == -1) {
101                                    break;
102                            }
103    
104                            String includeFileName = content.substring(x + 1, y);
105    
106                            Matcher matcher = _jspIncludeFilePattern.matcher(includeFileName);
107    
108                            if (!matcher.find()) {
109                                    throw new RuntimeException(
110                                            "Invalid include " + includeFileName);
111                            }
112    
113                            includeFileName = buildFullPathIncludeFileName(
114                                    fileName, includeFileName);
115    
116                            if ((includeFileName.endsWith("jsp") ||
117                                     includeFileName.endsWith("jspf")) &&
118                                    !includeFileName.endsWith("html/common/init.jsp") &&
119                                    !includeFileName.endsWith("html/portlet/init.jsp") &&
120                                    !includeFileName.endsWith("html/taglib/init.jsp") &&
121                                    !_includeFileNames.contains(includeFileName)) {
122    
123                                    _includeFileNames.add(includeFileName);
124                            }
125    
126                            x = y;
127                    }
128            }
129    
130            protected void addJSPReferenceFileNames(String fileName) {
131                    for (Map.Entry<String, String> entry : _jspContents.entrySet()) {
132                            String referenceFileName = entry.getKey();
133    
134                            if (_includeFileNames.contains(referenceFileName)) {
135                                    continue;
136                            }
137    
138                            String sharedPath = fileName.substring(
139                                    0, StringUtil.startsWithWeight(referenceFileName, fileName));
140    
141                            if (Validator.isNull(sharedPath) ||
142                                    !sharedPath.contains(StringPool.SLASH)) {
143    
144                                    continue;
145                            }
146    
147                            if (!sharedPath.endsWith(StringPool.SLASH)) {
148                                    sharedPath = sharedPath.substring(
149                                            0, sharedPath.lastIndexOf(CharPool.SLASH) + 1);
150                            }
151    
152                            String content = null;
153    
154                            for (int x = -1;;) {
155                                    x = sharedPath.indexOf(CharPool.SLASH, x + 1);
156    
157                                    if (x == -1) {
158                                            break;
159                                    }
160    
161                                    if (content == null) {
162                                            content = entry.getValue();
163                                    }
164    
165                                    if (content.contains(
166                                                    "<%@ include file=\"" + fileName.substring(x))) {
167    
168                                            _includeFileNames.add(referenceFileName);
169    
170                                            break;
171                                    }
172                            }
173                    }
174            }
175    
176            protected void addJSPUnusedImports(
177                    String fileName, List<String> importLines,
178                    List<String> unneededImports) {
179    
180                    for (String importLine : importLines) {
181                            int x = importLine.indexOf(StringPool.QUOTE);
182                            int y = importLine.indexOf(StringPool.QUOTE, x + 1);
183    
184                            if ((x == -1) || (y == -1)) {
185                                    continue;
186                            }
187    
188                            String className = importLine.substring(x + 1, y);
189    
190                            className = className.substring(
191                                    className.lastIndexOf(StringPool.PERIOD) + 1);
192    
193                            String regex = "[^A-Za-z0-9_\"]" + className + "[^A-Za-z0-9_\"]";
194    
195                            if (hasUnusedJSPTerm(fileName, regex, "class")) {
196                                    unneededImports.add(importLine);
197                            }
198                    }
199            }
200    
201            protected String buildFullPathIncludeFileName(
202                    String fileName, String includeFileName) {
203    
204                    String topLevelDirName = null;
205    
206                    int x = includeFileName.indexOf(CharPool.SLASH, 1);
207    
208                    if (x != -1) {
209                            topLevelDirName = includeFileName.substring(1, x);
210                    }
211    
212                    String path = fileName;
213    
214                    while (true) {
215                            int y = path.lastIndexOf(CharPool.SLASH);
216    
217                            if (y == -1) {
218                                    return StringPool.BLANK;
219                            }
220    
221                            if (Validator.isNull(topLevelDirName) ||
222                                    path.equals(topLevelDirName) ||
223                                    path.endsWith(StringPool.SLASH + topLevelDirName)) {
224    
225                                    String fullPathIncludeFileName =
226                                            path.substring(0, y) + includeFileName;
227    
228                                    if (_jspContents.containsKey(fullPathIncludeFileName) &&
229                                            !fullPathIncludeFileName.equals(fileName)) {
230    
231                                            return fullPathIncludeFileName;
232                                    }
233                            }
234    
235                            path = path.substring(0, y);
236                    }
237            }
238    
239            protected boolean checkTaglibVulnerability(
240                    String jspContent, String vulnerability) {
241    
242                    int pos1 = -1;
243    
244                    do {
245                            pos1 = jspContent.indexOf(vulnerability, pos1 + 1);
246    
247                            if (pos1 != -1) {
248                                    int pos2 = jspContent.lastIndexOf(CharPool.LESS_THAN, pos1);
249    
250                                    while ((pos2 > 0) &&
251                                               (jspContent.charAt(pos2 + 1) == CharPool.PERCENT)) {
252    
253                                            pos2 = jspContent.lastIndexOf(CharPool.LESS_THAN, pos2 - 1);
254                                    }
255    
256                                    String tagContent = jspContent.substring(pos2, pos1);
257    
258                                    if (!tagContent.startsWith("<aui:") &&
259                                            !tagContent.startsWith("<liferay-portlet:") &&
260                                            !tagContent.startsWith("<liferay-util:") &&
261                                            !tagContent.startsWith("<portlet:")) {
262    
263                                            return true;
264                                    }
265                            }
266                    }
267                    while (pos1 != -1);
268    
269                    return false;
270            }
271    
272            protected void checkXSS(String fileName, String jspContent) {
273                    Matcher matcher = _xssPattern.matcher(jspContent);
274    
275                    while (matcher.find()) {
276                            boolean xssVulnerable = false;
277    
278                            String jspVariable = matcher.group(1);
279    
280                            String anchorVulnerability = " href=\"<%= " + jspVariable + " %>";
281    
282                            if (checkTaglibVulnerability(jspContent, anchorVulnerability)) {
283                                    xssVulnerable = true;
284                            }
285    
286                            String inputVulnerability = " value=\"<%= " + jspVariable + " %>";
287    
288                            if (checkTaglibVulnerability(jspContent, inputVulnerability)) {
289                                    xssVulnerable = true;
290                            }
291    
292                            String inlineStringVulnerability1 = "'<%= " + jspVariable + " %>";
293    
294                            if (jspContent.contains(inlineStringVulnerability1)) {
295                                    xssVulnerable = true;
296                            }
297    
298                            String inlineStringVulnerability2 = "(\"<%= " + jspVariable + " %>";
299    
300                            if (jspContent.contains(inlineStringVulnerability2)) {
301                                    xssVulnerable = true;
302                            }
303    
304                            String inlineStringVulnerability3 = " \"<%= " + jspVariable + " %>";
305    
306                            if (jspContent.contains(inlineStringVulnerability3)) {
307                                    xssVulnerable = true;
308                            }
309    
310                            String documentIdVulnerability = ".<%= " + jspVariable + " %>";
311    
312                            if (jspContent.contains(documentIdVulnerability)) {
313                                    xssVulnerable = true;
314                            }
315    
316                            if (xssVulnerable) {
317                                    processErrorMessage(
318                                            fileName, "(xss): " + fileName + " (" + jspVariable + ")");
319                            }
320                    }
321            }
322    
323            @Override
324            protected String doFormat(
325                            File file, String fileName, String absolutePath, String content)
326                    throws Exception {
327    
328                    String newContent = formatJSP(fileName, absolutePath, content);
329    
330                    newContent = StringUtil.replace(
331                            newContent,
332                            new String[] {
333                                    "<br/>", "\"/>", "\" >", "@page import", "\"%>", ")%>", "else{",
334                                    "for(", "function (", "if(", "javascript: ", "while(", "){\n",
335                                    ";;\n", "\n\n\n"
336                            },
337                            new String[] {
338                                    "<br />", "\" />", "\">", "@ page import", "\" %>", ") %>",
339                                    "else {", "for (", "function(", "if (", "javascript:",
340                                    "while (", ") {\n", ";\n", "\n\n"
341                            });
342    
343                    newContent = fixRedirectBackURL(newContent);
344    
345                    newContent = fixCompatClassImports(absolutePath, newContent);
346    
347                    if (_stripJSPImports && !_jspContents.isEmpty()) {
348                            try {
349                                    newContent = stripJSPImports(fileName, newContent);
350                            }
351                            catch (RuntimeException re) {
352                                    _stripJSPImports = false;
353                            }
354                    }
355    
356                    if (portalSource &&
357                            content.contains("page import=") &&
358                            !fileName.contains("init.jsp") &&
359                            !fileName.contains("init-ext.jsp") &&
360                            !fileName.contains("/taglib/aui/") &&
361                            !fileName.endsWith("touch.jsp") &&
362                            (fileName.endsWith(".jspf") || content.contains("include file="))) {
363    
364                            processErrorMessage(
365                                    fileName, "move imports to init.jsp: " + fileName);
366                    }
367    
368                    newContent = fixCopyright(newContent, absolutePath, fileName);
369    
370                    newContent = StringUtil.replace(
371                            newContent,
372                            new String[] {
373                                    "alert('<%= LanguageUtil.", "alert(\"<%= LanguageUtil.",
374                                    "confirm('<%= LanguageUtil.", "confirm(\"<%= LanguageUtil."
375                            },
376                            new String[] {
377                                    "alert('<%= UnicodeLanguageUtil.",
378                                    "alert(\"<%= UnicodeLanguageUtil.",
379                                    "confirm('<%= UnicodeLanguageUtil.",
380                                    "confirm(\"<%= UnicodeLanguageUtil."
381                            });
382    
383                    if (newContent.contains("    ")) {
384                            if (!fileName.matches(".*template.*\\.vm$")) {
385                                    processErrorMessage(fileName, "tab: " + fileName);
386                            }
387                    }
388    
389                    if (fileName.endsWith("init.jsp") || fileName.endsWith("init.jspf")) {
390                            int x = newContent.indexOf("<%@ page import=");
391    
392                            int y = newContent.lastIndexOf("<%@ page import=");
393    
394                            y = newContent.indexOf("%>", y);
395    
396                            if ((x != -1) && (y != -1) && (y > x)) {
397    
398                                    // Set compressImports to false to decompress imports
399    
400                                    boolean compressImports = true;
401    
402                                    if (compressImports) {
403                                            String imports = newContent.substring(x, y);
404    
405                                            imports = StringUtil.replace(
406                                                    imports, new String[] {"%>\r\n<%@ ", "%>\n<%@ "},
407                                                    new String[] {"%><%@\r\n", "%><%@\n"});
408    
409                                            newContent =
410                                                    newContent.substring(0, x) + imports +
411                                                            newContent.substring(y);
412                                    }
413                            }
414                    }
415    
416                    newContent = fixSessionKey(fileName, newContent, sessionKeyPattern);
417                    newContent = fixSessionKey(
418                            fileName, newContent, taglibSessionKeyPattern);
419    
420                    checkLanguageKeys(fileName, newContent, languageKeyPattern);
421                    checkLanguageKeys(fileName, newContent, _taglibLanguageKeyPattern1);
422                    checkLanguageKeys(fileName, newContent, _taglibLanguageKeyPattern2);
423                    checkLanguageKeys(fileName, newContent, _taglibLanguageKeyPattern3);
424    
425                    checkXSS(fileName, newContent);
426    
427                    // LPS-47682
428    
429                    newContent = fixIncorrectParameterTypeForLanguageUtil(
430                            newContent, true, fileName);
431    
432                    Matcher matcher = _javaClassPattern.matcher(newContent);
433    
434                    if (matcher.find()) {
435                            String javaClassContent = matcher.group();
436    
437                            javaClassContent = javaClassContent.substring(1);
438    
439                            String javaClassName = matcher.group(2);
440    
441                            String beforeJavaClass = newContent.substring(
442                                    0, matcher.start() + 1);
443    
444                            int javaClassLineCount =
445                                    StringUtil.count(beforeJavaClass, "\n") + 1;
446    
447                            newContent = formatJavaTerms(
448                                    javaClassName, null, file, fileName, absolutePath, newContent,
449                                    javaClassContent, javaClassLineCount, null, null, null, null);
450                    }
451    
452                    if (!content.equals(newContent)) {
453                            _jspContents.put(fileName, newContent);
454                    }
455    
456                    return newContent;
457            }
458    
459            protected String fixRedirectBackURL(String content) {
460                    Matcher matcher = _redirectBackURLPattern.matcher(content);
461    
462                    String newContent = content;
463    
464                    while (matcher.find()) {
465                            newContent = StringUtil.replaceFirst(
466                                    newContent, matcher.group(),
467                                    matcher.group(1) + "\n\n" + matcher.group(2), matcher.start());
468                    }
469    
470                    return newContent;
471            }
472    
473            @Override
474            protected void format() throws Exception {
475                    _moveFrequentlyUsedImportsToCommonInit = GetterUtil.getBoolean(
476                            getProperty("move.frequently.used.imports.to.common.init"));
477                    _unusedVariablesExclusions = getPropertyList(
478                            "jsp.unused.variables.excludes.files");
479    
480                    String[] excludes = new String[] {"**\\null.jsp", "**\\tools\\**"};
481                    String[] includes = new String[] {
482                            "**\\*.jsp", "**\\*.jspf", "**\\*.vm"
483                    };
484    
485                    List<String> fileNames = getFileNames(excludes, includes);
486    
487                    Pattern pattern = Pattern.compile(
488                            "\\s*@\\s*include\\s*file=['\"](.*)['\"]");
489    
490                    for (String fileName : fileNames) {
491                            File file = new File(BASEDIR + fileName);
492    
493                            fileName = StringUtil.replace(
494                                    fileName, StringPool.BACK_SLASH, StringPool.SLASH);
495    
496                            String absolutePath = getAbsolutePath(file);
497    
498                            String content = fileUtil.read(file);
499    
500                            Matcher matcher = pattern.matcher(content);
501    
502                            String newContent = content;
503    
504                            while (matcher.find()) {
505                                    newContent = StringUtil.replaceFirst(
506                                            newContent, matcher.group(),
507                                            "@ include file=\"" + matcher.group(1) + "\"",
508                                            matcher.start());
509                            }
510    
511                            processFormattedFile(file, fileName, content, newContent);
512    
513                            if (portalSource &&
514                                    _moveFrequentlyUsedImportsToCommonInit &&
515                                    fileName.endsWith("/init.jsp") &&
516                                    !absolutePath.contains("/modules/") &&
517                                    !fileName.endsWith("/common/init.jsp")) {
518    
519                                    addImportCounts(content);
520                            }
521    
522                            _jspContents.put(fileName, newContent);
523                    }
524    
525                    if (portalSource && _moveFrequentlyUsedImportsToCommonInit) {
526                            moveFrequentlyUsedImportsToCommonInit(4);
527                    }
528    
529                    for (String fileName : fileNames) {
530                            format(fileName);
531                    }
532            }
533    
534            protected String formatJSP(
535                            String fileName, String absolutePath, String content)
536                    throws Exception {
537    
538                    StringBundler sb = new StringBundler();
539    
540                    String currentAttributeAndValue = null;
541                    String previousAttribute = null;
542                    String previousAttributeAndValue = null;
543                    String tag = null;
544    
545                    String currentException = null;
546                    String previousException = null;
547    
548                    boolean hasUnsortedExceptions = false;
549    
550                    try (UnsyncBufferedReader unsyncBufferedReader =
551                                    new UnsyncBufferedReader(new UnsyncStringReader(content))) {
552    
553                            _checkedForIncludesFileNames = new HashSet<String>();
554                            _includeFileNames = new HashSet<String>();
555    
556                            int lineCount = 0;
557    
558                            String line = null;
559    
560                            String previousLine = StringPool.BLANK;
561    
562                            boolean readAttributes = false;
563    
564                            boolean javaSource = false;
565    
566                            while ((line = unsyncBufferedReader.readLine()) != null) {
567                                    lineCount++;
568    
569                                    if (portalSource && hasUnusedTaglib(fileName, line)) {
570                                            continue;
571                                    }
572    
573                                    if (!fileName.contains("jsonw") ||
574                                            !fileName.endsWith("action.jsp")) {
575    
576                                            line = trimLine(line, false);
577                                    }
578    
579                                    if (line.contains("<aui:button ") &&
580                                            line.contains("type=\"button\"")) {
581    
582                                            processErrorMessage(
583                                                    fileName, "aui:button " + fileName + " " + lineCount);
584                                    }
585    
586                                    if (line.contains("debugger.")) {
587                                            processErrorMessage(
588                                                    fileName, "debugger " + fileName + " " + lineCount);
589                                    }
590    
591                                    String trimmedLine = StringUtil.trimLeading(line);
592                                    String trimmedPreviousLine = StringUtil.trimLeading(
593                                            previousLine);
594    
595                                    checkStringBundler(trimmedLine, fileName, lineCount);
596    
597                                    checkEmptyCollection(trimmedLine, fileName, lineCount);
598    
599                                    if (trimmedLine.equals("<%") || trimmedLine.equals("<%!")) {
600                                            javaSource = true;
601                                    }
602                                    else if (trimmedLine.equals("%>")) {
603                                            javaSource = false;
604                                    }
605    
606                                    if (javaSource || trimmedLine.contains("<%= ")) {
607                                            checkInefficientStringMethods(
608                                                    line, fileName, absolutePath, lineCount);
609                                    }
610    
611                                    if (javaSource && portalSource &&
612                                            !isExcluded(
613                                                    _unusedVariablesExclusions, absolutePath, lineCount) &&
614                                            !_jspContents.isEmpty() &&
615                                            hasUnusedVariable(fileName, trimmedLine)) {
616    
617                                            continue;
618                                    }
619    
620                                    // LPS-47179
621    
622                                    if (line.contains(".sendRedirect(") &&
623                                            !fileName.endsWith("_jsp.jsp")) {
624    
625                                            processErrorMessage(
626                                                    fileName,
627                                                    "Do not use sendRedirect in jsp: " + fileName + " " +
628                                                            lineCount);
629                                    }
630    
631                                    if (!trimmedLine.equals("%>") && line.contains("%>") &&
632                                            !line.contains("--%>") && !line.contains(" %>")) {
633    
634                                            line = StringUtil.replace(line, "%>", " %>");
635                                    }
636    
637                                    if (line.contains("<%=") && !line.contains("<%= ")) {
638                                            line = StringUtil.replace(line, "<%=", "<%= ");
639                                    }
640    
641                                    if (trimmedPreviousLine.equals("%>") &&
642                                            Validator.isNotNull(line) && !trimmedLine.equals("-->")) {
643    
644                                            sb.append("\n");
645                                    }
646                                    else if (Validator.isNotNull(previousLine) &&
647                                                     !trimmedPreviousLine.equals("<!--") &&
648                                                     trimmedLine.equals("<%")) {
649    
650                                            sb.append("\n");
651                                    }
652                                    else if (trimmedPreviousLine.equals("<%") &&
653                                                     Validator.isNull(line)) {
654    
655                                            continue;
656                                    }
657                                    else if (trimmedPreviousLine.equals("<%") &&
658                                                     trimmedLine.startsWith("//")) {
659    
660                                            sb.append("\n");
661                                    }
662                                    else if (Validator.isNull(previousLine) &&
663                                                     trimmedLine.equals("%>") && (sb.index() > 2)) {
664    
665                                            String lineBeforePreviousLine = sb.stringAt(sb.index() - 3);
666    
667                                            if (!lineBeforePreviousLine.startsWith("//")) {
668                                                    sb.setIndex(sb.index() - 1);
669                                            }
670                                    }
671    
672                                    if ((trimmedLine.startsWith("if (") ||
673                                             trimmedLine.startsWith("else if (") ||
674                                             trimmedLine.startsWith("while (")) &&
675                                            trimmedLine.endsWith(") {")) {
676    
677                                            checkIfClauseParentheses(trimmedLine, fileName, lineCount);
678                                    }
679    
680                                    if (readAttributes) {
681                                            if (!trimmedLine.startsWith(StringPool.FORWARD_SLASH) &&
682                                                    !trimmedLine.startsWith(StringPool.GREATER_THAN)) {
683    
684                                                    int pos = trimmedLine.indexOf(StringPool.EQUAL);
685    
686                                                    if (pos != -1) {
687                                                            String attribute = trimmedLine.substring(0, pos);
688                                                            String newLine = formatTagAttributeType(
689                                                                    line, tag, trimmedLine);
690    
691                                                            if (!newLine.equals(line)) {
692                                                                    line = newLine;
693    
694                                                                    readAttributes = false;
695                                                            }
696                                                            else if (!trimmedLine.endsWith(
697                                                                                    StringPool.APOSTROPHE) &&
698                                                                             !trimmedLine.endsWith(
699                                                                                     StringPool.GREATER_THAN) &&
700                                                                             !trimmedLine.endsWith(StringPool.QUOTE)) {
701    
702                                                                    processErrorMessage(
703                                                                            fileName,
704                                                                            "attribute: " + fileName + " " + lineCount);
705    
706                                                                    readAttributes = false;
707                                                            }
708                                                            else if (trimmedLine.endsWith(
709                                                                                    StringPool.APOSTROPHE) &&
710                                                                             !trimmedLine.contains(StringPool.QUOTE)) {
711    
712                                                                    line = StringUtil.replace(
713                                                                            line, StringPool.APOSTROPHE,
714                                                                                    StringPool.QUOTE);
715    
716                                                                    readAttributes = false;
717                                                            }
718                                                            else if (Validator.isNotNull(previousAttribute)) {
719                                                                    if (!isAttributName(attribute) &&
720                                                                            !attribute.startsWith(
721                                                                                    StringPool.LESS_THAN)) {
722    
723                                                                            processErrorMessage(
724                                                                                    fileName,
725                                                                                    "attribute: " + fileName + " " +
726                                                                                            lineCount);
727    
728                                                                            readAttributes = false;
729                                                                    }
730                                                                    else if (Validator.isNull(
731                                                                                            previousAttributeAndValue) &&
732                                                                                     (previousAttribute.compareTo(
733                                                                                             attribute) > 0)) {
734    
735                                                                            previousAttributeAndValue = previousLine;
736                                                                            currentAttributeAndValue = line;
737                                                                    }
738                                                            }
739    
740                                                            if (!readAttributes) {
741                                                                    previousAttribute = null;
742                                                                    previousAttributeAndValue = null;
743                                                            }
744                                                            else {
745                                                                    previousAttribute = attribute;
746                                                            }
747                                                    }
748                                            }
749                                            else {
750                                                    previousAttribute = null;
751    
752                                                    readAttributes = false;
753                                            }
754                                    }
755    
756                                    if (!hasUnsortedExceptions) {
757                                            int x = line.indexOf("<liferay-ui:error exception=\"<%=");
758    
759                                            if (x != -1) {
760                                                    int y = line.indexOf(".class %>", x);
761    
762                                                    if (y != -1) {
763                                                            currentException = line.substring(x, y);
764    
765                                                            if (Validator.isNotNull(previousException) &&
766                                                                    (previousException.compareTo(currentException) >
767                                                                            0)) {
768    
769                                                                    currentException = line;
770                                                                    previousException = previousLine;
771    
772                                                                    hasUnsortedExceptions = true;
773                                                            }
774                                                    }
775                                            }
776    
777                                            if (!hasUnsortedExceptions) {
778                                                    previousException = currentException;
779                                                    currentException = null;
780                                            }
781                                    }
782    
783                                    if (trimmedLine.startsWith(StringPool.LESS_THAN) &&
784                                            !trimmedLine.startsWith("<%") &&
785                                            !trimmedLine.startsWith("<!")) {
786    
787                                            if (!trimmedLine.contains(StringPool.GREATER_THAN) &&
788                                                    !trimmedLine.contains(StringPool.SPACE)) {
789    
790                                                    tag = trimmedLine.substring(1);
791    
792                                                    readAttributes = true;
793                                            }
794                                            else {
795                                                    line = sortAttributes(fileName, line, lineCount, true);
796                                            }
797                                    }
798    
799                                    if (!trimmedLine.contains(StringPool.DOUBLE_SLASH) &&
800                                            !trimmedLine.startsWith(StringPool.STAR)) {
801    
802                                            while (trimmedLine.contains(StringPool.TAB)) {
803                                                    line = StringUtil.replaceLast(
804                                                            line, StringPool.TAB, StringPool.SPACE);
805    
806                                                    trimmedLine = StringUtil.replaceLast(
807                                                            trimmedLine, StringPool.TAB, StringPool.SPACE);
808                                            }
809    
810                                            while (trimmedLine.contains(StringPool.DOUBLE_SPACE) &&
811                                                       !trimmedLine.contains(
812                                                               StringPool.QUOTE + StringPool.DOUBLE_SPACE) &&
813                                                       !fileName.endsWith(".vm")) {
814    
815                                                    line = StringUtil.replaceLast(
816                                                            line, StringPool.DOUBLE_SPACE, StringPool.SPACE);
817    
818                                                    trimmedLine = StringUtil.replaceLast(
819                                                            trimmedLine, StringPool.DOUBLE_SPACE,
820                                                            StringPool.SPACE);
821                                            }
822                                    }
823    
824                                    if (!fileName.endsWith("/touch.jsp")) {
825                                            int x = line.indexOf("<%@ include file");
826    
827                                            if (x != -1) {
828                                                    x = line.indexOf(StringPool.QUOTE, x);
829    
830                                                    int y = line.indexOf(StringPool.QUOTE, x + 1);
831    
832                                                    if (y != -1) {
833                                                            String includeFileName = line.substring(x + 1, y);
834    
835                                                            Matcher matcher = _jspIncludeFilePattern.matcher(
836                                                                    includeFileName);
837    
838                                                            if (!matcher.find()) {
839                                                                    processErrorMessage(
840                                                                            fileName,
841                                                                            "include: " + fileName + " " + lineCount);
842                                                            }
843                                                    }
844                                            }
845                                    }
846    
847                                    line = replacePrimitiveWrapperInstantiation(
848                                            fileName, line, lineCount);
849    
850                                    previousLine = line;
851    
852                                    sb.append(line);
853                                    sb.append("\n");
854                            }
855                    }
856    
857                    content = sb.toString();
858    
859                    if (content.endsWith("\n")) {
860                            content = content.substring(0, content.length() - 1);
861                    }
862    
863                    content = formatTaglibQuotes(fileName, content, StringPool.QUOTE);
864                    content = formatTaglibQuotes(fileName, content, StringPool.APOSTROPHE);
865    
866                    if (Validator.isNotNull(previousAttributeAndValue)) {
867                            content = StringUtil.replaceFirst(
868                                    content,
869                                    previousAttributeAndValue + "\n" + currentAttributeAndValue,
870                                    currentAttributeAndValue + "\n" + previousAttributeAndValue);
871                    }
872    
873                    if (hasUnsortedExceptions) {
874                            if ((StringUtil.count(content, currentException) > 1) ||
875                                    (StringUtil.count(content, previousException) > 1)) {
876    
877                                    processErrorMessage(
878                                            fileName, "unsorted exceptions: " + fileName);
879                            }
880                            else {
881                                    content = StringUtil.replaceFirst(
882                                            content, previousException, currentException);
883    
884                                    content = StringUtil.replaceLast(
885                                            content, currentException, previousException);
886                            }
887                    }
888    
889                    return content;
890            }
891    
892            @Override
893            protected String formatTagAttributeType(
894                            String line, String tag, String attributeAndValue)
895                    throws Exception {
896    
897                    if (!attributeAndValue.endsWith(StringPool.QUOTE) ||
898                            attributeAndValue.contains("\"<%=")) {
899    
900                            return line;
901                    }
902    
903                    if (tag.startsWith("liferay-")) {
904                            tag = tag.substring(8);
905                    }
906    
907                    JavaClass tagJavaClass = getTagJavaClass(tag);
908    
909                    if (tagJavaClass == null) {
910                            return line;
911                    }
912    
913                    int pos = attributeAndValue.indexOf("=\"");
914    
915                    String attribute = attributeAndValue.substring(0, pos);
916    
917                    String setAttributeMethodName =
918                            "set" + TextFormatter.format(attribute, TextFormatter.G);
919    
920                    for (String dataType : getPrimitiveTagAttributeDataTypes()) {
921                            Type javaType = new Type(dataType);
922    
923                            JavaMethod setAttributeMethod = tagJavaClass.getMethodBySignature(
924                                    setAttributeMethodName, new Type[] {javaType}, true);
925    
926                            if (setAttributeMethod != null) {
927                                    String value = attributeAndValue.substring(
928                                            pos + 2, attributeAndValue.length() - 1);
929    
930                                    if (!isValidTagAttributeValue(value, dataType)) {
931                                            return line;
932                                    }
933    
934                                    String newAttributeAndValue = StringUtil.replace(
935                                            attributeAndValue,
936                                            StringPool.QUOTE + value + StringPool.QUOTE,
937                                            "\"<%= " + value + " %>\"");
938    
939                                    return StringUtil.replace(
940                                            line, attributeAndValue, newAttributeAndValue);
941                            }
942                    }
943    
944                    return line;
945            }
946    
947            protected String formatTaglibQuotes(
948                    String fileName, String content, String quoteType) {
949    
950                    String quoteFix = StringPool.APOSTROPHE;
951    
952                    if (quoteFix.equals(quoteType)) {
953                            quoteFix = StringPool.QUOTE;
954                    }
955    
956                    Pattern pattern = Pattern.compile(getTaglibRegex(quoteType));
957    
958                    Matcher matcher = pattern.matcher(content);
959    
960                    while (matcher.find()) {
961                            int x = content.indexOf(quoteType + "<%=", matcher.start());
962                            int y = content.indexOf("%>" + quoteType, x);
963    
964                            while ((x != -1) && (y != -1)) {
965                                    String beforeResult = content.substring(matcher.start(), x);
966    
967                                    if (beforeResult.contains(" />\"")) {
968                                            break;
969                                    }
970    
971                                    String result = content.substring(x + 1, y + 2);
972    
973                                    if (result.contains(quoteType)) {
974                                            int lineCount = 1;
975    
976                                            char[] contentCharArray = content.toCharArray();
977    
978                                            for (int i = 0; i < x; i++) {
979                                                    if (contentCharArray[i] == CharPool.NEW_LINE) {
980                                                            lineCount++;
981                                                    }
982                                            }
983    
984                                            if (!result.contains(quoteFix)) {
985                                                    StringBundler sb = new StringBundler(5);
986    
987                                                    sb.append(content.substring(0, x));
988                                                    sb.append(quoteFix);
989                                                    sb.append(result);
990                                                    sb.append(quoteFix);
991                                                    sb.append(content.substring(y + 3, content.length()));
992    
993                                                    content = sb.toString();
994                                            }
995                                            else {
996                                                    processErrorMessage(
997                                                            fileName, "taglib: " + fileName + " " + lineCount);
998                                            }
999                                    }
1000    
1001                                    x = content.indexOf(quoteType + "<%=", y);
1002    
1003                                    if (x > matcher.end()) {
1004                                            break;
1005                                    }
1006    
1007                                    y = content.indexOf("%>" + quoteType, x);
1008                            }
1009                    }
1010    
1011                    return content;
1012            }
1013    
1014            protected List<String> getJSPDuplicateImports(
1015                    String fileName, String content, List<String> importLines) {
1016    
1017                    List<String> duplicateImports = new ArrayList<String>();
1018    
1019                    for (String importLine : importLines) {
1020                            int x = content.indexOf("<%@ include file=");
1021    
1022                            if (x == -1) {
1023                                    continue;
1024                            }
1025    
1026                            int y = content.indexOf("<%@ page import=");
1027    
1028                            if (y == -1) {
1029                                    continue;
1030                            }
1031    
1032                            if ((x < y) && isJSPDuplicateImport(fileName, importLine, false)) {
1033                                    duplicateImports.add(importLine);
1034                            }
1035                    }
1036    
1037                    return duplicateImports;
1038            }
1039    
1040            protected Set<String> getPrimitiveTagAttributeDataTypes() {
1041                    if (_primitiveTagAttributeDataTypes != null) {
1042                            return _primitiveTagAttributeDataTypes;
1043                    }
1044    
1045                    _primitiveTagAttributeDataTypes = SetUtil.fromArray(
1046                            new String[] {"boolean", "double", "int", "long"});
1047    
1048                    return _primitiveTagAttributeDataTypes;
1049            }
1050    
1051            protected JavaClass getTagJavaClass(String tag) throws Exception {
1052                    JavaClass tagJavaClass = _tagJavaClassesMap.get(tag);
1053    
1054                    if (tagJavaClass != null) {
1055                            return tagJavaClass;
1056                    }
1057    
1058                    String[] tagParts = StringUtil.split(tag, CharPool.COLON);
1059    
1060                    if (tagParts.length != 2) {
1061                            return null;
1062                    }
1063    
1064                    String utilTaglibDirName = getUtilTaglibDirName();
1065    
1066                    if (Validator.isNull(utilTaglibDirName)) {
1067                            return null;
1068                    }
1069    
1070                    String tagName = tagParts[1];
1071    
1072                    String tagJavaClassName = TextFormatter.format(
1073                            tagName, TextFormatter.M);
1074    
1075                    tagJavaClassName =
1076                            TextFormatter.format(tagJavaClassName, TextFormatter.G) + "Tag";
1077    
1078                    String tagCategory = tagParts[0];
1079    
1080                    StringBundler sb = new StringBundler(6);
1081    
1082                    sb.append(utilTaglibDirName);
1083                    sb.append("/src/com/liferay/taglib/");
1084                    sb.append(tagCategory);
1085                    sb.append(StringPool.SLASH);
1086                    sb.append(tagJavaClassName);
1087                    sb.append(".java");
1088    
1089                    File tagJavaFile = new File(sb.toString());
1090    
1091                    if (!tagJavaFile.exists()) {
1092                            return null;
1093                    }
1094    
1095                    JavaDocBuilder javaDocBuilder = new JavaDocBuilder();
1096    
1097                    javaDocBuilder.addSource(tagJavaFile);
1098    
1099                    sb = new StringBundler(4);
1100    
1101                    sb.append("com.liferay.taglib.");
1102                    sb.append(tagCategory);
1103                    sb.append(StringPool.PERIOD);
1104                    sb.append(tagJavaClassName);
1105    
1106                    tagJavaClass = javaDocBuilder.getClassByName(sb.toString());
1107    
1108                    _tagJavaClassesMap.put(tag, tagJavaClass);
1109    
1110                    return tagJavaClass;
1111            }
1112    
1113            protected String getTaglibRegex(String quoteType) {
1114                    StringBuilder sb = new StringBuilder();
1115    
1116                    sb.append("<(");
1117    
1118                    for (int i = 0; i < _TAG_LIBRARIES.length; i++) {
1119                            sb.append(_TAG_LIBRARIES[i]);
1120                            sb.append(StringPool.PIPE);
1121                    }
1122    
1123                    sb.deleteCharAt(sb.length() - 1);
1124                    sb.append("):([^>]|%>)*");
1125                    sb.append(quoteType);
1126                    sb.append("<%=.*");
1127                    sb.append(quoteType);
1128                    sb.append(".*%>");
1129                    sb.append(quoteType);
1130                    sb.append("([^>]|%>)*>");
1131    
1132                    return sb.toString();
1133            }
1134    
1135            protected String getUtilTaglibDirName() {
1136                    if (_utilTaglibDirName != null) {
1137                            return _utilTaglibDirName;
1138                    }
1139    
1140                    File utilTaglibDir = getFile("util-taglib", 4);
1141    
1142                    if (utilTaglibDir != null) {
1143                            _utilTaglibDirName = utilTaglibDir.getAbsolutePath();
1144    
1145                            _utilTaglibDirName = StringUtil.replace(
1146                                    _utilTaglibDirName, StringPool.BACK_SLASH, StringPool.SLASH);
1147                    }
1148                    else {
1149                            _utilTaglibDirName = StringPool.BLANK;
1150                    }
1151    
1152                    return _utilTaglibDirName;
1153            }
1154    
1155            protected String getVariableName(String line) {
1156                    if (!line.endsWith(";") || line.startsWith("//")) {
1157                            return null;
1158                    }
1159    
1160                    String variableName = null;
1161    
1162                    int x = line.indexOf(" = ");
1163    
1164                    if (x == -1) {
1165                            int y = line.lastIndexOf(" ");
1166    
1167                            if (y != -1) {
1168                                    variableName = line.substring(y + 1, line.length() - 1);
1169                            }
1170                    }
1171                    else {
1172                            line = line.substring(0, x);
1173    
1174                            int y = line.lastIndexOf(" ");
1175    
1176                            if (y != -1) {
1177                                    variableName = line.substring(y + 1);
1178                            }
1179                    }
1180    
1181                    if (Validator.isVariableName(variableName)) {
1182                            return variableName;
1183                    }
1184    
1185                    return null;
1186            }
1187    
1188            protected boolean hasUnusedJSPTerm(
1189                    String fileName, String regex, String type) {
1190    
1191                    _includeFileNames.add(fileName);
1192    
1193                    Set<String> checkedForUnusedJSPTerm = new HashSet<String>();
1194    
1195                    return !isJSPTermRequired(
1196                            fileName, regex, type, checkedForUnusedJSPTerm);
1197            }
1198    
1199            protected boolean hasUnusedTaglib(String fileName, String line) {
1200                    if (!line.startsWith("<%@ taglib uri=")) {
1201                            return false;
1202                    }
1203    
1204                    int x = line.indexOf(" prefix=");
1205    
1206                    if (x == -1) {
1207                            return false;
1208                    }
1209    
1210                    x = line.indexOf(StringPool.QUOTE, x);
1211    
1212                    int y = line.indexOf(StringPool.QUOTE, x + 1);
1213    
1214                    if ((x == -1) || (y == -1)) {
1215                            return false;
1216                    }
1217    
1218                    String taglibPrefix = line.substring(x + 1, y);
1219    
1220                    String regex = StringPool.LESS_THAN + taglibPrefix + StringPool.COLON;
1221    
1222                    return hasUnusedJSPTerm(fileName, regex, "taglib");
1223            }
1224    
1225            protected boolean hasUnusedVariable(String fileName, String line) {
1226                    if (line.contains(": ")) {
1227                            return false;
1228                    }
1229    
1230                    String variableName = getVariableName(line);
1231    
1232                    if (Validator.isNull(variableName) || variableName.equals("false") ||
1233                            variableName.equals("true")) {
1234    
1235                            return false;
1236                    }
1237    
1238                    String regex = "[^A-Za-z0-9_\"]" + variableName + "[^A-Za-z0-9_\"]";
1239    
1240                    return hasUnusedJSPTerm(fileName, regex, "variable");
1241            }
1242    
1243            protected boolean isJSPDuplicateImport(
1244                    String fileName, String importLine, boolean checkFile) {
1245    
1246                    String content = _jspContents.get(fileName);
1247    
1248                    if (Validator.isNull(content)) {
1249                            return false;
1250                    }
1251    
1252                    int x = importLine.indexOf("page");
1253    
1254                    if (x == -1) {
1255                            return false;
1256                    }
1257    
1258                    if (checkFile && content.contains(importLine.substring(x))) {
1259                            return true;
1260                    }
1261    
1262                    int y = content.indexOf("<%@ include file=");
1263    
1264                    if (y == -1) {
1265                            return false;
1266                    }
1267    
1268                    y = content.indexOf(StringPool.QUOTE, y);
1269    
1270                    if (y == -1) {
1271                            return false;
1272                    }
1273    
1274                    int z = content.indexOf(StringPool.QUOTE, y + 1);
1275    
1276                    if (z == -1) {
1277                            return false;
1278                    }
1279    
1280                    String includeFileName = content.substring(y + 1, z);
1281    
1282                    includeFileName = buildFullPathIncludeFileName(
1283                            fileName, includeFileName);
1284    
1285                    return isJSPDuplicateImport(includeFileName, importLine, true);
1286            }
1287    
1288            protected boolean isJSPTermRequired(
1289                    String fileName, String regex, String type,
1290                    Set<String> checkedForUnusedJSPTerm) {
1291    
1292                    if (checkedForUnusedJSPTerm.contains(fileName)) {
1293                            return false;
1294                    }
1295    
1296                    checkedForUnusedJSPTerm.add(fileName);
1297    
1298                    String content = _jspContents.get(fileName);
1299    
1300                    if (Validator.isNull(content)) {
1301                            return false;
1302                    }
1303    
1304                    Pattern pattern = Pattern.compile(regex);
1305    
1306                    Matcher matcher = pattern.matcher(content);
1307    
1308                    if (matcher.find() &&
1309                            (!type.equals("variable") || (checkedForUnusedJSPTerm.size() > 1) ||
1310                             matcher.find())) {
1311    
1312                            return true;
1313                    }
1314    
1315                    if (!_checkedForIncludesFileNames.contains(fileName)) {
1316                            addJSPIncludeFileNames(fileName);
1317    
1318                            if (fileName.endsWith("init.jsp") ||
1319                                    fileName.endsWith("init.jspf") ||
1320                                    fileName.contains("init-ext.jsp")) {
1321    
1322                                    addJSPReferenceFileNames(fileName);
1323                            }
1324                    }
1325    
1326                    _checkedForIncludesFileNames.add(fileName);
1327    
1328                    String[] includeFileNamesArray = _includeFileNames.toArray(
1329                            new String[_includeFileNames.size()]);
1330    
1331                    for (String includeFileName : includeFileNamesArray) {
1332                            if (!checkedForUnusedJSPTerm.contains(includeFileName) &&
1333                                    isJSPTermRequired(
1334                                            includeFileName, regex, type, checkedForUnusedJSPTerm)) {
1335    
1336                                    return true;
1337                            }
1338                    }
1339    
1340                    return false;
1341            }
1342    
1343            protected boolean isValidTagAttributeValue(String value, String dataType) {
1344                    if (dataType.equals("boolean")) {
1345                            return Validator.isBoolean(value);
1346                    }
1347    
1348                    if (dataType.equals("double")) {
1349                            try {
1350                                    Double.parseDouble(value);
1351                            }
1352                            catch (NumberFormatException nfe) {
1353                                    return false;
1354                            }
1355    
1356                            return true;
1357                    }
1358    
1359                    if (dataType.equals("int") || dataType.equals("long")) {
1360                            return Validator.isNumber(value);
1361                    }
1362    
1363                    return false;
1364            }
1365    
1366            protected void moveFrequentlyUsedImportsToCommonInit(int minCount)
1367                    throws IOException {
1368    
1369                    if (_importCountMap.isEmpty()) {
1370                            return;
1371                    }
1372    
1373                    String commonInitFileName = "portal-web/docroot/html/common/init.jsp";
1374    
1375                    File commonInitFile = null;
1376                    String commonInitFileContent = null;
1377    
1378                    int x = -1;
1379    
1380                    for (Map.Entry<String, Integer> importCount :
1381                                    _importCountMap.entrySet()) {
1382    
1383                            Integer count = importCount.getValue();
1384    
1385                            if (count < minCount) {
1386                                    continue;
1387                            }
1388    
1389                            String importName = importCount.getKey();
1390    
1391                            int y = importName.lastIndexOf(StringPool.PERIOD);
1392    
1393                            String importClassName = importName.substring(y + 1);
1394    
1395                            if (_duplicateImportClassNames.contains(importClassName)) {
1396                                    continue;
1397                            }
1398    
1399                            if (commonInitFileContent == null) {
1400                                    commonInitFile = new File(commonInitFileName);
1401    
1402                                    commonInitFileContent = fileUtil.read(commonInitFile);
1403    
1404                                    x = commonInitFileContent.indexOf("<%@ page import");
1405                            }
1406    
1407                            commonInitFileContent = StringUtil.insert(
1408                                    commonInitFileContent,
1409                                    "<%@ page import=\"" + importName + "\" %>\n", x);
1410                    }
1411    
1412                    if (commonInitFileContent != null) {
1413                            fileUtil.write(commonInitFile, commonInitFileContent);
1414    
1415                            _jspContents.put(commonInitFileName, commonInitFileContent);
1416                    }
1417            }
1418    
1419            protected String stripJSPImports(String fileName, String content)
1420                    throws IOException {
1421    
1422                    fileName = fileName.replace(
1423                            CharPool.BACK_SLASH, CharPool.FORWARD_SLASH);
1424    
1425                    if (fileName.endsWith("init-ext.jsp")) {
1426                            return content;
1427                    }
1428    
1429                    Matcher matcher = _jspImportPattern.matcher(content);
1430    
1431                    if (!matcher.find()) {
1432                            return content;
1433                    }
1434    
1435                    String imports = matcher.group();
1436    
1437                    imports = StringUtil.replace(
1438                            imports, new String[] {"%><%@\r\n", "%><%@\n"},
1439                            new String[] {"%>\r\n<%@ ", "%>\n<%@ "});
1440    
1441                    List<String> importLines = new ArrayList<String>();
1442    
1443                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
1444                            new UnsyncStringReader(imports));
1445    
1446                    String line = null;
1447    
1448                    while ((line = unsyncBufferedReader.readLine()) != null) {
1449                            if (line.contains("import=")) {
1450                                    importLines.add(line);
1451                            }
1452                    }
1453    
1454                    List<String> unneededImports = getJSPDuplicateImports(
1455                            fileName, content, importLines);
1456    
1457                    addJSPUnusedImports(fileName, importLines, unneededImports);
1458    
1459                    for (String unneededImport : unneededImports) {
1460                            imports = StringUtil.replace(
1461                                    imports, unneededImport, StringPool.BLANK);
1462                    }
1463    
1464                    ImportsFormatter importsFormatter = new JSPImportsFormatter();
1465    
1466                    imports = importsFormatter.format(imports);
1467    
1468                    String beforeImports = content.substring(0, matcher.start());
1469    
1470                    if (Validator.isNull(imports)) {
1471                            beforeImports = StringUtil.replaceLast(
1472                                    beforeImports, "\n", StringPool.BLANK);
1473                    }
1474    
1475                    String afterImports = content.substring(matcher.end());
1476    
1477                    if (Validator.isNull(afterImports)) {
1478                            imports = StringUtil.replaceLast(imports, "\n", StringPool.BLANK);
1479    
1480                            content = beforeImports + imports;
1481    
1482                            return content;
1483                    }
1484    
1485                    content = beforeImports + imports + "\n" + afterImports;
1486    
1487                    return content;
1488            }
1489    
1490            private static final String[] _TAG_LIBRARIES = new String[] {
1491                    "aui", "c", "html", "jsp", "liferay-portlet", "liferay-security",
1492                    "liferay-theme", "liferay-ui", "liferay-util", "portlet", "struts",
1493                    "tiles"
1494            };
1495    
1496            private Set<String> _checkedForIncludesFileNames = new HashSet<String>();
1497            private List<String> _duplicateImportClassNames = new ArrayList<String>();
1498            private List<String> _importClassNames = new ArrayList<String>();
1499            private Map<String, Integer> _importCountMap =
1500                    new HashMap<String, Integer>();
1501            private Pattern _importsPattern = Pattern.compile("page import=\"(.+)\"");
1502            private Set<String> _includeFileNames = new HashSet<String>();
1503            private Pattern _javaClassPattern = Pattern.compile(
1504                    "\n(private|protected|public).* class ([A-Za-z0-9]+) " +
1505                            "([\\s\\S]*?)\n\\}\n");
1506            private Map<String, String> _jspContents = new HashMap<String, String>();
1507            private Pattern _jspImportPattern = Pattern.compile(
1508                    "(<.*\n*page.import=\".*>\n*)+", Pattern.MULTILINE);
1509            private Pattern _jspIncludeFilePattern = Pattern.compile("/.*[.]jsp[f]?");
1510            private boolean _moveFrequentlyUsedImportsToCommonInit;
1511            private Set<String> _primitiveTagAttributeDataTypes;
1512            private Pattern _redirectBackURLPattern = Pattern.compile(
1513                    "(String redirect = ParamUtil\\.getString\\(request, \"redirect\".*" +
1514                            "\\);)\n(String backURL = ParamUtil\\.getString\\(request, \"" +
1515                                    "backURL\", redirect\\);)");
1516            private boolean _stripJSPImports = true;
1517            private Map<String, JavaClass> _tagJavaClassesMap =
1518                    new HashMap<String, JavaClass>();
1519            private Pattern _taglibLanguageKeyPattern1 = Pattern.compile(
1520                    "(?:confirmation|label|(?:M|m)essage|message key|names|title)=\"[^A-Z" +
1521                            "<=%\\[\\s]+\"");
1522            private Pattern _taglibLanguageKeyPattern2 = Pattern.compile(
1523                    "(aui:)(?:input|select|field-wrapper) (?!.*label=(?:'|\").*(?:'|\").*" +
1524                            "name=\"[^<=%\\[\\s]+\")(?!.*name=\"[^<=%\\[\\s]+\".*title=" +
1525                                    "(?:'|\").+(?:'|\"))(?!.*name=\"[^<=%\\[\\s]+\".*type=\"" +
1526                                            "hidden\").*name=\"([^<=%\\[\\s]+)\"");
1527            private Pattern _taglibLanguageKeyPattern3 = Pattern.compile(
1528                    "(liferay-ui:)(?:input-resource) .*id=\"([^<=%\\[\\s]+)\"(?!.*title=" +
1529                            "(?:'|\").+(?:'|\"))");
1530            private List<String> _unusedVariablesExclusions;
1531            private String _utilTaglibDirName;
1532            private Pattern _xssPattern = Pattern.compile(
1533                    "\\s+([^\\s]+)\\s*=\\s*(Bean)?ParamUtil\\.getString\\(");
1534    
1535    }