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