001 /** 002 * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved. 003 * 004 * The contents of this file are subject to the terms of the Liferay Enterprise 005 * Subscription License ("License"). You may not use this file except in 006 * compliance with the License. You can obtain a copy of the License by 007 * contacting Liferay, Inc. See the License for the specific language governing 008 * permissions and limitations under the License, including but not limited to 009 * distribution rights of the Software. 010 * 011 * 012 * 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 _formatSH(); 075 _formatWebXML(); 076 } 077 catch (Exception e) { 078 e.printStackTrace(); 079 } 080 } 081 }; 082 083 Thread thread2 = new Thread () { 084 public void run() { 085 try { 086 _formatJava(); 087 } 088 catch (Exception e) { 089 e.printStackTrace(); 090 } 091 } 092 }; 093 094 thread1.start(); 095 thread2.start(); 096 097 thread1.join(); 098 thread2.join(); 099 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\\**"}); 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 void _formatFriendlyURLRoutesXML() 434 throws DocumentException, IOException { 435 436 String basedir = "./"; 437 438 DirectoryScanner directoryScanner = new DirectoryScanner(); 439 440 directoryScanner.setBasedir(basedir); 441 directoryScanner.setIncludes(new String[] {"**\\*routes.xml"}); 442 directoryScanner.setExcludes( 443 new String[] {"**\\classes\\**", "**\\bin\\**"}); 444 445 List<String> fileNames = _sourceFormatterHelper.scanForFiles( 446 directoryScanner); 447 448 for (String fileName : fileNames) { 449 File file = new File(basedir + fileName); 450 451 String content = _fileUtil.read(file); 452 453 if (content.indexOf("<!-- SourceFormatter.Ignore -->") != -1) { 454 continue; 455 } 456 457 String newContent = _formatFriendlyURLRoutesXML(content); 458 459 if ((newContent != null) && !content.equals(newContent)) { 460 _fileUtil.write(file, newContent); 461 462 _sourceFormatterHelper.printError(fileName, file); 463 } 464 } 465 } 466 467 private static String _formatFriendlyURLRoutesXML(String content) 468 throws DocumentException { 469 470 Document document = _saxReaderUtil.read(content); 471 472 Element rootElement = document.getRootElement(); 473 474 List<ComparableRoute> comparableRoutes = 475 new ArrayList<ComparableRoute>(); 476 477 for (Element routeElement : rootElement.elements("route")) { 478 String pattern = routeElement.elementText("pattern"); 479 480 ComparableRoute comparableRoute = new ComparableRoute(pattern); 481 482 for (Element generatedParameterElement : 483 routeElement.elements("generated-parameter")) { 484 485 String name = generatedParameterElement.attributeValue("name"); 486 String value = generatedParameterElement.getText(); 487 488 comparableRoute.addGeneratedParameter(name, value); 489 } 490 491 for (Element ignoredParameterElement : 492 routeElement.elements("ignored-parameter")) { 493 494 String name = ignoredParameterElement.attributeValue("name"); 495 496 comparableRoute.addIgnoredParameter(name); 497 } 498 499 for (Element implicitParameterElement : 500 routeElement.elements("implicit-parameter")) { 501 502 String name = implicitParameterElement.attributeValue("name"); 503 String value = implicitParameterElement.getText(); 504 505 comparableRoute.addImplicitParameter(name, value); 506 } 507 508 for (Element overriddenParameterElement : 509 routeElement.elements("overridden-parameter")) { 510 511 String name = overriddenParameterElement.attributeValue("name"); 512 String value = overriddenParameterElement.getText(); 513 514 comparableRoute.addOverriddenParameter(name, value); 515 } 516 517 comparableRoutes.add(comparableRoute); 518 } 519 520 Collections.sort(comparableRoutes); 521 522 StringBundler sb = new StringBundler(); 523 524 sb.append("<?xml version=\"1.0\"?>\n"); 525 sb.append("<!DOCTYPE routes PUBLIC \"-//Liferay//DTD Friendly URL "); 526 sb.append("Routes 6.0.0//EN\" \"http://www.liferay.com/dtd/"); 527 sb.append("liferay-friendly-url-routes_6_0_0.dtd\">\n\n<routes>\n"); 528 529 for (ComparableRoute comparableRoute : comparableRoutes) { 530 sb.append("\t<route>\n"); 531 sb.append("\t\t<pattern>"); 532 sb.append(comparableRoute.getPattern()); 533 sb.append("</pattern>\n"); 534 535 Map<String, String> generatedParameters = 536 comparableRoute.getGeneratedParameters(); 537 538 for (Map.Entry<String, String> entry : 539 generatedParameters.entrySet()) { 540 541 sb.append("\t\t<generated-parameter name=\""); 542 sb.append(entry.getKey()); 543 sb.append("\">"); 544 sb.append(entry.getValue()); 545 sb.append("</generated-parameter>\n"); 546 } 547 548 Set<String> ignoredParameters = 549 comparableRoute.getIgnoredParameters(); 550 551 for (String entry : ignoredParameters) { 552 sb.append("\t\t<ignored-parameter name=\""); 553 sb.append(entry); 554 sb.append("\" />\n"); 555 } 556 557 Map<String, String> implicitParameters = 558 comparableRoute.getImplicitParameters(); 559 560 for (Map.Entry<String, String> entry : 561 implicitParameters.entrySet()) { 562 563 sb.append("\t\t<implicit-parameter name=\""); 564 sb.append(entry.getKey()); 565 sb.append("\">"); 566 sb.append(entry.getValue()); 567 sb.append("</implicit-parameter>\n"); 568 } 569 570 Map<String, String> overriddenParameters = 571 comparableRoute.getOverriddenParameters(); 572 573 for (Map.Entry<String, String> entry : 574 overriddenParameters.entrySet()) { 575 576 sb.append("\t\t<overridden-parameter name=\""); 577 sb.append(entry.getKey()); 578 sb.append("\">"); 579 sb.append(entry.getValue()); 580 sb.append("</overridden-parameter>\n"); 581 } 582 583 sb.append("\t</route>\n"); 584 } 585 586 sb.append("</routes>"); 587 588 return sb.toString(); 589 } 590 591 private static String _formatImports(String imports) throws IOException { 592 if ((imports.indexOf("/*") != -1) || 593 (imports.indexOf("*/") != -1) || 594 (imports.indexOf("//") != -1)) { 595 596 return imports + "\n"; 597 } 598 599 List<String> importsList = new ArrayList<String>(); 600 601 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader( 602 new UnsyncStringReader(imports)); 603 604 String line = null; 605 606 while ((line = unsyncBufferedReader.readLine()) != null) { 607 if (line.indexOf("import ") != -1) { 608 if (!importsList.contains(line)) { 609 importsList.add(line); 610 } 611 } 612 } 613 614 importsList = ListUtil.sort(importsList); 615 616 StringBuilder sb = new StringBuilder(); 617 618 String temp = null; 619 620 for (int i = 0; i < importsList.size(); i++) { 621 String s = importsList.get(i); 622 623 int pos = s.indexOf("."); 624 625 pos = s.indexOf(".", pos + 1); 626 627 if (pos == -1) { 628 pos = s.indexOf("."); 629 } 630 631 String packageLevel = s.substring(7, pos); 632 633 if ((i != 0) && (!packageLevel.equals(temp))) { 634 sb.append("\n"); 635 } 636 637 temp = packageLevel; 638 639 sb.append(s); 640 sb.append("\n"); 641 } 642 643 return sb.toString(); 644 } 645 646 private static void _formatJava() throws IOException { 647 String basedir = "./"; 648 649 String copyright = _getCopyright(); 650 String oldCopyright = _getOldCopyright(); 651 652 boolean portalJavaFiles = true; 653 654 Collection<String> fileNames = null; 655 656 if (_fileUtil.exists(basedir + "portal-impl")) { 657 fileNames = _getPortalJavaFiles(); 658 } 659 else { 660 portalJavaFiles = false; 661 662 fileNames = _getPluginJavaFiles(); 663 } 664 665 for (String fileName : fileNames) { 666 File file = new File(fileName); 667 668 String content = _fileUtil.read(file); 669 670 String className = file.getName(); 671 672 className = className.substring(0, className.length() - 5); 673 674 String packagePath = fileName; 675 676 int packagePathX = packagePath.indexOf( 677 File.separator + "src" + File.separator); 678 int packagePathY = packagePath.lastIndexOf(File.separator); 679 680 if ((packagePathX + 5) >= packagePathY) { 681 packagePath = StringPool.BLANK; 682 } 683 else { 684 packagePath = packagePath.substring( 685 packagePathX + 5, packagePathY); 686 } 687 688 packagePath = StringUtil.replace( 689 packagePath, File.separator, StringPool.PERIOD); 690 691 if (packagePath.endsWith(".model")) { 692 if (content.indexOf( 693 "extends " + className + "Model {") != -1) { 694 695 continue; 696 } 697 } 698 699 String newContent = _formatJavaContent( 700 fileName, className, content); 701 702 if (newContent.indexOf("$\n */") != -1) { 703 _sourceFormatterHelper.printError(fileName, "*: " + fileName); 704 705 newContent = StringUtil.replace( 706 newContent, "$\n */", "$\n *\n */"); 707 } 708 709 if ((oldCopyright != null) && newContent.contains(oldCopyright)) { 710 newContent = StringUtil.replace( 711 newContent, oldCopyright, copyright); 712 713 _sourceFormatterHelper.printError( 714 fileName, "old (c): " + fileName); 715 } 716 717 if (newContent.indexOf(copyright) == -1) { 718 _sourceFormatterHelper.printError(fileName, "(c): " + fileName); 719 } 720 721 if (newContent.indexOf(className + ".java.html") != -1) { 722 _sourceFormatterHelper.printError( 723 fileName, "Java2HTML: " + fileName); 724 } 725 726 if (newContent.contains(" * @author Raymond Aug") && 727 !newContent.contains(" * @author Raymond Aug\u00e9")) { 728 729 newContent = newContent.replaceFirst( 730 "Raymond Aug.++", "Raymond Aug\u00e9"); 731 732 _sourceFormatterHelper.printError( 733 fileName, "UTF-8: " + fileName); 734 } 735 736 if (newContent.contains("com.liferay.portal.PortalException")) { 737 newContent = StringUtil.replace( 738 newContent, "com.liferay.portal.PortalException", 739 "com.liferay.portal.kernel.exception.PortalException"); 740 } 741 742 if (newContent.contains("com.liferay.portal.SystemException")) { 743 newContent = StringUtil.replace( 744 newContent, "com.liferay.portal.SystemException", 745 "com.liferay.portal.kernel.exception.SystemException"); 746 } 747 748 if (newContent.contains("com.liferay.util.LocalizationUtil")) { 749 newContent = StringUtil.replace( 750 newContent, "com.liferay.util.LocalizationUtil", 751 "com.liferay.portal.kernel.util.LocalizationUtil"); 752 } 753 754 newContent = stripImports(newContent, packagePath, className); 755 756 if (newContent.indexOf(";\n/**") != -1) { 757 newContent = StringUtil.replace( 758 newContent, 759 ";\n/**", 760 ";\n\n/**"); 761 } 762 763 if (newContent.indexOf("\t/*\n\t *") != -1) { 764 newContent = StringUtil.replace( 765 newContent, 766 "\t/*\n\t *", 767 "\t/**\n\t *"); 768 } 769 770 if (newContent.indexOf("if(") != -1) { 771 newContent = StringUtil.replace( 772 newContent, 773 "if(", 774 "if ("); 775 } 776 777 if (newContent.indexOf("while(") != -1) { 778 newContent = StringUtil.replace( 779 newContent, 780 "while(", 781 "while ("); 782 } 783 784 if (newContent.indexOf("\n\n\n") != -1) { 785 newContent = StringUtil.replace( 786 newContent, 787 "\n\n\n", 788 "\n\n"); 789 } 790 791 if (newContent.indexOf("*/\npackage ") != -1) { 792 _sourceFormatterHelper.printError( 793 fileName, "package: " + fileName); 794 } 795 796 if (newContent.indexOf(" ") != -1) { 797 if (!fileName.endsWith("StringPool.java")) { 798 _sourceFormatterHelper.printError( 799 fileName, "tab: " + fileName); 800 } 801 } 802 803 if (newContent.indexOf(" {") != -1) { 804 _sourceFormatterHelper.printError(fileName, "{:" + fileName); 805 } 806 807 if (!newContent.endsWith("\n\n}") && 808 !newContent.endsWith("{\n}")) { 809 810 _sourceFormatterHelper.printError(fileName, "}: " + fileName); 811 } 812 813 if (portalJavaFiles && className.endsWith("ServiceImpl") && 814 (newContent.indexOf("ServiceUtil.") != -1)) { 815 816 _sourceFormatterHelper.printError( 817 fileName, "ServiceUtil: " + fileName); 818 } 819 820 if ((newContent != null) && !content.equals(newContent)) { 821 _fileUtil.write(file, newContent); 822 823 _sourceFormatterHelper.printError(fileName, file); 824 } 825 } 826 } 827 828 private static String _formatJavaContent( 829 String fileName, String className, String content) 830 throws IOException { 831 832 boolean longLogFactoryUtil = false; 833 834 StringBuilder sb = new StringBuilder(); 835 836 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader( 837 new UnsyncStringReader(content)); 838 839 int lineCount = 0; 840 841 String line = null; 842 843 while ((line = unsyncBufferedReader.readLine()) != null) { 844 lineCount++; 845 846 if (line.trim().length() == 0) { 847 line = StringPool.BLANK; 848 } 849 850 line = StringUtil.trimTrailing(line); 851 852 line = StringUtil.replace( 853 line, 854 new String[] { 855 "* Copyright (c) 2000-2009 Liferay, Inc." 856 }, 857 new String[] { 858 "* Copyright (c) 2000-2010 Liferay, Inc." 859 }); 860 861 sb.append(line); 862 sb.append("\n"); 863 864 StringBuilder lineSB = new StringBuilder(); 865 866 int spacesPerTab = 4; 867 868 for (char c : line.toCharArray()) { 869 if (c == CharPool.TAB) { 870 for (int i = 0; i < spacesPerTab; i++) { 871 lineSB.append(CharPool.SPACE); 872 } 873 874 spacesPerTab = 4; 875 } 876 else { 877 lineSB.append(c); 878 879 spacesPerTab--; 880 881 if (spacesPerTab <= 0) { 882 spacesPerTab = 4; 883 } 884 } 885 } 886 887 line = lineSB.toString(); 888 889 if (line.endsWith("private static Log _log =")) { 890 longLogFactoryUtil = true; 891 } 892 893 String excluded = _exclusions.getProperty( 894 StringUtil.replace(fileName, "\\", "/") + StringPool.AT + 895 lineCount); 896 897 if (excluded == null) { 898 excluded = _exclusions.getProperty( 899 StringUtil.replace(fileName, "\\", "/")); 900 } 901 902 if ((excluded == null) && (line.length() > 80) && 903 !line.startsWith("import ") && !line.startsWith("package ") && 904 !line.matches("\\s*\\*.*")) { 905 906 if (fileName.endsWith("Table.java") && 907 line.contains("String TABLE_SQL_CREATE = ")) { 908 } 909 else { 910 _sourceFormatterHelper.printError( 911 fileName, "> 80: " + fileName + " " + lineCount); 912 } 913 } 914 } 915 916 unsyncBufferedReader.close(); 917 918 String newContent = sb.toString(); 919 920 if (newContent.endsWith("\n")) { 921 newContent = newContent.substring(0, newContent.length() -1); 922 } 923 924 if (longLogFactoryUtil) { 925 newContent = StringUtil.replace( 926 newContent, 927 "private static Log _log =\n\t\tLogFactoryUtil.getLog(", 928 "private static Log _log = LogFactoryUtil.getLog(\n\t\t"); 929 } 930 931 return newContent; 932 } 933 934 private static void _formatJSP() throws IOException { 935 String basedir = "./"; 936 937 String copyright = _getCopyright(); 938 String oldCopyright = _getOldCopyright(); 939 940 List<String> list = new ArrayList<String>(); 941 942 DirectoryScanner directoryScanner = new DirectoryScanner(); 943 944 directoryScanner.setBasedir(basedir); 945 directoryScanner.setExcludes( 946 new String[] { 947 "**\\portal\\aui\\**", "**\\bin\\**", "**\\null.jsp", 948 "**\\tmp\\**", "**\\tools\\**" 949 }); 950 directoryScanner.setIncludes( 951 new String[] {"**\\*.jsp", "**\\*.jspf", "**\\*.vm"}); 952 953 list.addAll(_sourceFormatterHelper.scanForFiles(directoryScanner)); 954 955 String[] files = list.toArray(new String[list.size()]); 956 957 for (int i = 0; i < files.length; i++) { 958 File file = new File(basedir + files[i]); 959 960 String content = _fileUtil.read(file); 961 String newContent = _formatJSPContent(files[i], content); 962 963 newContent = StringUtil.replace( 964 newContent, 965 new String[] { 966 "<br/>", "\"/>", "\" >", "@page import", "\"%>", ")%>", 967 "javascript: " 968 }, 969 new String[] { 970 "<br />", "\" />", "\">", "@ page import", "\" %>", ") %>", 971 "javascript:" 972 }); 973 974 newContent = StringUtil.replace( 975 newContent, 976 new String[] { 977 "* Copyright (c) 2000-2009 Liferay, Inc." 978 }, 979 new String[] { 980 "* Copyright (c) 2000-2010 Liferay, Inc." 981 }); 982 983 if (files[i].endsWith(".jsp") || files[i].endsWith(".jspf")) { 984 if ((oldCopyright != null) && 985 newContent.contains(oldCopyright)) { 986 987 newContent = StringUtil.replace( 988 newContent, oldCopyright, copyright); 989 990 _sourceFormatterHelper.printError( 991 files[i], "old (c): " + files[i]); 992 } 993 994 if (newContent.indexOf(copyright) == -1) { 995 _sourceFormatterHelper.printError( 996 files[i], "(c): " + files[i]); 997 } 998 } 999 1000 if (newContent.indexOf("alert('<%= LanguageUtil.") != -1) { 1001 newContent = StringUtil.replace(newContent, 1002 "alert('<%= LanguageUtil.", 1003 "alert('<%= UnicodeLanguageUtil."); 1004 } 1005 1006 if (newContent.indexOf("alert(\"<%= LanguageUtil.") != -1) { 1007 newContent = StringUtil.replace(newContent, 1008 "alert(\"<%= LanguageUtil.", 1009 "alert(\"<%= UnicodeLanguageUtil."); 1010 } 1011 1012 if (newContent.indexOf("confirm('<%= LanguageUtil.") != -1) { 1013 newContent = StringUtil.replace(newContent, 1014 "confirm('<%= LanguageUtil.", 1015 "confirm('<%= UnicodeLanguageUtil."); 1016 } 1017 1018 if (newContent.indexOf("confirm(\"<%= LanguageUtil.") != -1) { 1019 newContent = StringUtil.replace(newContent, 1020 "confirm(\"<%= LanguageUtil.", 1021 "confirm(\"<%= UnicodeLanguageUtil."); 1022 } 1023 1024 if (newContent.indexOf(" ") != -1) { 1025 if (!files[i].endsWith("template.vm")) { 1026 _sourceFormatterHelper.printError( 1027 files[i], "tab: " + files[i]); 1028 } 1029 } 1030 1031 _checkXSS(files[i], content); 1032 1033 if ((newContent != null) && !content.equals(newContent)) { 1034 _fileUtil.write(file, newContent); 1035 _sourceFormatterHelper.printError(files[i], file); 1036 } 1037 } 1038 1039 } 1040 1041 private static String _formatJSPContent(String fileName, String content) 1042 throws IOException { 1043 1044 StringBuilder sb = new StringBuilder(); 1045 1046 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader( 1047 new UnsyncStringReader(content)); 1048 1049 String line = null; 1050 1051 while ((line = unsyncBufferedReader.readLine()) != null) { 1052 if (line.trim().length() == 0) { 1053 line = StringPool.BLANK; 1054 } 1055 1056 line = StringUtil.trimTrailing(line); 1057 1058 sb.append(line); 1059 sb.append("\n"); 1060 } 1061 1062 unsyncBufferedReader.close(); 1063 1064 content = sb.toString(); 1065 1066 if (content.endsWith("\n")) { 1067 content = content.substring(0, content.length() -1); 1068 } 1069 1070 content = _formatTaglibQuotes(fileName, content, StringPool.QUOTE); 1071 content = _formatTaglibQuotes(fileName, content, StringPool.APOSTROPHE); 1072 1073 return content; 1074 } 1075 1076 private static void _formatSH() throws IOException { 1077 _formatSH("ext/create.sh"); 1078 _formatSH("hooks/create.sh"); 1079 _formatSH("layouttpl/create.sh"); 1080 _formatSH("portlets/create.sh"); 1081 _formatSH("themes/create.sh"); 1082 } 1083 1084 private static void _formatSH(String fileName) throws IOException { 1085 File file = new File(fileName); 1086 1087 if (!file.exists()) { 1088 return; 1089 } 1090 1091 String content = _fileUtil.read(new File(fileName), true); 1092 1093 if (content.contains("\r")) { 1094 _sourceFormatterHelper.printError( 1095 fileName, "Invalid new line character"); 1096 1097 content = StringUtil.replace(content, "\r", ""); 1098 1099 _fileUtil.write(fileName, content); 1100 } 1101 } 1102 1103 private static String _formatTaglibQuotes( 1104 String fileName, String content, String quoteType) { 1105 1106 String quoteFix = StringPool.APOSTROPHE; 1107 1108 if (quoteFix.equals(quoteType)) { 1109 quoteFix = StringPool.QUOTE; 1110 } 1111 1112 Pattern pattern = Pattern.compile(_getTaglibRegex(quoteType)); 1113 1114 Matcher matcher = pattern.matcher(content); 1115 1116 while (matcher.find()) { 1117 int x = content.indexOf(quoteType + "<%=", matcher.start()); 1118 int y = content.indexOf("%>" + quoteType, x); 1119 1120 while ((x != -1) && (y != -1)) { 1121 String result = content.substring(x + 1, y + 2); 1122 1123 if (result.indexOf(quoteType) != -1) { 1124 int lineCount = 1; 1125 1126 char contentCharArray[] = content.toCharArray(); 1127 1128 for (int i = 0; i < x; i++) { 1129 if (contentCharArray[i] == CharPool.NEW_LINE) { 1130 lineCount++; 1131 } 1132 } 1133 1134 if (result.indexOf(quoteFix) == -1) { 1135 StringBuilder sb = new StringBuilder(); 1136 1137 sb.append(content.substring(0, x)); 1138 sb.append(quoteFix); 1139 sb.append(result); 1140 sb.append(quoteFix); 1141 sb.append(content.substring(y + 3, content.length())); 1142 1143 content = sb.toString(); 1144 } 1145 else { 1146 _sourceFormatterHelper.printError( 1147 fileName, "taglib: " + fileName + " " + lineCount); 1148 } 1149 } 1150 1151 x = content.indexOf(quoteType + "<%=", y); 1152 1153 if (x > matcher.end()) { 1154 break; 1155 } 1156 1157 y = content.indexOf("%>" + quoteType, x); 1158 } 1159 } 1160 1161 return content; 1162 } 1163 1164 private static void _formatWebXML() throws IOException { 1165 String basedir = "./"; 1166 1167 if (_fileUtil.exists(basedir + "portal-impl")) { 1168 Properties properties = new Properties(); 1169 1170 String propertiesContent = _fileUtil.read( 1171 basedir + "portal-impl/src/portal.properties"); 1172 1173 PropertiesUtil.load(properties, propertiesContent); 1174 1175 String[] locales = StringUtil.split( 1176 properties.getProperty(PropsKeys.LOCALES)); 1177 1178 Arrays.sort(locales); 1179 1180 Set<String> urlPatterns = new TreeSet<String>(); 1181 1182 for (String locale : locales) { 1183 int pos = locale.indexOf(StringPool.UNDERLINE); 1184 1185 String languageCode = locale.substring(0, pos); 1186 1187 urlPatterns.add(languageCode); 1188 urlPatterns.add(locale); 1189 } 1190 1191 StringBuilder sb = new StringBuilder(); 1192 1193 for (String urlPattern : urlPatterns) { 1194 sb.append("\t<servlet-mapping>\n"); 1195 sb.append("\t\t<servlet-name>I18n Servlet</servlet-name>\n"); 1196 sb.append( 1197 "\t\t<url-pattern>/" + urlPattern +"/*</url-pattern>\n"); 1198 sb.append("\t</servlet-mapping>\n"); 1199 } 1200 1201 File file = new File( 1202 basedir + "portal-web/docroot/WEB-INF/web.xml"); 1203 1204 String content = _fileUtil.read(file); 1205 1206 int x = content.indexOf("<servlet-mapping>"); 1207 1208 x = content.indexOf("<servlet-name>I18n Servlet</servlet-name>", x); 1209 1210 x = content.lastIndexOf("<servlet-mapping>", x) - 1; 1211 1212 int y = content.lastIndexOf( 1213 "<servlet-name>I18n Servlet</servlet-name>"); 1214 1215 y = content.indexOf("</servlet-mapping>", y) + 19; 1216 1217 String newContent = 1218 content.substring(0, x) + sb.toString() + content.substring(y); 1219 1220 x = newContent.indexOf("<security-constraint>"); 1221 1222 x = newContent.indexOf( 1223 "<web-resource-name>/c/portal/protected</web-resource-name>", 1224 x); 1225 1226 x = newContent.indexOf("<url-pattern>", x) - 3; 1227 1228 y = newContent.indexOf("<http-method>", x); 1229 1230 y = newContent.lastIndexOf("</url-pattern>", y) + 15; 1231 1232 sb = new StringBuilder(); 1233 1234 sb.append( 1235 "\t\t\t<url-pattern>/c/portal/protected</url-pattern>\n"); 1236 1237 for (String urlPattern : urlPatterns) { 1238 sb.append( 1239 "\t\t\t<url-pattern>/" + urlPattern + 1240 "/c/portal/protected</url-pattern>\n"); 1241 } 1242 1243 newContent = 1244 newContent.substring(0, x) + sb.toString() + 1245 newContent.substring(y); 1246 1247 if ((newContent != null) && !content.equals(newContent)) { 1248 _fileUtil.write(file, newContent); 1249 1250 System.out.println(file); 1251 } 1252 } 1253 else { 1254 String webXML = ContentUtil.get( 1255 "com/liferay/portal/deploy/dependencies/web.xml"); 1256 1257 DirectoryScanner directoryScanner = new DirectoryScanner(); 1258 1259 directoryScanner.setBasedir(basedir); 1260 directoryScanner.setIncludes(new String[] {"**\\web.xml"}); 1261 1262 List<String> fileNames = _sourceFormatterHelper.scanForFiles( 1263 directoryScanner); 1264 1265 for (String fileName : fileNames) { 1266 String content = _fileUtil.read(basedir + fileName); 1267 1268 if (content.equals(webXML)) { 1269 _sourceFormatterHelper.printError(fileName, fileName); 1270 } 1271 } 1272 } 1273 } 1274 1275 private static String _getCopyright() throws IOException { 1276 String copyright = _fileUtil.read("copyright.txt"); 1277 1278 if (copyright == null) { 1279 copyright = _fileUtil.read("../copyright.txt"); 1280 } 1281 1282 if (copyright == null) { 1283 copyright = _fileUtil.read("../../copyright.txt"); 1284 } 1285 1286 return copyright; 1287 } 1288 1289 private static String _getOldCopyright() throws IOException { 1290 String copyright = _fileUtil.read("old-copyright.txt"); 1291 1292 if (copyright == null) { 1293 copyright = _fileUtil.read("../old-copyright.txt"); 1294 } 1295 1296 if (copyright == null) { 1297 copyright = _fileUtil.read("../../old-copyright.txt"); 1298 } 1299 1300 return copyright; 1301 } 1302 1303 private static Collection<String> _getPluginJavaFiles() { 1304 String basedir = "./"; 1305 1306 Collection<String> fileNames = new TreeSet<String>(); 1307 1308 DirectoryScanner directoryScanner = new DirectoryScanner(); 1309 1310 directoryScanner.setBasedir(basedir); 1311 directoryScanner.setExcludes( 1312 new String[] { 1313 "**\\bin\\**", "**\\model\\*Clp.java", 1314 "**\\model\\impl\\*ModelImpl.java", 1315 "**\\service\\**\\model\\*Model.java", 1316 "**\\service\\**\\model\\*Soap.java", 1317 "**\\service\\**\\model\\*Wrapper.java", 1318 "**\\service\\**\\service\\*Service.java", 1319 "**\\service\\**\\service\\*ServiceClp.java", 1320 "**\\service\\**\\service\\*ServiceFactory.java", 1321 "**\\service\\**\\service\\*ServiceUtil.java", 1322 "**\\service\\**\\service\\*ServiceWrapper.java", 1323 "**\\service\\**\\service\\ClpSerializer.java", 1324 "**\\service\\**\\service\\messaging\\*ClpMessageListener.java", 1325 "**\\service\\**\\service\\persistence\\*Finder.java", 1326 "**\\service\\**\\service\\persistence\\*Persistence.java", 1327 "**\\service\\**\\service\\persistence\\*Util.java", 1328 "**\\service\\base\\*ServiceBaseImpl.java", 1329 "**\\service\\http\\*JSONSerializer.java", 1330 "**\\service\\http\\*ServiceHttp.java", 1331 "**\\service\\http\\*ServiceJSON.java", 1332 "**\\service\\http\\*ServiceSoap.java", 1333 "**\\service\\persistence\\*PersistenceImpl.java", 1334 "**\\tmp\\**" 1335 }); 1336 directoryScanner.setIncludes(new String[] {"**\\*.java"}); 1337 1338 fileNames.addAll(_sourceFormatterHelper.scanForFiles(directoryScanner)); 1339 1340 return fileNames; 1341 } 1342 1343 private static Collection<String> _getPortalJavaFiles() { 1344 String basedir = "./"; 1345 1346 Collection<String> fileNames = new TreeSet<String>(); 1347 1348 DirectoryScanner directoryScanner = new DirectoryScanner(); 1349 1350 directoryScanner.setBasedir(basedir); 1351 directoryScanner.setExcludes( 1352 new String[] { 1353 "**\\InstanceWrapperBuilder.java", "**\\*_IW.java", 1354 "**\\PropsKeys.java", "**\\PropsValues.java", 1355 "**\\ServiceBuilder.java", "**\\SourceFormatter.java", 1356 "**\\UserAttributes.java", "**\\WebKeys.java", 1357 "**\\bin\\**", "**\\classes\\*", "**\\counter\\service\\**", 1358 "**\\jsp\\*", "**\\model\\impl\\*ModelImpl.java", 1359 "**\\portal\\service\\**", "**\\portal-client\\**", 1360 "**\\portal-service\\**\\model\\*Model.java", 1361 "**\\portal-service\\**\\model\\*Soap.java", 1362 "**\\portal-service\\**\\model\\*Wrapper.java", 1363 "**\\portal-web\\classes\\**\\*.java", 1364 "**\\portal-web\\test\\**\\*Test.java", 1365 "**\\portlet\\**\\service\\**", "**\\tmp\\**", "**\\tools\\**" 1366 }); 1367 directoryScanner.setIncludes(new String[] {"**\\*.java"}); 1368 1369 fileNames.addAll(_sourceFormatterHelper.scanForFiles(directoryScanner)); 1370 1371 directoryScanner = new DirectoryScanner(); 1372 1373 directoryScanner.setBasedir(basedir); 1374 directoryScanner.setExcludes( 1375 new String[] { 1376 "**\\bin\\**", "**\\portal-client\\**", 1377 "**\\tools\\ext_tmpl\\**", "**\\*_IW.java", 1378 "**\\test\\**\\*PersistenceTest.java" 1379 }); 1380 directoryScanner.setIncludes( 1381 new String[] { 1382 "**\\com\\liferay\\portal\\service\\ServiceContext*.java", 1383 "**\\model\\BaseModel.java", 1384 "**\\model\\impl\\BaseModelImpl.java", 1385 "**\\service\\base\\PrincipalBean.java", 1386 "**\\service\\http\\*HttpTest.java", 1387 "**\\service\\http\\*SoapTest.java", 1388 "**\\service\\http\\TunnelUtil.java", 1389 "**\\service\\impl\\*.java", "**\\service\\jms\\*.java", 1390 "**\\service\\permission\\*.java", 1391 "**\\service\\persistence\\BasePersistence.java", 1392 "**\\service\\persistence\\BatchSession*.java", 1393 "**\\service\\persistence\\*FinderImpl.java", 1394 "**\\service\\persistence\\*Query.java", 1395 "**\\service\\persistence\\impl\\BasePersistenceImpl.java", 1396 "**\\portal-impl\\test\\**\\*.java", 1397 "**\\portal-service\\**\\liferay\\documentlibrary\\**.java", 1398 "**\\portal-service\\**\\liferay\\lock\\**.java", 1399 "**\\portal-service\\**\\liferay\\mail\\**.java", 1400 "**\\util-bridges\\**\\*.java" 1401 }); 1402 1403 fileNames.addAll(_sourceFormatterHelper.scanForFiles(directoryScanner)); 1404 1405 return fileNames; 1406 } 1407 1408 private static String _getTaglibRegex(String quoteType) { 1409 StringBuilder sb = new StringBuilder(); 1410 1411 sb.append("<("); 1412 1413 for (int i = 0; i < _TAG_LIBRARIES.length; i++) { 1414 sb.append(_TAG_LIBRARIES[i]); 1415 sb.append(StringPool.PIPE); 1416 } 1417 1418 sb.deleteCharAt(sb.length() - 1); 1419 sb.append("):([^>]|%>)*"); 1420 sb.append(quoteType); 1421 sb.append("<%=.*"); 1422 sb.append(quoteType); 1423 sb.append(".*%>"); 1424 sb.append(quoteType); 1425 sb.append("([^>]|%>)*>"); 1426 1427 return sb.toString(); 1428 } 1429 1430 private static void _readExclusions() throws IOException { 1431 _exclusions = new Properties(); 1432 1433 ClassLoader classLoader = SourceFormatter.class.getClassLoader(); 1434 1435 String sourceFormatterExclusions = System.getProperty( 1436 "source-formatter-exclusions", 1437 "com/liferay/portal/tools/dependencies/" + 1438 "source_formatter_exclusions.properties"); 1439 1440 URL url = classLoader.getResource(sourceFormatterExclusions); 1441 1442 if (url == null) { 1443 return; 1444 } 1445 1446 InputStream is = url.openStream(); 1447 1448 _exclusions.load(is); 1449 1450 is.close(); 1451 } 1452 1453 private static final String[] _TAG_LIBRARIES = new String[] { 1454 "aui", "c", "html", "jsp", "liferay-portlet", "liferay-security", 1455 "liferay-theme", "liferay-ui", "liferay-util", "portlet", "struts", 1456 "tiles" 1457 }; 1458 1459 private static Properties _exclusions; 1460 private static FileImpl _fileUtil = FileImpl.getInstance(); 1461 private static SAXReaderImpl _saxReaderUtil = SAXReaderImpl.getInstance(); 1462 private static SourceFormatterHelper _sourceFormatterHelper; 1463 private static Pattern _xssPattern = Pattern.compile( 1464 "String\\s+([^\\s]+)\\s*=\\s*(Bean)?ParamUtil\\.getString\\("); 1465 1466 }