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                    _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                    return _compatClassNamesMap;
604            }
605    
606            protected String getCopyright() throws IOException {
607                    if (Validator.isNotNull(_copyright)) {
608                            return _copyright;
609                    }
610    
611                    _copyright = fileUtil.read("copyright.txt");
612    
613                    if (Validator.isNull(_copyright)) {
614                            _copyright = fileUtil.read("../copyright.txt");
615                    }
616    
617                    if (Validator.isNull(_copyright)) {
618                            _copyright = fileUtil.read("../../copyright.txt");
619                    }
620    
621                    return _copyright;
622            }
623    
624            protected String getCustomCopyright(File file) throws IOException {
625                    String absolutePath = fileUtil.getAbsolutePath(file);
626    
627                    for (int x = absolutePath.length();;) {
628                            x = absolutePath.lastIndexOf(StringPool.SLASH, x);
629    
630                            if (x == -1) {
631                                    break;
632                            }
633    
634                            String copyright = fileUtil.read(
635                                    absolutePath.substring(0, x + 1) + "copyright.txt");
636    
637                            if (Validator.isNotNull(copyright)) {
638                                    return copyright;
639                            }
640    
641                            x = x - 1;
642                    }
643    
644                    return null;
645            }
646    
647            protected Properties getExclusionsProperties(String fileName)
648                    throws IOException {
649    
650                    InputStream inputStream = null;
651    
652                    int level = 0;
653    
654                    if (portalSource) {
655                            ClassLoader classLoader =
656                                    BaseSourceProcessor.class.getClassLoader();
657    
658                            String sourceFormatterExclusions = System.getProperty(
659                                    "source-formatter-exclusions",
660                                    "com/liferay/portal/tools/dependencies/" + fileName);
661    
662                            URL url = classLoader.getResource(sourceFormatterExclusions);
663    
664                            if (url == null) {
665                                    return null;
666                            }
667    
668                            inputStream = url.openStream();
669                    }
670                    else {
671                            try {
672                                    inputStream = new FileInputStream(fileName);
673                            }
674                            catch (FileNotFoundException fnfe) {
675                            }
676    
677                            if (inputStream == null) {
678                                    try {
679                                            inputStream = new FileInputStream("../" + fileName);
680    
681                                            level = 1;
682                                    }
683                                    catch (FileNotFoundException fnfe) {
684                                    }
685                            }
686    
687                            if (inputStream == null) {
688                                    try {
689                                            inputStream = new FileInputStream("../../" + fileName);
690    
691                                            level = 2;
692                                    }
693                                    catch (FileNotFoundException fnfe) {
694                                            return null;
695                                    }
696                            }
697                    }
698    
699                    Properties properties = new Properties();
700    
701                    properties.load(inputStream);
702    
703                    inputStream.close();
704    
705                    if (level > 0) {
706                            properties = stripTopLevelDirectories(properties, level);
707                    }
708    
709                    return properties;
710            }
711    
712            protected List<String> getFileNames(
713                    String basedir, String[] excludes, String[] includes) {
714    
715                    DirectoryScanner directoryScanner = new DirectoryScanner();
716    
717                    directoryScanner.setBasedir(basedir);
718    
719                    excludes = ArrayUtil.append(
720                            excludes, _excludes, new String[] {"**\\.git\\**", "**\\tmp\\**"});
721    
722                    if (portalSource) {
723                            excludes = ArrayUtil.append(
724                                    excludes, new String[] {"**\\webapps\\**"});
725                    }
726    
727                    directoryScanner.setExcludes(excludes);
728    
729                    directoryScanner.setIncludes(includes);
730    
731                    return sourceFormatterHelper.scanForFiles(directoryScanner);
732            }
733    
734            protected List<String> getFileNames(String[] excludes, String[] includes) {
735                    return getFileNames(BASEDIR, excludes, includes);
736            }
737    
738            protected String[] getLanguageKeys(Matcher matcher) {
739                    if (matcher.groupCount() > 0) {
740                            String languageKey = matcher.group(1);
741    
742                            if (Validator.isNotNull(languageKey)) {
743                                    return new String[] {languageKey};
744                            }
745                    }
746    
747                    StringBundler sb = new StringBundler();
748    
749                    String match = matcher.group();
750    
751                    int count = 0;
752    
753                    for (int i = 0; i < match.length(); i++) {
754                            char c = match.charAt(i);
755    
756                            switch (c) {
757                                    case CharPool.CLOSE_PARENTHESIS:
758                                            if (count <= 1) {
759                                                    return new String[0];
760                                            }
761    
762                                            count--;
763    
764                                            break;
765    
766                                    case CharPool.OPEN_PARENTHESIS:
767                                            count++;
768    
769                                            break;
770    
771                                    case CharPool.QUOTE:
772                                            if (count > 1) {
773                                                    break;
774                                            }
775    
776                                            while (i < match.length()) {
777                                                    i++;
778    
779                                                    if (match.charAt(i) == CharPool.QUOTE) {
780                                                            String languageKey = sb.toString();
781    
782                                                            if (match.startsWith("names")) {
783                                                                    return StringUtil.split(languageKey);
784                                                            }
785                                                            else {
786                                                                    return new String[] {languageKey};
787                                                            }
788    
789                                                    }
790    
791                                                    sb.append(match.charAt(i));
792                                            }
793                            }
794                    }
795    
796                    return new String[0];
797            }
798    
799            protected String getOldCopyright() throws IOException {
800                    if (Validator.isNotNull(_oldCopyright)) {
801                            return _oldCopyright;
802                    }
803    
804                    _oldCopyright = fileUtil.read("old-copyright.txt");
805    
806                    if (Validator.isNull(_oldCopyright)) {
807                            _oldCopyright = fileUtil.read("../old-copyright.txt");
808                    }
809    
810                    if (Validator.isNull(_oldCopyright)) {
811                            _oldCopyright = fileUtil.read("../../old-copyright.txt");
812                    }
813    
814                    return _oldCopyright;
815            }
816    
817            protected boolean hasMissingParentheses(String s) {
818                    if (Validator.isNull(s)) {
819                            return false;
820                    }
821    
822                    boolean containsAndOrOperator = (s.contains("&&") || s.contains("||"));
823    
824                    boolean containsCompareOperator =
825                            (s.contains(" == ") || s.contains(" != ") || s.contains(" < ") ||
826                             s.contains(" > ") || s.contains(" =< ") || s.contains(" => ") ||
827                             s.contains(" <= ") || s.contains(" >= "));
828    
829                    boolean containsMathOperator =
830                            (s.contains(" = ") || s.contains(" - ") || s.contains(" + ") ||
831                             s.contains(" & ") || s.contains(" % ") || s.contains(" * ") ||
832                             s.contains(" / "));
833    
834                    if (containsCompareOperator &&
835                            (containsAndOrOperator ||
836                             (containsMathOperator && !s.contains(StringPool.OPEN_BRACKET)))) {
837    
838                            return true;
839                    }
840                    else {
841                            return false;
842                    }
843            }
844    
845            protected boolean hasRedundantParentheses(String s) {
846                    if (!s.contains("&&") && !s.contains("||")) {
847                            for (int x = 0;;) {
848                                    x = s.indexOf(StringPool.CLOSE_PARENTHESIS);
849    
850                                    if (x == -1) {
851                                            break;
852                                    }
853    
854                                    int y = s.substring(0, x).lastIndexOf(
855                                            StringPool.OPEN_PARENTHESIS);
856    
857                                    if (y == -1) {
858                                            break;
859                                    }
860    
861                                    s = s.substring(0, y) + s.substring(x + 1);
862                            }
863                    }
864    
865                    if (Validator.isNotNull(s) && !s.contains(StringPool.SPACE)) {
866                            return true;
867                    }
868                    else {
869                            return false;
870                    }
871            }
872    
873            protected boolean isAutoFix() {
874                    return _autoFix;
875            }
876    
877            protected void processErrorMessage(String fileName, String message) {
878                    _errorMessages.add(message);
879    
880                    if (_printErrors) {
881                            sourceFormatterHelper.printError(fileName, message);
882                    }
883            }
884    
885            protected String replacePrimitiveWrapperInstantiation(
886                    String fileName, String line, int lineCount) {
887    
888                    if (true) {
889                            return line;
890                    }
891    
892                    String newLine = StringUtil.replace(
893                            line,
894                            new String[] {
895                                    "new Boolean(", "new Byte(", "new Character(", "new Integer(",
896                                    "new Long(", "new Short("
897                            },
898                            new String[] {
899                                    "Boolean.valueOf(", "Byte.valueOf(", "Character.valueOf(",
900                                    "Integer.valueOf(", "Long.valueOf(", "Short.valueOf("
901                            });
902    
903                    if (!line.equals(newLine)) {
904                            processErrorMessage(
905                                    fileName, "> new Primitive(: " + fileName + " " + lineCount);
906                    }
907    
908                    return newLine;
909            }
910    
911            protected String stripQuotes(String s, char delimeter) {
912                    boolean insideQuotes = false;
913    
914                    StringBundler sb = new StringBundler();
915    
916                    for (int i = 0; i < s.length(); i++) {
917                            char c = s.charAt(i);
918    
919                            if (insideQuotes) {
920                                    if (c == delimeter) {
921                                            if ((c > 1) && (s.charAt(i - 1) == CharPool.BACK_SLASH) &&
922                                                    (s.charAt(i - 2) != CharPool.BACK_SLASH)) {
923    
924                                                    continue;
925                                            }
926    
927                                            insideQuotes = false;
928                                    }
929                            }
930                            else if (c == delimeter) {
931                                    insideQuotes = true;
932                            }
933                            else {
934                                    sb.append(c);
935                            }
936                    }
937    
938                    return sb.toString();
939            }
940    
941            protected String stripRedundantParentheses(String s) {
942                    for (int x = 0;;) {
943                            x = s.indexOf(StringPool.OPEN_PARENTHESIS, x + 1);
944                            int y = s.indexOf(StringPool.CLOSE_PARENTHESIS, x);
945    
946                            if ((x == -1) || (y == -1)) {
947                                    return s;
948                            }
949    
950                            String linePart = s.substring(x + 1, y);
951    
952                            linePart = StringUtil.replace(
953                                    linePart, StringPool.COMMA, StringPool.BLANK);
954    
955                            if (Validator.isAlphanumericName(linePart) ||
956                                    Validator.isNull(linePart)) {
957    
958                                    s = s.substring(0, x) + s.substring(y + 1);
959                            }
960                    }
961            }
962    
963            protected Properties stripTopLevelDirectories(
964                            Properties properties, int level)
965                    throws IOException {
966    
967                    File dir = new File(".");
968    
969                    String dirName = dir.getCanonicalPath();
970    
971                    dirName = StringUtil.replace(
972                            dirName, StringPool.BACK_SLASH, StringPool.SLASH);
973    
974                    int pos = dirName.length();
975    
976                    for (int i = 0; i < level; i++) {
977                            pos = dirName.lastIndexOf(StringPool.SLASH, pos - 1);
978                    }
979    
980                    String topLevelDirNames = dirName.substring(pos + 1) + StringPool.SLASH;
981    
982                    Properties newProperties = new Properties();
983    
984                    for (Map.Entry<Object, Object> entry : properties.entrySet()) {
985                            String key = (String)entry.getKey();
986    
987                            if (!key.startsWith(topLevelDirNames)) {
988                                    continue;
989                            }
990    
991                            key = StringUtil.replaceFirst(
992                                    key, topLevelDirNames, StringPool.BLANK);
993    
994                            String value = (String)entry.getValue();
995    
996                            newProperties.setProperty(key, value);
997                    }
998    
999                    return newProperties;
1000            }
1001    
1002            protected String trimContent(String content, boolean allowLeadingSpaces)
1003                    throws IOException {
1004    
1005                    StringBundler sb = new StringBundler();
1006    
1007                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
1008                            new UnsyncStringReader(content));
1009    
1010                    String line = null;
1011    
1012                    while ((line = unsyncBufferedReader.readLine()) != null) {
1013                            sb.append(trimLine(line, allowLeadingSpaces));
1014                            sb.append("\n");
1015                    }
1016    
1017                    unsyncBufferedReader.close();
1018    
1019                    content = sb.toString();
1020    
1021                    if (content.endsWith("\n")) {
1022                            content = content.substring(0, content.length() - 1);
1023                    }
1024    
1025                    return content;
1026            }
1027    
1028            protected String trimLine(String line, boolean allowLeadingSpaces) {
1029                    if (line.trim().length() == 0) {
1030                            return StringPool.BLANK;
1031                    }
1032    
1033                    line = StringUtil.trimTrailing(line);
1034    
1035                    if (allowLeadingSpaces || !line.startsWith(StringPool.SPACE) ||
1036                            line.startsWith(" *")) {
1037    
1038                            return line;
1039                    }
1040    
1041                    if (!line.startsWith(StringPool.FOUR_SPACES)) {
1042                            while (line.startsWith(StringPool.SPACE)) {
1043                                    line = StringUtil.replaceFirst(
1044                                            line, StringPool.SPACE, StringPool.BLANK);
1045                            }
1046                    }
1047                    else {
1048                            int pos = 0;
1049    
1050                            String temp = line;
1051    
1052                            while (temp.startsWith(StringPool.FOUR_SPACES)) {
1053                                    line = StringUtil.replaceFirst(
1054                                            line, StringPool.FOUR_SPACES, StringPool.TAB);
1055    
1056                                    pos++;
1057    
1058                                    temp = line.substring(pos);
1059                            }
1060                    }
1061    
1062                    return line;
1063            }
1064    
1065            protected static final String BASEDIR = "./";
1066    
1067            protected static final String MAIN_RELEASE_VERSION_6_1_0 = "6.1.0";
1068    
1069            protected static final String MAIN_RELEASE_VERSION_6_2_0 = "6.2.0";
1070    
1071            protected static FileImpl fileUtil = FileImpl.getInstance();
1072            protected static Pattern languageKeyPattern = Pattern.compile(
1073                    "LanguageUtil.(?:get|format)\\([^;%]+|Liferay.Language.get\\('([^']+)");
1074            protected static String mainReleaseVersion;
1075            protected static boolean portalSource;
1076            protected static SAXReaderImpl saxReaderUtil = SAXReaderImpl.getInstance();
1077            protected static Pattern sessionKeyPattern = Pattern.compile(
1078                    "SessionErrors.(?:add|contains|get)\\([^;%&|!]+|".concat(
1079                            "SessionMessages.(?:add|contains|get)\\([^;%&|!]+"),
1080                    Pattern.MULTILINE);
1081            protected static SourceFormatterHelper sourceFormatterHelper;
1082            protected static Pattern taglibSessionKeyPattern = Pattern.compile(
1083                    "<liferay-ui:error [^>]+>|<liferay-ui:success [^>]+>",
1084                    Pattern.MULTILINE);
1085    
1086            private void _init(
1087                            boolean useProperties, boolean printErrors, boolean autoFix)
1088                    throws Exception {
1089    
1090                    _errorMessages = new ArrayList<String>();
1091    
1092                    sourceFormatterHelper = new SourceFormatterHelper(useProperties);
1093    
1094                    sourceFormatterHelper.init();
1095    
1096                    if (_initialized) {
1097                            return;
1098                    }
1099    
1100                    _autoFix = autoFix;
1101    
1102                    _setVersion();
1103    
1104                    _excludes = StringUtil.split(
1105                            GetterUtil.getString(
1106                                    System.getProperty("source.formatter.excludes")));
1107    
1108                    portalSource = _isPortalSource();
1109    
1110                    _printErrors = printErrors;
1111    
1112                    _initialized = true;
1113            }
1114    
1115            private boolean _isPortalSource() {
1116                    if (fileUtil.exists(BASEDIR + "portal-impl")) {
1117                            return true;
1118                    }
1119                    else {
1120                            return false;
1121                    }
1122            }
1123    
1124            private void _setVersion() throws Exception {
1125                    String releaseInfoVersion = ReleaseInfo.getVersion();
1126    
1127                    if (releaseInfoVersion.startsWith("6.1")) {
1128                            mainReleaseVersion = MAIN_RELEASE_VERSION_6_1_0;
1129                    }
1130                    else if (releaseInfoVersion.startsWith("6.2")) {
1131                            mainReleaseVersion = MAIN_RELEASE_VERSION_6_2_0;
1132                    }
1133                    else {
1134                            throw new Exception(
1135                                    "Invalid release information: " + ReleaseInfo.getVersion());
1136                    }
1137            }
1138    
1139            private static boolean _autoFix;
1140            private static Map<String, String> _compatClassNamesMap;
1141            private static String _copyright;
1142            private static List<String> _errorMessages = new ArrayList<String>();
1143            private static String[] _excludes;
1144            private static boolean _initialized;
1145            private static String _oldCopyright;
1146            private static Properties _portalLanguageKeysProperties;
1147            private static boolean _printErrors;
1148    
1149    }