001 /** 002 * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved. 003 * 004 * This library is free software; you can redistribute it and/or modify it under 005 * the terms of the GNU Lesser General Public License as published by the Free 006 * Software Foundation; either version 2.1 of the License, or (at your option) 007 * any later version. 008 * 009 * This library is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 011 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 012 * details. 013 */ 014 015 package com.liferay.portal.tools; 016 017 import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader; 018 import com.liferay.portal.kernel.io.unsync.UnsyncStringReader; 019 import com.liferay.portal.kernel.util.CharPool; 020 import com.liferay.portal.kernel.util.ClassUtil; 021 import com.liferay.portal.kernel.util.ListUtil; 022 import com.liferay.portal.kernel.util.PropertiesUtil; 023 import com.liferay.portal.kernel.util.PropsKeys; 024 import com.liferay.portal.kernel.util.StringBundler; 025 import com.liferay.portal.kernel.util.StringPool; 026 import com.liferay.portal.kernel.util.StringUtil; 027 import com.liferay.portal.kernel.xml.Document; 028 import com.liferay.portal.kernel.xml.DocumentException; 029 import com.liferay.portal.kernel.xml.Element; 030 import com.liferay.portal.util.ContentUtil; 031 import com.liferay.portal.util.FileImpl; 032 import com.liferay.portal.xml.SAXReaderImpl; 033 034 import java.io.File; 035 import java.io.IOException; 036 import java.io.InputStream; 037 import java.net.URL; 038 import java.util.ArrayList; 039 import java.util.Arrays; 040 import java.util.Collection; 041 import java.util.Collections; 042 import java.util.List; 043 import java.util.Map; 044 import java.util.Properties; 045 import java.util.Set; 046 import java.util.TreeSet; 047 import java.util.regex.Matcher; 048 import java.util.regex.Pattern; 049 050 import org.apache.tools.ant.DirectoryScanner; 051 052 /** 053 * @author Brian Wing Shun Chan 054 * @author Igor Spasic 055 * @author Wesley Gong 056 */ 057 public class SourceFormatter { 058 059 public static void main(String[] args) { 060 try { 061 _sourceFormatterHelper = new SourceFormatterHelper(false); 062 063 _sourceFormatterHelper.init(); 064 065 _readExclusions(); 066 067 Thread thread1 = new Thread () { 068 public void run() { 069 try { 070 _checkPersistenceTestSuite(); 071 _formatJSP(); 072 _formatAntXML(); 073 _formatFriendlyURLRoutesXML(); 074 _formatWebXML(); 075 } 076 catch (Exception e) { 077 e.printStackTrace(); 078 } 079 } 080 }; 081 082 Thread thread2 = new Thread () { 083 public void run() { 084 try { 085 _formatJava(); 086 } 087 catch (Exception e) { 088 e.printStackTrace(); 089 } 090 } 091 }; 092 093 thread1.start(); 094 thread2.start(); 095 096 thread1.join(); 097 thread2.join(); 098 099 _sourceFormatterHelper.close(); 100 } 101 catch (Exception e) { 102 e.printStackTrace(); 103 } 104 } 105 106 public static String stripImports( 107 String content, String packageDir, String className) 108 throws IOException { 109 110 Pattern pattern = Pattern.compile( 111 "(^[ \t]*import\\s+.*;\n+)+", Pattern.MULTILINE); 112 113 Matcher matcher = pattern.matcher(content); 114 115 if (!matcher.find()) { 116 return content; 117 } 118 119 String imports = _formatImports(matcher.group()); 120 121 content = 122 content.substring(0, matcher.start()) + imports + 123 content.substring(matcher.end()); 124 125 Set<String> classes = ClassUtil.getClasses( 126 new UnsyncStringReader(content), className); 127 128 matcher = pattern.matcher(content); 129 130 matcher.find(); 131 132 imports = matcher.group(); 133 134 StringBuilder sb = new StringBuilder(); 135 136 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader( 137 new UnsyncStringReader(imports)); 138 139 String line = null; 140 141 while ((line = unsyncBufferedReader.readLine()) != null) { 142 if (line.indexOf("import ") != -1) { 143 int importX = line.indexOf(" "); 144 int importY = line.lastIndexOf("."); 145 146 String importPackage = line.substring(importX + 1, importY); 147 String importClass = line.substring( 148 importY + 1, line.length() - 1); 149 150 if (!packageDir.equals(importPackage)) { 151 if (!importClass.equals("*")) { 152 if (classes.contains(importClass)) { 153 sb.append(line); 154 sb.append("\n"); 155 } 156 } 157 else { 158 sb.append(line); 159 sb.append("\n"); 160 } 161 } 162 } 163 } 164 165 imports = _formatImports(sb.toString()); 166 167 content = 168 content.substring(0, matcher.start()) + imports + 169 content.substring(matcher.end()); 170 171 // Ensure a blank line exists between the package and the first import 172 173 content = content.replaceFirst( 174 "(?m)^[ \t]*(package .*;)\\s*^[ \t]*import", "$1\n\nimport"); 175 176 // Ensure a blank line exists between the last import (or package if 177 // there are no imports) and the class comment 178 179 content = content.replaceFirst( 180 "(?m)^[ \t]*((?:package|import) .*;)\\s*^[ \t]*/\\*\\*", 181 "$1\n\n/**"); 182 183 return content; 184 } 185 186 private static void _checkPersistenceTestSuite() throws IOException { 187 String basedir = "./portal-impl/test"; 188 189 if (!_fileUtil.exists(basedir)) { 190 return; 191 } 192 193 DirectoryScanner directoryScanner = new DirectoryScanner(); 194 195 directoryScanner.setBasedir(basedir); 196 directoryScanner.setIncludes( 197 new String[] {"**\\*PersistenceTest.java"}); 198 199 List<String> fileNames = _sourceFormatterHelper.scanForFiles( 200 directoryScanner); 201 202 List<String> persistenceTests = new ArrayList<String>(); 203 204 for (String fileName : fileNames) { 205 String persistenceTest = fileName.substring( 206 0, fileName.length() - 5); 207 208 persistenceTest = persistenceTest.substring( 209 persistenceTest.lastIndexOf(File.separator) + 1, 210 persistenceTest.length()); 211 212 persistenceTests.add(persistenceTest); 213 } 214 215 String persistenceTestSuiteFileName = 216 basedir + "/com/liferay/portal/service/persistence/" + 217 "PersistenceTestSuite.java"; 218 219 String persistenceTestSuiteContent = _fileUtil.read( 220 persistenceTestSuiteFileName); 221 222 for (String persistenceTest : persistenceTests) { 223 if (!persistenceTestSuiteContent.contains(persistenceTest)) { 224 _sourceFormatterHelper.printError( 225 persistenceTestSuiteFileName, 226 "PersistenceTestSuite: " + persistenceTest); 227 } 228 } 229 } 230 231 private static void _checkXSS(String fileName, String jspContent) { 232 Matcher matcher = _xssPattern.matcher(jspContent); 233 234 while (matcher.find()) { 235 boolean xssVulnerable = false; 236 237 String jspVariable = matcher.group(1); 238 239 String inputVulnerability = 240 "<input[^<>]*(<[^(/>)]*/>)*[^<>]* value=\"<%= " + jspVariable + 241 " %>"; 242 243 Pattern inputVulnerabilityPattern = 244 Pattern.compile(inputVulnerability, Pattern.CASE_INSENSITIVE); 245 246 Matcher inputVulnerabilityMatcher = 247 inputVulnerabilityPattern.matcher(jspContent); 248 249 if (inputVulnerabilityMatcher.find()) { 250 xssVulnerable = true; 251 } 252 253 String anchorVulnerability = " href=\"<%= " + jspVariable + " %>"; 254 255 if (jspContent.indexOf(anchorVulnerability) != -1) { 256 xssVulnerable = true; 257 } 258 259 String inlineStringVulnerability1 = "'<%= " + jspVariable + " %>"; 260 261 if (jspContent.indexOf(inlineStringVulnerability1) != -1) { 262 xssVulnerable = true; 263 } 264 265 String inlineStringVulnerability2 = "(\"<%= " + jspVariable + " %>"; 266 267 if (jspContent.indexOf(inlineStringVulnerability2) != -1) { 268 xssVulnerable = true; 269 } 270 271 String inlineStringVulnerability3 = " \"<%= " + jspVariable + " %>"; 272 273 if (jspContent.indexOf(inlineStringVulnerability3) != -1) { 274 xssVulnerable = true; 275 } 276 277 String documentIdVulnerability = ".<%= " + jspVariable + " %>"; 278 279 if (jspContent.indexOf(documentIdVulnerability) != -1) { 280 xssVulnerable = true; 281 } 282 283 if (xssVulnerable) { 284 _sourceFormatterHelper.printError( 285 fileName, "(xss): " + fileName + " (" + jspVariable + ")"); 286 } 287 } 288 } 289 290 private static String _fixAntXMLProjectName( 291 String basedir, String fileName, String content) 292 throws IOException { 293 294 int x = 0; 295 296 if (fileName.endsWith("-ext/build.xml")) { 297 x = fileName.indexOf("ext/"); 298 299 if (x == -1) { 300 x = 0; 301 } 302 else { 303 x = x + 5; 304 } 305 } 306 else if (fileName.endsWith("-hook/build.xml")) { 307 x = fileName.indexOf("hooks/"); 308 309 if (x == -1) { 310 x = 0; 311 } 312 else { 313 x = x + 6; 314 } 315 } 316 else if (fileName.endsWith("-layouttpl/build.xml")) { 317 x = fileName.indexOf("layouttpl/"); 318 319 if (x == -1) { 320 x = 0; 321 } 322 else { 323 x = x + 10; 324 } 325 } 326 else if (fileName.endsWith("-portlet/build.xml")) { 327 x = fileName.indexOf("portlets/"); 328 329 if (x == -1) { 330 x = 0; 331 } 332 else { 333 x = x + 9; 334 } 335 } 336 else if (fileName.endsWith("-theme/build.xml")) { 337 x = fileName.indexOf("themes/"); 338 339 if (x == -1) { 340 x = 0; 341 } 342 else { 343 x = x + 7; 344 } 345 } 346 else if (fileName.endsWith("-web/build.xml") && 347 !fileName.endsWith("/ext-web/build.xml")) { 348 349 x = fileName.indexOf("webs/"); 350 351 if (x == -1) { 352 x = 0; 353 } 354 else { 355 x = x + 5; 356 } 357 } 358 else { 359 return content; 360 } 361 362 int y = fileName.indexOf("/", x); 363 364 String correctProjectElementText = 365 "<project name=\"" + fileName.substring(x, y) + "\""; 366 367 if (!content.contains(correctProjectElementText)) { 368 x = content.indexOf("<project name=\""); 369 370 y = content.indexOf("\"", x) + 1; 371 y = content.indexOf("\"", y) + 1; 372 373 content = 374 content.substring(0, x) + correctProjectElementText + 375 content.substring(y); 376 377 _sourceFormatterHelper.printError( 378 fileName, fileName + " has an incorrect project name"); 379 380 _fileUtil.write(basedir + fileName, content); 381 } 382 383 return content; 384 } 385 386 private static void _formatAntXML() throws DocumentException, IOException { 387 String basedir = "./"; 388 389 DirectoryScanner directoryScanner = new DirectoryScanner(); 390 391 directoryScanner.setBasedir(basedir); 392 directoryScanner.setIncludes(new String[] {"**\\b*.xml"}); 393 directoryScanner.setExcludes(new String[] {"**\\tools\\**"}); 394 395 List<String> fileNames = _sourceFormatterHelper.scanForFiles( 396 directoryScanner); 397 398 for (String fileName : fileNames) { 399 fileName = StringUtil.replace(fileName, "\\", "/"); 400 401 String content = _fileUtil.read(basedir + fileName); 402 403 content = _fixAntXMLProjectName(basedir, fileName, content); 404 405 Document document = _saxReaderUtil.read(content); 406 407 Element rootElement = document.getRootElement(); 408 409 String previousName = StringPool.BLANK; 410 411 List<Element> targetElements = rootElement.elements("target"); 412 413 for (Element targetElement : targetElements) { 414 String name = targetElement.attributeValue("name"); 415 416 if (name.equals("Test")) { 417 name = name.toLowerCase(); 418 } 419 420 if (name.compareTo(previousName) < -1) { 421 _sourceFormatterHelper.printError( 422 fileName, fileName + " has an unordered target " + name); 423 424 break; 425 } 426 427 previousName = name; 428 } 429 } 430 } 431 432 private static void _formatFriendlyURLRoutesXML() 433 throws DocumentException, IOException { 434 435 String basedir = "./"; 436 437 DirectoryScanner directoryScanner = new DirectoryScanner(); 438 439 directoryScanner.setBasedir(basedir); 440 directoryScanner.setIncludes(new String[] {"**\\*routes.xml"}); 441 directoryScanner.setExcludes( 442 new String[] {"**\\classes\\**", "**\\bin\\**"}); 443 444 List<String> fileNames = _sourceFormatterHelper.scanForFiles( 445 directoryScanner); 446 447 for (String fileName : fileNames) { 448 File file = new File(basedir + fileName); 449 450 String content = _fileUtil.read(file); 451 452 if (content.indexOf("<!-- SourceFormatter.Ignore -->") != -1) { 453 continue; 454 } 455 456 String newContent = _formatFriendlyURLRoutesXML(content); 457 458 if ((newContent != null) && !content.equals(newContent)) { 459 _fileUtil.write(file, newContent); 460 461 _sourceFormatterHelper.printError(fileName, file); 462 } 463 } 464 } 465 466 private static String _formatFriendlyURLRoutesXML(String content) 467 throws DocumentException { 468 469 Document document = _saxReaderUtil.read(content); 470 471 Element rootElement = document.getRootElement(); 472 473 List<ComparableRoute> comparableRoutes = 474 new ArrayList<ComparableRoute>(); 475 476 for (Element routeElement : rootElement.elements("route")) { 477 String pattern = routeElement.elementText("pattern"); 478 479 ComparableRoute comparableRoute = new ComparableRoute(pattern); 480 481 for (Element generatedParameterElement : 482 routeElement.elements("generated-parameter")) { 483 484 String name = generatedParameterElement.attributeValue("name"); 485 String value = generatedParameterElement.getText(); 486 487 comparableRoute.addGeneratedParameter(name, value); 488 } 489 490 for (Element ignoredParameterElement : 491 routeElement.elements("ignored-parameter")) { 492 493 String name = ignoredParameterElement.attributeValue("name"); 494 495 comparableRoute.addIgnoredParameter(name); 496 } 497 498 for (Element implicitParameterElement : 499 routeElement.elements("implicit-parameter")) { 500 501 String name = implicitParameterElement.attributeValue("name"); 502 String value = implicitParameterElement.getText(); 503 504 comparableRoute.addImplicitParameter(name, value); 505 } 506 507 for (Element overriddenParameterElement : 508 routeElement.elements("overridden-parameter")) { 509 510 String name = overriddenParameterElement.attributeValue("name"); 511 String value = overriddenParameterElement.getText(); 512 513 comparableRoute.addOverriddenParameter(name, value); 514 } 515 516 comparableRoutes.add(comparableRoute); 517 } 518 519 Collections.sort(comparableRoutes); 520 521 StringBundler sb = new StringBundler(); 522 523 sb.append("<?xml version=\"1.0\"?>\n"); 524 sb.append("<!DOCTYPE routes PUBLIC \"-//Liferay//DTD Friendly URL "); 525 sb.append("Routes 6.0.0//EN\" \"http://www.liferay.com/dtd/"); 526 sb.append("liferay-friendly-url-routes_6_0_0.dtd\">\n\n<routes>\n"); 527 528 for (ComparableRoute comparableRoute : comparableRoutes) { 529 sb.append("\t<route>\n"); 530 sb.append("\t\t<pattern>"); 531 sb.append(comparableRoute.getPattern()); 532 sb.append("</pattern>\n"); 533 534 Map<String, String> generatedParameters = 535 comparableRoute.getGeneratedParameters(); 536 537 for (Map.Entry<String, String> entry : 538 generatedParameters.entrySet()) { 539 540 sb.append("\t\t<generated-parameter name=\""); 541 sb.append(entry.getKey()); 542 sb.append("\">"); 543 sb.append(entry.getValue()); 544 sb.append("</generated-parameter>\n"); 545 } 546 547 Set<String> ignoredParameters = 548 comparableRoute.getIgnoredParameters(); 549 550 for (String entry : ignoredParameters) { 551 sb.append("\t\t<ignored-parameter name=\""); 552 sb.append(entry); 553 sb.append("\" />\n"); 554 } 555 556 Map<String, String> implicitParameters = 557 comparableRoute.getImplicitParameters(); 558 559 for (Map.Entry<String, String> entry : 560 implicitParameters.entrySet()) { 561 562 sb.append("\t\t<implicit-parameter name=\""); 563 sb.append(entry.getKey()); 564 sb.append("\">"); 565 sb.append(entry.getValue()); 566 sb.append("</implicit-parameter>\n"); 567 } 568 569 Map<String, String> overriddenParameters = 570 comparableRoute.getOverriddenParameters(); 571 572 for (Map.Entry<String, String> entry : 573 overriddenParameters.entrySet()) { 574 575 sb.append("\t\t<overridden-parameter name=\""); 576 sb.append(entry.getKey()); 577 sb.append("\">"); 578 sb.append(entry.getValue()); 579 sb.append("</overridden-parameter>\n"); 580 } 581 582 sb.append("\t</route>\n"); 583 } 584 585 sb.append("</routes>"); 586 587 return sb.toString(); 588 } 589 590 private static String _formatImports(String imports) throws IOException { 591 if ((imports.indexOf("/*") != -1) || 592 (imports.indexOf("*/") != -1) || 593 (imports.indexOf("//") != -1)) { 594 595 return imports + "\n"; 596 } 597 598 List<String> importsList = new ArrayList<String>(); 599 600 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader( 601 new UnsyncStringReader(imports)); 602 603 String line = null; 604 605 while ((line = unsyncBufferedReader.readLine()) != null) { 606 if (line.indexOf("import ") != -1) { 607 if (!importsList.contains(line)) { 608 importsList.add(line); 609 } 610 } 611 } 612 613 importsList = ListUtil.sort(importsList); 614 615 StringBuilder sb = new StringBuilder(); 616 617 String temp = null; 618 619 for (int i = 0; i < importsList.size(); i++) { 620 String s = importsList.get(i); 621 622 int pos = s.indexOf("."); 623 624 pos = s.indexOf(".", pos + 1); 625 626 if (pos == -1) { 627 pos = s.indexOf("."); 628 } 629 630 String packageLevel = s.substring(7, pos); 631 632 if ((i != 0) && (!packageLevel.equals(temp))) { 633 sb.append("\n"); 634 } 635 636 temp = packageLevel; 637 638 sb.append(s); 639 sb.append("\n"); 640 } 641 642 return sb.toString(); 643 } 644 645 private static void _formatJava() throws IOException { 646 String basedir = "./"; 647 648 String copyright = _getCopyright(); 649 String oldCopyright = _getOldCopyright(); 650 651 boolean portalJavaFiles = true; 652 653 Collection<String> fileNames = null; 654 655 if (_fileUtil.exists(basedir + "portal-impl")) { 656 fileNames = _getPortalJavaFiles(); 657 } 658 else { 659 portalJavaFiles = false; 660 661 fileNames = _getPluginJavaFiles(); 662 } 663 664 for (String fileName : fileNames) { 665 File file = new File(fileName); 666 667 String content = _fileUtil.read(file); 668 669 String className = file.getName(); 670 671 className = className.substring(0, className.length() - 5); 672 673 String packagePath = fileName; 674 675 int packagePathX = packagePath.indexOf( 676 File.separator + "src" + File.separator); 677 int packagePathY = packagePath.lastIndexOf(File.separator); 678 679 if ((packagePathX + 5) >= packagePathY) { 680 packagePath = StringPool.BLANK; 681 } 682 else { 683 packagePath = packagePath.substring( 684 packagePathX + 5, packagePathY); 685 } 686 687 packagePath = StringUtil.replace( 688 packagePath, File.separator, StringPool.PERIOD); 689 690 if (packagePath.endsWith(".model")) { 691 if (content.indexOf( 692 "extends " + className + "Model {") != -1) { 693 694 continue; 695 } 696 } 697 698 String newContent = _formatJavaContent( 699 fileName, className, content); 700 701 if (newContent.indexOf("$\n */") != -1) { 702 _sourceFormatterHelper.printError(fileName, "*: " + fileName); 703 704 newContent = StringUtil.replace( 705 newContent, "$\n */", "$\n *\n */"); 706 } 707 708 if ((oldCopyright != null) && newContent.contains(oldCopyright)) { 709 newContent = StringUtil.replace( 710 newContent, oldCopyright, copyright); 711 712 _sourceFormatterHelper.printError( 713 fileName, "old (c): " + fileName); 714 } 715 716 if (newContent.indexOf(copyright) == -1) { 717 _sourceFormatterHelper.printError(fileName, "(c): " + fileName); 718 } 719 720 if (newContent.indexOf(className + ".java.html") != -1) { 721 _sourceFormatterHelper.printError( 722 fileName, "Java2HTML: " + fileName); 723 } 724 725 if (newContent.contains(" * @author Raymond Aug") && 726 !newContent.contains(" * @author Raymond Aug\u00e9")) { 727 728 newContent = newContent.replaceFirst( 729 "Raymond Aug.++", "Raymond Aug\u00e9"); 730 731 _sourceFormatterHelper.printError( 732 fileName, "UTF-8: " + fileName); 733 } 734 735 if (newContent.contains("com.liferay.portal.PortalException")) { 736 newContent = StringUtil.replace( 737 newContent, "com.liferay.portal.PortalException", 738 "com.liferay.portal.kernel.exception.PortalException"); 739 } 740 741 if (newContent.contains("com.liferay.portal.SystemException")) { 742 newContent = StringUtil.replace( 743 newContent, "com.liferay.portal.SystemException", 744 "com.liferay.portal.kernel.exception.SystemException"); 745 } 746 747 if (newContent.contains("com.liferay.util.LocalizationUtil")) { 748 newContent = StringUtil.replace( 749 newContent, "com.liferay.util.LocalizationUtil", 750 "com.liferay.portal.kernel.util.LocalizationUtil"); 751 } 752 753 newContent = stripImports(newContent, packagePath, className); 754 755 if (newContent.indexOf(";\n/**") != -1) { 756 newContent = StringUtil.replace( 757 newContent, 758 ";\n/**", 759 ";\n\n/**"); 760 } 761 762 if (newContent.indexOf("\t/*\n\t *") != -1) { 763 newContent = StringUtil.replace( 764 newContent, 765 "\t/*\n\t *", 766 "\t/**\n\t *"); 767 } 768 769 if (newContent.indexOf("if(") != -1) { 770 newContent = StringUtil.replace( 771 newContent, 772 "if(", 773 "if ("); 774 } 775 776 if (newContent.indexOf("while(") != -1) { 777 newContent = StringUtil.replace( 778 newContent, 779 "while(", 780 "while ("); 781 } 782 783 if (newContent.indexOf("\n\n\n") != -1) { 784 newContent = StringUtil.replace( 785 newContent, 786 "\n\n\n", 787 "\n\n"); 788 } 789 790 if (newContent.indexOf("*/\npackage ") != -1) { 791 _sourceFormatterHelper.printError( 792 fileName, "package: " + fileName); 793 } 794 795 if (newContent.indexOf(" ") != -1) { 796 if (!fileName.endsWith("StringPool.java")) { 797 _sourceFormatterHelper.printError( 798 fileName, "tab: " + fileName); 799 } 800 } 801 802 if (newContent.indexOf(" {") != -1) { 803 _sourceFormatterHelper.printError(fileName, "{:" + fileName); 804 } 805 806 if (!newContent.endsWith("\n\n}") && 807 !newContent.endsWith("{\n}")) { 808 809 _sourceFormatterHelper.printError(fileName, "}: " + fileName); 810 } 811 812 if (portalJavaFiles && className.endsWith("ServiceImpl") && 813 (newContent.indexOf("ServiceUtil.") != -1)) { 814 815 _sourceFormatterHelper.printError( 816 fileName, "ServiceUtil: " + fileName); 817 } 818 819 if ((newContent != null) && !content.equals(newContent)) { 820 _fileUtil.write(file, newContent); 821 822 _sourceFormatterHelper.printError(fileName, file); 823 } 824 } 825 } 826 827 private static String _formatJavaContent( 828 String fileName, String className, String content) 829 throws IOException { 830 831 boolean longLogFactoryUtil = false; 832 833 StringBuilder sb = new StringBuilder(); 834 835 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader( 836 new UnsyncStringReader(content)); 837 838 int lineCount = 0; 839 840 String line = null; 841 842 while ((line = unsyncBufferedReader.readLine()) != null) { 843 lineCount++; 844 845 if (line.trim().length() == 0) { 846 line = StringPool.BLANK; 847 } 848 849 line = StringUtil.trimTrailing(line); 850 851 line = StringUtil.replace( 852 line, 853 new String[] { 854 "* Copyright (c) 2000-2009 Liferay, Inc." 855 }, 856 new String[] { 857 "* Copyright (c) 2000-2010 Liferay, Inc." 858 }); 859 860 sb.append(line); 861 sb.append("\n"); 862 863 StringBuilder lineSB = new StringBuilder(); 864 865 int spacesPerTab = 4; 866 867 for (char c : line.toCharArray()) { 868 if (c == CharPool.TAB) { 869 for (int i = 0; i < spacesPerTab; i++) { 870 lineSB.append(CharPool.SPACE); 871 } 872 873 spacesPerTab = 4; 874 } 875 else { 876 lineSB.append(c); 877 878 spacesPerTab--; 879 880 if (spacesPerTab <= 0) { 881 spacesPerTab = 4; 882 } 883 } 884 } 885 886 line = lineSB.toString(); 887 888 if (line.endsWith("private static Log _log =")) { 889 longLogFactoryUtil = true; 890 } 891 892 String excluded = _exclusions.getProperty( 893 StringUtil.replace(fileName, "\\", "/") + StringPool.AT + 894 lineCount); 895 896 if (excluded == null) { 897 excluded = _exclusions.getProperty( 898 StringUtil.replace(fileName, "\\", "/")); 899 } 900 901 if ((excluded == null) && (line.length() > 80) && 902 !line.startsWith("import ") && !line.startsWith("package ") && 903 !line.matches("\\s*\\*.*")) { 904 905 if (fileName.endsWith("Table.java") && 906 line.contains("String TABLE_SQL_CREATE = ")) { 907 } 908 else { 909 _sourceFormatterHelper.printError( 910 fileName, "> 80: " + fileName + " " + lineCount); 911 } 912 } 913 } 914 915 unsyncBufferedReader.close(); 916 917 String newContent = sb.toString(); 918 919 if (newContent.endsWith("\n")) { 920 newContent = newContent.substring(0, newContent.length() -1); 921 } 922 923 if (longLogFactoryUtil) { 924 newContent = StringUtil.replace( 925 newContent, 926 "private static Log _log =\n\t\tLogFactoryUtil.getLog(", 927 "private static Log _log = LogFactoryUtil.getLog(\n\t\t"); 928 } 929 930 return newContent; 931 } 932 933 private static void _formatJSP() throws IOException { 934 String basedir = "./"; 935 936 String copyright = _getCopyright(); 937 String oldCopyright = _getOldCopyright(); 938 939 List<String> list = new ArrayList<String>(); 940 941 DirectoryScanner directoryScanner = new DirectoryScanner(); 942 943 directoryScanner.setBasedir(basedir); 944 directoryScanner.setExcludes( 945 new String[] { 946 "**\\portal\\aui\\**", "**\\bin\\**", "**\\null.jsp", 947 "**\\tmp\\**", "**\\tools\\**" 948 }); 949 directoryScanner.setIncludes( 950 new String[] {"**\\*.jsp", "**\\*.jspf", "**\\*.vm"}); 951 952 list.addAll(_sourceFormatterHelper.scanForFiles(directoryScanner)); 953 954 String[] files = list.toArray(new String[list.size()]); 955 956 for (int i = 0; i < files.length; i++) { 957 File file = new File(basedir + files[i]); 958 959 String content = _fileUtil.read(file); 960 String newContent = _formatJSPContent(files[i], content); 961 962 newContent = StringUtil.replace( 963 newContent, 964 new String[] { 965 "<br/>", "\"/>", "\" >", "@page import", "\"%>", ")%>", 966 "javascript: " 967 }, 968 new String[] { 969 "<br />", "\" />", "\">", "@ page import", "\" %>", ") %>", 970 "javascript:" 971 }); 972 973 newContent = StringUtil.replace( 974 newContent, 975 new String[] { 976 "* Copyright (c) 2000-2009 Liferay, Inc." 977 }, 978 new String[] { 979 "* Copyright (c) 2000-2010 Liferay, Inc." 980 }); 981 982 if (files[i].endsWith(".jsp") || files[i].endsWith(".jspf")) { 983 if ((oldCopyright != null) && 984 newContent.contains(oldCopyright)) { 985 986 newContent = StringUtil.replace( 987 newContent, oldCopyright, copyright); 988 989 _sourceFormatterHelper.printError( 990 files[i], "old (c): " + files[i]); 991 } 992 993 if (newContent.indexOf(copyright) == -1) { 994 _sourceFormatterHelper.printError( 995 files[i], "(c): " + files[i]); 996 } 997 } 998 999 if (newContent.indexOf("alert('<%= LanguageUtil.") != -1) { 1000 newContent = StringUtil.replace(newContent, 1001 "alert('<%= LanguageUtil.", 1002 "alert('<%= UnicodeLanguageUtil."); 1003 } 1004 1005 if (newContent.indexOf("alert(\"<%= LanguageUtil.") != -1) { 1006 newContent = StringUtil.replace(newContent, 1007 "alert(\"<%= LanguageUtil.", 1008 "alert(\"<%= UnicodeLanguageUtil."); 1009 } 1010 1011 if (newContent.indexOf("confirm('<%= LanguageUtil.") != -1) { 1012 newContent = StringUtil.replace(newContent, 1013 "confirm('<%= LanguageUtil.", 1014 "confirm('<%= UnicodeLanguageUtil."); 1015 } 1016 1017 if (newContent.indexOf("confirm(\"<%= LanguageUtil.") != -1) { 1018 newContent = StringUtil.replace(newContent, 1019 "confirm(\"<%= LanguageUtil.", 1020 "confirm(\"<%= UnicodeLanguageUtil."); 1021 } 1022 1023 if (newContent.indexOf(" ") != -1) { 1024 if (!files[i].endsWith("template.vm")) { 1025 _sourceFormatterHelper.printError( 1026 files[i], "tab: " + files[i]); 1027 } 1028 } 1029 1030 _checkXSS(files[i], content); 1031 1032 if ((newContent != null) && !content.equals(newContent)) { 1033 _fileUtil.write(file, newContent); 1034 _sourceFormatterHelper.printError(files[i], file); 1035 } 1036 } 1037 1038 } 1039 1040 private static String _formatJSPContent(String fileName, String content) 1041 throws IOException { 1042 1043 StringBuilder sb = new StringBuilder(); 1044 1045 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader( 1046 new UnsyncStringReader(content)); 1047 1048 String line = null; 1049 1050 while ((line = unsyncBufferedReader.readLine()) != null) { 1051 if (line.trim().length() == 0) { 1052 line = StringPool.BLANK; 1053 } 1054 1055 line = StringUtil.trimTrailing(line); 1056 1057 sb.append(line); 1058 sb.append("\n"); 1059 } 1060 1061 unsyncBufferedReader.close(); 1062 1063 content = sb.toString(); 1064 1065 if (content.endsWith("\n")) { 1066 content = content.substring(0, content.length() -1); 1067 } 1068 1069 content = _formatTaglibQuotes(fileName, content, StringPool.QUOTE); 1070 content = _formatTaglibQuotes(fileName, content, StringPool.APOSTROPHE); 1071 1072 return content; 1073 } 1074 1075 private static String _formatTaglibQuotes( 1076 String fileName, String content, String quoteType) { 1077 1078 String quoteFix = StringPool.APOSTROPHE; 1079 1080 if (quoteFix.equals(quoteType)) { 1081 quoteFix = StringPool.QUOTE; 1082 } 1083 1084 Pattern pattern = Pattern.compile(_getTaglibRegex(quoteType)); 1085 1086 Matcher matcher = pattern.matcher(content); 1087 1088 while (matcher.find()) { 1089 int x = content.indexOf(quoteType + "<%=", matcher.start()); 1090 int y = content.indexOf("%>" + quoteType, x); 1091 1092 while ((x != -1) && (y != -1)) { 1093 String result = content.substring(x + 1, y + 2); 1094 1095 if (result.indexOf(quoteType) != -1) { 1096 int lineCount = 1; 1097 1098 char contentCharArray[] = content.toCharArray(); 1099 1100 for (int i = 0; i < x; i++) { 1101 if (contentCharArray[i] == CharPool.NEW_LINE) { 1102 lineCount++; 1103 } 1104 } 1105 1106 if (result.indexOf(quoteFix) == -1) { 1107 StringBuilder sb = new StringBuilder(); 1108 1109 sb.append(content.substring(0, x)); 1110 sb.append(quoteFix); 1111 sb.append(result); 1112 sb.append(quoteFix); 1113 sb.append(content.substring(y + 3, content.length())); 1114 1115 content = sb.toString(); 1116 } 1117 else { 1118 _sourceFormatterHelper.printError( 1119 fileName, "taglib: " + fileName + " " + lineCount); 1120 } 1121 } 1122 1123 x = content.indexOf(quoteType + "<%=", y); 1124 1125 if (x > matcher.end()) { 1126 break; 1127 } 1128 1129 y = content.indexOf("%>" + quoteType, x); 1130 } 1131 } 1132 1133 return content; 1134 } 1135 1136 private static void _formatWebXML() throws IOException { 1137 String basedir = "./"; 1138 1139 if (_fileUtil.exists(basedir + "portal-impl")) { 1140 Properties properties = new Properties(); 1141 1142 String propertiesContent = _fileUtil.read( 1143 basedir + "portal-impl/src/portal.properties"); 1144 1145 PropertiesUtil.load(properties, propertiesContent); 1146 1147 String[] locales = StringUtil.split( 1148 properties.getProperty(PropsKeys.LOCALES)); 1149 1150 Arrays.sort(locales); 1151 1152 Set<String> urlPatterns = new TreeSet<String>(); 1153 1154 for (String locale : locales) { 1155 int pos = locale.indexOf(StringPool.UNDERLINE); 1156 1157 String languageCode = locale.substring(0, pos); 1158 1159 urlPatterns.add(languageCode); 1160 urlPatterns.add(locale); 1161 } 1162 1163 StringBuilder sb = new StringBuilder(); 1164 1165 for (String urlPattern : urlPatterns) { 1166 sb.append("\t<servlet-mapping>\n"); 1167 sb.append("\t\t<servlet-name>I18n Servlet</servlet-name>\n"); 1168 sb.append( 1169 "\t\t<url-pattern>/" + urlPattern +"/*</url-pattern>\n"); 1170 sb.append("\t</servlet-mapping>\n"); 1171 } 1172 1173 File file = new File( 1174 basedir + "portal-web/docroot/WEB-INF/web.xml"); 1175 1176 String content = _fileUtil.read(file); 1177 1178 int x = content.indexOf("<servlet-mapping>"); 1179 1180 x = content.indexOf("<servlet-name>I18n Servlet</servlet-name>", x); 1181 1182 x = content.lastIndexOf("<servlet-mapping>", x) - 1; 1183 1184 int y = content.lastIndexOf( 1185 "<servlet-name>I18n Servlet</servlet-name>"); 1186 1187 y = content.indexOf("</servlet-mapping>", y) + 19; 1188 1189 String newContent = 1190 content.substring(0, x) + sb.toString() + content.substring(y); 1191 1192 x = newContent.indexOf("<security-constraint>"); 1193 1194 x = newContent.indexOf( 1195 "<web-resource-name>/c/portal/protected</web-resource-name>", 1196 x); 1197 1198 x = newContent.indexOf("<url-pattern>", x) - 3; 1199 1200 y = newContent.indexOf("<http-method>", x); 1201 1202 y = newContent.lastIndexOf("</url-pattern>", y) + 15; 1203 1204 sb = new StringBuilder(); 1205 1206 sb.append( 1207 "\t\t\t<url-pattern>/c/portal/protected</url-pattern>\n"); 1208 1209 for (String urlPattern : urlPatterns) { 1210 sb.append( 1211 "\t\t\t<url-pattern>/" + urlPattern + 1212 "/c/portal/protected</url-pattern>\n"); 1213 } 1214 1215 newContent = 1216 newContent.substring(0, x) + sb.toString() + 1217 newContent.substring(y); 1218 1219 if ((newContent != null) && !content.equals(newContent)) { 1220 _fileUtil.write(file, newContent); 1221 1222 System.out.println(file); 1223 } 1224 } 1225 else { 1226 String webXML = ContentUtil.get( 1227 "com/liferay/portal/deploy/dependencies/web.xml"); 1228 1229 DirectoryScanner directoryScanner = new DirectoryScanner(); 1230 1231 directoryScanner.setBasedir(basedir); 1232 directoryScanner.setIncludes(new String[] {"**\\web.xml"}); 1233 1234 List<String> fileNames = _sourceFormatterHelper.scanForFiles( 1235 directoryScanner); 1236 1237 for (String fileName : fileNames) { 1238 String content = _fileUtil.read(basedir + fileName); 1239 1240 if (content.equals(webXML)) { 1241 _sourceFormatterHelper.printError(fileName, fileName); 1242 } 1243 } 1244 } 1245 } 1246 1247 private static String _getCopyright() throws IOException { 1248 String copyright = _fileUtil.read("copyright.txt"); 1249 1250 if (copyright == null) { 1251 copyright = _fileUtil.read("../copyright.txt"); 1252 } 1253 1254 if (copyright == null) { 1255 copyright = _fileUtil.read("../../copyright.txt"); 1256 } 1257 1258 return copyright; 1259 } 1260 1261 private static String _getOldCopyright() throws IOException { 1262 String copyright = _fileUtil.read("old-copyright.txt"); 1263 1264 if (copyright == null) { 1265 copyright = _fileUtil.read("../old-copyright.txt"); 1266 } 1267 1268 if (copyright == null) { 1269 copyright = _fileUtil.read("../../old-copyright.txt"); 1270 } 1271 1272 return copyright; 1273 } 1274 1275 private static Collection<String> _getPluginJavaFiles() { 1276 String basedir = "./"; 1277 1278 Collection<String> fileNames = new TreeSet<String>(); 1279 1280 DirectoryScanner directoryScanner = new DirectoryScanner(); 1281 1282 directoryScanner.setBasedir(basedir); 1283 directoryScanner.setExcludes( 1284 new String[] { 1285 "**\\bin\\**", "**\\model\\*Clp.java", 1286 "**\\model\\impl\\*ModelImpl.java", 1287 "**\\service\\**\\model\\*Model.java", 1288 "**\\service\\**\\model\\*Soap.java", 1289 "**\\service\\**\\model\\*Wrapper.java", 1290 "**\\service\\**\\service\\*Service.java", 1291 "**\\service\\**\\service\\*ServiceClp.java", 1292 "**\\service\\**\\service\\*ServiceFactory.java", 1293 "**\\service\\**\\service\\*ServiceUtil.java", 1294 "**\\service\\**\\service\\*ServiceWrapper.java", 1295 "**\\service\\**\\service\\ClpSerializer.java", 1296 "**\\service\\**\\service\\messaging\\*ClpMessageListener.java", 1297 "**\\service\\**\\service\\persistence\\*Finder.java", 1298 "**\\service\\**\\service\\persistence\\*Persistence.java", 1299 "**\\service\\**\\service\\persistence\\*Util.java", 1300 "**\\service\\base\\*ServiceBaseImpl.java", 1301 "**\\service\\http\\*JSONSerializer.java", 1302 "**\\service\\http\\*ServiceHttp.java", 1303 "**\\service\\http\\*ServiceJSON.java", 1304 "**\\service\\http\\*ServiceSoap.java", 1305 "**\\service\\persistence\\*PersistenceImpl.java", 1306 "**\\tmp\\**" 1307 }); 1308 directoryScanner.setIncludes(new String[] {"**\\*.java"}); 1309 1310 fileNames.addAll(_sourceFormatterHelper.scanForFiles(directoryScanner)); 1311 1312 return fileNames; 1313 } 1314 1315 private static Collection<String> _getPortalJavaFiles() { 1316 String basedir = "./"; 1317 1318 Collection<String> fileNames = new TreeSet<String>(); 1319 1320 DirectoryScanner directoryScanner = new DirectoryScanner(); 1321 1322 directoryScanner.setBasedir(basedir); 1323 directoryScanner.setExcludes( 1324 new String[] { 1325 "**\\InstanceWrapperBuilder.java", "**\\*_IW.java", 1326 "**\\PropsKeys.java", "**\\PropsValues.java", 1327 "**\\ServiceBuilder.java", "**\\SourceFormatter.java", 1328 "**\\UserAttributes.java", "**\\WebKeys.java", 1329 "**\\bin\\**", "**\\classes\\*", "**\\counter\\service\\**", 1330 "**\\jsp\\*", "**\\model\\impl\\*ModelImpl.java", 1331 "**\\portal\\service\\**", "**\\portal-client\\**", 1332 "**\\portal-service\\**\\model\\*Model.java", 1333 "**\\portal-service\\**\\model\\*Soap.java", 1334 "**\\portal-service\\**\\model\\*Wrapper.java", 1335 "**\\portal-web\\classes\\**\\*.java", 1336 "**\\portal-web\\test\\**\\*Test.java", 1337 "**\\portlet\\**\\service\\**", "**\\tmp\\**", "**\\tools\\**" 1338 }); 1339 directoryScanner.setIncludes(new String[] {"**\\*.java"}); 1340 1341 fileNames.addAll(_sourceFormatterHelper.scanForFiles(directoryScanner)); 1342 1343 directoryScanner = new DirectoryScanner(); 1344 1345 directoryScanner.setBasedir(basedir); 1346 directoryScanner.setExcludes( 1347 new String[] { 1348 "**\\bin\\**", "**\\portal-client\\**", 1349 "**\\tools\\ext_tmpl\\**", "**\\*_IW.java", 1350 "**\\test\\**\\*PersistenceTest.java" 1351 }); 1352 directoryScanner.setIncludes( 1353 new String[] { 1354 "**\\com\\liferay\\portal\\service\\ServiceContext*.java", 1355 "**\\model\\BaseModel.java", 1356 "**\\model\\impl\\BaseModelImpl.java", 1357 "**\\service\\base\\PrincipalBean.java", 1358 "**\\service\\http\\*HttpTest.java", 1359 "**\\service\\http\\*SoapTest.java", 1360 "**\\service\\http\\TunnelUtil.java", 1361 "**\\service\\impl\\*.java", "**\\service\\jms\\*.java", 1362 "**\\service\\permission\\*.java", 1363 "**\\service\\persistence\\BasePersistence.java", 1364 "**\\service\\persistence\\BatchSession*.java", 1365 "**\\service\\persistence\\*FinderImpl.java", 1366 "**\\service\\persistence\\*Query.java", 1367 "**\\service\\persistence\\impl\\BasePersistenceImpl.java", 1368 "**\\portal-impl\\test\\**\\*.java", 1369 "**\\portal-service\\**\\liferay\\documentlibrary\\**.java", 1370 "**\\portal-service\\**\\liferay\\lock\\**.java", 1371 "**\\portal-service\\**\\liferay\\mail\\**.java", 1372 "**\\util-bridges\\**\\*.java" 1373 }); 1374 1375 fileNames.addAll(_sourceFormatterHelper.scanForFiles(directoryScanner)); 1376 1377 return fileNames; 1378 } 1379 1380 private static String _getTaglibRegex(String quoteType) { 1381 StringBuilder sb = new StringBuilder(); 1382 1383 sb.append("<("); 1384 1385 for (int i = 0; i < _TAG_LIBRARIES.length; i++) { 1386 sb.append(_TAG_LIBRARIES[i]); 1387 sb.append(StringPool.PIPE); 1388 } 1389 1390 sb.deleteCharAt(sb.length() - 1); 1391 sb.append("):([^>]|%>)*"); 1392 sb.append(quoteType); 1393 sb.append("<%=.*"); 1394 sb.append(quoteType); 1395 sb.append(".*%>"); 1396 sb.append(quoteType); 1397 sb.append("([^>]|%>)*>"); 1398 1399 return sb.toString(); 1400 } 1401 1402 private static void _readExclusions() throws IOException { 1403 _exclusions = new Properties(); 1404 1405 ClassLoader classLoader = SourceFormatter.class.getClassLoader(); 1406 1407 String sourceFormatterExclusions = System.getProperty( 1408 "source-formatter-exclusions", 1409 "com/liferay/portal/tools/dependencies/" + 1410 "source_formatter_exclusions.properties"); 1411 1412 URL url = classLoader.getResource(sourceFormatterExclusions); 1413 1414 if (url == null) { 1415 return; 1416 } 1417 1418 InputStream is = url.openStream(); 1419 1420 _exclusions.load(is); 1421 1422 is.close(); 1423 } 1424 1425 private static final String[] _TAG_LIBRARIES = new String[] { 1426 "aui", "c", "html", "jsp", "liferay-portlet", "liferay-security", 1427 "liferay-theme", "liferay-ui", "liferay-util", "portlet", "struts", 1428 "tiles" 1429 }; 1430 1431 private static Properties _exclusions; 1432 private static FileImpl _fileUtil = FileImpl.getInstance(); 1433 private static SAXReaderImpl _saxReaderUtil = SAXReaderImpl.getInstance(); 1434 private static SourceFormatterHelper _sourceFormatterHelper; 1435 private static Pattern _xssPattern = Pattern.compile( 1436 "String\\s+([^\\s]+)\\s*=\\s*(Bean)?ParamUtil\\.getString\\("); 1437 1438 }