1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.tools;
16  
17  import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
18  import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
19  import com.liferay.portal.kernel.util.CharPool;
20  import com.liferay.portal.kernel.util.ClassUtil;
21  import com.liferay.portal.kernel.util.ListUtil;
22  import com.liferay.portal.kernel.util.PropertiesUtil;
23  import com.liferay.portal.kernel.util.PropsKeys;
24  import com.liferay.portal.kernel.util.StringPool;
25  import com.liferay.portal.kernel.util.StringUtil;
26  import com.liferay.portal.kernel.xml.Document;
27  import com.liferay.portal.kernel.xml.DocumentException;
28  import com.liferay.portal.kernel.xml.Element;
29  import com.liferay.portal.util.ContentUtil;
30  import com.liferay.portal.util.FileImpl;
31  import com.liferay.portal.xml.SAXReaderImpl;
32  
33  import java.io.File;
34  import java.io.IOException;
35  import java.io.InputStream;
36  
37  import java.net.URL;
38  
39  import java.util.ArrayList;
40  import java.util.Arrays;
41  import java.util.Collection;
42  import java.util.List;
43  import java.util.Properties;
44  import java.util.Set;
45  import java.util.TreeSet;
46  import java.util.regex.Matcher;
47  import java.util.regex.Pattern;
48  
49  import org.apache.tools.ant.DirectoryScanner;
50  
51  /**
52   * <a href="SourceFormatter.java.html"><b><i>View Source</i></b></a>
53   *
54   * @author Brian Wing Shun Chan
55   * @author Igor Spasic
56   */
57  public class SourceFormatter {
58  
59      public static void main(String[] args) {
60          try {
61              _sourceFormatterHelper = new SourceFormatterHelper(true);
62  
63              _sourceFormatterHelper.init();
64  
65              _readExclusions();
66  
67              Thread thread1 = new Thread () {
68                  public void run() {
69                      try {
70                          _checkPersistenceTestSuite();
71                          _formatJSP();
72                          _formatAntXML();
73                          _formatWebXML();
74                      }
75                      catch (Exception e) {
76                          e.printStackTrace();
77                      }
78                  }
79              };
80  
81              Thread thread2 = new Thread () {
82                  public void run() {
83                      try {
84                          _formatJava();
85                      }
86                      catch (Exception e) {
87                          e.printStackTrace();
88                      }
89                  }
90              };
91  
92              thread1.start();
93              thread2.start();
94  
95              thread1.join();
96              thread2.join();
97  
98              _sourceFormatterHelper.close();
99          }
100         catch (Exception e) {
101             e.printStackTrace();
102         }
103     }
104 
105     public static String stripImports(
106             String content, String packageDir, String className)
107         throws IOException {
108 
109         int x = content.indexOf("import ");
110 
111         if (x == -1) {
112             return content;
113         }
114 
115         int y = content.indexOf("{", x);
116 
117         y = content.substring(0, y).lastIndexOf(";") + 1;
118 
119         String imports = _formatImports(content.substring(x, y));
120 
121         content =
122             content.substring(0, x) + imports +
123                 content.substring(y + 1, content.length());
124 
125         Set<String> classes = ClassUtil.getClasses(
126             new UnsyncStringReader(content), className);
127 
128         x = content.indexOf("import ");
129 
130         y = content.indexOf("{", x);
131 
132         y = content.substring(0, y).lastIndexOf(";") + 1;
133 
134         imports = content.substring(x, y);
135 
136         StringBuilder sb = new StringBuilder();
137 
138         UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
139             new UnsyncStringReader(imports));
140 
141         String line = null;
142 
143         while ((line = unsyncBufferedReader.readLine()) != null) {
144             if (line.indexOf("import ") != -1) {
145                 int importX = line.indexOf(" ");
146                 int importY = line.lastIndexOf(".");
147 
148                 String importPackage = line.substring(importX + 1, importY);
149                 String importClass = line.substring(
150                     importY + 1, line.length() - 1);
151 
152                 if (!packageDir.equals(importPackage)) {
153                     if (!importClass.equals("*")) {
154                         if (classes.contains(importClass)) {
155                             sb.append(line);
156                             sb.append("\n");
157                         }
158                     }
159                     else {
160                         sb.append(line);
161                         sb.append("\n");
162                     }
163                 }
164             }
165         }
166 
167         imports = _formatImports(sb.toString());
168 
169         content =
170             content.substring(0, x) + imports +
171                 content.substring(y + 1, content.length());
172 
173         return content;
174     }
175 
176     private static void _checkPersistenceTestSuite() throws IOException {
177         String basedir = "./portal-impl/test";
178 
179         if (!_fileUtil.exists(basedir)) {
180             return;
181         }
182 
183         DirectoryScanner directoryScanner = new DirectoryScanner();
184 
185         directoryScanner.setBasedir(basedir);
186         directoryScanner.setIncludes(
187             new String[] {"**\\*PersistenceTest.java"});
188 
189         List<String> fileNames = _sourceFormatterHelper.scanForFiles(
190             directoryScanner);
191 
192         List<String> persistenceTests = new ArrayList<String>();
193 
194         for (String fileName : fileNames) {
195             String persistenceTest = fileName.substring(
196                 0, fileName.length() - 5);
197 
198             persistenceTest = persistenceTest.substring(
199                 persistenceTest.lastIndexOf(File.separator) + 1,
200                 persistenceTest.length());
201 
202             persistenceTests.add(persistenceTest);
203         }
204 
205         String persistenceTestSuiteFileName =
206             basedir + "/com/liferay/portal/service/persistence/" +
207                 "PersistenceTestSuite.java"; 
208 
209         String persistenceTestSuiteContent = _fileUtil.read(
210             persistenceTestSuiteFileName);
211 
212         for (String persistenceTest : persistenceTests) {
213             if (!persistenceTestSuiteContent.contains(persistenceTest)) {
214                 _sourceFormatterHelper.printError(
215                     persistenceTestSuiteFileName,
216                     "PersistenceTestSuite: " + persistenceTest);
217             }
218         }
219     }
220 
221     private static void _checkXSS(String fileName, String jspContent) {
222         Matcher matcher = _xssPattern.matcher(jspContent);
223 
224         while (matcher.find()) {
225             boolean xssVulnerable = false;
226 
227             String jspVariable = matcher.group(1);
228 
229             String inputVulnerability =
230                 "<input[^<>]*(<[^(/>)]*/>)*[^<>]* value=\"<%= " + jspVariable +
231                     " %>";
232 
233             Pattern inputVulnerabilityPattern =
234                 Pattern.compile(inputVulnerability, Pattern.CASE_INSENSITIVE);
235 
236             Matcher inputVulnerabilityMatcher =
237                 inputVulnerabilityPattern.matcher(jspContent);
238 
239             if (inputVulnerabilityMatcher.find()) {
240                 xssVulnerable = true;
241             }
242 
243             String anchorVulnerability = " href=\"<%= " + jspVariable + " %>";
244 
245             if (jspContent.indexOf(anchorVulnerability) != -1) {
246                 xssVulnerable = true;
247             }
248 
249             String inlineStringVulnerability1 = "'<%= " + jspVariable + " %>";
250 
251             if (jspContent.indexOf(inlineStringVulnerability1) != -1) {
252                 xssVulnerable = true;
253             }
254 
255             String inlineStringVulnerability2 = "(\"<%= " + jspVariable + " %>";
256 
257             if (jspContent.indexOf(inlineStringVulnerability2) != -1) {
258                 xssVulnerable = true;
259             }
260 
261             String inlineStringVulnerability3 = " \"<%= " + jspVariable + " %>";
262 
263             if (jspContent.indexOf(inlineStringVulnerability3) != -1) {
264                 xssVulnerable = true;
265             }
266 
267             String documentIdVulnerability = ".<%= " + jspVariable + " %>";
268 
269             if (jspContent.indexOf(documentIdVulnerability) != -1) {
270                 xssVulnerable = true;
271             }
272 
273             if (xssVulnerable) {
274                 _sourceFormatterHelper.printError(
275                     fileName, "(xss): " + fileName + " (" + jspVariable + ")");
276             }
277         }
278     }
279 
280     private static void _formatAntXML() throws DocumentException, IOException {
281         String basedir = "./";
282 
283         DirectoryScanner directoryScanner = new DirectoryScanner();
284 
285         directoryScanner.setBasedir(basedir);
286         directoryScanner.setIncludes(new String[] {"**\\b*.xml"});
287         directoryScanner.setExcludes(new String[] {"**\\tools\\tck\\**"});
288 
289         List<String> fileNames = _sourceFormatterHelper.scanForFiles(
290             directoryScanner);
291 
292         for (String fileName : fileNames) {
293             String content = _fileUtil.read(basedir + fileName);
294 
295             Document document = _saxReaderUtil.read(content);
296 
297             Element rootElement = document.getRootElement();
298 
299             String previousName = StringPool.BLANK;
300 
301             List<Element> targetElements = rootElement.elements("target");
302 
303             for (Element targetElement : targetElements) {
304                 String name = targetElement.attributeValue("name");
305 
306                 if (name.equals("Test")) {
307                     name = name.toLowerCase();
308                 }
309 
310                 if (name.compareTo(previousName) < -1) {
311                     _sourceFormatterHelper.printError(
312                         fileName, fileName + " has an unordered target " + name);
313 
314                     break;
315                 }
316 
317                 previousName = name;
318             }
319         }
320     }
321 
322     private static String _formatImports(String imports) throws IOException {
323         if ((imports.indexOf("/*") != -1) ||
324             (imports.indexOf("*/") != -1) ||
325             (imports.indexOf("//") != -1)) {
326 
327             return imports + "\n";
328         }
329 
330         List<String> importsList = new ArrayList<String>();
331 
332         UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
333             new UnsyncStringReader(imports));
334 
335         String line = null;
336 
337         while ((line = unsyncBufferedReader.readLine()) != null) {
338             if (line.indexOf("import ") != -1) {
339                 if (!importsList.contains(line)) {
340                     importsList.add(line);
341                 }
342             }
343         }
344 
345         importsList = ListUtil.sort(importsList);
346 
347         StringBuilder sb = new StringBuilder();
348 
349         String temp = null;
350 
351         for (int i = 0; i < importsList.size(); i++) {
352             String s = importsList.get(i);
353 
354             int pos = s.indexOf(".");
355 
356             pos = s.indexOf(".", pos + 1);
357 
358             if (pos == -1) {
359                 pos = s.indexOf(".");
360             }
361 
362             String packageLevel = s.substring(7, pos);
363 
364             if ((i != 0) && (!packageLevel.equals(temp))) {
365                 sb.append("\n");
366             }
367 
368             temp = packageLevel;
369 
370             sb.append(s);
371             sb.append("\n");
372         }
373 
374         return sb.toString();
375     }
376 
377     private static void _formatJava() throws IOException {
378         String basedir = "./";
379 
380         String copyright = _getCopyright();
381         String oldCopyright = _getOldCopyright();
382 
383         boolean portalJavaFiles = true;
384 
385         Collection<String> fileNames = null;
386 
387         if (_fileUtil.exists(basedir + "portal-impl")) {
388             fileNames = _getPortalJavaFiles();
389         }
390         else {
391             portalJavaFiles = false;
392 
393             fileNames = _getPluginJavaFiles();
394         }
395 
396         for (String fileName : fileNames) {
397             File file = new File(fileName);
398 
399             String content = _fileUtil.read(file);
400 
401             String className = file.getName();
402 
403             className = className.substring(0, className.length() - 5);
404 
405             String packagePath = fileName;
406 
407             int packagePathX = packagePath.indexOf(
408                 File.separator + "src" + File.separator);
409             int packagePathY = packagePath.lastIndexOf(File.separator);
410 
411             if ((packagePathX + 5) >= packagePathY) {
412                 packagePath = StringPool.BLANK;
413             }
414             else {
415                 packagePath = packagePath.substring(
416                     packagePathX + 5, packagePathY);
417             }
418 
419             packagePath = StringUtil.replace(
420                 packagePath, File.separator, StringPool.PERIOD);
421 
422             if (packagePath.endsWith(".model")) {
423                 if (content.indexOf(
424                         "extends " + className + "Model {") != -1) {
425 
426                     continue;
427                 }
428             }
429 
430             String newContent = _formatJavaContent(
431                 fileName, className, content);
432 
433             if (newContent.indexOf("$\n */") != -1) {
434                 _sourceFormatterHelper.printError(fileName, "*: " + fileName);
435 
436                 newContent = StringUtil.replace(
437                     newContent, "$\n */", "$\n *\n */");
438             }
439 
440             if ((oldCopyright != null) && newContent.contains(oldCopyright)) {
441                 newContent = StringUtil.replace(
442                     newContent, oldCopyright, copyright);
443 
444                 _sourceFormatterHelper.printError(
445                     fileName, "old (c): " + fileName);
446             }
447 
448             if (newContent.indexOf(copyright) == -1) {
449                 _sourceFormatterHelper.printError(fileName, "(c): " + fileName);
450             }
451 
452             if (newContent.indexOf(className + ".java.html") == -1) {
453                 _sourceFormatterHelper.printError(
454                     fileName, "Java2HTML: " + fileName);
455             }
456 
457             if (newContent.contains(" * @author Raymond Aug") && 
458                 !newContent.contains(" * @author Raymond Aug\u00e9")) {
459 
460                 newContent = newContent.replaceFirst(
461                     "Raymond Aug.++", "Raymond Aug\u00e9");
462 
463                 _sourceFormatterHelper.printError(
464                     fileName, "UTF-8: " + fileName);
465             }
466 
467             if (newContent.contains("com.liferay.portal.PortalException")) {
468                 newContent = StringUtil.replace(
469                     newContent, "com.liferay.portal.PortalException",
470                     "com.liferay.portal.kernel.exception.PortalException");
471             }
472 
473             if (newContent.contains("com.liferay.portal.SystemException")) {
474                 newContent = StringUtil.replace(
475                     newContent, "com.liferay.portal.SystemException",
476                     "com.liferay.portal.kernel.exception.SystemException");
477             }
478 
479             if (newContent.contains("com.liferay.util.LocalizationUtil")) {
480                 newContent = StringUtil.replace(
481                     newContent, "com.liferay.util.LocalizationUtil",
482                     "com.liferay.portal.kernel.util.LocalizationUtil");
483             }
484 
485             newContent = stripImports(newContent, packagePath, className);
486 
487             if (newContent.indexOf(";\n/**") != -1) {
488                 newContent = StringUtil.replace(
489                     newContent,
490                     ";\n/**",
491                     ";\n\n/**");
492             }
493 
494             if (newContent.indexOf("\t/*\n\t *") != -1) {
495                 newContent = StringUtil.replace(
496                     newContent,
497                     "\t/*\n\t *",
498                     "\t/**\n\t *");
499             }
500 
501             if (newContent.indexOf("if(") != -1) {
502                 newContent = StringUtil.replace(
503                     newContent,
504                     "if(",
505                     "if (");
506             }
507 
508             if (newContent.indexOf("while(") != -1) {
509                 newContent = StringUtil.replace(
510                     newContent,
511                     "while(",
512                     "while (");
513             }
514 
515             if (newContent.indexOf("\n\n\n") != -1) {
516                 newContent = StringUtil.replace(
517                     newContent,
518                     "\n\n\n",
519                     "\n\n");
520             }
521 
522             if (newContent.indexOf("*/\npackage ") != -1) {
523                 _sourceFormatterHelper.printError(
524                     fileName, "package: " + fileName);
525             }
526 
527             if (newContent.indexOf("    ") != -1) {
528                 if (!fileName.endsWith("StringPool.java")) {
529                     _sourceFormatterHelper.printError(
530                         fileName, "tab: " + fileName);
531                 }
532             }
533 
534             if (newContent.indexOf("  {") != -1) {
535                 _sourceFormatterHelper.printError(fileName, "{:" + fileName);
536             }
537 
538             if (!newContent.endsWith("\n\n}") &&
539                 !newContent.endsWith("{\n}")) {
540 
541                 _sourceFormatterHelper.printError(fileName, "}: " + fileName);
542             }
543 
544             if (portalJavaFiles && className.endsWith("ServiceImpl") &&
545                 (newContent.indexOf("ServiceUtil.") != -1)) {
546 
547                 _sourceFormatterHelper.printError(
548                     fileName, "ServiceUtil: " + fileName);
549             }
550 
551             if ((newContent != null) && !content.equals(newContent)) {
552                 _fileUtil.write(file, newContent);
553 
554                 _sourceFormatterHelper.printError(fileName, file);
555             }
556         }
557     }
558 
559     private static String _formatJavaContent(
560             String fileName, String className, String content)
561         throws IOException {
562 
563         boolean longLogFactoryUtil = false;
564 
565         StringBuilder sb = new StringBuilder();
566 
567         UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
568             new UnsyncStringReader(content));
569 
570         int lineCount = 0;
571 
572         String line = null;
573 
574         while ((line = unsyncBufferedReader.readLine()) != null) {
575             lineCount++;
576 
577             if (line.trim().length() == 0) {
578                 line = StringPool.BLANK;
579             }
580 
581             line = StringUtil.trimTrailing(line);
582 
583             line = StringUtil.replace(
584                 line,
585                 new String[] {
586                     "* Copyright (c) 2000-2009 Liferay, Inc."
587                 },
588                 new String[] {
589                     "* Copyright (c) 2000-2010 Liferay, Inc."
590                 });
591 
592             sb.append(line);
593             sb.append("\n");
594 
595             StringBuilder lineSB = new StringBuilder();
596 
597             int spacesPerTab = 4;
598 
599             for (char c : line.toCharArray()) {
600                 if (c == CharPool.TAB) {
601                     for (int i = 0; i < spacesPerTab; i++) {
602                         lineSB.append(CharPool.SPACE);
603                     }
604 
605                     spacesPerTab = 4;
606                 }
607                 else {
608                     lineSB.append(c);
609 
610                     spacesPerTab--;
611 
612                     if (spacesPerTab <= 0) {
613                         spacesPerTab = 4;
614                     }
615                 }
616             }
617 
618             line = lineSB.toString();
619 
620             if (line.endsWith("private static Log _log =")) {
621                 longLogFactoryUtil = true;
622             }
623 
624             String excluded = _exclusions.getProperty(
625                 StringUtil.replace(fileName, "\\", "/") + StringPool.AT +
626                     lineCount);
627 
628             if (excluded == null) {
629                 excluded = _exclusions.getProperty(
630                     StringUtil.replace(fileName, "\\", "/"));
631             }
632 
633             if ((excluded == null) && (line.length() > 80) &&
634                 !line.startsWith("import ") && !line.startsWith("package ")) {
635 
636                 if (fileName.endsWith("Table.java") &&
637                     line.contains("String TABLE_SQL_CREATE = ")) {
638                 }
639                 else {
640                     _sourceFormatterHelper.printError(
641                         fileName, "> 80: " + fileName + " " + lineCount);
642                 }
643             }
644         }
645 
646         unsyncBufferedReader.close();
647 
648         String newContent = sb.toString();
649 
650         if (newContent.endsWith("\n")) {
651             newContent = newContent.substring(0, newContent.length() -1);
652         }
653 
654         if (longLogFactoryUtil) {
655             newContent = StringUtil.replace(
656                 newContent,
657                 "private static Log _log =\n\t\tLogFactoryUtil.getLog(",
658                 "private static Log _log = LogFactoryUtil.getLog(\n\t\t");
659         }
660 
661         return newContent;
662     }
663 
664     private static void _formatJSP() throws IOException {
665         String basedir = "./";
666 
667         String copyright = _getCopyright();
668         String oldCopyright = _getOldCopyright();
669 
670         List<String> list = new ArrayList<String>();
671 
672         DirectoryScanner directoryScanner = new DirectoryScanner();
673 
674         directoryScanner.setBasedir(basedir);
675         directoryScanner.setExcludes(
676             new String[] {
677                 "**\\portal\\aui\\**", "**\\bin\\**", "**\\null.jsp",
678                 "**\\tmp\\**", "**\\tools\\tck\\**"
679             });
680         directoryScanner.setIncludes(
681             new String[] {"**\\*.jsp", "**\\*.jspf", "**\\*.vm"});
682 
683         list.addAll(_sourceFormatterHelper.scanForFiles(directoryScanner));
684 
685         String[] files = list.toArray(new String[list.size()]);
686 
687         for (int i = 0; i < files.length; i++) {
688             File file = new File(basedir + files[i]);
689 
690             String content = _fileUtil.read(file);
691             String newContent = _formatJSPContent(files[i], content);
692 
693             newContent = StringUtil.replace(
694                 newContent,
695                 new String[] {
696                     "<br/>", "\"/>", "\" >", "@page import", "\"%>", ")%>",
697                     "javascript: "
698                 },
699                 new String[] {
700                     "<br />", "\" />", "\">", "@ page import", "\" %>", ") %>",
701                     "javascript:"
702                 });
703 
704             newContent = StringUtil.replace(
705                 newContent,
706                 new String[] {
707                     "* Copyright (c) 2000-2009 Liferay, Inc."
708                 },
709                 new String[] {
710                     "* Copyright (c) 2000-2010 Liferay, Inc."
711                 });
712 
713             if (files[i].endsWith(".jsp") || files[i].endsWith(".jspf")) {
714                 if ((oldCopyright != null) &&
715                     newContent.contains(oldCopyright)) {
716 
717                     newContent = StringUtil.replace(
718                         newContent, oldCopyright, copyright);
719 
720                     _sourceFormatterHelper.printError(
721                         files[i], "old (c): " + files[i]);
722                 }
723 
724                 if (newContent.indexOf(copyright) == -1) {
725                     _sourceFormatterHelper.printError(
726                         files[i], "(c): " + files[i]);
727                 }
728             }
729 
730             if (newContent.indexOf("alert('<%= LanguageUtil.") != -1) {
731                 newContent = StringUtil.replace(newContent,
732                     "alert('<%= LanguageUtil.",
733                     "alert('<%= UnicodeLanguageUtil.");
734             }
735 
736             if (newContent.indexOf("alert(\"<%= LanguageUtil.") != -1) {
737                 newContent = StringUtil.replace(newContent,
738                     "alert(\"<%= LanguageUtil.",
739                     "alert(\"<%= UnicodeLanguageUtil.");
740             }
741 
742             if (newContent.indexOf("confirm('<%= LanguageUtil.") != -1) {
743                 newContent = StringUtil.replace(newContent,
744                     "confirm('<%= LanguageUtil.",
745                     "confirm('<%= UnicodeLanguageUtil.");
746             }
747 
748             if (newContent.indexOf("confirm(\"<%= LanguageUtil.") != -1) {
749                 newContent = StringUtil.replace(newContent,
750                     "confirm(\"<%= LanguageUtil.",
751                     "confirm(\"<%= UnicodeLanguageUtil.");
752             }
753 
754             if (newContent.indexOf("    ") != -1) {
755                 if (!files[i].endsWith("template.vm")) {
756                     _sourceFormatterHelper.printError(
757                         files[i], "tab: " + files[i]);
758                 }
759             }
760 
761             _checkXSS(files[i], content);
762 
763             if ((newContent != null) && !content.equals(newContent)) {
764                 _fileUtil.write(file, newContent);
765                 _sourceFormatterHelper.printError(files[i], file);
766             }
767         }
768 
769     }
770 
771     private static String _formatJSPContent(String fileName, String content)
772         throws IOException {
773 
774         StringBuilder sb = new StringBuilder();
775 
776         UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
777             new UnsyncStringReader(content));
778 
779         String line = null;
780 
781         while ((line = unsyncBufferedReader.readLine()) != null) {
782             if (line.trim().length() == 0) {
783                 line = StringPool.BLANK;
784             }
785 
786             line = StringUtil.trimTrailing(line);
787 
788             sb.append(line);
789             sb.append("\n");
790         }
791 
792         unsyncBufferedReader.close();
793 
794         content = sb.toString();
795 
796         if (content.endsWith("\n")) {
797             content = content.substring(0, content.length() -1);
798         }
799 
800         content = _formatTaglibQuotes(fileName, content, StringPool.QUOTE);
801         content = _formatTaglibQuotes(fileName, content, StringPool.APOSTROPHE);
802 
803         return content;
804     }
805 
806     private static String _formatTaglibQuotes(
807         String fileName, String content, String quoteType) {
808 
809         String quoteFix = StringPool.APOSTROPHE;
810 
811         if (quoteFix.equals(quoteType)) {
812             quoteFix = StringPool.QUOTE;
813         }
814 
815         Pattern pattern = Pattern.compile(_getTaglibRegex(quoteType));
816 
817         Matcher matcher = pattern.matcher(content);
818 
819         while (matcher.find()) {
820             int x = content.indexOf(quoteType + "<%=", matcher.start());
821             int y = content.indexOf("%>" + quoteType, x);
822 
823             while ((x != -1) && (y != -1)) {
824                 String result = content.substring(x + 1, y + 2);
825 
826                 if (result.indexOf(quoteType) != -1) {
827                     int lineCount = 1;
828 
829                     char contentCharArray[] = content.toCharArray();
830 
831                     for (int i = 0; i < x; i++) {
832                         if (contentCharArray[i] == CharPool.NEW_LINE) {
833                             lineCount++;
834                         }
835                     }
836 
837                     if (result.indexOf(quoteFix) == -1) {
838                         StringBuilder sb = new StringBuilder();
839 
840                         sb.append(content.substring(0, x));
841                         sb.append(quoteFix);
842                         sb.append(result);
843                         sb.append(quoteFix);
844                         sb.append(content.substring(y + 3, content.length()));
845 
846                         content = sb.toString();
847                     }
848                     else {
849                         _sourceFormatterHelper.printError(
850                             fileName, "taglib: " + fileName + " " + lineCount);
851                     }
852                 }
853 
854                 x = content.indexOf(quoteType + "<%=", y);
855 
856                 if (x > matcher.end()) {
857                     break;
858                 }
859 
860                 y = content.indexOf("%>" + quoteType, x);
861             }
862         }
863 
864         return content;
865     }
866 
867     private static void _formatWebXML() throws IOException {
868         String basedir = "./";
869 
870         if (_fileUtil.exists(basedir + "portal-impl")) {
871             Properties properties = new Properties();
872 
873             String propertiesContent = _fileUtil.read(
874                 basedir + "portal-impl/src/portal.properties");
875 
876             PropertiesUtil.load(properties, propertiesContent);
877 
878             String[] locales = StringUtil.split(
879                 properties.getProperty(PropsKeys.LOCALES));
880 
881             Arrays.sort(locales);
882 
883             Set<String> urlPatterns = new TreeSet<String>();
884 
885             for (String locale : locales) {
886                 int pos = locale.indexOf(StringPool.UNDERLINE);
887 
888                 String languageCode = locale.substring(0, pos);
889 
890                 urlPatterns.add(languageCode);
891                 urlPatterns.add(locale);
892             }
893 
894             StringBuilder sb = new StringBuilder();
895 
896             for (String urlPattern : urlPatterns) {
897                 sb.append("\t<servlet-mapping>\n");
898                 sb.append("\t\t<servlet-name>I18n Servlet</servlet-name>\n");
899                 sb.append(
900                     "\t\t<url-pattern>/" + urlPattern +"/*</url-pattern>\n");
901                 sb.append("\t</servlet-mapping>\n");
902             }
903 
904             File file = new File(
905                 basedir + "portal-web/docroot/WEB-INF/web.xml");
906 
907             String content = _fileUtil.read(file);
908 
909             int x = content.indexOf("<servlet-mapping>");
910 
911             x = content.indexOf("<servlet-name>I18n Servlet</servlet-name>", x);
912 
913             x = content.lastIndexOf("<servlet-mapping>", x) - 1;
914 
915             int y = content.lastIndexOf(
916                 "<servlet-name>I18n Servlet</servlet-name>");
917 
918             y = content.indexOf("</servlet-mapping>", y) + 19;
919 
920             String newContent =
921                 content.substring(0, x) + sb.toString() + content.substring(y);
922 
923             if ((newContent != null) && !content.equals(newContent)) {
924                 _fileUtil.write(file, newContent);
925 
926                 System.out.println(file);
927             }
928         }
929         else {
930             String webXML = ContentUtil.get(
931                 "com/liferay/portal/deploy/dependencies/web.xml");
932 
933             DirectoryScanner directoryScanner = new DirectoryScanner();
934 
935             directoryScanner.setBasedir(basedir);
936             directoryScanner.setIncludes(new String[] {"**\\web.xml"});
937 
938             List<String> fileNames = _sourceFormatterHelper.scanForFiles(
939                 directoryScanner);
940 
941             for (String fileName : fileNames) {
942                 String content = _fileUtil.read(basedir + fileName);
943 
944                 if (content.equals(webXML)) {
945                     _sourceFormatterHelper.printError(fileName, fileName);
946                 }
947             }
948         }
949     }
950 
951     private static String _getCopyright() throws IOException {
952         try {
953             return _fileUtil.read("copyright.txt");
954         }
955         catch (Exception e1) {
956             try {
957                 return _fileUtil.read("../copyright.txt");
958             }
959             catch (Exception e2) {
960                 return _fileUtil.read("../../copyright.txt");
961             }
962         }
963     }
964 
965     private static String _getOldCopyright() {
966         try {
967             return _fileUtil.read("old-copyright.txt");
968         }
969         catch (Exception e1) {
970             try {
971                 return _fileUtil.read("../old-copyright.txt");
972             }
973             catch (Exception e2) {
974                 try {
975                     return _fileUtil.read("../../old-copyright.txt");
976                 }
977                 catch (Exception e3) {
978                     return null;
979                 }
980             }
981         }
982     }
983 
984     private static Collection<String> _getPluginJavaFiles() {
985         String basedir = "./";
986 
987         Collection<String> fileNames = new TreeSet<String>();
988 
989         DirectoryScanner directoryScanner = new DirectoryScanner();
990 
991         directoryScanner.setBasedir(basedir);
992         directoryScanner.setExcludes(
993             new String[] {
994                 "**\\bin\\**", "**\\model\\*Clp.java",
995                 "**\\model\\impl\\*ModelImpl.java",
996                 "**\\service\\**\\model\\*Model.java",
997                 "**\\service\\**\\model\\*Soap.java",
998                 "**\\service\\**\\model\\*Wrapper.java",
999                 "**\\service\\**\\service\\*Service.java",
1000                "**\\service\\**\\service\\*ServiceClp.java",
1001                "**\\service\\**\\service\\*ServiceFactory.java",
1002                "**\\service\\**\\service\\*ServiceUtil.java",
1003                "**\\service\\**\\service\\*ServiceWrapper.java",
1004                "**\\service\\**\\service\\ClpSerializer.java",
1005                "**\\service\\**\\service\\messaging\\*ClpMessageListener.java",
1006                "**\\service\\**\\service\\persistence\\*Finder.java",
1007                "**\\service\\**\\service\\persistence\\*Persistence.java",
1008                "**\\service\\**\\service\\persistence\\*Util.java",
1009                "**\\service\\base\\*ServiceBaseImpl.java",
1010                "**\\service\\http\\*JSONSerializer.java",
1011                "**\\service\\http\\*ServiceHttp.java",
1012                "**\\service\\http\\*ServiceJSON.java",
1013                "**\\service\\http\\*ServiceSoap.java",
1014                "**\\service\\persistence\\*PersistenceImpl.java",
1015                "**\\tmp\\**"
1016            });
1017        directoryScanner.setIncludes(new String[] {"**\\*.java"});
1018
1019        fileNames.addAll(_sourceFormatterHelper.scanForFiles(directoryScanner));
1020
1021        return fileNames;
1022    }
1023
1024    private static Collection<String> _getPortalJavaFiles() {
1025        String basedir = "./";
1026
1027        Collection<String> fileNames = new TreeSet<String>();
1028
1029        DirectoryScanner directoryScanner = new DirectoryScanner();
1030
1031        directoryScanner.setBasedir(basedir);
1032        directoryScanner.setExcludes(
1033            new String[] {
1034                "**\\InstanceWrapperBuilder.java", "**\\*_IW.java",
1035                "**\\PropsKeys.java", "**\\PropsValues.java",
1036                "**\\ServiceBuilder.java", "**\\SourceFormatter.java",
1037                "**\\UserAttributes.java", "**\\WebKeys.java",
1038                "**\\bin\\**", "**\\classes\\*", "**\\counter\\service\\**",
1039                "**\\jsp\\*", "**\\model\\impl\\*ModelImpl.java",
1040                "**\\portal\\service\\**", "**\\portal-client\\**",
1041                "**\\portal-service\\**\\model\\*Model.java",
1042                "**\\portal-service\\**\\model\\*Soap.java",
1043                "**\\portal-service\\**\\model\\*Wrapper.java",
1044                "**\\portal-web\\classes\\**\\*.java",
1045                "**\\portal-web\\test\\**\\*Test.java",
1046                "**\\portlet\\**\\service\\**", "**\\tmp\\**",
1047                "**\\tools\\ext_tmpl\\**",  "**\\tools\\tck\\**"
1048            });
1049        directoryScanner.setIncludes(new String[] {"**\\*.java"});
1050
1051        fileNames.addAll(_sourceFormatterHelper.scanForFiles(directoryScanner));
1052
1053        directoryScanner = new DirectoryScanner();
1054
1055        directoryScanner.setBasedir(basedir);
1056        directoryScanner.setExcludes(
1057            new String[] {
1058                "**\\bin\\**", "**\\portal-client\\**",
1059                "**\\tools\\ext_tmpl\\**", "**\\*_IW.java",
1060                "**\\test\\**\\*PersistenceTest.java"
1061            });
1062        directoryScanner.setIncludes(
1063            new String[] {
1064                "**\\com\\liferay\\portal\\service\\ServiceContext*.java",
1065                "**\\model\\BaseModel.java",
1066                "**\\model\\impl\\BaseModelImpl.java",
1067                "**\\service\\base\\PrincipalBean.java",
1068                "**\\service\\http\\*HttpTest.java",
1069                "**\\service\\http\\*SoapTest.java",
1070                "**\\service\\http\\TunnelUtil.java",
1071                "**\\service\\impl\\*.java", "**\\service\\jms\\*.java",
1072                "**\\service\\permission\\*.java",
1073                "**\\service\\persistence\\BasePersistence.java",
1074                "**\\service\\persistence\\BatchSession*.java",
1075                "**\\service\\persistence\\*FinderImpl.java",
1076                "**\\service\\persistence\\*Query.java",
1077                "**\\service\\persistence\\impl\\BasePersistenceImpl.java",
1078                "**\\portal-impl\\test\\**\\*.java",
1079                "**\\portal-service\\**\\liferay\\documentlibrary\\**.java",
1080                "**\\portal-service\\**\\liferay\\lock\\**.java",
1081                "**\\portal-service\\**\\liferay\\mail\\**.java",
1082                "**\\util-bridges\\**\\*.java"
1083            });
1084
1085        fileNames.addAll(_sourceFormatterHelper.scanForFiles(directoryScanner));
1086
1087        return fileNames;
1088    }
1089
1090    private static String _getTaglibRegex(String quoteType) {
1091        StringBuilder sb = new StringBuilder();
1092
1093        sb.append("<(");
1094
1095        for (int i = 0; i < _TAG_LIBRARIES.length; i++) {
1096            sb.append(_TAG_LIBRARIES[i]);
1097            sb.append(StringPool.PIPE);
1098        }
1099
1100        sb.deleteCharAt(sb.length() - 1);
1101        sb.append("):([^>]|%>)*");
1102        sb.append(quoteType);
1103        sb.append("<%=.*");
1104        sb.append(quoteType);
1105        sb.append(".*%>");
1106        sb.append(quoteType);
1107        sb.append("([^>]|%>)*>");
1108
1109        return sb.toString();
1110    }
1111
1112    private static void _readExclusions() throws IOException {
1113        _exclusions = new Properties();
1114
1115        ClassLoader classLoader = SourceFormatter.class.getClassLoader();
1116
1117        String sourceFormatterExclusions = System.getProperty(
1118            "source-formatter-exclusions",
1119            "com/liferay/portal/tools/dependencies/" +
1120                "source_formatter_exclusions.properties");
1121
1122        URL url = classLoader.getResource(sourceFormatterExclusions);
1123
1124        if (url == null) {
1125            return;
1126        }
1127
1128        InputStream is = url.openStream();
1129
1130        _exclusions.load(is);
1131
1132        is.close();
1133    }
1134
1135    private static final String[] _TAG_LIBRARIES = new String[] {
1136        "aui", "c", "html", "jsp", "liferay-portlet", "liferay-security",
1137        "liferay-theme", "liferay-ui", "liferay-util", "portlet", "struts",
1138        "tiles"
1139    };
1140
1141    private static Properties _exclusions;
1142    private static FileImpl _fileUtil = FileImpl.getInstance();
1143    private static SAXReaderImpl _saxReaderUtil = SAXReaderImpl.getInstance();
1144    private static SourceFormatterHelper _sourceFormatterHelper;
1145    private static Pattern _xssPattern = Pattern.compile(
1146        "String\\s+([^\\s]+)\\s*=\\s*(Bean)?ParamUtil\\.getString\\(");
1147
1148}