001    /**
002     * Copyright (c) 2000-present 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.ReflectionUtil;
024    import com.liferay.portal.kernel.util.ReleaseInfo;
025    import com.liferay.portal.kernel.util.SetUtil;
026    import com.liferay.portal.kernel.util.StringBundler;
027    import com.liferay.portal.kernel.util.StringPool;
028    import com.liferay.portal.kernel.util.StringUtil;
029    import com.liferay.portal.kernel.util.TextFormatter;
030    import com.liferay.portal.kernel.util.Validator;
031    import com.liferay.portal.util.FileImpl;
032    import com.liferay.portal.xml.SAXReaderImpl;
033    
034    import java.io.File;
035    import java.io.FileInputStream;
036    import java.io.FileNotFoundException;
037    import java.io.IOException;
038    import java.io.InputStream;
039    
040    import java.util.ArrayList;
041    import java.util.Enumeration;
042    import java.util.HashMap;
043    import java.util.List;
044    import java.util.Map;
045    import java.util.Properties;
046    import java.util.Set;
047    import java.util.regex.Matcher;
048    import java.util.regex.Pattern;
049    
050    import org.apache.tools.ant.DirectoryScanner;
051    
052    /**
053     * @author Brian Wing Shun Chan
054     * @author Igor Spasic
055     * @author Wesley Gong
056     * @author Hugo Huijser
057     */
058    public abstract class BaseSourceProcessor implements SourceProcessor {
059    
060            public BaseSourceProcessor() {
061                    portalSource = _isPortalSource();
062    
063                    try {
064                            _properties = _getProperties();
065                    }
066                    catch (Exception e) {
067                            ReflectionUtil.throwException(e);
068                    }
069            }
070    
071            @Override
072            public void format(
073                            boolean useProperties, boolean printErrors, boolean autoFix)
074                    throws Exception {
075    
076                    _init(useProperties, printErrors, autoFix);
077    
078                    format();
079    
080                    sourceFormatterHelper.close();
081            }
082    
083            @Override
084            public String format(
085                            String fileName, boolean useProperties, boolean printErrors,
086                            boolean autoFix)
087                    throws Exception {
088    
089                    try {
090                            _init(useProperties, printErrors, autoFix);
091    
092                            return format(fileName);
093                    }
094                    finally {
095                            sourceFormatterHelper.close();
096                    }
097            }
098    
099            @Override
100            public List<String> getErrorMessages() {
101                    List<String> errorMessages = new ArrayList<String>();
102    
103                    for (Map.Entry<String, List<String>> entry :
104                                    _errorMessagesMap.entrySet()) {
105    
106                            errorMessages.addAll(entry.getValue());
107                    }
108    
109                    return errorMessages;
110            }
111    
112            @Override
113            public SourceMismatchException getFirstSourceMismatchException() {
114                    return _firstSourceMismatchException;
115            }
116    
117            protected static boolean isExcluded(
118                    List<String> exclusions, String absolutePath) {
119    
120                    return isExcluded(exclusions, absolutePath, -1);
121            }
122    
123            protected static boolean isExcluded(
124                    List<String> exclusions, String absolutePath, int lineCount) {
125    
126                    return isExcluded(exclusions, absolutePath, lineCount, null);
127            }
128    
129            protected static boolean isExcluded(
130                    List<String> exclusions, String absolutePath, int lineCount,
131                    String javaTermName) {
132    
133                    if (ListUtil.isEmpty(exclusions)) {
134                            return false;
135                    }
136    
137                    String absolutePathWithJavaTermName = null;
138    
139                    if (Validator.isNotNull(javaTermName)) {
140                            absolutePathWithJavaTermName =
141                                    absolutePath + StringPool.AT + javaTermName;
142                    }
143    
144                    String absolutePathWithLineCount = null;
145    
146                    if (lineCount > 0) {
147                            absolutePathWithLineCount =
148                                    absolutePath + StringPool.AT + lineCount;
149                    }
150    
151                    for (String exclusion : exclusions) {
152                            if (absolutePath.endsWith(exclusion) ||
153                                    ((absolutePathWithJavaTermName != null) &&
154                                     absolutePathWithJavaTermName.endsWith(exclusion)) ||
155                                    ((absolutePathWithLineCount != null) &&
156                                     absolutePathWithLineCount.endsWith(exclusion))) {
157    
158                                    return true;
159                            }
160                    }
161    
162                    return false;
163            }
164    
165            protected static void processErrorMessage(String fileName, String message) {
166                    List<String> errorMessages = _errorMessagesMap.get(fileName);
167    
168                    if (errorMessages == null) {
169                            errorMessages = new ArrayList<String>();
170                    }
171    
172                    errorMessages.add(message);
173    
174                    _errorMessagesMap.put(fileName, errorMessages);
175            }
176    
177            protected void checkEmptyCollection(
178                    String line, String fileName, int lineCount) {
179    
180                    // LPS-46028
181    
182                    Matcher matcher = emptyCollectionPattern.matcher(line);
183    
184                    if (matcher.find()) {
185                            String collectionType = TextFormatter.format(
186                                    matcher.group(1), TextFormatter.J);
187    
188                            processErrorMessage(
189                                    fileName,
190                                    "Use Collections.empty" + collectionType + "(): " + fileName +
191                                            " " + lineCount);
192                    }
193            }
194    
195            protected void checkIfClauseParentheses(
196                    String ifClause, String fileName, int lineCount) {
197    
198                    int quoteCount = StringUtil.count(ifClause, StringPool.QUOTE);
199    
200                    if ((quoteCount % 2) == 1) {
201                            return;
202                    }
203    
204                    ifClause = stripQuotes(ifClause, CharPool.QUOTE);
205    
206                    ifClause = stripQuotes(ifClause, CharPool.APOSTROPHE);
207    
208                    if (ifClause.contains(StringPool.DOUBLE_SLASH) ||
209                            ifClause.contains("/*") || ifClause.contains("*/")) {
210    
211                            return;
212                    }
213    
214                    if (hasRedundantParentheses(ifClause, "||", "&&") ||
215                            hasRedundantParentheses(ifClause, "&&", "||")) {
216    
217                            processErrorMessage(
218                                    fileName,
219                                    "redundant parentheses: " + fileName + " " + lineCount);
220                    }
221    
222                    ifClause = stripRedundantParentheses(ifClause);
223    
224                    int level = 0;
225                    int max = StringUtil.count(ifClause, StringPool.OPEN_PARENTHESIS);
226                    int previousParenthesisPos = -1;
227    
228                    int[] levels = new int[max];
229    
230                    for (int i = 0; i < ifClause.length(); i++) {
231                            char c = ifClause.charAt(i);
232    
233                            if ((c == CharPool.OPEN_PARENTHESIS) ||
234                                    (c == CharPool.CLOSE_PARENTHESIS)) {
235    
236                                    if (previousParenthesisPos != -1) {
237                                            String s = ifClause.substring(
238                                                    previousParenthesisPos + 1, i);
239    
240                                            if (hasMissingParentheses(s)) {
241                                                    processErrorMessage(
242                                                            fileName,
243                                                            "missing parentheses: " + fileName + " " +
244                                                                    lineCount);
245                                            }
246                                    }
247    
248                                    previousParenthesisPos = i;
249    
250                                    if (c == CharPool.OPEN_PARENTHESIS) {
251                                            levels[level] = i;
252    
253                                            level += 1;
254                                    }
255                                    else {
256                                            int posOpenParenthesis = levels[level - 1];
257    
258                                            if (level > 1) {
259                                                    char nextChar = ifClause.charAt(i + 1);
260                                                    char previousChar = ifClause.charAt(
261                                                            posOpenParenthesis - 1);
262    
263                                                    if (!Character.isLetterOrDigit(nextChar) &&
264                                                            (nextChar != CharPool.PERIOD) &&
265                                                            !Character.isLetterOrDigit(previousChar)) {
266    
267                                                            String s = ifClause.substring(
268                                                                    posOpenParenthesis + 1, i);
269    
270                                                            if (hasRedundantParentheses(s)) {
271                                                                    processErrorMessage(
272                                                                            fileName,
273                                                                            "redundant parentheses: " + fileName + " " +
274                                                                                    lineCount);
275                                                            }
276                                                    }
277    
278                                                    if ((previousChar == CharPool.OPEN_PARENTHESIS) &&
279                                                            (nextChar == CharPool.CLOSE_PARENTHESIS)) {
280    
281                                                            processErrorMessage(
282                                                                    fileName,
283                                                                    "redundant parentheses: " + fileName + " " +
284                                                                            lineCount);
285                                                    }
286                                            }
287    
288                                            level -= 1;
289                                    }
290                            }
291                    }
292            }
293    
294            protected void checkInefficientStringMethods(
295                    String line, String fileName, String absolutePath, int lineCount) {
296    
297                    if (isRunsOutsidePortal(absolutePath) ||
298                            fileName.endsWith("GetterUtil.java")) {
299    
300                            return;
301                    }
302    
303                    String methodName = "toLowerCase";
304    
305                    int pos = line.indexOf(".toLowerCase()");
306    
307                    if (pos == -1) {
308                            methodName = "toUpperCase";
309    
310                            pos = line.indexOf(".toUpperCase()");
311                    }
312    
313                    if ((pos == -1) && !line.contains("StringUtil.equalsIgnoreCase(")) {
314                            methodName = "equalsIgnoreCase";
315    
316                            pos = line.indexOf(".equalsIgnoreCase(");
317                    }
318    
319                    if (pos != -1) {
320                            processErrorMessage(
321                                    fileName,
322                                    "Use StringUtil." + methodName + ": " + fileName + " " +
323                                            lineCount);
324                    }
325            }
326    
327            protected void checkLanguageKeys(
328                            String fileName, String content, Pattern pattern)
329                    throws IOException {
330    
331                    String fileExtension = fileUtil.getExtension(fileName);
332    
333                    if (!portalSource || fileExtension.equals("vm")) {
334                            return;
335                    }
336    
337                    if (_portalLanguageProperties == null) {
338                            _portalLanguageProperties = new Properties();
339    
340                            ClassLoader classLoader =
341                                    BaseSourceProcessor.class.getClassLoader();
342    
343                            InputStream inputStream = classLoader.getResourceAsStream(
344                                    "content/Language.properties");
345    
346                            _portalLanguageProperties.load(inputStream);
347                    }
348    
349                    Matcher matcher = pattern.matcher(content);
350    
351                    while (matcher.find()) {
352                            String[] languageKeys = getLanguageKeys(matcher);
353    
354                            for (String languageKey : languageKeys) {
355                                    if (Validator.isNumber(languageKey) ||
356                                            languageKey.endsWith(StringPool.DASH) ||
357                                            languageKey.endsWith(StringPool.OPEN_BRACKET) ||
358                                            languageKey.endsWith(StringPool.PERIOD) ||
359                                            languageKey.endsWith(StringPool.UNDERLINE) ||
360                                            languageKey.startsWith(StringPool.DASH) ||
361                                            languageKey.startsWith(StringPool.OPEN_BRACKET) ||
362                                            languageKey.startsWith(StringPool.OPEN_CURLY_BRACE) ||
363                                            languageKey.startsWith(StringPool.PERIOD) ||
364                                            languageKey.startsWith(StringPool.UNDERLINE) ||
365                                            _portalLanguageProperties.containsKey(languageKey)) {
366    
367                                            continue;
368                                    }
369    
370                                    Properties languageProperties = getLanguageProperties(fileName);
371    
372                                    if ((languageProperties == null) ||
373                                            !languageProperties.containsKey(languageKey)) {
374    
375                                            processErrorMessage(
376                                                    fileName,
377                                                    "missing language key: " + languageKey +
378                                                            StringPool.SPACE + fileName);
379                                    }
380                            }
381                    }
382            }
383    
384            protected void checkStringBundler(
385                    String line, String fileName, int lineCount) {
386    
387                    if ((!line.startsWith("sb.append(") && !line.contains("SB.append(")) ||
388                            !line.endsWith(");")) {
389    
390                            return;
391                    }
392    
393                    int pos = line.indexOf(".append(");
394    
395                    line = line.substring(pos + 8, line.length() - 2);
396    
397                    line = stripQuotes(line, CharPool.QUOTE);
398    
399                    if (!line.contains(" + ")) {
400                            return;
401                    }
402    
403                    String[] lineParts = StringUtil.split(line, " + ");
404    
405                    for (String linePart : lineParts) {
406                            int closeParenthesesCount = StringUtil.count(
407                                    linePart, StringPool.CLOSE_PARENTHESIS);
408                            int openParenthesesCount = StringUtil.count(
409                                    linePart, StringPool.OPEN_PARENTHESIS);
410    
411                            if (closeParenthesesCount != openParenthesesCount) {
412                                    return;
413                            }
414    
415                            if (Validator.isNumber(linePart)) {
416                                    return;
417                            }
418                    }
419    
420                    processErrorMessage(fileName, "plus: " + fileName + " " + lineCount);
421            }
422    
423            protected abstract String doFormat(
424                            File file, String fileName, String absolutePath, String content)
425                    throws Exception;
426    
427            protected String fixCompatClassImports(String absolutePath, String content)
428                    throws IOException {
429    
430                    if (portalSource || !_usePortalCompatImport ||
431                            absolutePath.contains("/ext-") ||
432                            absolutePath.contains("/portal-compat-shared/")) {
433    
434                            return content;
435                    }
436    
437                    Map<String, String> compatClassNamesMap = getCompatClassNamesMap();
438    
439                    String newContent = content;
440    
441                    for (Map.Entry<String, String> entry : compatClassNamesMap.entrySet()) {
442                            String compatClassName = entry.getKey();
443                            String extendedClassName = entry.getValue();
444    
445                            Pattern pattern = Pattern.compile(extendedClassName + "\\W");
446    
447                            while (true) {
448                                    Matcher matcher = pattern.matcher(newContent);
449    
450                                    if (!matcher.find()) {
451                                            break;
452                                    }
453    
454                                    newContent =
455                                            newContent.substring(0, matcher.start()) + compatClassName +
456                                                    newContent.substring(matcher.end() - 1);
457                            }
458                    }
459    
460                    return newContent;
461            }
462    
463            protected String fixCopyright(
464                            String content, String absolutePath, String fileName)
465                    throws IOException {
466    
467                    if (_copyright == null) {
468                            _copyright = getContent("copyright.txt", 4);
469                    }
470    
471                    String copyright = _copyright;
472    
473                    if (fileName.endsWith(".vm") || Validator.isNull(copyright)) {
474                            return content;
475                    }
476    
477                    if (_oldCopyright == null) {
478                            _oldCopyright = getContent("old-copyright.txt", 4);
479                    }
480    
481                    if (Validator.isNotNull(_oldCopyright) &&
482                            content.contains(_oldCopyright)) {
483    
484                            content = StringUtil.replace(content, _oldCopyright, copyright);
485    
486                            processErrorMessage(fileName, "old (c): " + fileName);
487                    }
488    
489                    if (!content.contains(copyright)) {
490                            String customCopyright = getCustomCopyright(absolutePath);
491    
492                            if (Validator.isNotNull(customCopyright)) {
493                                    copyright = customCopyright;
494                            }
495    
496                            if (!content.contains(copyright)) {
497                                    processErrorMessage(fileName, "(c): " + fileName);
498                            }
499                    }
500    
501                    if (fileName.endsWith(".jsp") || fileName.endsWith(".jspf")) {
502                            content = StringUtil.replace(
503                                    content, "<%\n" + copyright + "\n%>",
504                                    "<%--\n" + copyright + "\n--%>");
505                    }
506    
507                    int x = content.indexOf("* Copyright (c) 2000-");
508    
509                    if (x == -1) {
510                            return content;
511                    }
512    
513                    int y = content.indexOf("Liferay", x);
514    
515                    String contentCopyrightYear = content.substring(x, y);
516    
517                    x = copyright.indexOf("* Copyright (c) 2000-");
518    
519                    if (x == -1) {
520                            return content;
521                    }
522    
523                    y = copyright.indexOf("Liferay", x);
524    
525                    String copyrightYear = copyright.substring(x, y);
526    
527                    return StringUtil.replace(content, contentCopyrightYear, copyrightYear);
528            }
529    
530            protected String fixIncorrectParameterTypeForLanguageUtil(
531                    String content, boolean autoFix, String fileName) {
532    
533                    if (portalSource) {
534                            return content;
535                    }
536    
537                    String expectedParameter = getProperty(
538                            "languageutil.expected.parameter");
539                    String incorrectParameter = getProperty(
540                            "languageutil.incorrect.parameter");
541    
542                    if (!content.contains(
543                                    "LanguageUtil.format(" + incorrectParameter + ", ") &&
544                            !content.contains(
545                                    "LanguageUtil.get(" + incorrectParameter + ", ")) {
546    
547                            return content;
548                    }
549    
550                    if (autoFix) {
551                            content = StringUtil.replace(
552                                    content,
553                                    new String[] {
554                                            "LanguageUtil.format(" + incorrectParameter + ", ",
555                                            "LanguageUtil.get(" + incorrectParameter + ", "
556                                    },
557                                    new String[] {
558                                            "LanguageUtil.format(" + expectedParameter + ", ",
559                                            "LanguageUtil.get(" + expectedParameter + ", "
560                                    });
561                    }
562                    else {
563                            processErrorMessage(
564                                    fileName,
565                                    "(Unicode)LanguageUtil.format/get methods require " +
566                                            expectedParameter + " parameter instead of " +
567                                                    incorrectParameter + " " + fileName);
568                    }
569    
570                    return content;
571            }
572    
573            protected String fixSessionKey(
574                    String fileName, String content, Pattern pattern) {
575    
576                    Matcher matcher = pattern.matcher(content);
577    
578                    if (!matcher.find()) {
579                            return content;
580                    }
581    
582                    String newContent = content;
583    
584                    do {
585                            String match = matcher.group();
586    
587                            String s = null;
588    
589                            if (pattern.equals(sessionKeyPattern)) {
590                                    s = StringPool.COMMA;
591                            }
592                            else if (pattern.equals(taglibSessionKeyPattern)) {
593                                    s = "key=";
594                            }
595    
596                            int x = match.indexOf(s);
597    
598                            if (x == -1) {
599                                    continue;
600                            }
601    
602                            x = x + s.length();
603    
604                            String substring = match.substring(x).trim();
605    
606                            String quote = StringPool.BLANK;
607    
608                            if (substring.startsWith(StringPool.APOSTROPHE)) {
609                                    quote = StringPool.APOSTROPHE;
610                            }
611                            else if (substring.startsWith(StringPool.QUOTE)) {
612                                    quote = StringPool.QUOTE;
613                            }
614                            else {
615                                    continue;
616                            }
617    
618                            int y = match.indexOf(quote, x);
619                            int z = match.indexOf(quote, y + 1);
620    
621                            if ((y == -1) || (z == -1)) {
622                                    continue;
623                            }
624    
625                            String prefix = match.substring(0, y + 1);
626                            String suffix = match.substring(z);
627                            String oldKey = match.substring(y + 1, z);
628    
629                            boolean alphaNumericKey = true;
630    
631                            for (char c : oldKey.toCharArray()) {
632                                    if (!Validator.isChar(c) && !Validator.isDigit(c) &&
633                                            (c != CharPool.DASH) && (c != CharPool.UNDERLINE)) {
634    
635                                            alphaNumericKey = false;
636                                    }
637                            }
638    
639                            if (!alphaNumericKey) {
640                                    continue;
641                            }
642    
643                            String newKey = TextFormatter.format(oldKey, TextFormatter.O);
644    
645                            newKey = TextFormatter.format(newKey, TextFormatter.M);
646    
647                            if (newKey.equals(oldKey)) {
648                                    continue;
649                            }
650    
651                            String oldSub = prefix.concat(oldKey).concat(suffix);
652                            String newSub = prefix.concat(newKey).concat(suffix);
653    
654                            newContent = StringUtil.replaceFirst(newContent, oldSub, newSub);
655                    }
656                    while (matcher.find());
657    
658                    return newContent;
659            }
660    
661            protected abstract void format() throws Exception;
662    
663            protected String format(
664                            File file, String fileName, String absolutePath, String content)
665                    throws Exception {
666    
667                    _errorMessagesMap.remove(fileName);
668    
669                    String newContent = doFormat(file, fileName, absolutePath, content);
670    
671                    newContent = StringUtil.replace(
672                            newContent, StringPool.RETURN, StringPool.BLANK);
673    
674                    if (content.equals(newContent)) {
675                            return content;
676                    }
677    
678                    return format(file, fileName, absolutePath, newContent);
679            }
680    
681            protected String format(String fileName) throws Exception {
682                    File file = new File(BASEDIR + fileName);
683    
684                    fileName = StringUtil.replace(
685                            fileName, StringPool.BACK_SLASH, StringPool.SLASH);
686    
687                    String absolutePath = getAbsolutePath(file);
688    
689                    String content = fileUtil.read(file);
690    
691                    String newContent = format(file, fileName, absolutePath, content);
692    
693                    processFormattedFile(file, fileName, content, newContent);
694    
695                    return newContent;
696            }
697    
698            protected String formatJavaTerms(
699                            String javaClassName, String packagePath, File file,
700                            String fileName, String absolutePath, String content,
701                            String javaClassContent, int javaClassLineCount,
702                            List<String> checkJavaFieldTypesExclusions,
703                            List<String> javaTermAccessLevelModifierExclusions,
704                            List<String> javaTermSortExclusions,
705                            List<String> testAnnotationsExclusions)
706                    throws Exception {
707    
708                    JavaClass javaClass = new JavaClass(
709                            javaClassName, packagePath, file, fileName, absolutePath,
710                            javaClassContent, javaClassLineCount, StringPool.TAB, null,
711                            javaTermAccessLevelModifierExclusions);
712    
713                    String newJavaClassContent = javaClass.formatJavaTerms(
714                            getAnnotationsExclusions(), getImmutableFieldTypes(),
715                            checkJavaFieldTypesExclusions, javaTermSortExclusions,
716                            testAnnotationsExclusions);
717    
718                    if (!javaClassContent.equals(newJavaClassContent)) {
719                            return StringUtil.replaceFirst(
720                                    content, javaClassContent, newJavaClassContent);
721                    }
722    
723                    return content;
724            }
725    
726            protected String formatTagAttributeType(
727                            String line, String tag, String attributeAndValue)
728                    throws Exception {
729    
730                    return line;
731            }
732    
733            protected String getAbsolutePath(File file) {
734                    String absolutePath = fileUtil.getAbsolutePath(file);
735    
736                    return StringUtil.replace(absolutePath, "/./", StringPool.SLASH);
737            }
738    
739            protected Set<String> getAnnotationsExclusions() {
740                    if (_annotationsExclusions != null) {
741                            return _annotationsExclusions;
742                    }
743    
744                    _annotationsExclusions = SetUtil.fromArray(
745                            new String[] {
746                                    "ArquillianResource", "BeanReference", "Inject", "Mock",
747                                    "SuppressWarnings"
748                            });
749    
750                    return _annotationsExclusions;
751            }
752    
753            protected Map<String, String> getCompatClassNamesMap() throws IOException {
754                    if (_compatClassNamesMap != null) {
755                            return _compatClassNamesMap;
756                    }
757    
758                    Map<String, String> compatClassNamesMap = new HashMap<String, String>();
759    
760                    String[] includes = new String[] {
761                            "**\\portal-compat-shared\\src\\com\\liferay\\compat\\**\\*.java"
762                    };
763    
764                    String basedir = BASEDIR;
765    
766                    List<String> fileNames = new ArrayList<String>();
767    
768                    for (int i = 0; i < 3; i++) {
769                            fileNames = getFileNames(basedir, new String[0], includes);
770    
771                            if (!fileNames.isEmpty()) {
772                                    break;
773                            }
774    
775                            basedir = "../" + basedir;
776                    }
777    
778                    for (String fileName : fileNames) {
779                            if (!fileName.startsWith("shared")) {
780                                    break;
781                            }
782    
783                            File file = new File(basedir + fileName);
784    
785                            String content = fileUtil.read(file);
786    
787                            fileName = StringUtil.replace(
788                                    fileName, StringPool.BACK_SLASH, StringPool.SLASH);
789    
790                            fileName = StringUtil.replace(
791                                    fileName, StringPool.SLASH, StringPool.PERIOD);
792    
793                            int pos = fileName.indexOf("com.");
794    
795                            String compatClassName = fileName.substring(pos);
796    
797                            compatClassName = compatClassName.substring(
798                                    0, compatClassName.length() - 5);
799    
800                            String extendedClassName = StringUtil.replace(
801                                    compatClassName, "compat.", StringPool.BLANK);
802    
803                            if (content.contains("extends " + extendedClassName)) {
804                                    compatClassNamesMap.put(compatClassName, extendedClassName);
805                            }
806                    }
807    
808                    _compatClassNamesMap = compatClassNamesMap;
809    
810                    return _compatClassNamesMap;
811            }
812    
813            protected String getContent(String fileName, int level) throws IOException {
814                    File file = getFile(fileName, level);
815    
816                    if (file != null) {
817                            String content = fileUtil.read(file);
818    
819                            if (Validator.isNotNull(content)) {
820                                    return content;
821                            }
822                    }
823    
824                    return StringPool.BLANK;
825            }
826    
827            protected String getCustomCopyright(String absolutePath)
828                    throws IOException {
829    
830                    for (int x = absolutePath.length();;) {
831                            x = absolutePath.lastIndexOf(StringPool.SLASH, x);
832    
833                            if (x == -1) {
834                                    break;
835                            }
836    
837                            String copyright = fileUtil.read(
838                                    absolutePath.substring(0, x + 1) + "copyright.txt");
839    
840                            if (Validator.isNotNull(copyright)) {
841                                    return copyright;
842                            }
843    
844                            x = x - 1;
845                    }
846    
847                    return null;
848            }
849    
850            protected File getFile(String fileName, int level) {
851                    for (int i = 0; i < level; i++) {
852                            if (fileUtil.exists(fileName)) {
853                                    return new File(fileName);
854                            }
855    
856                            fileName = "../" + fileName;
857                    }
858    
859                    return null;
860            }
861    
862            protected List<String> getFileNames(
863                    String basedir, String[] excludes, String[] includes) {
864    
865                    DirectoryScanner directoryScanner = new DirectoryScanner();
866    
867                    directoryScanner.setBasedir(basedir);
868    
869                    if (_excludes != null) {
870                            excludes = ArrayUtil.append(excludes, _excludes);
871                    }
872    
873                    directoryScanner.setExcludes(excludes);
874    
875                    directoryScanner.setIncludes(includes);
876    
877                    return sourceFormatterHelper.scanForFiles(directoryScanner);
878            }
879    
880            protected List<String> getFileNames(String[] excludes, String[] includes) {
881                    return getFileNames(BASEDIR, excludes, includes);
882            }
883    
884            protected Set<String> getImmutableFieldTypes() {
885                    if (_immutableFieldTypes != null) {
886                            return _immutableFieldTypes;
887                    }
888    
889                    Set<String> immutableFieldTypes = SetUtil.fromArray(
890                            new String[] {
891                                    "boolean", "byte", "char", "double", "float", "int", "long",
892                                    "short", "Boolean", "Byte", "Character", "Class", "Double",
893                                    "Float", "Int", "Long", "Number", "Short", "String",
894                            });
895    
896                    immutableFieldTypes.addAll(getPropertyList("immutable.field.types"));
897    
898                    _immutableFieldTypes = immutableFieldTypes;
899    
900                    return _immutableFieldTypes;
901            }
902    
903            protected String[] getLanguageKeys(Matcher matcher) {
904                    int groupCount = matcher.groupCount();
905    
906                    if (groupCount == 1) {
907                            String languageKey = matcher.group(1);
908    
909                            if (Validator.isNotNull(languageKey)) {
910                                    return new String[] {languageKey};
911                            }
912                    }
913                    else if (groupCount == 2) {
914                            String languageKey = matcher.group(2);
915    
916                            languageKey = TextFormatter.format(languageKey, TextFormatter.P);
917    
918                            return new String[] {languageKey};
919                    }
920    
921                    StringBundler sb = new StringBundler();
922    
923                    String match = matcher.group();
924    
925                    int count = 0;
926    
927                    for (int i = 0; i < match.length(); i++) {
928                            char c = match.charAt(i);
929    
930                            switch (c) {
931                                    case CharPool.CLOSE_PARENTHESIS:
932                                            if (count <= 1) {
933                                                    return new String[0];
934                                            }
935    
936                                            count--;
937    
938                                            break;
939    
940                                    case CharPool.OPEN_PARENTHESIS:
941                                            count++;
942    
943                                            break;
944    
945                                    case CharPool.QUOTE:
946                                            if (count > 1) {
947                                                    break;
948                                            }
949    
950                                            while (i < match.length()) {
951                                                    i++;
952    
953                                                    if (match.charAt(i) == CharPool.QUOTE) {
954                                                            String languageKey = sb.toString();
955    
956                                                            if (match.startsWith("names")) {
957                                                                    return StringUtil.split(languageKey);
958                                                            }
959                                                            else {
960                                                                    return new String[] {languageKey};
961                                                            }
962                                                    }
963    
964                                                    sb.append(match.charAt(i));
965                                            }
966                            }
967                    }
968    
969                    return new String[0];
970            }
971    
972            protected Properties getLanguageProperties(String fileName) {
973                    StringBundler sb = new StringBundler(4);
974    
975                    int pos = fileName.indexOf("/docroot/");
976    
977                    sb.append(BASEDIR);
978    
979                    if (pos != -1) {
980                            sb.append(fileName.substring(0, pos + 9));
981                            sb.append("WEB-INF/src/");
982                    }
983                    else {
984                            pos = fileName.indexOf("/src/");
985    
986                            if (pos == -1) {
987                                    return null;
988                            }
989    
990                            sb.append(fileName.substring(0, pos + 5));
991                    }
992    
993                    sb.append("content/Language.properties");
994    
995                    try {
996                            Properties properties = new Properties();
997    
998                            InputStream inputStream = new FileInputStream(sb.toString());
999    
1000                            properties.load(inputStream);
1001    
1002                            return properties;
1003                    }
1004                    catch (Exception e) {
1005                    }
1006    
1007                    return null;
1008            }
1009    
1010            protected String getMainReleaseVersion() {
1011                    if (_mainReleaseVersion != null) {
1012                            return _mainReleaseVersion;
1013                    }
1014    
1015                    String releaseVersion = ReleaseInfo.getVersion();
1016    
1017                    int pos = releaseVersion.lastIndexOf(StringPool.PERIOD);
1018    
1019                    _mainReleaseVersion = releaseVersion.substring(0, pos) + ".0";
1020    
1021                    return _mainReleaseVersion;
1022            }
1023    
1024            protected String getProperty(String key) {
1025                    return _properties.getProperty(key);
1026            }
1027    
1028            protected List<String> getPropertyList(String key) {
1029                    return ListUtil.fromString(
1030                            GetterUtil.getString(getProperty(key)), StringPool.COMMA);
1031            }
1032    
1033            protected boolean hasMissingParentheses(String s) {
1034                    if (Validator.isNull(s)) {
1035                            return false;
1036                    }
1037    
1038                    boolean containsAndOperator = s.contains("&&");
1039                    boolean containsOrOperator = s.contains("||");
1040    
1041                    if (containsAndOperator && containsOrOperator) {
1042                            return true;
1043                    }
1044    
1045                    boolean containsCompareOperator =
1046                            (s.contains(" == ") || s.contains(" != ") || s.contains(" < ") ||
1047                             s.contains(" > ") || s.contains(" =< ") || s.contains(" => ") ||
1048                             s.contains(" <= ") || s.contains(" >= "));
1049                    boolean containsMathOperator =
1050                            (s.contains(" = ") || s.contains(" - ") || s.contains(" + ") ||
1051                             s.contains(" & ") || s.contains(" % ") || s.contains(" * ") ||
1052                             s.contains(" / "));
1053    
1054                    if (containsCompareOperator &&
1055                            (containsAndOperator || containsOrOperator ||
1056                             (containsMathOperator && !s.contains(StringPool.OPEN_BRACKET)))) {
1057    
1058                            return true;
1059                    }
1060    
1061                    return false;
1062            }
1063    
1064            protected boolean hasRedundantParentheses(String s) {
1065                    if (!s.contains("&&") && !s.contains("||")) {
1066                            for (int x = 0;;) {
1067                                    x = s.indexOf(StringPool.CLOSE_PARENTHESIS);
1068    
1069                                    if (x == -1) {
1070                                            break;
1071                                    }
1072    
1073                                    int y = s.substring(0, x).lastIndexOf(
1074                                            StringPool.OPEN_PARENTHESIS);
1075    
1076                                    if (y == -1) {
1077                                            break;
1078                                    }
1079    
1080                                    s = s.substring(0, y) + s.substring(x + 1);
1081                            }
1082                    }
1083    
1084                    if (Validator.isNotNull(s) && !s.contains(StringPool.SPACE)) {
1085                            return true;
1086                    }
1087                    else {
1088                            return false;
1089                    }
1090            }
1091    
1092            protected boolean hasRedundantParentheses(
1093                    String s, String operator1, String operator2) {
1094    
1095                    String[] parts = StringUtil.split(s, operator1);
1096    
1097                    if (parts.length < 3) {
1098                            return false;
1099                    }
1100    
1101                    for (int i = 1; i < (parts.length - 1); i++) {
1102                            String part = parts[i];
1103    
1104                            if (part.contains(operator2) || part.contains("!(")) {
1105                                    continue;
1106                            }
1107    
1108                            int closeParenthesesCount = StringUtil.count(
1109                                    part, StringPool.CLOSE_PARENTHESIS);
1110                            int openParenthesesCount = StringUtil.count(
1111                                    part, StringPool.OPEN_PARENTHESIS);
1112    
1113                            if (Math.abs(closeParenthesesCount - openParenthesesCount) == 1) {
1114                                    return true;
1115                            }
1116                    }
1117    
1118                    return false;
1119            }
1120    
1121            protected boolean isAttributName(String attributeName) {
1122                    if (Validator.isNull(attributeName)) {
1123                            return false;
1124                    }
1125    
1126                    Matcher matcher = attributeNamePattern.matcher(attributeName);
1127    
1128                    return matcher.matches();
1129            }
1130    
1131            protected boolean isRunsOutsidePortal(String absolutePath) {
1132                    if (_runOutsidePortalExclusions == null) {
1133                            _runOutsidePortalExclusions = getPropertyList(
1134                                    "run.outside.portal.excludes");
1135                    }
1136    
1137                    for (String runOutsidePortalExclusions : _runOutsidePortalExclusions) {
1138                            if (absolutePath.contains(runOutsidePortalExclusions)) {
1139                                    return true;
1140                            }
1141                    }
1142    
1143                    return false;
1144            }
1145    
1146            protected void processFormattedFile(
1147                            File file, String fileName, String content, String newContent)
1148                    throws IOException {
1149    
1150                    if (_printErrors) {
1151                            List<String> errorMessages = _errorMessagesMap.get(fileName);
1152    
1153                            if (errorMessages != null) {
1154                                    for (String errorMessage : errorMessages) {
1155                                            sourceFormatterHelper.printError(fileName, errorMessage);
1156                                    }
1157                            }
1158                    }
1159    
1160                    if (content.equals(newContent)) {
1161                            return;
1162                    }
1163    
1164                    if (_autoFix) {
1165                            fileUtil.write(file, newContent);
1166                    }
1167                    else if (_firstSourceMismatchException == null) {
1168                            _firstSourceMismatchException = new SourceMismatchException(
1169                                    fileName, content, newContent);
1170                    }
1171    
1172                    if (_printErrors) {
1173                            sourceFormatterHelper.printError(fileName, file);
1174                    }
1175            }
1176    
1177            protected String replacePrimitiveWrapperInstantiation(
1178                    String fileName, String line, int lineCount) {
1179    
1180                    if (true) {
1181                            return line;
1182                    }
1183    
1184                    String newLine = StringUtil.replace(
1185                            line,
1186                            new String[] {
1187                                    "new Boolean(", "new Byte(", "new Character(", "new Integer(",
1188                                    "new Long(", "new Short("
1189                            },
1190                            new String[] {
1191                                    "Boolean.valueOf(", "Byte.valueOf(", "Character.valueOf(",
1192                                    "Integer.valueOf(", "Long.valueOf(", "Short.valueOf("
1193                            });
1194    
1195                    if (!line.equals(newLine)) {
1196                            processErrorMessage(
1197                                    fileName, "> new Primitive(: " + fileName + " " + lineCount);
1198                    }
1199    
1200                    return newLine;
1201            }
1202    
1203            protected String sortAttributes(
1204                            String fileName, String line, int lineCount,
1205                            boolean allowApostropheDelimeter)
1206                    throws Exception {
1207    
1208                    String s = line;
1209    
1210                    int x = s.indexOf(StringPool.LESS_THAN);
1211                    int y = s.indexOf(StringPool.SPACE);
1212    
1213                    if ((x == -1) || (x >= y)) {
1214                            return line;
1215                    }
1216    
1217                    String tag = s.substring(x + 1, y);
1218    
1219                    s = s.substring(y + 1);
1220    
1221                    String previousAttribute = null;
1222                    String previousAttributeAndValue = null;
1223    
1224                    boolean wrongOrder = false;
1225    
1226                    for (x = 0;;) {
1227                            x = s.indexOf(StringPool.EQUAL);
1228    
1229                            if ((x == -1) || (s.length() <= (x + 1))) {
1230                                    return line;
1231                            }
1232    
1233                            String attribute = s.substring(0, x);
1234    
1235                            if (!isAttributName(attribute)) {
1236                                    return line;
1237                            }
1238    
1239                            if (Validator.isNotNull(previousAttribute) &&
1240                                    (previousAttribute.compareTo(attribute) > 0)) {
1241    
1242                                    wrongOrder = true;
1243                            }
1244    
1245                            s = s.substring(x + 1);
1246    
1247                            char delimeter = s.charAt(0);
1248    
1249                            if ((delimeter != CharPool.APOSTROPHE) &&
1250                                    (delimeter != CharPool.QUOTE)) {
1251    
1252                                    if (delimeter != CharPool.AMPERSAND) {
1253                                            processErrorMessage(
1254                                                    fileName, "delimeter: " + fileName + " " + lineCount);
1255                                    }
1256    
1257                                    return line;
1258                            }
1259    
1260                            s = s.substring(1);
1261    
1262                            String value = null;
1263    
1264                            y = -1;
1265    
1266                            while (true) {
1267                                    y = s.indexOf(delimeter, y + 1);
1268    
1269                                    if ((y == -1) || (s.length() <= (y + 1))) {
1270                                            return line;
1271                                    }
1272    
1273                                    value = s.substring(0, y);
1274    
1275                                    if (value.startsWith("<%")) {
1276                                            int endJavaCodeSignCount = StringUtil.count(value, "%>");
1277                                            int startJavaCodeSignCount = StringUtil.count(value, "<%");
1278    
1279                                            if (endJavaCodeSignCount == startJavaCodeSignCount) {
1280                                                    break;
1281                                            }
1282                                    }
1283                                    else {
1284                                            int greaterThanCount = StringUtil.count(
1285                                                    value, StringPool.GREATER_THAN);
1286                                            int lessThanCount = StringUtil.count(
1287                                                    value, StringPool.LESS_THAN);
1288    
1289                                            if (greaterThanCount == lessThanCount) {
1290                                                    break;
1291                                            }
1292                                    }
1293                            }
1294    
1295                            if (delimeter == CharPool.APOSTROPHE) {
1296                                    if (!value.contains(StringPool.QUOTE)) {
1297                                            line = StringUtil.replace(
1298                                                    line,
1299                                                    StringPool.APOSTROPHE + value + StringPool.APOSTROPHE,
1300                                                    StringPool.QUOTE + value + StringPool.QUOTE);
1301    
1302                                            return sortAttributes(
1303                                                    fileName, line, lineCount, allowApostropheDelimeter);
1304                                    }
1305                                    else if (!allowApostropheDelimeter) {
1306                                            String newValue = StringUtil.replace(
1307                                                    value, StringPool.QUOTE, "&quot;");
1308    
1309                                            line = StringUtil.replace(
1310                                                    line,
1311                                                    StringPool.APOSTROPHE + value + StringPool.APOSTROPHE,
1312                                                    StringPool.QUOTE + newValue + StringPool.QUOTE);
1313    
1314                                            return sortAttributes(
1315                                                    fileName, line, lineCount, allowApostropheDelimeter);
1316                                    }
1317                            }
1318    
1319                            StringBundler sb = new StringBundler(5);
1320    
1321                            sb.append(attribute);
1322                            sb.append(StringPool.EQUAL);
1323                            sb.append(delimeter);
1324                            sb.append(value);
1325                            sb.append(delimeter);
1326    
1327                            String currentAttributeAndValue = sb.toString();
1328    
1329                            String newLine = formatTagAttributeType(
1330                                    line, tag, currentAttributeAndValue);
1331    
1332                            if (!newLine.equals(line)) {
1333                                    return sortAttributes(
1334                                            fileName, newLine, lineCount, allowApostropheDelimeter);
1335                            }
1336    
1337                            if (wrongOrder) {
1338                                    if ((StringUtil.count(line, currentAttributeAndValue) == 1) &&
1339                                            (StringUtil.count(line, previousAttributeAndValue) == 1)) {
1340    
1341                                            line = StringUtil.replaceFirst(
1342                                                    line, previousAttributeAndValue,
1343                                                    currentAttributeAndValue);
1344    
1345                                            line = StringUtil.replaceLast(
1346                                                    line, currentAttributeAndValue,
1347                                                    previousAttributeAndValue);
1348    
1349                                            return sortAttributes(
1350                                                    fileName, line, lineCount, allowApostropheDelimeter);
1351                                    }
1352    
1353                                    return line;
1354                            }
1355    
1356                            s = s.substring(y + 1);
1357    
1358                            if (s.startsWith(StringPool.GREATER_THAN)) {
1359                                    x = s.indexOf(StringPool.SPACE);
1360    
1361                                    if (x == -1) {
1362                                            return line;
1363                                    }
1364    
1365                                    s = s.substring(x + 1);
1366    
1367                                    previousAttribute = null;
1368                                    previousAttributeAndValue = null;
1369                            }
1370                            else {
1371                                    s = StringUtil.trimLeading(s);
1372    
1373                                    previousAttribute = attribute;
1374                                    previousAttributeAndValue = currentAttributeAndValue;
1375                            }
1376                    }
1377            }
1378    
1379            protected String stripLine(
1380                    String s, char startDelimeter, char endDelimeter) {
1381    
1382                    boolean insideDelimeters = false;
1383                    int level = 0;
1384    
1385                    StringBundler sb = new StringBundler();
1386    
1387                    for (int i = 0; i < s.length(); i++) {
1388                            char c = s.charAt(i);
1389    
1390                            if (insideDelimeters) {
1391                                    if (c == endDelimeter) {
1392                                            if (level > 0) {
1393                                                    level -= 1;
1394                                            }
1395                                            else {
1396                                                    if ((c > 1) &&
1397                                                            (s.charAt(i - 1) == CharPool.BACK_SLASH) &&
1398                                                            (s.charAt(i - 2) != CharPool.BACK_SLASH)) {
1399    
1400                                                            continue;
1401                                                    }
1402    
1403                                                    insideDelimeters = false;
1404                                            }
1405                                    }
1406                                    else if (c == startDelimeter) {
1407                                            level += 1;
1408                                    }
1409                            }
1410                            else if (c == startDelimeter) {
1411                                    insideDelimeters = true;
1412                            }
1413                            else {
1414                                    sb.append(c);
1415                            }
1416                    }
1417    
1418                    return sb.toString();
1419            }
1420    
1421            protected String stripQuotes(String s, char delimeter) {
1422                    return stripLine(s, delimeter, delimeter);
1423            }
1424    
1425            protected String stripRedundantParentheses(String s) {
1426                    for (int x = 0;;) {
1427                            x = s.indexOf(StringPool.OPEN_PARENTHESIS, x + 1);
1428                            int y = s.indexOf(StringPool.CLOSE_PARENTHESIS, x);
1429    
1430                            if ((x == -1) || (y == -1)) {
1431                                    return s;
1432                            }
1433    
1434                            String linePart = s.substring(x + 1, y);
1435    
1436                            linePart = StringUtil.replace(
1437                                    linePart, StringPool.COMMA, StringPool.BLANK);
1438    
1439                            if (Validator.isAlphanumericName(linePart) ||
1440                                    Validator.isNull(linePart)) {
1441    
1442                                    s = s.substring(0, x) + s.substring(y + 1);
1443                            }
1444                    }
1445            }
1446    
1447            protected String trimContent(String content, boolean allowLeadingSpaces)
1448                    throws IOException {
1449    
1450                    StringBundler sb = new StringBundler();
1451    
1452                    try (UnsyncBufferedReader unsyncBufferedReader =
1453                                    new UnsyncBufferedReader(new UnsyncStringReader(content))) {
1454    
1455                            String line = null;
1456    
1457                            while ((line = unsyncBufferedReader.readLine()) != null) {
1458                                    sb.append(trimLine(line, allowLeadingSpaces));
1459                                    sb.append("\n");
1460                            }
1461                    }
1462    
1463                    content = sb.toString();
1464    
1465                    if (content.endsWith("\n")) {
1466                            content = content.substring(0, content.length() - 1);
1467                    }
1468    
1469                    return content;
1470            }
1471    
1472            protected String trimLine(String line, boolean allowLeadingSpaces) {
1473                    if (line.trim().length() == 0) {
1474                            return StringPool.BLANK;
1475                    }
1476    
1477                    line = StringUtil.trimTrailing(line);
1478    
1479                    if (allowLeadingSpaces || !line.startsWith(StringPool.SPACE) ||
1480                            line.startsWith(" *")) {
1481    
1482                            return line;
1483                    }
1484    
1485                    if (!line.startsWith(StringPool.FOUR_SPACES)) {
1486                            while (line.startsWith(StringPool.SPACE)) {
1487                                    line = StringUtil.replaceFirst(
1488                                            line, StringPool.SPACE, StringPool.BLANK);
1489                            }
1490                    }
1491                    else {
1492                            int pos = 0;
1493    
1494                            String temp = line;
1495    
1496                            while (temp.startsWith(StringPool.FOUR_SPACES)) {
1497                                    line = StringUtil.replaceFirst(
1498                                            line, StringPool.FOUR_SPACES, StringPool.TAB);
1499    
1500                                    pos++;
1501    
1502                                    temp = line.substring(pos);
1503                            }
1504                    }
1505    
1506                    return line;
1507            }
1508    
1509            protected static final String BASEDIR = "./";
1510    
1511            protected static Pattern attributeNamePattern = Pattern.compile(
1512                    "[a-z]+[-_a-zA-Z0-9]*");
1513            protected static Pattern emptyCollectionPattern = Pattern.compile(
1514                    "Collections\\.EMPTY_(LIST|MAP|SET)");
1515            protected static FileImpl fileUtil = FileImpl.getInstance();
1516            protected static Pattern languageKeyPattern = Pattern.compile(
1517                    "LanguageUtil.(?:get|format)\\([^;%]+|Liferay.Language.get\\('([^']+)");
1518            protected static boolean portalSource;
1519            protected static SAXReaderImpl saxReaderUtil = SAXReaderImpl.getInstance();
1520            protected static Pattern sessionKeyPattern = Pattern.compile(
1521                    "SessionErrors.(?:add|contains|get)\\([^;%&|!]+|".concat(
1522                            "SessionMessages.(?:add|contains|get)\\([^;%&|!]+"),
1523                    Pattern.MULTILINE);
1524            protected static SourceFormatterHelper sourceFormatterHelper;
1525            protected static Pattern taglibSessionKeyPattern = Pattern.compile(
1526                    "<liferay-ui:error [^>]+>|<liferay-ui:success [^>]+>",
1527                    Pattern.MULTILINE);
1528    
1529            private String[] _getExcludes() {
1530                    List<String> excludesList = ListUtil.fromString(
1531                            GetterUtil.getString(
1532                                    System.getProperty("source.formatter.excludes")));
1533    
1534                    excludesList.addAll(getPropertyList("source.formatter.excludes"));
1535    
1536                    String[] includes = new String[] {"**\\source_formatter.ignore"};
1537    
1538                    List<String> ignoreFileNames = getFileNames(new String[0], includes);
1539    
1540                    for (String ignoreFileName : ignoreFileNames) {
1541                            excludesList.add(
1542                                    ignoreFileName.substring(0, ignoreFileName.length() - 23) +
1543                                            "**");
1544                    }
1545    
1546                    return excludesList.toArray(new String[excludesList.size()]);
1547            }
1548    
1549            private Properties _getProperties() throws Exception {
1550                    String fileName = "source-formatter.properties";
1551    
1552                    Properties properties = new Properties();
1553    
1554                    List<Properties> propertiesList = new ArrayList<Properties>();
1555    
1556                    int level = 2;
1557    
1558                    if (portalSource) {
1559                            level = 3;
1560                    }
1561    
1562                    for (int i = 0; i <= level; i++) {
1563                            try {
1564                                    InputStream inputStream = new FileInputStream(fileName);
1565    
1566                                    Properties props = new Properties();
1567    
1568                                    props.load(inputStream);
1569    
1570                                    propertiesList.add(props);
1571                            }
1572                            catch (FileNotFoundException fnfe) {
1573                            }
1574    
1575                            fileName = "../" + fileName;
1576                    }
1577    
1578                    if (propertiesList.isEmpty()) {
1579                            return properties;
1580                    }
1581    
1582                    properties = propertiesList.get(0);
1583    
1584                    if (propertiesList.size() == 1) {
1585                            return properties;
1586                    }
1587    
1588                    for (int i = 1; i < propertiesList.size(); i++) {
1589                            Properties props = propertiesList.get(i);
1590    
1591                            Enumeration<String> enu =
1592                                    (Enumeration<String>)props.propertyNames();
1593    
1594                            while (enu.hasMoreElements()) {
1595                                    String key = enu.nextElement();
1596    
1597                                    String value = props.getProperty(key);
1598    
1599                                    if (Validator.isNull(value)) {
1600                                            continue;
1601                                    }
1602    
1603                                    if (key.contains("excludes")) {
1604                                            String existingValue = properties.getProperty(key);
1605    
1606                                            if (Validator.isNotNull(existingValue)) {
1607                                                    value = existingValue + StringPool.COMMA + value;
1608                                            }
1609    
1610                                            properties.put(key, value);
1611                                    }
1612                                    else if (!properties.containsKey(key)) {
1613                                            properties.put(key, value);
1614                                    }
1615                            }
1616                    }
1617    
1618                    return properties;
1619            }
1620    
1621            private void _init(
1622                            boolean useProperties, boolean printErrors, boolean autoFix)
1623                    throws Exception {
1624    
1625                    _errorMessagesMap = new HashMap<String, List<String>>();
1626    
1627                    sourceFormatterHelper = new SourceFormatterHelper(useProperties);
1628    
1629                    sourceFormatterHelper.init();
1630    
1631                    _autoFix = autoFix;
1632    
1633                    _excludes = _getExcludes();
1634    
1635                    _printErrors = printErrors;
1636    
1637                    _usePortalCompatImport = GetterUtil.getBoolean(
1638                            getProperty("use.portal.compat.import"));
1639            }
1640    
1641            private boolean _isPortalSource() {
1642                    if (getFile("portal-impl", 4) != null) {
1643                            return true;
1644                    }
1645                    else {
1646                            return false;
1647                    }
1648            }
1649    
1650            private static Map<String, List<String>> _errorMessagesMap =
1651                    new HashMap<String, List<String>>();
1652            private static boolean _printErrors;
1653    
1654            private Set<String> _annotationsExclusions;
1655            private boolean _autoFix;
1656            private Map<String, String> _compatClassNamesMap;
1657            private String _copyright;
1658            private String[] _excludes;
1659            private SourceMismatchException _firstSourceMismatchException;
1660            private Set<String> _immutableFieldTypes;
1661            private String _mainReleaseVersion;
1662            private String _oldCopyright;
1663            private Properties _portalLanguageProperties;
1664            private Properties _properties;
1665            private List<String> _runOutsidePortalExclusions;
1666            private boolean _usePortalCompatImport;
1667    
1668    }