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 checkLanguageKeys(
243                            String fileName, String content, Pattern pattern)
244                    throws IOException {
245    
246                    String fileExtension = fileUtil.getExtension(fileName);
247    
248                    if (!portalSource || fileExtension.equals("vm")) {
249                            return;
250                    }
251    
252                    if (_portalLanguageKeysProperties == null) {
253                            _portalLanguageKeysProperties = new Properties();
254    
255                            ClassLoader classLoader =
256                                    BaseSourceProcessor.class.getClassLoader();
257    
258                            InputStream inputStream = classLoader.getResourceAsStream(
259                                    "content/Language.properties");
260    
261                            _portalLanguageKeysProperties.load(inputStream);
262                    }
263    
264                    Matcher matcher = pattern.matcher(content);
265    
266                    while (matcher.find()) {
267                            String[] languageKeys = getLanguageKeys(matcher);
268    
269                            for (String languageKey : languageKeys) {
270                                    if (Validator.isNumber(languageKey) ||
271                                            languageKey.endsWith(StringPool.DASH) ||
272                                            languageKey.endsWith(StringPool.OPEN_BRACKET) ||
273                                            languageKey.endsWith(StringPool.PERIOD) ||
274                                            languageKey.endsWith(StringPool.UNDERLINE) ||
275                                            languageKey.startsWith(StringPool.DASH) ||
276                                            languageKey.startsWith(StringPool.OPEN_BRACKET) ||
277                                            languageKey.startsWith(StringPool.OPEN_CURLY_BRACE) ||
278                                            languageKey.startsWith(StringPool.PERIOD) ||
279                                            languageKey.startsWith(StringPool.UNDERLINE)) {
280    
281                                            continue;
282                                    }
283    
284                                    if (!_portalLanguageKeysProperties.containsKey(languageKey)) {
285                                            processErrorMessage(
286                                                    fileName,
287                                                    "missing language key: " + languageKey +
288                                                            StringPool.SPACE + fileName);
289                                    }
290                            }
291                    }
292            }
293    
294            protected void checkStringBundler(
295                    String line, String fileName, int lineCount) {
296    
297                    if ((!line.startsWith("sb.append(") && !line.contains("SB.append(")) ||
298                            !line.endsWith(");")) {
299    
300                            return;
301                    }
302    
303                    int pos = line.indexOf(".append(");
304    
305                    line = line.substring(pos + 8, line.length() - 2);
306    
307                    line = stripQuotes(line, CharPool.QUOTE);
308    
309                    if (!line.contains(" + ")) {
310                            return;
311                    }
312    
313                    String[] lineParts = StringUtil.split(line, " + ");
314    
315                    for (String linePart : lineParts) {
316                            int closeParenthesesCount = StringUtil.count(
317                                    linePart, StringPool.CLOSE_PARENTHESIS);
318                            int openParenthesesCount = StringUtil.count(
319                                    linePart, StringPool.OPEN_PARENTHESIS);
320    
321                            if (closeParenthesesCount != openParenthesesCount) {
322                                    return;
323                            }
324    
325                            if (Validator.isNumber(linePart)) {
326                                    return;
327                            }
328                    }
329    
330                    processErrorMessage(fileName, "plus: " + fileName + " " + lineCount);
331            }
332    
333            protected String fixCompatClassImports(File file, String content)
334                    throws IOException {
335    
336                    String absolutePath = fileUtil.getAbsolutePath(file);
337    
338                    if (portalSource ||
339                            !mainReleaseVersion.equals(MAIN_RELEASE_VERSION_6_1_0) ||
340                            absolutePath.contains("/ext-") ||
341                            absolutePath.contains("/portal-compat-shared/")) {
342    
343                            return content;
344                    }
345    
346                    Map<String, String> compatClassNamesMap = getCompatClassNamesMap();
347    
348                    String newContent = content;
349    
350                    for (Map.Entry<String, String> entry : compatClassNamesMap.entrySet()) {
351                            String compatClassName = entry.getKey();
352                            String extendedClassName = entry.getValue();
353    
354                            Pattern pattern = Pattern.compile(extendedClassName + "\\W");
355    
356                            while (true) {
357                                    Matcher matcher = pattern.matcher(newContent);
358    
359                                    if (!matcher.find()) {
360                                            break;
361                                    }
362    
363                                    newContent =
364                                            newContent.substring(0, matcher.start()) + compatClassName +
365                                                    newContent.substring(matcher.end() - 1);
366                            }
367                    }
368    
369                    return newContent;
370            }
371    
372            protected String fixCopyright(
373                            String content, String copyright, String oldCopyright, File file,
374                            String fileName)
375                    throws IOException {
376    
377                    if (fileName.endsWith(".vm")) {
378                            return content;
379                    }
380    
381                    if ((oldCopyright != null) && content.contains(oldCopyright)) {
382                            content = StringUtil.replace(content, oldCopyright, copyright);
383    
384                            processErrorMessage(fileName, "old (c): " + fileName);
385                    }
386    
387                    if (!content.contains(copyright)) {
388                            String customCopyright = getCustomCopyright(file);
389    
390                            if (Validator.isNotNull(customCopyright)) {
391                                    copyright = customCopyright;
392                            }
393    
394                            if (!content.contains(copyright)) {
395                                    processErrorMessage(fileName, "(c): " + fileName);
396                            }
397                    }
398    
399                    if (fileName.endsWith(".jsp") || fileName.endsWith(".jspf")) {
400                            content = StringUtil.replace(
401                                    content, "<%\n" + copyright + "\n%>",
402                                    "<%--\n" + copyright + "\n--%>");
403                    }
404    
405                    int x = content.indexOf("* Copyright (c) 2000-20");
406    
407                    if (x == -1) {
408                            return content;
409                    }
410    
411                    int y = copyright.indexOf("* Copyright (c) 2000-20");
412    
413                    if (y == -1) {
414                            return content;
415                    }
416    
417                    String contentCopyrightYear = content.substring(x, x + 25);
418                    String copyrightYear = copyright.substring(y, y + 25);
419    
420                    return StringUtil.replace(content, contentCopyrightYear, copyrightYear);
421            }
422    
423            protected String fixSessionKey(
424                    String fileName, String content, Pattern pattern) {
425    
426                    if (mainReleaseVersion.equals(MAIN_RELEASE_VERSION_6_1_0)) {
427                            return content;
428                    }
429    
430                    Matcher matcher = pattern.matcher(content);
431    
432                    if (!matcher.find()) {
433                            return content;
434                    }
435    
436                    String newContent = content;
437    
438                    do {
439                            String match = matcher.group();
440    
441                            String s = null;
442    
443                            if (pattern.equals(sessionKeyPattern)) {
444                                    s = StringPool.COMMA;
445                            }
446                            else if (pattern.equals(taglibSessionKeyPattern)) {
447                                    s = "key=";
448                            }
449    
450                            int x = match.indexOf(s);
451    
452                            if (x == -1) {
453                                    continue;
454                            }
455    
456                            x = x + s.length();
457    
458                            String substring = match.substring(x).trim();
459    
460                            String quote = StringPool.BLANK;
461    
462                            if (substring.startsWith(StringPool.APOSTROPHE)) {
463                                    quote = StringPool.APOSTROPHE;
464                            }
465                            else if (substring.startsWith(StringPool.QUOTE)) {
466                                    quote = StringPool.QUOTE;
467                            }
468                            else {
469                                    continue;
470                            }
471    
472                            int y = match.indexOf(quote, x);
473                            int z = match.indexOf(quote, y + 1);
474    
475                            if ((y == -1) || (z == -1)) {
476                                    continue;
477                            }
478    
479                            String prefix = match.substring(0, y + 1);
480                            String suffix = match.substring(z);
481                            String oldKey = match.substring(y + 1, z);
482    
483                            boolean alphaNumericKey = true;
484    
485                            for (char c : oldKey.toCharArray()) {
486                                    if (!Validator.isChar(c) && !Validator.isDigit(c) &&
487                                            (c != CharPool.DASH) && (c != CharPool.UNDERLINE)) {
488    
489                                            alphaNumericKey = false;
490                                    }
491                            }
492    
493                            if (!alphaNumericKey) {
494                                    continue;
495                            }
496    
497                            String newKey = TextFormatter.format(oldKey, TextFormatter.O);
498    
499                            newKey = TextFormatter.format(newKey, TextFormatter.M);
500    
501                            if (newKey.equals(oldKey)) {
502                                    continue;
503                            }
504    
505                            String oldSub = prefix.concat(oldKey).concat(suffix);
506                            String newSub = prefix.concat(newKey).concat(suffix);
507    
508                            newContent = StringUtil.replaceFirst(newContent, oldSub, newSub);
509                    }
510                    while (matcher.find());
511    
512                    return newContent;
513            }
514    
515            protected abstract void format() throws Exception;
516    
517            protected String format(String fileName) throws Exception {
518                    return null;
519            }
520    
521            protected Map<String, String> getCompatClassNamesMap() throws IOException {
522                    if (_compatClassNamesMap != null) {
523                            return _compatClassNamesMap;
524                    }
525    
526                    _compatClassNamesMap = new HashMap<String, String>();
527    
528                    String[] includes = new String[] {
529                            "**\\portal-compat-shared\\src\\com\\liferay\\compat\\**\\*.java"
530                    };
531    
532                    String basedir = BASEDIR;
533    
534                    List<String> fileNames = new ArrayList<String>();
535    
536                    for (int i = 0; i < 3; i++) {
537                            fileNames = getFileNames(basedir, new String[0], includes);
538    
539                            if (!fileNames.isEmpty()) {
540                                    break;
541                            }
542    
543                            basedir = "../" + basedir;
544                    }
545    
546                    for (String fileName : fileNames) {
547                            File file = new File(basedir + fileName);
548    
549                            String content = fileUtil.read(file);
550    
551                            fileName = StringUtil.replace(
552                                    fileName, StringPool.BACK_SLASH, StringPool.SLASH);
553    
554                            fileName = StringUtil.replace(
555                                    fileName, StringPool.SLASH, StringPool.PERIOD);
556    
557                            int pos = fileName.indexOf("com.");
558    
559                            String compatClassName = fileName.substring(pos);
560    
561                            compatClassName = compatClassName.substring(
562                                    0, compatClassName.length() - 5);
563    
564                            String extendedClassName = StringUtil.replace(
565                                    compatClassName, "compat.", StringPool.BLANK);
566    
567                            if (content.contains("extends " + extendedClassName)) {
568                                    _compatClassNamesMap.put(compatClassName, extendedClassName);
569                            }
570                    }
571    
572                    return _compatClassNamesMap;
573            }
574    
575            protected String getCopyright() throws IOException {
576                    if (Validator.isNotNull(_copyright)) {
577                            return _copyright;
578                    }
579    
580                    _copyright = fileUtil.read("copyright.txt");
581    
582                    if (Validator.isNull(_copyright)) {
583                            _copyright = fileUtil.read("../copyright.txt");
584                    }
585    
586                    if (Validator.isNull(_copyright)) {
587                            _copyright = fileUtil.read("../../copyright.txt");
588                    }
589    
590                    return _copyright;
591            }
592    
593            protected String getCustomCopyright(File file) throws IOException {
594                    String absolutePath = fileUtil.getAbsolutePath(file);
595    
596                    for (int x = absolutePath.length();;) {
597                            x = absolutePath.lastIndexOf(StringPool.SLASH, x);
598    
599                            if (x == -1) {
600                                    break;
601                            }
602    
603                            String copyright = fileUtil.read(
604                                    absolutePath.substring(0, x + 1) + "copyright.txt");
605    
606                            if (Validator.isNotNull(copyright)) {
607                                    return copyright;
608                            }
609    
610                            x = x - 1;
611                    }
612    
613                    return null;
614            }
615    
616            protected Properties getExclusionsProperties(String fileName)
617                    throws IOException {
618    
619                    InputStream inputStream = null;
620    
621                    int level = 0;
622    
623                    if (portalSource) {
624                            ClassLoader classLoader =
625                                    BaseSourceProcessor.class.getClassLoader();
626    
627                            String sourceFormatterExclusions = System.getProperty(
628                                    "source-formatter-exclusions",
629                                    "com/liferay/portal/tools/dependencies/" + fileName);
630    
631                            URL url = classLoader.getResource(sourceFormatterExclusions);
632    
633                            if (url == null) {
634                                    return null;
635                            }
636    
637                            inputStream = url.openStream();
638                    }
639                    else {
640                            try {
641                                    inputStream = new FileInputStream(fileName);
642                            }
643                            catch (FileNotFoundException fnfe) {
644                            }
645    
646                            if (inputStream == null) {
647                                    try {
648                                            inputStream = new FileInputStream("../" + fileName);
649    
650                                            level = 1;
651                                    }
652                                    catch (FileNotFoundException fnfe) {
653                                    }
654                            }
655    
656                            if (inputStream == null) {
657                                    try {
658                                            inputStream = new FileInputStream("../../" + fileName);
659    
660                                            level = 2;
661                                    }
662                                    catch (FileNotFoundException fnfe) {
663                                            return null;
664                                    }
665                            }
666                    }
667    
668                    Properties properties = new Properties();
669    
670                    properties.load(inputStream);
671    
672                    inputStream.close();
673    
674                    if (level > 0) {
675                            properties = stripTopLevelDirectories(properties, level);
676                    }
677    
678                    return properties;
679            }
680    
681            protected List<String> getFileNames(
682                    String basedir, String[] excludes, String[] includes) {
683    
684                    DirectoryScanner directoryScanner = new DirectoryScanner();
685    
686                    directoryScanner.setBasedir(basedir);
687    
688                    excludes = ArrayUtil.append(
689                            excludes, _excludes, new String[] {"**\\.git\\**", "**\\tmp\\**"});
690    
691                    if (portalSource) {
692                            excludes = ArrayUtil.append(
693                                    excludes, new String[] {"**\\webapps\\**"});
694                    }
695    
696                    directoryScanner.setExcludes(excludes);
697    
698                    directoryScanner.setIncludes(includes);
699    
700                    return sourceFormatterHelper.scanForFiles(directoryScanner);
701            }
702    
703            protected List<String> getFileNames(String[] excludes, String[] includes) {
704                    return getFileNames(BASEDIR, excludes, includes);
705            }
706    
707            protected String[] getLanguageKeys(Matcher matcher) {
708                    if (matcher.groupCount() > 0) {
709                            String languageKey = matcher.group(1);
710    
711                            if (Validator.isNotNull(languageKey)) {
712                                    return new String[] {languageKey};
713                            }
714                    }
715    
716                    StringBundler sb = new StringBundler();
717    
718                    String match = matcher.group();
719    
720                    int count = 0;
721    
722                    for (int i = 0; i < match.length(); i++) {
723                            char c = match.charAt(i);
724    
725                            switch (c) {
726                                    case CharPool.CLOSE_PARENTHESIS:
727                                            if (count <= 1) {
728                                                    return new String[0];
729                                            }
730    
731                                            count--;
732    
733                                            break;
734    
735                                    case CharPool.OPEN_PARENTHESIS:
736                                            count++;
737    
738                                            break;
739    
740                                    case CharPool.QUOTE:
741                                            if (count > 1) {
742                                                    break;
743                                            }
744    
745                                            while (i < match.length()) {
746                                                    i++;
747    
748                                                    if (match.charAt(i) == CharPool.QUOTE) {
749                                                            String languageKey = sb.toString();
750    
751                                                            if (match.startsWith("names")) {
752                                                                    return StringUtil.split(languageKey);
753                                                            }
754                                                            else {
755                                                                    return new String[] {languageKey};
756                                                            }
757    
758                                                    }
759    
760                                                    sb.append(match.charAt(i));
761                                            }
762                            }
763                    }
764    
765                    return new String[0];
766            }
767    
768            protected String getOldCopyright() throws IOException {
769                    if (Validator.isNotNull(_oldCopyright)) {
770                            return _oldCopyright;
771                    }
772    
773                    _oldCopyright = fileUtil.read("old-copyright.txt");
774    
775                    if (Validator.isNull(_oldCopyright)) {
776                            _oldCopyright = fileUtil.read("../old-copyright.txt");
777                    }
778    
779                    if (Validator.isNull(_oldCopyright)) {
780                            _oldCopyright = fileUtil.read("../../old-copyright.txt");
781                    }
782    
783                    return _oldCopyright;
784            }
785    
786            protected boolean hasMissingParentheses(String s) {
787                    if (Validator.isNull(s)) {
788                            return false;
789                    }
790    
791                    boolean containsAndOrOperator = (s.contains("&&") || s.contains("||"));
792    
793                    boolean containsCompareOperator =
794                            (s.contains(" == ") || s.contains(" != ") || s.contains(" < ") ||
795                             s.contains(" > ") || s.contains(" =< ") || s.contains(" => ") ||
796                             s.contains(" <= ") || s.contains(" >= "));
797    
798                    boolean containsMathOperator =
799                            (s.contains(" = ") || s.contains(" - ") || s.contains(" + ") ||
800                             s.contains(" & ") || s.contains(" % ") || s.contains(" * ") ||
801                             s.contains(" / "));
802    
803                    if (containsCompareOperator &&
804                            (containsAndOrOperator ||
805                             (containsMathOperator && !s.contains(StringPool.OPEN_BRACKET)))) {
806    
807                            return true;
808                    }
809                    else {
810                            return false;
811                    }
812            }
813    
814            protected boolean hasRedundantParentheses(String s) {
815                    if (!s.contains("&&") && !s.contains("||")) {
816                            for (int x = 0;;) {
817                                    x = s.indexOf(StringPool.CLOSE_PARENTHESIS);
818    
819                                    if (x == -1) {
820                                            break;
821                                    }
822    
823                                    int y = s.substring(0, x).lastIndexOf(
824                                            StringPool.OPEN_PARENTHESIS);
825    
826                                    if (y == -1) {
827                                            break;
828                                    }
829    
830                                    s = s.substring(0, y) + s.substring(x + 1);
831                            }
832                    }
833    
834                    if (Validator.isNotNull(s) && !s.contains(StringPool.SPACE)) {
835                            return true;
836                    }
837                    else {
838                            return false;
839                    }
840            }
841    
842            protected boolean isAutoFix() {
843                    return _autoFix;
844            }
845    
846            protected void processErrorMessage(String fileName, String message) {
847                    _errorMessages.add(message);
848    
849                    if (_printErrors) {
850                            sourceFormatterHelper.printError(fileName, message);
851                    }
852            }
853    
854            protected String replacePrimitiveWrapperInstantiation(
855                    String fileName, String line, int lineCount) {
856    
857                    if (true) {
858                            return line;
859                    }
860    
861                    String newLine = StringUtil.replace(
862                            line,
863                            new String[] {
864                                    "new Boolean(", "new Byte(", "new Character(", "new Integer(",
865                                    "new Long(", "new Short("
866                            },
867                            new String[] {
868                                    "Boolean.valueOf(", "Byte.valueOf(", "Character.valueOf(",
869                                    "Integer.valueOf(", "Long.valueOf(", "Short.valueOf("
870                            });
871    
872                    if (!line.equals(newLine)) {
873                            processErrorMessage(
874                                    fileName, "> new Primitive(: " + fileName + " " + lineCount);
875                    }
876    
877                    return newLine;
878            }
879    
880            protected String stripQuotes(String s, char delimeter) {
881                    boolean insideQuotes = false;
882    
883                    StringBundler sb = new StringBundler();
884    
885                    for (int i = 0; i < s.length(); i++) {
886                            char c = s.charAt(i);
887    
888                            if (insideQuotes) {
889                                    if (c == delimeter) {
890                                            if ((c > 1) && (s.charAt(i - 1) == CharPool.BACK_SLASH) &&
891                                                    (s.charAt(i - 2) != CharPool.BACK_SLASH)) {
892    
893                                                    continue;
894                                            }
895    
896                                            insideQuotes = false;
897                                    }
898                            }
899                            else if (c == delimeter) {
900                                    insideQuotes = true;
901                            }
902                            else {
903                                    sb.append(c);
904                            }
905                    }
906    
907                    return sb.toString();
908            }
909    
910            protected String stripRedundantParentheses(String s) {
911                    for (int x = 0;;) {
912                            x = s.indexOf(StringPool.OPEN_PARENTHESIS, x + 1);
913                            int y = s.indexOf(StringPool.CLOSE_PARENTHESIS, x);
914    
915                            if ((x == -1) || (y == -1)) {
916                                    return s;
917                            }
918    
919                            String linePart = s.substring(x + 1, y);
920    
921                            linePart = StringUtil.replace(
922                                    linePart, StringPool.COMMA, StringPool.BLANK);
923    
924                            if (Validator.isAlphanumericName(linePart) ||
925                                    Validator.isNull(linePart)) {
926    
927                                    s = s.substring(0, x) + s.substring(y + 1);
928                            }
929                    }
930            }
931    
932            protected Properties stripTopLevelDirectories(
933                            Properties properties, int level)
934                    throws IOException {
935    
936                    File dir = new File(".");
937    
938                    String dirName = dir.getCanonicalPath();
939    
940                    dirName = StringUtil.replace(
941                            dirName, StringPool.BACK_SLASH, StringPool.SLASH);
942    
943                    int pos = dirName.length();
944    
945                    for (int i = 0; i < level; i++) {
946                            pos = dirName.lastIndexOf(StringPool.SLASH, pos - 1);
947                    }
948    
949                    String topLevelDirNames = dirName.substring(pos + 1) + StringPool.SLASH;
950    
951                    Properties newProperties = new Properties();
952    
953                    for (Map.Entry<Object, Object> entry : properties.entrySet()) {
954                            String key = (String)entry.getKey();
955    
956                            if (!key.startsWith(topLevelDirNames)) {
957                                    continue;
958                            }
959    
960                            key = StringUtil.replaceFirst(
961                                    key, topLevelDirNames, StringPool.BLANK);
962    
963                            String value = (String)entry.getValue();
964    
965                            newProperties.setProperty(key, value);
966                    }
967    
968                    return newProperties;
969            }
970    
971            protected String trimContent(String content, boolean allowLeadingSpaces)
972                    throws IOException {
973    
974                    StringBundler sb = new StringBundler();
975    
976                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
977                            new UnsyncStringReader(content));
978    
979                    String line = null;
980    
981                    while ((line = unsyncBufferedReader.readLine()) != null) {
982                            sb.append(trimLine(line, allowLeadingSpaces));
983                            sb.append("\n");
984                    }
985    
986                    unsyncBufferedReader.close();
987    
988                    content = sb.toString();
989    
990                    if (content.endsWith("\n")) {
991                            content = content.substring(0, content.length() - 1);
992                    }
993    
994                    return content;
995            }
996    
997            protected String trimLine(String line, boolean allowLeadingSpaces) {
998                    if (line.trim().length() == 0) {
999                            return StringPool.BLANK;
1000                    }
1001    
1002                    line = StringUtil.trimTrailing(line);
1003    
1004                    if (allowLeadingSpaces || !line.startsWith(StringPool.SPACE) ||
1005                            line.startsWith(" *")) {
1006    
1007                            return line;
1008                    }
1009    
1010                    if (!line.startsWith(StringPool.FOUR_SPACES)) {
1011                            while (line.startsWith(StringPool.SPACE)) {
1012                                    line = StringUtil.replaceFirst(
1013                                            line, StringPool.SPACE, StringPool.BLANK);
1014                            }
1015                    }
1016                    else {
1017                            int pos = 0;
1018    
1019                            String temp = line;
1020    
1021                            while (temp.startsWith(StringPool.FOUR_SPACES)) {
1022                                    line = StringUtil.replaceFirst(
1023                                            line, StringPool.FOUR_SPACES, StringPool.TAB);
1024    
1025                                    pos++;
1026    
1027                                    temp = line.substring(pos);
1028                            }
1029                    }
1030    
1031                    return line;
1032            }
1033    
1034            protected static final String BASEDIR = "./";
1035    
1036            protected static final String MAIN_RELEASE_VERSION_6_1_0 = "6.1.0";
1037    
1038            protected static final String MAIN_RELEASE_VERSION_6_2_0 = "6.2.0";
1039    
1040            protected static FileImpl fileUtil = FileImpl.getInstance();
1041            protected static Pattern languageKeyPattern = Pattern.compile(
1042                    "LanguageUtil.(?:get|format)\\([^;%]+|Liferay.Language.get\\('([^']+)");
1043            protected static String mainReleaseVersion;
1044            protected static boolean portalSource;
1045            protected static SAXReaderImpl saxReaderUtil = SAXReaderImpl.getInstance();
1046            protected static Pattern sessionKeyPattern = Pattern.compile(
1047                    "SessionErrors.(?:add|contains|get)\\([^;%&|!]+|".concat(
1048                            "SessionMessages.(?:add|contains|get)\\([^;%&|!]+"),
1049                    Pattern.MULTILINE);
1050            protected static SourceFormatterHelper sourceFormatterHelper;
1051            protected static Pattern taglibSessionKeyPattern = Pattern.compile(
1052                    "<liferay-ui:error [^>]+>|<liferay-ui:success [^>]+>",
1053                    Pattern.MULTILINE);
1054    
1055            private void _init(
1056                            boolean useProperties, boolean printErrors, boolean autoFix)
1057                    throws Exception {
1058    
1059                    _errorMessages = new ArrayList<String>();
1060    
1061                    sourceFormatterHelper = new SourceFormatterHelper(useProperties);
1062    
1063                    sourceFormatterHelper.init();
1064    
1065                    if (_initialized) {
1066                            return;
1067                    }
1068    
1069                    _autoFix = autoFix;
1070    
1071                    _setVersion();
1072    
1073                    _excludes = StringUtil.split(
1074                            GetterUtil.getString(
1075                                    System.getProperty("source.formatter.excludes")));
1076    
1077                    portalSource = _isPortalSource();
1078    
1079                    _printErrors = printErrors;
1080    
1081                    _initialized = true;
1082            }
1083    
1084            private boolean _isPortalSource() {
1085                    if (fileUtil.exists(BASEDIR + "portal-impl")) {
1086                            return true;
1087                    }
1088                    else {
1089                            return false;
1090                    }
1091            }
1092    
1093            private void _setVersion() throws Exception {
1094                    String releaseInfoVersion = ReleaseInfo.getVersion();
1095    
1096                    if (releaseInfoVersion.startsWith("6.1")) {
1097                            mainReleaseVersion = MAIN_RELEASE_VERSION_6_1_0;
1098                    }
1099                    else if (releaseInfoVersion.startsWith("6.2")) {
1100                            mainReleaseVersion = MAIN_RELEASE_VERSION_6_2_0;
1101                    }
1102                    else {
1103                            throw new Exception(
1104                                    "Invalid release information: " + ReleaseInfo.getVersion());
1105                    }
1106            }
1107    
1108            private static boolean _autoFix;
1109            private static Map<String, String> _compatClassNamesMap;
1110            private static String _copyright;
1111            private static List<String> _errorMessages = new ArrayList<String>();
1112            private static String[] _excludes;
1113            private static boolean _initialized;
1114            private static String _oldCopyright;
1115            private static Properties _portalLanguageKeysProperties;
1116            private static boolean _printErrors;
1117    
1118    }