1
22
23 package com.liferay.portal.tools;
24
25 import com.liferay.portal.kernel.util.CharPool;
26 import com.liferay.portal.kernel.util.ClassUtil;
27 import com.liferay.portal.kernel.util.ListUtil;
28 import com.liferay.portal.kernel.util.StringPool;
29 import com.liferay.portal.kernel.util.StringUtil;
30 import com.liferay.portal.util.ContentUtil;
31 import com.liferay.portal.util.FileImpl;
32
33 import java.io.BufferedReader;
34 import java.io.File;
35 import java.io.InputStream;
36 import java.io.IOException;
37 import java.io.StringReader;
38 import java.net.URL;
39 import java.util.ArrayList;
40 import java.util.HashSet;
41 import java.util.List;
42 import java.util.Properties;
43 import java.util.Set;
44 import java.util.regex.Matcher;
45 import java.util.regex.Pattern;
46
47 import org.apache.tools.ant.DirectoryScanner;
48
49
55 public class SourceFormatter {
56
57 public static void main(String[] args) {
58 try {
59 _readExclusions();
60
61 _checkPersistenceTestSuite();
62 _checkWebXML();
63 _formatJava();
64 _formatJSP();
65 }
66 catch (Exception e) {
67 e.printStackTrace();
68 }
69 }
70
71 public static String stripImports(
72 String content, String packageDir, String className)
73 throws IOException {
74
75 int x = content.indexOf("import ");
76
77 if (x == -1) {
78 return content;
79 }
80
81 int y = content.indexOf("{", x);
82
83 y = content.substring(0, y).lastIndexOf(";") + 1;
84
85 String imports = _formatImports(content.substring(x, y));
86
87 content =
88 content.substring(0, x) + imports +
89 content.substring(y + 1, content.length());
90
91 Set<String> classes = ClassUtil.getClasses(
92 new StringReader(content), className);
93
94 classes.add("_getMarkup");
95 classes.add("_performBlockingInteraction");
96
97 x = content.indexOf("import ");
98
99 y = content.indexOf("{", x);
100
101 y = content.substring(0, y).lastIndexOf(";") + 1;
102
103 imports = content.substring(x, y);
104
105 StringBuilder sb = new StringBuilder();
106
107 BufferedReader br = new BufferedReader(new StringReader(imports));
108
109 String line = null;
110
111 while ((line = br.readLine()) != null) {
112 if (line.indexOf("import ") != -1) {
113 int importX = line.indexOf(" ");
114 int importY = line.lastIndexOf(".");
115
116 String importPackage = line.substring(importX + 1, importY);
117 String importClass = line.substring(
118 importY + 1, line.length() - 1);
119
120 if (!packageDir.equals(importPackage)) {
121 if (!importClass.equals("*")) {
122 if (classes.contains(importClass)) {
123 sb.append(line);
124 sb.append("\n");
125 }
126 }
127 else {
128 sb.append(line);
129 sb.append("\n");
130 }
131 }
132 }
133 }
134
135 imports = _formatImports(sb.toString());
136
137 content =
138 content.substring(0, x) + imports +
139 content.substring(y + 1, content.length());
140
141 return content;
142 }
143
144 public static void _checkPersistenceTestSuite() throws IOException {
145 String basedir = "./portal-impl/test";
146
147 if (!_fileUtil.exists(basedir)) {
148 return;
149 }
150
151 DirectoryScanner ds = new DirectoryScanner();
152
153 ds.setBasedir(basedir);
154 ds.setIncludes(new String[] {"**\\*PersistenceTest.java"});
155
156 ds.scan();
157
158 String[] files = ds.getIncludedFiles();
159
160 Set<String> persistenceTests = new HashSet<String>();
161
162 for (String file : files) {
163 String persistenceTest = file.substring(0, file.length() - 5);
164
165 persistenceTest = persistenceTest.substring(
166 persistenceTest.lastIndexOf(File.separator) + 1,
167 persistenceTest.length());
168
169 persistenceTests.add(persistenceTest);
170 }
171
172 String persistenceTestSuite = _fileUtil.read(
173 basedir + "/com/liferay/portal/service/persistence/" +
174 "PersistenceTestSuite.java");
175
176 for (String persistenceTest : persistenceTests) {
177 if (persistenceTestSuite.indexOf(persistenceTest) == -1) {
178 System.out.println("PersistenceTestSuite: " + persistenceTest);
179 }
180 }
181 }
182
183 private static void _checkWebXML() throws IOException {
184 String basedir = "./";
185
186 if (_fileUtil.exists(basedir + "portal-impl")) {
187 return;
188 }
189
190 String webXML = ContentUtil.get(
191 "com/liferay/portal/deploy/dependencies/web.xml");
192
193 DirectoryScanner ds = new DirectoryScanner();
194
195 ds.setBasedir(basedir);
196 ds.setIncludes(new String[] {"**\\web.xml"});
197
198 ds.scan();
199
200 String[] files = ds.getIncludedFiles();
201
202 for (String file : files) {
203 String content = _fileUtil.read(basedir + file);
204
205 if (content.equals(webXML)) {
206 System.out.println(file);
207 }
208 }
209 }
210
211 private static void _checkXSS(String fileName, String jspContent) {
212 Matcher matcher = _xssPattern.matcher(jspContent);
213
214 while (matcher.find()) {
215 boolean xssVulnerable = false;
216
217 String jspVariable = matcher.group(1);
218
219 String inputVulnerability =
220 " type=\"hidden\" value=\"<%= " + jspVariable + " %>";
221
222 if (jspContent.indexOf(inputVulnerability) != -1) {
223 xssVulnerable = true;
224 }
225
226 String anchorVulnerability = " href=\"<%= " + jspVariable + " %>";
227
228 if (jspContent.indexOf(anchorVulnerability) != -1) {
229 xssVulnerable = true;
230 }
231
232 String inlineStringVulnerability1 = "'<%= " + jspVariable + " %>";
233
234 if (jspContent.indexOf(inlineStringVulnerability1) != -1) {
235 xssVulnerable = true;
236 }
237
238 String inlineStringVulnerability2 = "(\"<%= " + jspVariable + " %>";
239
240 if (jspContent.indexOf(inlineStringVulnerability2) != -1) {
241 xssVulnerable = true;
242 }
243
244 String inlineStringVulnerability3 = " \"<%= " + jspVariable + " %>";
245
246 if (jspContent.indexOf(inlineStringVulnerability3) != -1) {
247 xssVulnerable = true;
248 }
249
250 String documentIdVulnerability = ".<%= " + jspVariable + " %>";
251
252 if (jspContent.indexOf(documentIdVulnerability) != -1) {
253 xssVulnerable = true;
254 }
255
256 if (xssVulnerable) {
257 System.out.println(
258 "(xss): " + fileName + " (" + jspVariable + ")");
259 }
260 }
261 }
262
263 public static String _formatImports(String imports) throws IOException {
264 if ((imports.indexOf("/*") != -1) ||
265 (imports.indexOf("*/") != -1) ||
266 (imports.indexOf("//") != -1)) {
267
268 return imports + "\n";
269 }
270
271 List<String> importsList = new ArrayList<String>();
272
273 BufferedReader br = new BufferedReader(new StringReader(imports));
274
275 String line = null;
276
277 while ((line = br.readLine()) != null) {
278 if (line.indexOf("import ") != -1) {
279 if (!importsList.contains(line)) {
280 importsList.add(line);
281 }
282 }
283 }
284
285 importsList = ListUtil.sort(importsList);
286
287 StringBuilder sb = new StringBuilder();
288
289 String temp = null;
290
291 for (int i = 0; i < importsList.size(); i++) {
292 String s = importsList.get(i);
293
294 int pos = s.indexOf(".");
295
296 pos = s.indexOf(".", pos + 1);
297
298 if (pos == -1) {
299 pos = s.indexOf(".");
300 }
301
302 String packageLevel = s.substring(7, pos);
303
304 if ((i != 0) && (!packageLevel.equals(temp))) {
305 sb.append("\n");
306 }
307
308 temp = packageLevel;
309
310 sb.append(s);
311 sb.append("\n");
312 }
313
314 return sb.toString();
315 }
316
317 private static void _formatJava() throws IOException {
318 String basedir = "./";
319
320 String copyright = _getCopyright();
321
322 String[] files = null;
323
324 if (_fileUtil.exists(basedir + "portal-impl")) {
325 files = _getPortalJavaFiles();
326 }
327 else {
328 files = _getPluginJavaFiles();
329 }
330
331 for (int i = 0; i < files.length; i++) {
332 File file = new File(basedir + files[i]);
333
334 String content = _fileUtil.read(file);
335
336 String className = file.getName();
337
338 className = className.substring(0, className.length() - 5);
339
340 String packagePath = files[i];
341
342 int packagePathX = packagePath.indexOf(
343 File.separator + "src" + File.separator);
344 int packagePathY = packagePath.lastIndexOf(File.separator);
345
346 if ((packagePathX + 5) >= packagePathY) {
347 packagePath = StringPool.BLANK;
348 }
349 else {
350 packagePath = packagePath.substring(
351 packagePathX + 5, packagePathY);
352 }
353
354 packagePath = StringUtil.replace(
355 packagePath, File.separator, StringPool.PERIOD);
356
357 if (packagePath.endsWith(".model")) {
358 if (content.indexOf(
359 "extends " + className + "Model {") != -1) {
360
361 continue;
362 }
363 }
364
365 String newContent = _formatJavaContent(files[i], content);
366
367 if (newContent.indexOf("$\n */") != -1) {
368 System.out.println("*: " + files[i]);
369
370 newContent = StringUtil.replace(
371 newContent, "$\n */", "$\n *\n */");
372 }
373
374 if (newContent.indexOf(copyright) == -1) {
375 System.out.println("(c): " + files[i]);
376 }
377
378 if (newContent.indexOf(className + ".java.html") == -1) {
379 System.out.println("Java2HTML: " + files[i]);
380 }
381
382 newContent = stripImports(newContent, packagePath, className);
383
384 newContent = StringUtil.replace(
385 newContent, "@author Raymond Aug?", "@author Raymond Augé");
386
387 if (newContent.indexOf(";\n/**") != -1) {
388 newContent = StringUtil.replace(
389 newContent,
390 ";\n/**",
391 ";\n\n/**");
392 }
393
394 if (newContent.indexOf("\t/*\n\t *") != -1) {
395 newContent = StringUtil.replace(
396 newContent,
397 "\t/*\n\t *",
398 "\t/**\n\t *");
399 }
400
401 if (newContent.indexOf("if(") != -1) {
402 newContent = StringUtil.replace(
403 newContent,
404 "if(",
405 "if (");
406 }
407
408 if (newContent.indexOf("while(") != -1) {
409 newContent = StringUtil.replace(
410 newContent,
411 "while(",
412 "while (");
413 }
414
415 if (newContent.indexOf("\n\n\n") != -1) {
416 newContent = StringUtil.replace(
417 newContent,
418 "\n\n\n",
419 "\n\n");
420 }
421
422 if (newContent.indexOf("*/\npackage ") != -1) {
423 System.out.println("package: " + files[i]);
424 }
425
426 if (newContent.indexOf(" ") != -1) {
427 if (!files[i].endsWith("StringPool.java")) {
428 System.out.println("tab: " + files[i]);
429 }
430 }
431
432 if (newContent.indexOf(" {") != -1) {
433 System.out.println("{:" + files[i]);
434 }
435
436 if (!newContent.endsWith("\n\n}") &&
437 !newContent.endsWith("{\n}")) {
438
439 System.out.println("}: " + files[i]);
440 }
441
442 if ((newContent != null) && !content.equals(newContent)) {
443 _fileUtil.write(file, newContent);
444
445 System.out.println(file);
446 }
447 }
448 }
449
450 private static String _formatJavaContent(String fileName, String content)
451 throws IOException {
452
453 StringBuilder sb = new StringBuilder();
454
455 BufferedReader br = new BufferedReader(new StringReader(content));
456
457 int lineCount = 0;
458
459 String line = null;
460
461 while ((line = br.readLine()) != null) {
462 lineCount++;
463
464 if (line.trim().length() == 0) {
465 line = StringPool.BLANK;
466 }
467
468 line = StringUtil.trimTrailing(line);
469
470 sb.append(line);
471 sb.append("\n");
472
473 line = StringUtil.replace(line, "\t", " ");
474
475 String excluded = _exclusions.getProperty(
476 StringUtil.replace(fileName, "\\", "/") + StringPool.AT +
477 lineCount);
478
479 if (excluded == null) {
480 excluded = _exclusions.getProperty(
481 StringUtil.replace(fileName, "\\", "/"));
482 }
483
484 if ((excluded == null) && ((line.length() - 1) > 79) &&
485 (!line.startsWith("import "))) {
486
487 System.out.println("> 80: " + fileName + " " + lineCount);
488 }
489 }
490
491 br.close();
492
493 String newContent = sb.toString();
494
495 if (newContent.endsWith("\n")) {
496 newContent = newContent.substring(0, newContent.length() -1);
497 }
498
499 return newContent;
500 }
501
502 private static void _formatJSP() throws IOException {
503 String basedir = "./";
504
505 List<File> list = new ArrayList<File>();
506
507 DirectoryScanner ds = new DirectoryScanner();
508
509 ds.setBasedir(basedir);
510 ds.setExcludes(new String[] {"**\\null.jsp", "**\\tmp\\**"});
511 ds.setIncludes(new String[] {"**\\*.jsp", "**\\*.jspf", "**\\*.vm"});
512
513 ds.scan();
514
515 list.addAll(ListUtil.fromArray(ds.getIncludedFiles()));
516
517 String copyright = _getCopyright();
518
519 String[] files = list.toArray(new String[list.size()]);
520
521 for (int i = 0; i < files.length; i++) {
522 File file = new File(basedir + files[i]);
523
524 String content = _fileUtil.read(file);
525 String newContent = _formatJSPContent(files[i], content);
526
527 newContent = StringUtil.replace(
528 newContent,
529 new String[] {
530 "<br/>", "\"/>", "\" >", "@page import", "\"%>", ")%>"
531 },
532 new String[] {
533 "<br />", "\" />", "\">", "@ page import", "\" %>", ") %>"
534 });
535
536 if (files[i].endsWith(".jsp")) {
537 if (newContent.indexOf(copyright) == -1) {
538 System.out.println("(c): " + files[i]);
539 }
540 }
541
542 if (newContent.indexOf("alert('<%= LanguageUtil.") != -1) {
543 newContent = StringUtil.replace(newContent,
544 "alert('<%= LanguageUtil.",
545 "alert('<%= UnicodeLanguageUtil.");
546 }
547
548 if (newContent.indexOf("alert(\"<%= LanguageUtil.") != -1) {
549 newContent = StringUtil.replace(newContent,
550 "alert(\"<%= LanguageUtil.",
551 "alert(\"<%= UnicodeLanguageUtil.");
552 }
553
554 if (newContent.indexOf("confirm('<%= LanguageUtil.") != -1) {
555 newContent = StringUtil.replace(newContent,
556 "confirm('<%= LanguageUtil.",
557 "confirm('<%= UnicodeLanguageUtil.");
558 }
559
560 if (newContent.indexOf("confirm(\"<%= LanguageUtil.") != -1) {
561 newContent = StringUtil.replace(newContent,
562 "confirm(\"<%= LanguageUtil.",
563 "confirm(\"<%= UnicodeLanguageUtil.");
564 }
565
566 if (newContent.indexOf(" ") != -1) {
567 if (!files[i].endsWith("template.vm")) {
568 System.out.println("tab: " + files[i]);
569 }
570 }
571
572 _checkXSS(files[i], content);
573
574 if ((newContent != null) && !content.equals(newContent)) {
575 _fileUtil.write(file, newContent);
576
577 System.out.println(file);
578 }
579 }
580 }
581
582 private static String _formatJSPContent(String fileName, String content)
583 throws IOException {
584
585 StringBuilder sb = new StringBuilder();
586
587 BufferedReader br = new BufferedReader(new StringReader(content));
588
589 String line = null;
590
591 while ((line = br.readLine()) != null) {
592 if (line.trim().length() == 0) {
593 line = StringPool.BLANK;
594 }
595
596 line = StringUtil.trimTrailing(line);
597
598 sb.append(line);
599 sb.append("\n");
600 }
601
602 br.close();
603
604 content = sb.toString();
605
606 if (content.endsWith("\n")) {
607 content = content.substring(0, content.length() -1);
608 }
609
610 content = _formatTaglibQuotes(fileName, content, StringPool.QUOTE);
611 content = _formatTaglibQuotes(fileName, content, StringPool.APOSTROPHE);
612
613 return content;
614 }
615
616 private static String _formatTaglibQuotes(
617 String fileName, String content, String quoteType) {
618
619 String quoteFix = StringPool.APOSTROPHE;
620
621 if (quoteFix.equals(quoteType)) {
622 quoteFix = StringPool.QUOTE;
623 }
624
625 Pattern pattern = Pattern.compile(_getTaglibRegex(quoteType));
626
627 Matcher matcher = pattern.matcher(content);
628
629 while (matcher.find()) {
630 int x = content.indexOf(quoteType + "<%=", matcher.start());
631 int y = content.indexOf("%>" + quoteType, x);
632
633 while ((x != -1) && (y != -1)) {
634 String result = content.substring(x + 1, y + 2);
635
636 if (result.indexOf(quoteType) != -1) {
637 int lineCount = 1;
638
639 char contentCharArray[] = content.toCharArray();
640
641 for (int i = 0; i < x; i++) {
642 if (contentCharArray[i] == CharPool.NEW_LINE) {
643 lineCount++;
644 }
645 }
646
647 if (result.indexOf(quoteFix) == -1) {
648 StringBuilder sb = new StringBuilder();
649
650 sb.append(content.substring(0, x));
651 sb.append(quoteFix);
652 sb.append(result);
653 sb.append(quoteFix);
654 sb.append(content.substring(y + 3, content.length()));
655
656 content = sb.toString();
657 }
658 else {
659 System.out.println(
660 "taglib: " + fileName + " " + lineCount);
661 }
662 }
663
664 x = content.indexOf(quoteType + "<%=", y);
665
666 if (x > matcher.end()) {
667 break;
668 }
669
670 y = content.indexOf("%>" + quoteType, x);
671 }
672 }
673
674 return content;
675 }
676
677 private static String _getCopyright() throws IOException {
678 try {
679 return _fileUtil.read("copyright.txt");
680 }
681 catch (Exception e1) {
682 try {
683 return _fileUtil.read("../copyright.txt");
684 }
685 catch (Exception e2) {
686 return _fileUtil.read("../../copyright.txt");
687 }
688 }
689 }
690
691 private static String[] _getPluginJavaFiles() {
692 String basedir = "./";
693
694 List<File> list = new ArrayList<File>();
695
696 DirectoryScanner ds = new DirectoryScanner();
697
698 ds.setBasedir(basedir);
699 ds.setExcludes(
700 new String[] {
701 "**\\model\\*Clp.java", "**\\model\\*Model.java",
702 "**\\model\\*Soap.java", "**\\model\\impl\\*ModelImpl.java",
703 "**\\service\\*Service.java", "**\\service\\*ServiceClp.java",
704 "**\\service\\*ServiceFactory.java",
705 "**\\service\\*ServiceUtil.java",
706 "**\\service\\ClpSerializer.java",
707 "**\\service\\base\\*ServiceBaseImpl.java",
708 "**\\service\\http\\*JSONSerializer.java",
709 "**\\service\\http\\*ServiceHttp.java",
710 "**\\service\\http\\*ServiceJSON.java",
711 "**\\service\\http\\*ServiceSoap.java",
712 "**\\service\\persistence\\*Finder.java",
713 "**\\service\\persistence\\*Persistence.java",
714 "**\\service\\persistence\\*PersistenceImpl.java",
715 "**\\service\\persistence\\*Util.java"
716 });
717 ds.setIncludes(new String[] {"**\\*.java"});
718
719 ds.scan();
720
721 list.addAll(ListUtil.fromArray(ds.getIncludedFiles()));
722
723 return list.toArray(new String[list.size()]);
724 }
725
726 private static String[] _getPortalJavaFiles() {
727 String basedir = "./";
728
729 List<File> list = new ArrayList<File>();
730
731 DirectoryScanner ds = new DirectoryScanner();
732
733 ds.setBasedir(basedir);
734 ds.setExcludes(
735 new String[] {
736 "**\\classes\\*", "**\\jsp\\*", "**\\tmp\\**",
737 "**\\EARXMLBuilder.java", "**\\EJBXMLBuilder.java",
738 "**\\PropsKeys.java", "**\\InstanceWrapperBuilder.java",
739 "**\\ServiceBuilder.java", "**\\SourceFormatter.java",
740 "**\\UserAttributes.java", "**\\WebKeys.java",
741 "**\\*_IW.java", "**\\XHTMLComplianceFormatter.java",
742 "**\\portal-service\\**\\model\\*Model.java",
743 "**\\portal-service\\**\\model\\*Soap.java",
744 "**\\model\\impl\\*ModelImpl.java",
745 "**\\portal\\service\\**", "**\\portal-client\\**",
746 "**\\portal-web\\classes\\**\\*.java",
747 "**\\portal-web\\test\\**\\*Test.java",
748 "**\\portlet\\**\\service\\**", "**\\tools\\ext_tmpl\\**"
749 });
750 ds.setIncludes(new String[] {"**\\*.java"});
751
752 ds.scan();
753
754 list.addAll(ListUtil.fromArray(ds.getIncludedFiles()));
755
756 ds = new DirectoryScanner();
757
758 ds.setBasedir(basedir);
759 ds.setExcludes(
760 new String[] {
761 "**\\tools\\ext_tmpl\\**", "**\\*_IW.java",
762 "**\\test\\**\\*PersistenceTest.java"
763 });
764 ds.setIncludes(
765 new String[] {
766 "**\\service\\http\\*HttpTest.java",
767 "**\\service\\http\\*SoapTest.java",
768 "**\\service\\impl\\*.java", "**\\service\\jms\\*.java",
769 "**\\service\\permission\\*.java",
770 "**\\service\\persistence\\BasePersistence.java",
771 "**\\service\\persistence\\*FinderImpl.java",
772 "**\\portal-impl\\test\\**\\*.java",
773 "**\\portal-service\\**\\liferay\\counter\\**.java",
774 "**\\portal-service\\**\\liferay\\documentlibrary\\**.java",
775 "**\\portal-service\\**\\liferay\\lock\\**.java",
776 "**\\portal-service\\**\\liferay\\mail\\**.java",
777 "**\\util-bridges\\**\\*.java"
778 });
779
780 ds.scan();
781
782 list.addAll(ListUtil.fromArray(ds.getIncludedFiles()));
783
784 return list.toArray(new String[list.size()]);
785 }
786
787 private static String _getTaglibRegex(String quoteType) {
788 StringBuilder sb = new StringBuilder();
789
790 sb.append("<(");
791
792 for (int i = 0; i < _TAG_LIBRARIES.length; i++) {
793 sb.append(_TAG_LIBRARIES[i]);
794 sb.append(StringPool.PIPE);
795 }
796
797 sb.deleteCharAt(sb.length() - 1);
798 sb.append("):([^>]|%>)*");
799 sb.append(quoteType);
800 sb.append("<%=[^>]*");
801 sb.append(quoteType);
802 sb.append("[^>]*%>");
803 sb.append(quoteType);
804 sb.append("([^>]|%>)*>");
805
806 return sb.toString();
807 }
808
809 private static void _readExclusions() throws IOException {
810 _exclusions = new Properties();
811
812 ClassLoader classLoader = SourceFormatter.class.getClassLoader();
813
814 URL url = classLoader.getResource(
815 "com/liferay/portal/tools/dependencies/" +
816 "source_formatter_exclusions.properties");
817
818 if (url == null) {
819 return;
820 }
821
822 InputStream is = url.openStream();
823
824 _exclusions.load(is);
825
826 is.close();
827 }
828
829 private static final String[] _TAG_LIBRARIES = new String[] {
830 "c", "html", "jsp", "liferay-portlet", "liferay-security",
831 "liferay-theme", "liferay-ui", "liferay-util", "portlet", "struts",
832 "tiles"
833 };
834
835 private static FileImpl _fileUtil = FileImpl.getInstance();
836 private static Properties _exclusions;
837 private static Pattern _xssPattern = Pattern.compile(
838 "String\\s+([^\\s]+)\\s*=\\s*ParamUtil\\.getString\\(");
839 }
840