001    /**
002     * Copyright (c) 2000-2013 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.sourceformatter;
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.ArrayUtil;
020    import com.liferay.portal.kernel.util.CharPool;
021    import com.liferay.portal.kernel.util.GetterUtil;
022    import com.liferay.portal.kernel.util.ListUtil;
023    import com.liferay.portal.kernel.util.ReleaseInfo;
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.util.TextFormatter;
028    import com.liferay.portal.kernel.util.Validator;
029    import com.liferay.portal.util.FileImpl;
030    import com.liferay.portal.xml.SAXReaderImpl;
031    
032    import java.io.File;
033    import java.io.FileInputStream;
034    import java.io.FileNotFoundException;
035    import java.io.IOException;
036    import java.io.InputStream;
037    
038    import java.net.URL;
039    
040    import java.util.ArrayList;
041    import java.util.HashMap;
042    import java.util.List;
043    import java.util.Map;
044    import java.util.Properties;
045    import java.util.regex.Matcher;
046    import java.util.regex.Pattern;
047    
048    import org.apache.tools.ant.DirectoryScanner;
049    
050    /**
051     * @author Brian Wing Shun Chan
052     * @author Igor Spasic
053     * @author Wesley Gong
054     * @author Hugo Huijser
055     */
056    public abstract class BaseSourceProcessor implements SourceProcessor {
057    
058            @Override
059            public void format(
060                            boolean useProperties, boolean printErrors, boolean autoFix)
061                    throws Exception {
062    
063                    _init(useProperties, printErrors, autoFix);
064    
065                    format();
066    
067                    sourceFormatterHelper.close();
068            }
069    
070            @Override
071            public String format(
072                            String fileName, boolean useProperties, boolean printErrors,
073                            boolean autoFix)
074                    throws Exception {
075    
076                    try {
077                            _init(useProperties, printErrors, autoFix);
078    
079                            return format(fileName);
080                    }
081                    finally {
082                            sourceFormatterHelper.close();
083                    }
084            }
085    
086            @Override
087            public List<String> getErrorMessages() {
088                    return _errorMessages;
089            }
090    
091            protected static String formatImports(String imports, int classStartPos)
092                    throws IOException {
093    
094                    if (imports.contains("/*") || imports.contains("*/") ||
095                            imports.contains("//")) {
096    
097                            return imports + "\n";
098                    }
099    
100                    List<ImportPackage> importPackages = new ArrayList<ImportPackage>();
101    
102                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
103                            new UnsyncStringReader(imports));
104    
105                    String line = null;
106    
107                    while ((line = unsyncBufferedReader.readLine()) != null) {
108                            ImportPackage importPackage = ImportPackageFactoryUtil.create(line);
109    
110                            if ((importPackage != null) &&
111                                    !importPackages.contains(importPackage)) {
112    
113                                    importPackages.add(importPackage);
114                            }
115                    }
116    
117                    importPackages = ListUtil.sort(importPackages);
118    
119                    StringBundler sb = new StringBundler();
120    
121                    String temp = null;
122    
123                    for (int i = 0; i < importPackages.size(); i++) {
124                            ImportPackage importPackage = importPackages.get(i);
125    
126                            String s = importPackage.getLine();
127    
128                            int pos = s.indexOf(".");
129    
130                            pos = s.indexOf(".", pos + 1);
131    
132                            if (pos == -1) {
133                                    pos = s.indexOf(".");
134                            }
135    
136                            String packageLevel = s.substring(classStartPos, pos);
137    
138                            if ((i != 0) && !packageLevel.equals(temp)) {
139                                    sb.append("\n");
140                            }
141    
142                            temp = packageLevel;
143    
144                            sb.append(s);
145                            sb.append("\n");
146                    }
147    
148                    return sb.toString();
149            }
150    
151            protected void checkIfClauseParentheses(
152                    String ifClause, String fileName, int lineCount) {
153    
154                    int quoteCount = StringUtil.count(ifClause, StringPool.QUOTE);
155    
156                    if ((quoteCount % 2) == 1) {
157                            return;
158                    }
159    
160                    ifClause = stripQuotes(ifClause, CharPool.QUOTE);
161    
162                    ifClause = stripQuotes(ifClause, CharPool.APOSTROPHE);
163    
164                    if (ifClause.contains(StringPool.DOUBLE_SLASH) ||
165                            ifClause.contains("/*") || ifClause.contains("*/")) {
166    
167                            return;
168                    }
169    
170                    ifClause = stripRedundantParentheses(ifClause);
171    
172                    int level = 0;
173                    int max = StringUtil.count(ifClause, StringPool.OPEN_PARENTHESIS);
174                    int previousParenthesisPos = -1;
175    
176                    int[] levels = new int[max];
177    
178                    for (int i = 0; i < ifClause.length(); i++) {
179                            char c = ifClause.charAt(i);
180    
181                            if ((c == CharPool.OPEN_PARENTHESIS) ||
182                                    (c == CharPool.CLOSE_PARENTHESIS)) {
183    
184                                    if (previousParenthesisPos != -1) {
185                                            String s = ifClause.substring(
186                                                    previousParenthesisPos + 1, i);
187    
188                                            if (hasMissingParentheses(s)) {
189                                                    processErrorMessage(
190                                                            fileName,
191                                                            "missing parentheses: " + fileName + " " +
192                                                                    lineCount);
193                                            }
194                                    }
195    
196                                    previousParenthesisPos = i;
197    
198                                    if (c == CharPool.OPEN_PARENTHESIS) {
199                                            levels[level] = i;
200    
201                                            level += 1;
202                                    }
203                                    else {
204                                            int posOpenParenthesis = levels[level - 1];
205    
206                                            if (level > 1) {
207                                                    char nextChar = ifClause.charAt(i + 1);
208                                                    char previousChar = ifClause.charAt(
209                                                            posOpenParenthesis - 1);
210    
211                                                    if (!Character.isLetterOrDigit(nextChar) &&
212                                                            (nextChar != CharPool.PERIOD) &&
213                                                            !Character.isLetterOrDigit(previousChar)) {
214    
215                                                            String s = ifClause.substring(
216                                                                    posOpenParenthesis + 1, i);
217    
218                                                            if (hasRedundantParentheses(s)) {
219                                                                    processErrorMessage(
220                                                                            fileName,
221                                                                            "redundant parentheses: " + fileName + " " +
222                                                                                    lineCount);
223                                                            }
224                                                    }
225    
226                                                    if ((previousChar == CharPool.OPEN_PARENTHESIS) &&
227                                                            (nextChar == CharPool.CLOSE_PARENTHESIS)) {
228    
229                                                            processErrorMessage(
230                                                                    fileName,
231                                                                    "redundant parentheses: " + fileName + " " +
232                                                                            lineCount);
233                                                    }
234                                            }
235    
236                                            level -= 1;
237                                    }
238                            }
239                    }
240            }
241    
242            protected void checkInefficientStringMethods(
243                    String line, String fileName, int lineCount) {
244    
245                    if (mainReleaseVersion.equals(MAIN_RELEASE_VERSION_6_1_0)) {
246                            return;
247                    }
248    
249                    String methodName = "toLowerCase";
250    
251                    int pos = line.indexOf(".toLowerCase()");
252    
253                    if (pos == -1) {
254                            methodName = "toUpperCase";
255    
256                            pos = line.indexOf(".toUpperCase()");
257                    }
258    
259                    if ((pos == -1) && !line.contains("StringUtil.equalsIgnoreCase(")) {
260                            methodName = "equalsIgnoreCase";
261    
262                            pos = line.indexOf(".equalsIgnoreCase(");
263                    }
264    
265                    if (pos != -1) {
266                            processErrorMessage(
267                                    fileName,
268                                    "Use StringUtil." + methodName + ": " + fileName + " " +
269                                            lineCount);
270                    }
271            }
272    
273            protected void checkLanguageKeys(
274                            String fileName, String content, Pattern pattern)
275                    throws IOException {
276    
277                    String fileExtension = fileUtil.getExtension(fileName);
278    
279                    if (!portalSource || fileExtension.equals("vm")) {
280                            return;
281                    }
282    
283                    if (_portalLanguageKeysProperties == null) {
284                            _portalLanguageKeysProperties = new Properties();
285    
286                            ClassLoader classLoader =
287                                    BaseSourceProcessor.class.getClassLoader();
288    
289                            InputStream inputStream = classLoader.getResourceAsStream(
290                                    "content/Language.properties");
291    
292                            _portalLanguageKeysProperties.load(inputStream);
293                    }
294    
295                    Matcher matcher = pattern.matcher(content);
296    
297                    while (matcher.find()) {
298                            String[] languageKeys = getLanguageKeys(matcher);
299    
300                            for (String languageKey : languageKeys) {
301                                    if (Validator.isNumber(languageKey) ||
302                                            languageKey.endsWith(StringPool.DASH) ||
303                                            languageKey.endsWith(StringPool.OPEN_BRACKET) ||
304                                            languageKey.endsWith(StringPool.PERIOD) ||
305                                            languageKey.endsWith(StringPool.UNDERLINE) ||
306                                            languageKey.startsWith(StringPool.DASH) ||
307                                            languageKey.startsWith(StringPool.OPEN_BRACKET) ||
308                                            languageKey.startsWith(StringPool.OPEN_CURLY_BRACE) ||
309                                            languageKey.startsWith(StringPool.PERIOD) ||
310                                            languageKey.startsWith(StringPool.UNDERLINE)) {
311    
312                                            continue;
313                                    }
314    
315                                    if (!_portalLanguageKeysProperties.containsKey(languageKey)) {
316                                            processErrorMessage(
317                                                    fileName,
318                                                    "missing language key: " + languageKey +
319                                                            StringPool.SPACE + fileName);
320                                    }
321                            }
322                    }
323            }
324    
325            protected void checkStringBundler(
326                    String line, String fileName, int lineCount) {
327    
328                    if ((!line.startsWith("sb.append(") && !line.contains("SB.append(")) ||
329                            !line.endsWith(");")) {
330    
331                            return;
332                    }
333    
334                    int pos = line.indexOf(".append(");
335    
336                    line = line.substring(pos + 8, line.length() - 2);
337    
338                    line = stripQuotes(line, CharPool.QUOTE);
339    
340                    if (!line.contains(" + ")) {
341                            return;
342                    }
343    
344                    String[] lineParts = StringUtil.split(line, " + ");
345    
346                    for (String linePart : lineParts) {
347                            int closeParenthesesCount = StringUtil.count(
348                                    linePart, StringPool.CLOSE_PARENTHESIS);
349                            int openParenthesesCount = StringUtil.count(
350                                    linePart, StringPool.OPEN_PARENTHESIS);
351    
352                            if (closeParenthesesCount != openParenthesesCount) {
353                                    return;
354                            }
355    
356                            if (Validator.isNumber(linePart)) {
357                                    return;
358                            }
359                    }
360    
361                    processErrorMessage(fileName, "plus: " + fileName + " " + lineCount);
362            }
363    
364            protected String fixCompatClassImports(File file, String content)
365                    throws IOException {
366    
367                    String absolutePath = fileUtil.getAbsolutePath(file);
368    
369                    if (portalSource ||
370                            !mainReleaseVersion.equals(MAIN_RELEASE_VERSION_6_1_0) ||
371                            absolutePath.contains("/ext-") ||
372                            absolutePath.contains("/portal-compat-shared/")) {
373    
374                            return content;
375                    }
376    
377                    Map<String, String> compatClassNamesMap = getCompatClassNamesMap();
378    
379                    String newContent = content;
380    
381                    for (Map.Entry<String, String> entry : compatClassNamesMap.entrySet()) {
382                            String compatClassName = entry.getKey();
383                            String extendedClassName = entry.getValue();
384    
385                            Pattern pattern = Pattern.compile(extendedClassName + "\\W");
386    
387                            while (true) {
388                                    Matcher matcher = pattern.matcher(newContent);
389    
390                                    if (!matcher.find()) {
391                                            break;
392                                    }
393    
394                                    newContent =
395                                            newContent.substring(0, matcher.start()) + compatClassName +
396                                                    newContent.substring(matcher.end() - 1);
397                            }
398                    }
399    
400                    return newContent;
401            }
402    
403            protected String fixCopyright(
404                            String content, String copyright, String oldCopyright, File file,
405                            String fileName)
406                    throws IOException {
407    
408                    if (fileName.endsWith(".vm")) {
409                            return content;
410                    }
411    
412                    if ((oldCopyright != null) && content.contains(oldCopyright)) {
413                            content = StringUtil.replace(content, oldCopyright, copyright);
414    
415                            processErrorMessage(fileName, "old (c): " + fileName);
416                    }
417    
418                    if (!content.contains(copyright)) {
419                            String customCopyright = getCustomCopyright(file);
420    
421                            if (Validator.isNotNull(customCopyright)) {
422                                    copyright = customCopyright;
423                            }
424    
425                            if (!content.contains(copyright)) {
426                                    processErrorMessage(fileName, "(c): " + fileName);
427                            }
428                    }
429    
430                    if (fileName.endsWith(".jsp") || fileName.endsWith(".jspf")) {
431                            content = StringUtil.replace(
432                                    content, "<%\n" + copyright + "\n%>",
433                                    "<%--\n" + copyright + "\n--%>");
434                    }
435    
436                    int x = content.indexOf("* Copyright (c) 2000-20");
437    
438                    if (x == -1) {
439                            return content;
440                    }
441    
442                    int y = copyright.indexOf("* Copyright (c) 2000-20");
443    
444                    if (y == -1) {
445                            return content;
446                    }
447    
448                    String contentCopyrightYear = content.substring(x, x + 25);
449                    String copyrightYear = copyright.substring(y, y + 25);
450    
451                    return StringUtil.replace(content, contentCopyrightYear, copyrightYear);
452            }
453    
454            protected String fixSessionKey(
455                    String fileName, String content, Pattern pattern) {
456    
457                    if (mainReleaseVersion.equals(MAIN_RELEASE_VERSION_6_1_0)) {
458                            return content;
459                    }
460    
461                    Matcher matcher = pattern.matcher(content);
462    
463                    if (!matcher.find()) {
464                            return content;
465                    }
466    
467                    String newContent = content;
468    
469                    do {
470                            String match = matcher.group();
471    
472                            String s = null;
473    
474                            if (pattern.equals(sessionKeyPattern)) {
475                                    s = StringPool.COMMA;
476                            }
477                            else if (pattern.equals(taglibSessionKeyPattern)) {
478                                    s = "key=";
479                            }
480    
481                            int x = match.indexOf(s);
482    
483                            if (x == -1) {
484                                    continue;
485                            }
486    
487                            x = x + s.length();
488    
489                            String substring = match.substring(x).trim();
490    
491                            String quote = StringPool.BLANK;
492    
493                            if (substring.startsWith(StringPool.APOSTROPHE)) {
494                                    quote = StringPool.APOSTROPHE;
495                            }
496                            else if (substring.startsWith(StringPool.QUOTE)) {
497                                    quote = StringPool.QUOTE;
498                            }
499                            else {
500                                    continue;
501                            }
502    
503                            int y = match.indexOf(quote, x);
504                            int z = match.indexOf(quote, y + 1);
505    
506                            if ((y == -1) || (z == -1)) {
507                                    continue;
508                            }
509    
510                            String prefix = match.substring(0, y + 1);
511                            String suffix = match.substring(z);
512                            String oldKey = match.substring(y + 1, z);
513    
514                            boolean alphaNumericKey = true;
515    
516                            for (char c : oldKey.toCharArray()) {
517                                    if (!Validator.isChar(c) && !Validator.isDigit(c) &&
518                                            (c != CharPool.DASH) && (c != CharPool.UNDERLINE)) {
519    
520                                            alphaNumericKey = false;
521                                    }
522                            }
523    
524                            if (!alphaNumericKey) {
525                                    continue;
526                            }
527    
528                            String newKey = TextFormatter.format(oldKey, TextFormatter.O);
529    
530                            newKey = TextFormatter.format(newKey, TextFormatter.M);
531    
532                            if (newKey.equals(oldKey)) {
533                                    continue;
534                            }
535    
536                            String oldSub = prefix.concat(oldKey).concat(suffix);
537                            String newSub = prefix.concat(newKey).concat(suffix);
538    
539                            newContent = StringUtil.replaceFirst(newContent, oldSub, newSub);
540                    }
541                    while (matcher.find());
542    
543                    return newContent;
544            }
545    
546            protected abstract void format() throws Exception;
547    
548            protected String format(String fileName) throws Exception {
549                    return null;
550            }
551    
552            protected Map<String, String> getCompatClassNamesMap() throws IOException {
553                    if (_compatClassNamesMap != null) {
554                            return _compatClassNamesMap;
555                    }
556    
557                    Map<String, String> compatClassNamesMap = new HashMap<String, String>();
558    
559                    String[] includes = new String[] {
560                            "**\\portal-compat-shared\\src\\com\\liferay\\compat\\**\\*.java"
561                    };
562    
563                    String basedir = BASEDIR;
564    
565                    List<String> fileNames = new ArrayList<String>();
566    
567                    for (int i = 0; i < 3; i++) {
568                            fileNames = getFileNames(basedir, new String[0], includes);
569    
570                            if (!fileNames.isEmpty()) {
571                                    break;
572                            }
573    
574                            basedir = "../" + basedir;
575                    }
576    
577                    for (String fileName : fileNames) {
578                            File file = new File(basedir + fileName);
579    
580                            String content = fileUtil.read(file);
581    
582                            fileName = StringUtil.replace(
583                                    fileName, StringPool.BACK_SLASH, StringPool.SLASH);
584    
585                            fileName = StringUtil.replace(
586                                    fileName, StringPool.SLASH, StringPool.PERIOD);
587    
588                            int pos = fileName.indexOf("com.");
589    
590                            String compatClassName = fileName.substring(pos);
591    
592                            compatClassName = compatClassName.substring(
593                                    0, compatClassName.length() - 5);
594    
595                            String extendedClassName = StringUtil.replace(
596                                    compatClassName, "compat.", StringPool.BLANK);
597    
598                            if (content.contains("extends " + extendedClassName)) {
599                                    compatClassNamesMap.put(compatClassName, extendedClassName);
600                            }
601                    }
602    
603                    _compatClassNamesMap = compatClassNamesMap;
604    
605                    return _compatClassNamesMap;
606            }
607    
608            protected String getCopyright() throws IOException {
609                    if (Validator.isNotNull(_copyright)) {
610                            return _copyright;
611                    }
612    
613                    _copyright = fileUtil.read("copyright.txt");
614    
615                    if (Validator.isNull(_copyright)) {
616                            _copyright = fileUtil.read("../copyright.txt");
617                    }
618    
619                    if (Validator.isNull(_copyright)) {
620                            _copyright = fileUtil.read("../../copyright.txt");
621                    }
622    
623                    return _copyright;
624            }
625    
626            protected String getCustomCopyright(File file) throws IOException {
627                    String absolutePath = fileUtil.getAbsolutePath(file);
628    
629                    for (int x = absolutePath.length();;) {
630                            x = absolutePath.lastIndexOf(StringPool.SLASH, x);
631    
632                            if (x == -1) {
633                                    break;
634                            }
635    
636                            String copyright = fileUtil.read(
637                                    absolutePath.substring(0, x + 1) + "copyright.txt");
638    
639                            if (Validator.isNotNull(copyright)) {
640                                    return copyright;
641                            }
642    
643                            x = x - 1;
644                    }
645    
646                    return null;
647            }
648    
649            protected Properties getExclusionsProperties(String fileName)
650                    throws IOException {
651    
652                    InputStream inputStream = null;
653    
654                    int level = 0;
655    
656                    if (portalSource) {
657                            ClassLoader classLoader =
658                                    BaseSourceProcessor.class.getClassLoader();
659    
660                            String sourceFormatterExclusions = System.getProperty(
661                                    "source-formatter-exclusions",
662                                    "com/liferay/portal/tools/dependencies/" + fileName);
663    
664                            URL url = classLoader.getResource(sourceFormatterExclusions);
665    
666                            if (url == null) {
667                                    return null;
668                            }
669    
670                            inputStream = url.openStream();
671                    }
672                    else {
673                            try {
674                                    inputStream = new FileInputStream(fileName);
675                            }
676                            catch (FileNotFoundException fnfe) {
677                            }
678    
679                            if (inputStream == null) {
680                                    try {
681                                            inputStream = new FileInputStream("../" + fileName);
682    
683                                            level = 1;
684                                    }
685                                    catch (FileNotFoundException fnfe) {
686                                    }
687                            }
688    
689                            if (inputStream == null) {
690                                    try {
691                                            inputStream = new FileInputStream("../../" + fileName);
692    
693                                            level = 2;
694                                    }
695                                    catch (FileNotFoundException fnfe) {
696                                            return null;
697                                    }
698                            }
699                    }
700    
701                    Properties properties = new Properties();
702    
703                    properties.load(inputStream);
704    
705                    inputStream.close();
706    
707                    if (level > 0) {
708                            properties = stripTopLevelDirectories(properties, level);
709                    }
710    
711                    return properties;
712            }
713    
714            protected List<String> getFileNames(
715                    String basedir, String[] excludes, String[] includes) {
716    
717                    DirectoryScanner directoryScanner = new DirectoryScanner();
718    
719                    directoryScanner.setBasedir(basedir);
720    
721                    excludes = ArrayUtil.append(
722                            excludes, _excludes, new String[] {"**\\.git\\**", "**\\tmp\\**"});
723    
724                    if (portalSource) {
725                            excludes = ArrayUtil.append(
726                                    excludes, new String[] {"**\\webapps\\**"});
727                    }
728    
729                    directoryScanner.setExcludes(excludes);
730    
731                    directoryScanner.setIncludes(includes);
732    
733                    return sourceFormatterHelper.scanForFiles(directoryScanner);
734            }
735    
736            protected List<String> getFileNames(String[] excludes, String[] includes) {
737                    return getFileNames(BASEDIR, excludes, includes);
738            }
739    
740            protected String[] getLanguageKeys(Matcher matcher) {
741                    if (matcher.groupCount() > 0) {
742                            String languageKey = matcher.group(1);
743    
744                            if (Validator.isNotNull(languageKey)) {
745                                    return new String[] {languageKey};
746                            }
747                    }
748    
749                    StringBundler sb = new StringBundler();
750    
751                    String match = matcher.group();
752    
753                    int count = 0;
754    
755                    for (int i = 0; i < match.length(); i++) {
756                            char c = match.charAt(i);
757    
758                            switch (c) {
759                                    case CharPool.CLOSE_PARENTHESIS:
760                                            if (count <= 1) {
761                                                    return new String[0];
762                                            }
763    
764                                            count--;
765    
766                                            break;
767    
768                                    case CharPool.OPEN_PARENTHESIS:
769                                            count++;
770    
771                                            break;
772    
773                                    case CharPool.QUOTE:
774                                            if (count > 1) {
775                                                    break;
776                                            }
777    
778                                            while (i < match.length()) {
779                                                    i++;
780    
781                                                    if (match.charAt(i) == CharPool.QUOTE) {
782                                                            String languageKey = sb.toString();
783    
784                                                            if (match.startsWith("names")) {
785                                                                    return StringUtil.split(languageKey);
786                                                            }
787                                                            else {
788                                                                    return new String[] {languageKey};
789                                                            }
790    
791                                                    }
792    
793                                                    sb.append(match.charAt(i));
794                                            }
795                            }
796                    }
797    
798                    return new String[0];
799            }
800    
801            protected String getOldCopyright() throws IOException {
802                    if (Validator.isNotNull(_oldCopyright)) {
803                            return _oldCopyright;
804                    }
805    
806                    _oldCopyright = fileUtil.read("old-copyright.txt");
807    
808                    if (Validator.isNull(_oldCopyright)) {
809                            _oldCopyright = fileUtil.read("../old-copyright.txt");
810                    }
811    
812                    if (Validator.isNull(_oldCopyright)) {
813                            _oldCopyright = fileUtil.read("../../old-copyright.txt");
814                    }
815    
816                    return _oldCopyright;
817            }
818    
819            protected boolean hasMissingParentheses(String s) {
820                    if (Validator.isNull(s)) {
821                            return false;
822                    }
823    
824                    boolean containsAndOrOperator = (s.contains("&&") || s.contains("||"));
825    
826                    boolean containsCompareOperator =
827                            (s.contains(" == ") || s.contains(" != ") || s.contains(" < ") ||
828                             s.contains(" > ") || s.contains(" =< ") || s.contains(" => ") ||
829                             s.contains(" <= ") || s.contains(" >= "));
830    
831                    boolean containsMathOperator =
832                            (s.contains(" = ") || s.contains(" - ") || s.contains(" + ") ||
833                             s.contains(" & ") || s.contains(" % ") || s.contains(" * ") ||
834                             s.contains(" / "));
835    
836                    if (containsCompareOperator &&
837                            (containsAndOrOperator ||
838                             (containsMathOperator && !s.contains(StringPool.OPEN_BRACKET)))) {
839    
840                            return true;
841                    }
842                    else {
843                            return false;
844                    }
845            }
846    
847            protected boolean hasRedundantParentheses(String s) {
848                    if (!s.contains("&&") && !s.contains("||")) {
849                            for (int x = 0;;) {
850                                    x = s.indexOf(StringPool.CLOSE_PARENTHESIS);
851    
852                                    if (x == -1) {
853                                            break;
854                                    }
855    
856                                    int y = s.substring(0, x).lastIndexOf(
857                                            StringPool.OPEN_PARENTHESIS);
858    
859                                    if (y == -1) {
860                                            break;
861                                    }
862    
863                                    s = s.substring(0, y) + s.substring(x + 1);
864                            }
865                    }
866    
867                    if (Validator.isNotNull(s) && !s.contains(StringPool.SPACE)) {
868                            return true;
869                    }
870                    else {
871                            return false;
872                    }
873            }
874    
875            protected boolean isAutoFix() {
876                    return _autoFix;
877            }
878    
879            protected void processErrorMessage(String fileName, String message) {
880                    _errorMessages.add(message);
881    
882                    if (_printErrors) {
883                            sourceFormatterHelper.printError(fileName, message);
884                    }
885            }
886    
887            protected String replacePrimitiveWrapperInstantiation(
888                    String fileName, String line, int lineCount) {
889    
890                    if (true) {
891                            return line;
892                    }
893    
894                    String newLine = StringUtil.replace(
895                            line,
896                            new String[] {
897                                    "new Boolean(", "new Byte(", "new Character(", "new Integer(",
898                                    "new Long(", "new Short("
899                            },
900                            new String[] {
901                                    "Boolean.valueOf(", "Byte.valueOf(", "Character.valueOf(",
902                                    "Integer.valueOf(", "Long.valueOf(", "Short.valueOf("
903                            });
904    
905                    if (!line.equals(newLine)) {
906                            processErrorMessage(
907                                    fileName, "> new Primitive(: " + fileName + " " + lineCount);
908                    }
909    
910                    return newLine;
911            }
912    
913            protected String stripQuotes(String s, char delimeter) {
914                    boolean insideQuotes = false;
915    
916                    StringBundler sb = new StringBundler();
917    
918                    for (int i = 0; i < s.length(); i++) {
919                            char c = s.charAt(i);
920    
921                            if (insideQuotes) {
922                                    if (c == delimeter) {
923                                            if ((c > 1) && (s.charAt(i - 1) == CharPool.BACK_SLASH) &&
924                                                    (s.charAt(i - 2) != CharPool.BACK_SLASH)) {
925    
926                                                    continue;
927                                            }
928    
929                                            insideQuotes = false;
930                                    }
931                            }
932                            else if (c == delimeter) {
933                                    insideQuotes = true;
934                            }
935                            else {
936                                    sb.append(c);
937                            }
938                    }
939    
940                    return sb.toString();
941            }
942    
943            protected String stripRedundantParentheses(String s) {
944                    for (int x = 0;;) {
945                            x = s.indexOf(StringPool.OPEN_PARENTHESIS, x + 1);
946                            int y = s.indexOf(StringPool.CLOSE_PARENTHESIS, x);
947    
948                            if ((x == -1) || (y == -1)) {
949                                    return s;
950                            }
951    
952                            String linePart = s.substring(x + 1, y);
953    
954                            linePart = StringUtil.replace(
955                                    linePart, StringPool.COMMA, StringPool.BLANK);
956    
957                            if (Validator.isAlphanumericName(linePart) ||
958                                    Validator.isNull(linePart)) {
959    
960                                    s = s.substring(0, x) + s.substring(y + 1);
961                            }
962                    }
963            }
964    
965            protected Properties stripTopLevelDirectories(
966                            Properties properties, int level)
967                    throws IOException {
968    
969                    File dir = new File(".");
970    
971                    String dirName = dir.getCanonicalPath();
972    
973                    dirName = StringUtil.replace(
974                            dirName, StringPool.BACK_SLASH, StringPool.SLASH);
975    
976                    int pos = dirName.length();
977    
978                    for (int i = 0; i < level; i++) {
979                            pos = dirName.lastIndexOf(StringPool.SLASH, pos - 1);
980                    }
981    
982                    String topLevelDirNames = dirName.substring(pos + 1) + StringPool.SLASH;
983    
984                    Properties newProperties = new Properties();
985    
986                    for (Map.Entry<Object, Object> entry : properties.entrySet()) {
987                            String key = (String)entry.getKey();
988    
989                            if (!key.startsWith(topLevelDirNames)) {
990                                    continue;
991                            }
992    
993                            key = StringUtil.replaceFirst(
994                                    key, topLevelDirNames, StringPool.BLANK);
995    
996                            String value = (String)entry.getValue();
997    
998                            newProperties.setProperty(key, value);
999                    }
1000    
1001                    return newProperties;
1002            }
1003    
1004            protected String trimContent(String content, boolean allowLeadingSpaces)
1005                    throws IOException {
1006    
1007                    StringBundler sb = new StringBundler();
1008    
1009                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
1010                            new UnsyncStringReader(content));
1011    
1012                    String line = null;
1013    
1014                    while ((line = unsyncBufferedReader.readLine()) != null) {
1015                            sb.append(trimLine(line, allowLeadingSpaces));
1016                            sb.append("\n");
1017                    }
1018    
1019                    unsyncBufferedReader.close();
1020    
1021                    content = sb.toString();
1022    
1023                    if (content.endsWith("\n")) {
1024                            content = content.substring(0, content.length() - 1);
1025                    }
1026    
1027                    return content;
1028            }
1029    
1030            protected String trimLine(String line, boolean allowLeadingSpaces) {
1031                    if (line.trim().length() == 0) {
1032                            return StringPool.BLANK;
1033                    }
1034    
1035                    line = StringUtil.trimTrailing(line);
1036    
1037                    if (allowLeadingSpaces || !line.startsWith(StringPool.SPACE) ||
1038                            line.startsWith(" *")) {
1039    
1040                            return line;
1041                    }
1042    
1043                    if (!line.startsWith(StringPool.FOUR_SPACES)) {
1044                            while (line.startsWith(StringPool.SPACE)) {
1045                                    line = StringUtil.replaceFirst(
1046                                            line, StringPool.SPACE, StringPool.BLANK);
1047                            }
1048                    }
1049                    else {
1050                            int pos = 0;
1051    
1052                            String temp = line;
1053    
1054                            while (temp.startsWith(StringPool.FOUR_SPACES)) {
1055                                    line = StringUtil.replaceFirst(
1056                                            line, StringPool.FOUR_SPACES, StringPool.TAB);
1057    
1058                                    pos++;
1059    
1060                                    temp = line.substring(pos);
1061                            }
1062                    }
1063    
1064                    return line;
1065            }
1066    
1067            protected static final String BASEDIR = "./";
1068    
1069            protected static final String MAIN_RELEASE_VERSION_6_1_0 = "6.1.0";
1070    
1071            protected static final String MAIN_RELEASE_VERSION_6_2_0 = "6.2.0";
1072    
1073            protected static FileImpl fileUtil = FileImpl.getInstance();
1074            protected static Pattern languageKeyPattern = Pattern.compile(
1075                    "LanguageUtil.(?:get|format)\\([^;%]+|Liferay.Language.get\\('([^']+)");
1076            protected static String mainReleaseVersion;
1077            protected static boolean portalSource;
1078            protected static SAXReaderImpl saxReaderUtil = SAXReaderImpl.getInstance();
1079            protected static Pattern sessionKeyPattern = Pattern.compile(
1080                    "SessionErrors.(?:add|contains|get)\\([^;%&|!]+|".concat(
1081                            "SessionMessages.(?:add|contains|get)\\([^;%&|!]+"),
1082                    Pattern.MULTILINE);
1083            protected static SourceFormatterHelper sourceFormatterHelper;
1084            protected static Pattern taglibSessionKeyPattern = Pattern.compile(
1085                    "<liferay-ui:error [^>]+>|<liferay-ui:success [^>]+>",
1086                    Pattern.MULTILINE);
1087    
1088            private void _init(
1089                            boolean useProperties, boolean printErrors, boolean autoFix)
1090                    throws Exception {
1091    
1092                    _errorMessages = new ArrayList<String>();
1093    
1094                    sourceFormatterHelper = new SourceFormatterHelper(useProperties);
1095    
1096                    sourceFormatterHelper.init();
1097    
1098                    if (_initialized) {
1099                            return;
1100                    }
1101    
1102                    _autoFix = autoFix;
1103    
1104                    _setVersion();
1105    
1106                    _excludes = StringUtil.split(
1107                            GetterUtil.getString(
1108                                    System.getProperty("source.formatter.excludes")));
1109    
1110                    portalSource = _isPortalSource();
1111    
1112                    _printErrors = printErrors;
1113    
1114                    _initialized = true;
1115            }
1116    
1117            private boolean _isPortalSource() {
1118                    if (fileUtil.exists(BASEDIR + "portal-impl")) {
1119                            return true;
1120                    }
1121                    else {
1122                            return false;
1123                    }
1124            }
1125    
1126            private void _setVersion() throws Exception {
1127                    String releaseInfoVersion = ReleaseInfo.getVersion();
1128    
1129                    if (releaseInfoVersion.startsWith("6.1")) {
1130                            mainReleaseVersion = MAIN_RELEASE_VERSION_6_1_0;
1131                    }
1132                    else if (releaseInfoVersion.startsWith("6.2")) {
1133                            mainReleaseVersion = MAIN_RELEASE_VERSION_6_2_0;
1134                    }
1135                    else {
1136                            throw new Exception(
1137                                    "Invalid release information: " + ReleaseInfo.getVersion());
1138                    }
1139            }
1140    
1141            private static boolean _autoFix;
1142            private static Map<String, String> _compatClassNamesMap;
1143            private static String _copyright;
1144            private static List<String> _errorMessages = new ArrayList<String>();
1145            private static String[] _excludes;
1146            private static boolean _initialized;
1147            private static String _oldCopyright;
1148            private static Properties _portalLanguageKeysProperties;
1149            private static boolean _printErrors;
1150    
1151    }