1
22
23 package com.liferay.portal.tools;
24
25 import com.liferay.portal.kernel.util.ClassUtil;
26 import com.liferay.portal.kernel.util.ListUtil;
27 import com.liferay.portal.kernel.util.StringPool;
28 import com.liferay.portal.kernel.util.StringUtil;
29 import com.liferay.portal.util.ContentUtil;
30 import com.liferay.portal.util.FileImpl;
31
32 import java.io.BufferedReader;
33 import java.io.File;
34 import java.io.InputStream;
35 import java.io.IOException;
36 import java.io.StringReader;
37 import java.net.URL;
38 import java.util.ArrayList;
39 import java.util.Collections;
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 Collections.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 packagePath = packagePath.substring(packagePathX + 5, packagePathY);
347 packagePath = StringUtil.replace(
348 packagePath, File.separator, StringPool.PERIOD);
349
350 if (packagePath.endsWith(".model")) {
351 if (content.indexOf(
352 "extends " + className + "Model {") != -1) {
353
354 continue;
355 }
356 }
357
358 String newContent = _formatJavaContent(files[i], content);
359
360 if (newContent.indexOf("$\n */") != -1) {
361 System.out.println("*: " + files[i]);
362
363 newContent = StringUtil.replace(
364 newContent, "$\n */", "$\n *\n */");
365 }
366
367 if (newContent.indexOf(copyright) == -1) {
368 System.out.println("(c): " + files[i]);
369 }
370
371 if (newContent.indexOf(className + ".java.html") == -1) {
372 System.out.println("Java2HTML: " + files[i]);
373 }
374
375 newContent = stripImports(newContent, packagePath, className);
376
377 newContent = StringUtil.replace(
378 newContent, "@author Raymond Aug?", "@author Raymond Augé");
379
380 if (newContent.indexOf(";\n/**") != -1) {
381 newContent = StringUtil.replace(
382 newContent,
383 ";\n/**",
384 ";\n\n/**");
385 }
386
387 if (newContent.indexOf("\t/*\n\t *") != -1) {
388 newContent = StringUtil.replace(
389 newContent,
390 "\t/*\n\t *",
391 "\t/**\n\t *");
392 }
393
394 if (newContent.indexOf("if(") != -1) {
395 newContent = StringUtil.replace(
396 newContent,
397 "if(",
398 "if (");
399 }
400
401 if (newContent.indexOf("while(") != -1) {
402 newContent = StringUtil.replace(
403 newContent,
404 "while(",
405 "while (");
406 }
407
408 if (newContent.indexOf("\n\n\n") != -1) {
409 newContent = StringUtil.replace(
410 newContent,
411 "\n\n\n",
412 "\n\n");
413 }
414
415 if (newContent.indexOf("*/\npackage ") != -1) {
416 System.out.println("package: " + files[i]);
417 }
418
419 if (newContent.indexOf(" ") != -1) {
420 if (!files[i].endsWith("StringPool.java")) {
421 System.out.println("tab: " + files[i]);
422 }
423 }
424
425 if (newContent.indexOf(" {") != -1) {
426 System.out.println("{:" + files[i]);
427 }
428
429 if (!newContent.endsWith("\n\n}") &&
430 !newContent.endsWith("{\n}")) {
431
432 System.out.println("}: " + files[i]);
433 }
434
435 if ((newContent != null) && !content.equals(newContent)) {
436 _fileUtil.write(file, newContent);
437
438 System.out.println(file);
439 }
440 }
441 }
442
443 private static String _formatJavaContent(String fileName, String content)
444 throws IOException {
445
446 StringBuilder sb = new StringBuilder();
447
448 BufferedReader br = new BufferedReader(new StringReader(content));
449
450 int lineCount = 0;
451
452 String line = null;
453
454 while ((line = br.readLine()) != null) {
455 lineCount++;
456
457 if (line.trim().length() == 0) {
458 line = StringPool.BLANK;
459 }
460
461 line = StringUtil.trimTrailing(line);
462
463 sb.append(line);
464 sb.append("\n");
465
466 line = StringUtil.replace(line, "\t", " ");
467
468 String excluded = _exclusions.getProperty(
469 StringUtil.replace(fileName, "\\", "/") + StringPool.AT +
470 lineCount);
471
472 if ((excluded == null) && ((line.length() - 1) > 79) &&
473 (!line.startsWith("import "))) {
474
475 System.out.println("> 80: " + fileName + " " + lineCount);
476 }
477 }
478
479 br.close();
480
481 String newContent = sb.toString();
482
483 if (newContent.endsWith("\n")) {
484 newContent = newContent.substring(0, newContent.length() -1);
485 }
486
487 return newContent;
488 }
489
490 private static void _formatJSP() throws IOException {
491 String basedir = "./";
492
493 List<File> list = new ArrayList<File>();
494
495 DirectoryScanner ds = new DirectoryScanner();
496
497 ds.setBasedir(basedir);
498 ds.setExcludes(new String[] {"**\\null.jsp", "**\\tmp\\**"});
499 ds.setIncludes(new String[] {"**\\*.jsp", "**\\*.jspf", "**\\*.vm"});
500
501 ds.scan();
502
503 list.addAll(ListUtil.fromArray(ds.getIncludedFiles()));
504
505 String copyright = _getCopyright();
506
507 String[] files = list.toArray(new String[list.size()]);
508
509 for (int i = 0; i < files.length; i++) {
510 File file = new File(basedir + files[i]);
511
512 String content = _fileUtil.read(file, true);
513 String newContent = _formatJSPContent(files[i], content);
514
515 newContent = StringUtil.replace(
516 newContent,
517 new String[] {"<br/>", "\"/>"},
518 new String[] {"<br />", "\" />"});
519
520 if (files[i].endsWith(".jsp")) {
521 if (newContent.indexOf(copyright) == -1) {
522 System.out.println("(c): " + files[i]);
523 }
524 }
525
526 if (newContent.indexOf("alert('<%= LanguageUtil.") != -1) {
527 newContent = StringUtil.replace(newContent,
528 "alert('<%= LanguageUtil.",
529 "alert('<%= UnicodeLanguageUtil.");
530 }
531
532 if (newContent.indexOf("alert(\"<%= LanguageUtil.") != -1) {
533 newContent = StringUtil.replace(newContent,
534 "alert(\"<%= LanguageUtil.",
535 "alert(\"<%= UnicodeLanguageUtil.");
536 }
537
538 if (newContent.indexOf("confirm('<%= LanguageUtil.") != -1) {
539 newContent = StringUtil.replace(newContent,
540 "confirm('<%= LanguageUtil.",
541 "confirm('<%= UnicodeLanguageUtil.");
542 }
543
544 if (newContent.indexOf("confirm(\"<%= LanguageUtil.") != -1) {
545 newContent = StringUtil.replace(newContent,
546 "confirm(\"<%= LanguageUtil.",
547 "confirm(\"<%= UnicodeLanguageUtil.");
548 }
549
550 if (newContent.indexOf(" ") != -1) {
551 if (!files[i].endsWith("template.vm")) {
552 System.out.println("tab: " + files[i]);
553 }
554 }
555
556 _checkXSS(files[i], content);
557
558 if ((newContent != null) && !content.equals(newContent)) {
559 _fileUtil.write(file, newContent);
560
561 System.out.println(file);
562 }
563 }
564 }
565
566 private static String _formatJSPContent(String fileName, String content)
567 throws IOException {
568
569 StringBuilder sb = new StringBuilder();
570
571 BufferedReader br =
572 new BufferedReader(new StringReader(content));
573
574 int lineCount = 0;
575
576 String line = null;
577
578 while ((line = br.readLine()) != null) {
579 lineCount++;
580
581 int x = line.indexOf("\"<%=");
582 int y = line.indexOf("%>\"", x);
583
584 boolean hasTagLibrary = false;
585
586 for (int i = 0; i < _TAG_LIBRARIES.length; i++) {
587 if (line.indexOf("<" + _TAG_LIBRARIES[i] + ":") != -1) {
588 hasTagLibrary = true;
589
590 break;
591 }
592 }
593
594 if ((x != -1) && (y != -1) && hasTagLibrary) {
595 String regexp = line.substring(x, y + 3);
596
597 if (regexp.indexOf("\\\"") == -1) {
598 regexp = regexp.substring(1, regexp.length() - 1);
599
600 if (regexp.indexOf("\"") != -1) {
601 line =
602 line.substring(0, x) + "'" + regexp + "'" +
603 line.substring(y + 3, line.length());
604 }
605 }
606 }
607
608 if (line.trim().length() == 0) {
609 line = StringPool.BLANK;
610 }
611
612 line = StringUtil.trimTrailing(line);
613
614 sb.append(line);
615 sb.append("\n");
616 }
617
618 br.close();
619
620 String newContent = sb.toString();
621
622 if (newContent.endsWith("\n")) {
623 newContent = newContent.substring(0, newContent.length() -1);
624 }
625
626 return newContent;
627 }
628
629 private static String _getCopyright() throws IOException {
630 try {
631 return _fileUtil.read("copyright.txt");
632 }
633 catch (Exception e1) {
634 try {
635 return _fileUtil.read("../copyright.txt");
636 }
637 catch (Exception e2) {
638 return _fileUtil.read("../../copyright.txt");
639 }
640 }
641 }
642
643 private static String[] _getPluginJavaFiles() {
644 String basedir = "./";
645
646 List<File> list = new ArrayList<File>();
647
648 DirectoryScanner ds = new DirectoryScanner();
649
650 ds.setBasedir(basedir);
651 ds.setExcludes(
652 new String[] {
653 "**\\com\\liferay\\portlet\\service\\*.java",
654 "**\\model\\*Model.java", "**\\model\\*Soap.java",
655 "**\\model\\impl\\*ModelImpl.java",
656 "**\\service\\*Service.java",
657 "**\\service\\*ServiceFactory.java",
658 "**\\service\\*ServiceUtil.java",
659 "**\\service\\base\\*ServiceBaseImpl.java",
660 "**\\service\\http\\*JSONSerializer.java",
661 "**\\service\\http\\*ServiceHttp.java",
662 "**\\service\\http\\*ServiceJSON.java",
663 "**\\service\\http\\*ServiceSoap.java",
664 "**\\service\\persistence\\*Finder.java",
665 "**\\service\\persistence\\*Persistence.java",
666 "**\\service\\persistence\\*PersistenceImpl.java",
667 "**\\service\\persistence\\*Util.java"
668 });
669 ds.setIncludes(new String[] {"**\\*.java"});
670
671 ds.scan();
672
673 list.addAll(ListUtil.fromArray(ds.getIncludedFiles()));
674
675 return list.toArray(new String[list.size()]);
676 }
677
678 private static String[] _getPortalJavaFiles() {
679 String basedir = "./";
680
681 List<File> list = new ArrayList<File>();
682
683 DirectoryScanner ds = new DirectoryScanner();
684
685 ds.setBasedir(basedir);
686 ds.setExcludes(
687 new String[] {
688 "**\\classes\\*", "**\\jsp\\*", "**\\tmp\\**",
689 "**\\EARXMLBuilder.java", "**\\EJBXMLBuilder.java",
690 "**\\JSMin.java", "**\\PropsKeys.java",
691 "**\\InstanceWrapperBuilder.java",
692 "**\\ServiceBuilder.java", "**\\SourceFormatter.java",
693 "**\\UserAttributes.java", "**\\WebKeys.java",
694 "**\\*_IW.java", "**\\XHTMLComplianceFormatter.java",
695 "**\\portal-service\\**\\model\\*Model.java",
696 "**\\portal-service\\**\\model\\*Soap.java",
697 "**\\model\\impl\\*ModelImpl.java",
698 "**\\portal\\service\\**", "**\\portal-client\\**",
699 "**\\portal-web\\test\\**\\*Test.java",
700 "**\\portlet\\**\\service\\**", "**\\tools\\ext_tmpl\\**",
701 "**\\util-wsrp\\**"
702 });
703 ds.setIncludes(new String[] {"**\\*.java"});
704
705 ds.scan();
706
707 list.addAll(ListUtil.fromArray(ds.getIncludedFiles()));
708
709 ds = new DirectoryScanner();
710
711 ds.setBasedir(basedir);
712 ds.setExcludes(
713 new String[] {
714 "**\\tools\\ext_tmpl\\**", "**\\*_IW.java",
715 "**\\test\\**\\*PersistenceTest.java"
716 });
717 ds.setIncludes(
718 new String[] {
719 "**\\service\\http\\*HttpTest.java",
720 "**\\service\\http\\*SoapTest.java",
721 "**\\service\\impl\\*.java", "**\\service\\jms\\*.java",
722 "**\\service\\permission\\*.java",
723 "**\\service\\persistence\\BasePersistence.java",
724 "**\\service\\persistence\\*FinderImpl.java",
725 "**\\portal-impl\\test\\**\\*.java",
726 "**\\portal-service\\**\\liferay\\counter\\**.java",
727 "**\\portal-service\\**\\liferay\\documentlibrary\\**.java",
728 "**\\portal-service\\**\\liferay\\lock\\**.java",
729 "**\\portal-service\\**\\liferay\\mail\\**.java",
730 "**\\util-bridges\\**\\*.java"
731 });
732
733 ds.scan();
734
735 list.addAll(ListUtil.fromArray(ds.getIncludedFiles()));
736
737 return list.toArray(new String[list.size()]);
738 }
739
740 private static void _readExclusions() throws IOException {
741 _exclusions = new Properties();
742
743 ClassLoader classLoader = SourceFormatter.class.getClassLoader();
744
745 URL url = classLoader.getResource(
746 "com/liferay/portal/tools/dependencies/" +
747 "source_formatter_exclusions.properties");
748
749 if (url == null) {
750 return;
751 }
752
753 InputStream is = url.openStream();
754
755 _exclusions.load(is);
756
757 is.close();
758 }
759
760 private static final String[] _TAG_LIBRARIES = new String[] {
761 "c", "html", "jsp", "liferay-portlet", "liferay-security",
762 "liferay-theme", "liferay-ui", "liferay-util", "portlet", "struts",
763 "tiles"
764 };
765
766 private static FileImpl _fileUtil = FileImpl.getInstance();
767 private static Properties _exclusions;
768 private static Pattern _xssPattern = Pattern.compile(
769 "String\\s+([^\\s]+)\\s*=\\s*ParamUtil\\.getString\\(");
770
771 }