Java tutorial
/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.tools.sourceformatter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.tools.ant.DirectoryScanner; import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader; import com.liferay.portal.kernel.io.unsync.UnsyncStringReader; import com.liferay.portal.kernel.util.ArrayUtil; import com.liferay.portal.kernel.util.CharPool; import com.liferay.portal.kernel.util.GetterUtil; import com.liferay.portal.kernel.util.ListUtil; import com.liferay.portal.kernel.util.ReflectionUtil; import com.liferay.portal.kernel.util.ReleaseInfo; import com.liferay.portal.kernel.util.SetUtil; import com.liferay.portal.kernel.util.StringBundler; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.kernel.util.TextFormatter; import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.util.FileImpl; import com.liferay.portal.xml.SAXReaderImpl; /** * @author Brian Wing Shun Chan * @author Igor Spasic * @author Wesley Gong * @author Hugo Huijser */ public abstract class BaseSourceProcessor implements SourceProcessor { public BaseSourceProcessor() { portalSource = _isPortalSource(); try { _properties = _getProperties(); } catch (Exception e) { ReflectionUtil.throwException(e); } } @Override public void format(boolean useProperties, boolean printErrors, boolean autoFix) throws Exception { _init(useProperties, printErrors, autoFix); format(); sourceFormatterHelper.close(); } @Override public String format(String fileName, boolean useProperties, boolean printErrors, boolean autoFix) throws Exception { try { _init(useProperties, printErrors, autoFix); return format(fileName); } finally { sourceFormatterHelper.close(); } } @Override public List<String> getErrorMessages() { List<String> errorMessages = new ArrayList<String>(); for (Map.Entry<String, List<String>> entry : _errorMessagesMap.entrySet()) { errorMessages.addAll(entry.getValue()); } return errorMessages; } @Override public SourceMismatchException getFirstSourceMismatchException() { return _firstSourceMismatchException; } protected static boolean isExcluded(List<String> exclusions, String absolutePath) { return isExcluded(exclusions, absolutePath, -1); } protected static boolean isExcluded(List<String> exclusions, String absolutePath, int lineCount) { return isExcluded(exclusions, absolutePath, lineCount, null); } protected static boolean isExcluded(List<String> exclusions, String absolutePath, int lineCount, String javaTermName) { if (ListUtil.isEmpty(exclusions)) { return false; } String absolutePathWithJavaTermName = null; if (Validator.isNotNull(javaTermName)) { absolutePathWithJavaTermName = absolutePath + StringPool.AT + javaTermName; } String absolutePathWithLineCount = null; if (lineCount > 0) { absolutePathWithLineCount = absolutePath + StringPool.AT + lineCount; } for (String exclusion : exclusions) { if (absolutePath.endsWith(exclusion) || ((absolutePathWithJavaTermName != null) && absolutePathWithJavaTermName.endsWith(exclusion)) || ((absolutePathWithLineCount != null) && absolutePathWithLineCount.endsWith(exclusion))) { return true; } } return false; } protected static void processErrorMessage(String fileName, String message) { List<String> errorMessages = _errorMessagesMap.get(fileName); if (errorMessages == null) { errorMessages = new ArrayList<String>(); } errorMessages.add(message); _errorMessagesMap.put(fileName, errorMessages); } protected void checkEmptyCollection(String line, String fileName, int lineCount) { // LPS-46028 Matcher matcher = emptyCollectionPattern.matcher(line); if (matcher.find()) { String collectionType = TextFormatter.format(matcher.group(1), TextFormatter.J); processErrorMessage(fileName, "Use Collections.empty" + collectionType + "(): " + fileName + " " + lineCount); } } protected void checkIfClauseParentheses(String ifClause, String fileName, int lineCount) { int quoteCount = StringUtil.count(ifClause, StringPool.QUOTE); if ((quoteCount % 2) == 1) { return; } ifClause = stripQuotes(ifClause, CharPool.QUOTE); ifClause = stripQuotes(ifClause, CharPool.APOSTROPHE); if (ifClause.contains(StringPool.DOUBLE_SLASH) || ifClause.contains("/*") || ifClause.contains("*/")) { return; } if (hasRedundantParentheses(ifClause, "||", "&&") || hasRedundantParentheses(ifClause, "&&", "||")) { processErrorMessage(fileName, "redundant parentheses: " + fileName + " " + lineCount); } ifClause = stripRedundantParentheses(ifClause); int level = 0; int max = StringUtil.count(ifClause, StringPool.OPEN_PARENTHESIS); int previousParenthesisPos = -1; int[] levels = new int[max]; for (int i = 0; i < ifClause.length(); i++) { char c = ifClause.charAt(i); if ((c == CharPool.OPEN_PARENTHESIS) || (c == CharPool.CLOSE_PARENTHESIS)) { if (previousParenthesisPos != -1) { String s = ifClause.substring(previousParenthesisPos + 1, i); if (hasMissingParentheses(s)) { processErrorMessage(fileName, "missing parentheses: " + fileName + " " + lineCount); } } previousParenthesisPos = i; if (c == CharPool.OPEN_PARENTHESIS) { levels[level] = i; level += 1; } else { int posOpenParenthesis = levels[level - 1]; if (level > 1) { char nextChar = ifClause.charAt(i + 1); char previousChar = ifClause.charAt(posOpenParenthesis - 1); if (!Character.isLetterOrDigit(nextChar) && (nextChar != CharPool.PERIOD) && !Character.isLetterOrDigit(previousChar)) { String s = ifClause.substring(posOpenParenthesis + 1, i); if (hasRedundantParentheses(s)) { processErrorMessage(fileName, "redundant parentheses: " + fileName + " " + lineCount); } } if ((previousChar == CharPool.OPEN_PARENTHESIS) && (nextChar == CharPool.CLOSE_PARENTHESIS)) { processErrorMessage(fileName, "redundant parentheses: " + fileName + " " + lineCount); } } level -= 1; } } } } protected void checkInefficientStringMethods(String line, String fileName, String absolutePath, int lineCount) { if (isRunsOutsidePortal(absolutePath) || fileName.endsWith("GetterUtil.java")) { return; } String methodName = "toLowerCase"; int pos = line.indexOf(".toLowerCase()"); if (pos == -1) { methodName = "toUpperCase"; pos = line.indexOf(".toUpperCase()"); } if ((pos == -1) && !line.contains("StringUtil.equalsIgnoreCase(")) { methodName = "equalsIgnoreCase"; pos = line.indexOf(".equalsIgnoreCase("); } if (pos != -1) { processErrorMessage(fileName, "Use StringUtil." + methodName + ": " + fileName + " " + lineCount); } } protected void checkLanguageKeys(String fileName, String content, Pattern pattern) throws IOException { String fileExtension = fileUtil.getExtension(fileName); if (!portalSource || fileExtension.equals("vm")) { return; } if (_portalLanguageProperties == null) { _portalLanguageProperties = new Properties(); ClassLoader classLoader = BaseSourceProcessor.class.getClassLoader(); InputStream inputStream = classLoader.getResourceAsStream("content/Language.properties"); _portalLanguageProperties.load(inputStream); } Matcher matcher = pattern.matcher(content); while (matcher.find()) { String[] languageKeys = getLanguageKeys(matcher); for (String languageKey : languageKeys) { if (Validator.isNumber(languageKey) || languageKey.endsWith(StringPool.DASH) || languageKey.endsWith(StringPool.OPEN_BRACKET) || languageKey.endsWith(StringPool.PERIOD) || languageKey.endsWith(StringPool.UNDERLINE) || languageKey.startsWith(StringPool.DASH) || languageKey.startsWith(StringPool.OPEN_BRACKET) || languageKey.startsWith(StringPool.OPEN_CURLY_BRACE) || languageKey.startsWith(StringPool.PERIOD) || languageKey.startsWith(StringPool.UNDERLINE) || _portalLanguageProperties.containsKey(languageKey)) { continue; } Properties languageProperties = getLanguageProperties(fileName); if ((languageProperties == null) || !languageProperties.containsKey(languageKey)) { processErrorMessage(fileName, "missing language key: " + languageKey + StringPool.SPACE + fileName); } } } } protected void checkStringBundler(String line, String fileName, int lineCount) { if ((!line.startsWith("sb.append(") && !line.contains("SB.append(")) || !line.endsWith(");")) { return; } int pos = line.indexOf(".append("); line = line.substring(pos + 8, line.length() - 2); line = stripQuotes(line, CharPool.QUOTE); if (!line.contains(" + ")) { return; } String[] lineParts = StringUtil.split(line, " + "); for (String linePart : lineParts) { int closeParenthesesCount = StringUtil.count(linePart, StringPool.CLOSE_PARENTHESIS); int openParenthesesCount = StringUtil.count(linePart, StringPool.OPEN_PARENTHESIS); if (closeParenthesesCount != openParenthesesCount) { return; } if (Validator.isNumber(linePart)) { return; } } processErrorMessage(fileName, "plus: " + fileName + " " + lineCount); } protected abstract String doFormat(File file, String fileName, String absolutePath, String content) throws Exception; protected String fixCompatClassImports(String absolutePath, String content) throws IOException { if (portalSource || !_usePortalCompatImport || absolutePath.contains("/ext-") || absolutePath.contains("/portal-compat-shared/")) { return content; } Map<String, String> compatClassNamesMap = getCompatClassNamesMap(); String newContent = content; for (Map.Entry<String, String> entry : compatClassNamesMap.entrySet()) { String compatClassName = entry.getKey(); String extendedClassName = entry.getValue(); Pattern pattern = Pattern.compile(extendedClassName + "\\W"); while (true) { Matcher matcher = pattern.matcher(newContent); if (!matcher.find()) { break; } newContent = newContent.substring(0, matcher.start()) + compatClassName + newContent.substring(matcher.end() - 1); } } return newContent; } protected String fixCopyright(String content, String absolutePath, String fileName) throws IOException { if (_copyright == null) { _copyright = getContent("copyright.txt", 4); } String copyright = _copyright; if (fileName.endsWith(".vm") || Validator.isNull(copyright)) { return content; } if (_oldCopyright == null) { _oldCopyright = getContent("old-copyright.txt", 4); } if (Validator.isNotNull(_oldCopyright) && content.contains(_oldCopyright)) { content = StringUtil.replace(content, _oldCopyright, copyright); processErrorMessage(fileName, "old (c): " + fileName); } if (!content.contains(copyright)) { String customCopyright = getCustomCopyright(absolutePath); if (Validator.isNotNull(customCopyright)) { copyright = customCopyright; } if (!content.contains(copyright)) { processErrorMessage(fileName, "(c): " + fileName); } } if (fileName.endsWith(".jsp") || fileName.endsWith(".jspf")) { content = StringUtil.replace(content, "<%\n" + copyright + "\n%>", "<%--\n" + copyright + "\n--%>"); } int x = content.indexOf("* Copyright (c) 2000-"); if (x == -1) { return content; } int y = content.indexOf("Liferay", x); String contentCopyrightYear = content.substring(x, y); x = copyright.indexOf("* Copyright (c) 2000-"); if (x == -1) { return content; } y = copyright.indexOf("Liferay", x); String copyrightYear = copyright.substring(x, y); return StringUtil.replace(content, contentCopyrightYear, copyrightYear); } protected String fixIncorrectParameterTypeForLanguageUtil(String content, boolean autoFix, String fileName) { if (portalSource) { return content; } String expectedParameter = getProperty("languageutil.expected.parameter"); String incorrectParameter = getProperty("languageutil.incorrect.parameter"); if (!content.contains("LanguageUtil.format(" + incorrectParameter + ", ") && !content.contains("LanguageUtil.get(" + incorrectParameter + ", ")) { return content; } if (autoFix) { content = StringUtil.replace(content, new String[] { "LanguageUtil.format(" + incorrectParameter + ", ", "LanguageUtil.get(" + incorrectParameter + ", " }, new String[] { "LanguageUtil.format(" + expectedParameter + ", ", "LanguageUtil.get(" + expectedParameter + ", " }); } else { processErrorMessage(fileName, "(Unicode)LanguageUtil.format/get methods require " + expectedParameter + " parameter instead of " + incorrectParameter + " " + fileName); } return content; } protected String fixSessionKey(String fileName, String content, Pattern pattern) { Matcher matcher = pattern.matcher(content); if (!matcher.find()) { return content; } String newContent = content; do { String match = matcher.group(); String s = null; if (pattern.equals(sessionKeyPattern)) { s = StringPool.COMMA; } else if (pattern.equals(taglibSessionKeyPattern)) { s = "key="; } int x = match.indexOf(s); if (x == -1) { continue; } x = x + s.length(); String substring = match.substring(x).trim(); String quote = StringPool.BLANK; if (substring.startsWith(StringPool.APOSTROPHE)) { quote = StringPool.APOSTROPHE; } else if (substring.startsWith(StringPool.QUOTE)) { quote = StringPool.QUOTE; } else { continue; } int y = match.indexOf(quote, x); int z = match.indexOf(quote, y + 1); if ((y == -1) || (z == -1)) { continue; } String prefix = match.substring(0, y + 1); String suffix = match.substring(z); String oldKey = match.substring(y + 1, z); boolean alphaNumericKey = true; for (char c : oldKey.toCharArray()) { if (!Validator.isChar(c) && !Validator.isDigit(c) && (c != CharPool.DASH) && (c != CharPool.UNDERLINE)) { alphaNumericKey = false; } } if (!alphaNumericKey) { continue; } String newKey = TextFormatter.format(oldKey, TextFormatter.O); newKey = TextFormatter.format(newKey, TextFormatter.M); if (newKey.equals(oldKey)) { continue; } String oldSub = prefix.concat(oldKey).concat(suffix); String newSub = prefix.concat(newKey).concat(suffix); newContent = StringUtil.replaceFirst(newContent, oldSub, newSub); } while (matcher.find()); return newContent; } protected abstract void format() throws Exception; protected String format(File file, String fileName, String absolutePath, String content) throws Exception { _errorMessagesMap.remove(fileName); String newContent = doFormat(file, fileName, absolutePath, content); newContent = StringUtil.replace(newContent, StringPool.RETURN, StringPool.BLANK); if (content.equals(newContent)) { return content; } return format(file, fileName, absolutePath, newContent); } protected String format(String fileName) throws Exception { File file = new File(fileName); if (!file.exists()) { file = new File(BASEDIR + fileName); } fileName = StringUtil.replace(fileName, StringPool.BACK_SLASH, StringPool.SLASH); String absolutePath = getAbsolutePath(file); String content = fileUtil.read(file); String newContent = format(file, fileName, absolutePath, content); processFormattedFile(file, fileName, content, newContent); return newContent; } protected String formatJavaTerms(String javaClassName, String fileName, String absolutePath, String content, String javaClassContent, int javaClassLineCount, List<String> checkJavaFieldTypesExclusions, List<String> javaTermAccessLevelModifierExclusions, List<String> javaTermSortExclusions, List<String> testAnnotationsExclusions) throws Exception { JavaClass javaClass = new JavaClass(javaClassName, fileName, absolutePath, javaClassContent, javaClassLineCount, StringPool.TAB, null, javaTermAccessLevelModifierExclusions); String newJavaClassContent = javaClass.formatJavaTerms(getAnnotationsExclusions(), getImmutableFieldTypes(), checkJavaFieldTypesExclusions, javaTermSortExclusions, testAnnotationsExclusions); if (!javaClassContent.equals(newJavaClassContent)) { return StringUtil.replaceFirst(content, javaClassContent, newJavaClassContent); } return content; } protected String getAbsolutePath(File file) { String absolutePath = fileUtil.getAbsolutePath(file); return StringUtil.replace(absolutePath, "/./", StringPool.SLASH); } protected Set<String> getAnnotationsExclusions() { if (_annotationsExclusions != null) { return _annotationsExclusions; } _annotationsExclusions = SetUtil.fromArray(new String[] { "BeanReference", "Mock", "SuppressWarnings" }); return _annotationsExclusions; } protected Map<String, String> getCompatClassNamesMap() throws IOException { if (_compatClassNamesMap != null) { return _compatClassNamesMap; } Map<String, String> compatClassNamesMap = new HashMap<String, String>(); String[] includes = new String[] { "**\\portal-compat-shared\\src\\com\\liferay\\compat\\**\\*.java" }; String basedir = BASEDIR; List<String> fileNames = new ArrayList<String>(); for (int i = 0; i < 3; i++) { fileNames = getFileNames(basedir, new String[0], includes); if (!fileNames.isEmpty()) { break; } basedir = "../" + basedir; } for (String fileName : fileNames) { if (!fileName.startsWith("shared")) { break; } File file = new File(basedir + fileName); String content = fileUtil.read(file); fileName = StringUtil.replace(fileName, StringPool.BACK_SLASH, StringPool.SLASH); fileName = StringUtil.replace(fileName, StringPool.SLASH, StringPool.PERIOD); int pos = fileName.indexOf("com."); String compatClassName = fileName.substring(pos); compatClassName = compatClassName.substring(0, compatClassName.length() - 5); String extendedClassName = StringUtil.replace(compatClassName, "compat.", StringPool.BLANK); if (content.contains("extends " + extendedClassName)) { compatClassNamesMap.put(compatClassName, extendedClassName); } } _compatClassNamesMap = compatClassNamesMap; return _compatClassNamesMap; } protected String getContent(String fileName, int level) throws IOException { File file = getFile(fileName, level); if (file != null) { String content = fileUtil.read(file); if (Validator.isNotNull(content)) { return content; } } return StringPool.BLANK; } protected String getCustomCopyright(String absolutePath) throws IOException { for (int x = absolutePath.length();;) { x = absolutePath.lastIndexOf(StringPool.SLASH, x); if (x == -1) { break; } String copyright = fileUtil.read(absolutePath.substring(0, x + 1) + "copyright.txt"); if (Validator.isNotNull(copyright)) { return copyright; } x = x - 1; } return null; } protected File getFile(String fileName, int level) { for (int i = 0; i < level; i++) { if (fileUtil.exists(fileName)) { return new File(fileName); } fileName = "../" + fileName; } return null; } protected List<String> getFileNames(String basedir, String[] excludes, String[] includes) { DirectoryScanner directoryScanner = new DirectoryScanner(); directoryScanner.setBasedir(basedir); if (_excludes != null) { excludes = ArrayUtil.append(excludes, _excludes); } directoryScanner.setExcludes(excludes); directoryScanner.setIncludes(includes); return sourceFormatterHelper.scanForFiles(directoryScanner); } protected List<String> getFileNames(String[] excludes, String[] includes) { return getFileNames(BASEDIR, excludes, includes); } protected Set<String> getImmutableFieldTypes() { if (_immutableFieldTypes != null) { return _immutableFieldTypes; } Set<String> immutableFieldTypes = SetUtil.fromArray(new String[] { "boolean", "byte", "char", "double", "float", "int", "long", "short", "Boolean", "Byte", "Character", "Class", "Double", "Float", "Int", "Long", "Number", "Short", "String", }); immutableFieldTypes.addAll(getPropertyList("immutable.field.types")); _immutableFieldTypes = immutableFieldTypes; return _immutableFieldTypes; } protected String[] getLanguageKeys(Matcher matcher) { int groupCount = matcher.groupCount(); if (groupCount == 1) { String languageKey = matcher.group(1); if (Validator.isNotNull(languageKey)) { return new String[] { languageKey }; } } else if (groupCount == 2) { String languageKey = matcher.group(2); languageKey = TextFormatter.format(languageKey, TextFormatter.P); return new String[] { languageKey }; } StringBundler sb = new StringBundler(); String match = matcher.group(); int count = 0; for (int i = 0; i < match.length(); i++) { char c = match.charAt(i); switch (c) { case CharPool.CLOSE_PARENTHESIS: if (count <= 1) { return new String[0]; } count--; break; case CharPool.OPEN_PARENTHESIS: count++; break; case CharPool.QUOTE: if (count > 1) { break; } while (i < match.length()) { i++; if (match.charAt(i) == CharPool.QUOTE) { String languageKey = sb.toString(); if (match.startsWith("names")) { return StringUtil.split(languageKey); } else { return new String[] { languageKey }; } } sb.append(match.charAt(i)); } } } return new String[0]; } protected Properties getLanguageProperties(String fileName) { StringBundler sb = new StringBundler(4); int pos = fileName.indexOf("/docroot/"); sb.append(BASEDIR); if (pos != -1) { sb.append(fileName.substring(0, pos + 9)); sb.append("WEB-INF/src/"); } else { pos = fileName.indexOf("/src/"); if (pos == -1) { return null; } sb.append(fileName.substring(0, pos + 5)); } sb.append("content/Language.properties"); try { Properties properties = new Properties(); InputStream inputStream = new FileInputStream(sb.toString()); properties.load(inputStream); return properties; } catch (Exception e) { } return null; } protected String getMainReleaseVersion() { if (_mainReleaseVersion != null) { return _mainReleaseVersion; } String releaseVersion = ReleaseInfo.getVersion(); int pos = releaseVersion.lastIndexOf(StringPool.PERIOD); _mainReleaseVersion = releaseVersion.substring(0, pos) + ".0"; return _mainReleaseVersion; } protected String getProperty(String key) { return _properties.getProperty(key); } protected List<String> getPropertyList(String key) { return ListUtil.fromString(GetterUtil.getString(getProperty(key)), StringPool.COMMA); } protected boolean hasMissingParentheses(String s) { if (Validator.isNull(s)) { return false; } boolean containsAndOperator = s.contains("&&"); boolean containsOrOperator = s.contains("||"); if (containsAndOperator && containsOrOperator) { return true; } boolean containsCompareOperator = (s.contains(" == ") || s.contains(" != ") || s.contains(" < ") || s.contains(" > ") || s.contains(" =< ") || s.contains(" => ") || s.contains(" <= ") || s.contains(" >= ")); boolean containsMathOperator = (s.contains(" = ") || s.contains(" - ") || s.contains(" + ") || s.contains(" & ") || s.contains(" % ") || s.contains(" * ") || s.contains(" / ")); if (containsCompareOperator && (containsAndOperator || containsOrOperator || (containsMathOperator && !s.contains(StringPool.OPEN_BRACKET)))) { return true; } return false; } protected boolean hasRedundantParentheses(String s) { if (!s.contains("&&") && !s.contains("||")) { for (int x = 0;;) { x = s.indexOf(StringPool.CLOSE_PARENTHESIS); if (x == -1) { break; } int y = s.substring(0, x).lastIndexOf(StringPool.OPEN_PARENTHESIS); if (y == -1) { break; } s = s.substring(0, y) + s.substring(x + 1); } } if (Validator.isNotNull(s) && !s.contains(StringPool.SPACE)) { return true; } else { return false; } } protected boolean hasRedundantParentheses(String s, String operator1, String operator2) { String[] parts = StringUtil.split(s, operator1); if (parts.length < 3) { return false; } for (int i = 1; i < (parts.length - 1); i++) { String part = parts[i]; if (part.contains(operator2) || part.contains("!(")) { continue; } int closeParenthesesCount = StringUtil.count(part, StringPool.CLOSE_PARENTHESIS); int openParenthesesCount = StringUtil.count(part, StringPool.OPEN_PARENTHESIS); if (Math.abs(closeParenthesesCount - openParenthesesCount) == 1) { return true; } } return false; } protected boolean isAttributName(String attributeName) { if (Validator.isNull(attributeName)) { return false; } Matcher matcher = attributeNamePattern.matcher(attributeName); return matcher.matches(); } protected boolean isRunsOutsidePortal(String absolutePath) { if (_runOutsidePortalExclusions == null) { _runOutsidePortalExclusions = getPropertyList("run.outside.portal.excludes"); } for (String runOutsidePortalExclusions : _runOutsidePortalExclusions) { if (absolutePath.contains(runOutsidePortalExclusions)) { return true; } } return false; } protected void processFormattedFile(File file, String fileName, String content, String newContent) throws IOException { if (_printErrors) { List<String> errorMessages = _errorMessagesMap.get(fileName); if (errorMessages != null) { for (String errorMessage : errorMessages) { sourceFormatterHelper.printError(fileName, errorMessage); } } } if (content.equals(newContent)) { return; } if (_autoFix) { fileUtil.write(file, newContent); } else if (_firstSourceMismatchException == null) { _firstSourceMismatchException = new SourceMismatchException(fileName, content, newContent); } if (_printErrors) { sourceFormatterHelper.printError(fileName, file); } } protected String replacePrimitiveWrapperInstantiation(String fileName, String line, int lineCount) { if (true) { return line; } String newLine = StringUtil.replace(line, new String[] { "new Boolean(", "new Byte(", "new Character(", "new Integer(", "new Long(", "new Short(" }, new String[] { "Boolean.valueOf(", "Byte.valueOf(", "Character.valueOf(", "Integer.valueOf(", "Long.valueOf(", "Short.valueOf(" }); if (!line.equals(newLine)) { processErrorMessage(fileName, "> new Primitive(: " + fileName + " " + lineCount); } return newLine; } protected String sortAttributes(String fileName, String line, int lineCount, boolean allowApostropheDelimeter) { String s = line; int x = s.indexOf(StringPool.SPACE); if (x == -1) { return line; } s = s.substring(x + 1); String previousAttribute = null; String previousAttributeAndValue = null; boolean wrongOrder = false; for (x = 0;;) { x = s.indexOf(StringPool.EQUAL); if ((x == -1) || (s.length() <= (x + 1))) { return line; } String attribute = s.substring(0, x); if (!isAttributName(attribute)) { return line; } if (Validator.isNotNull(previousAttribute) && (previousAttribute.compareTo(attribute) > 0)) { wrongOrder = true; } s = s.substring(x + 1); char delimeter = s.charAt(0); if ((delimeter != CharPool.APOSTROPHE) && (delimeter != CharPool.QUOTE)) { if (delimeter != CharPool.AMPERSAND) { processErrorMessage(fileName, "delimeter: " + fileName + " " + lineCount); } return line; } s = s.substring(1); String value = null; int y = -1; while (true) { y = s.indexOf(delimeter, y + 1); if ((y == -1) || (s.length() <= (y + 1))) { return line; } value = s.substring(0, y); if (value.startsWith("<%")) { int endJavaCodeSignCount = StringUtil.count(value, "%>"); int startJavaCodeSignCount = StringUtil.count(value, "<%"); if (endJavaCodeSignCount == startJavaCodeSignCount) { break; } } else { int greaterThanCount = StringUtil.count(value, StringPool.GREATER_THAN); int lessThanCount = StringUtil.count(value, StringPool.LESS_THAN); if (greaterThanCount == lessThanCount) { break; } } } if (delimeter == CharPool.APOSTROPHE) { if (!value.contains(StringPool.QUOTE)) { line = StringUtil.replace(line, StringPool.APOSTROPHE + value + StringPool.APOSTROPHE, StringPool.QUOTE + value + StringPool.QUOTE); return sortAttributes(fileName, line, lineCount, allowApostropheDelimeter); } else if (!allowApostropheDelimeter) { String newValue = StringUtil.replace(value, StringPool.QUOTE, """); line = StringUtil.replace(line, StringPool.APOSTROPHE + value + StringPool.APOSTROPHE, StringPool.QUOTE + newValue + StringPool.QUOTE); return sortAttributes(fileName, line, lineCount, allowApostropheDelimeter); } } StringBundler sb = new StringBundler(5); sb.append(attribute); sb.append(StringPool.EQUAL); sb.append(delimeter); sb.append(value); sb.append(delimeter); String currentAttributeAndValue = sb.toString(); if (wrongOrder) { if ((StringUtil.count(line, currentAttributeAndValue) == 1) && (StringUtil.count(line, previousAttributeAndValue) == 1)) { line = StringUtil.replaceFirst(line, previousAttributeAndValue, currentAttributeAndValue); line = StringUtil.replaceLast(line, currentAttributeAndValue, previousAttributeAndValue); return sortAttributes(fileName, line, lineCount, allowApostropheDelimeter); } return line; } s = s.substring(y + 1); if (s.startsWith(StringPool.GREATER_THAN)) { x = s.indexOf(StringPool.SPACE); if (x == -1) { return line; } s = s.substring(x + 1); previousAttribute = null; previousAttributeAndValue = null; } else { s = StringUtil.trimLeading(s); previousAttribute = attribute; previousAttributeAndValue = currentAttributeAndValue; } } } protected String stripLine(String s, char startDelimeter, char endDelimeter) { boolean insideDelimeters = false; int level = 0; StringBundler sb = new StringBundler(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (insideDelimeters) { if (c == endDelimeter) { if (level > 0) { level -= 1; } else { if ((c > 1) && (s.charAt(i - 1) == CharPool.BACK_SLASH) && (s.charAt(i - 2) != CharPool.BACK_SLASH)) { continue; } insideDelimeters = false; } } else if (c == startDelimeter) { level += 1; } } else if (c == startDelimeter) { insideDelimeters = true; } else { sb.append(c); } } return sb.toString(); } protected String stripQuotes(String s, char delimeter) { return stripLine(s, delimeter, delimeter); } protected String stripRedundantParentheses(String s) { for (int x = 0;;) { x = s.indexOf(StringPool.OPEN_PARENTHESIS, x + 1); int y = s.indexOf(StringPool.CLOSE_PARENTHESIS, x); if ((x == -1) || (y == -1)) { return s; } String linePart = s.substring(x + 1, y); linePart = StringUtil.replace(linePart, StringPool.COMMA, StringPool.BLANK); if (Validator.isAlphanumericName(linePart) || Validator.isNull(linePart)) { s = s.substring(0, x) + s.substring(y + 1); } } } protected String trimContent(String content, boolean allowLeadingSpaces) throws IOException { StringBundler sb = new StringBundler(); try (UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader( new UnsyncStringReader(content))) { String line = null; while ((line = unsyncBufferedReader.readLine()) != null) { sb.append(trimLine(line, allowLeadingSpaces)); sb.append("\n"); } } content = sb.toString(); if (content.endsWith("\n")) { content = content.substring(0, content.length() - 1); } return content; } protected String trimLine(String line, boolean allowLeadingSpaces) { if (line.trim().length() == 0) { return StringPool.BLANK; } line = StringUtil.trimTrailing(line); if (allowLeadingSpaces || !line.startsWith(StringPool.SPACE) || line.startsWith(" *")) { return line; } if (!line.startsWith(StringPool.FOUR_SPACES)) { while (line.startsWith(StringPool.SPACE)) { line = StringUtil.replaceFirst(line, StringPool.SPACE, StringPool.BLANK); } } else { int pos = 0; String temp = line; while (temp.startsWith(StringPool.FOUR_SPACES)) { line = StringUtil.replaceFirst(line, StringPool.FOUR_SPACES, StringPool.TAB); pos++; temp = line.substring(pos); } } return line; } protected static final String BASEDIR = "./"; protected static Pattern attributeNamePattern = Pattern.compile("[a-z]+[-_a-zA-Z0-9]*"); protected static Pattern emptyCollectionPattern = Pattern.compile("Collections\\.EMPTY_(LIST|MAP|SET)"); protected static FileImpl fileUtil = FileImpl.getInstance(); protected static Pattern languageKeyPattern = Pattern .compile("LanguageUtil.(?:get|format)\\([^;%]+|Liferay.Language.get\\('([^']+)"); protected static boolean portalSource; protected static SAXReaderImpl saxReaderUtil = SAXReaderImpl.getInstance(); protected static Pattern sessionKeyPattern = Pattern.compile("SessionErrors.(?:add|contains|get)\\([^;%&|!]+|" .concat("SessionMessages.(?:add|contains|get)\\([^;%&|!]+"), Pattern.MULTILINE); protected static SourceFormatterHelper sourceFormatterHelper; protected static Pattern taglibSessionKeyPattern = Pattern .compile("<liferay-ui:error [^>]+>|<liferay-ui:success [^>]+>", Pattern.MULTILINE); private String[] _getExcludes() { List<String> excludesList = ListUtil .fromString(GetterUtil.getString(System.getProperty("source.formatter.excludes"))); excludesList.addAll(getPropertyList("source.formatter.excludes")); String[] includes = new String[] { "**\\source_formatter.ignore" }; List<String> ignoreFileNames = getFileNames(new String[0], includes); for (String ignoreFileName : ignoreFileNames) { excludesList.add(ignoreFileName.substring(0, ignoreFileName.length() - 23) + "**"); } return excludesList.toArray(new String[excludesList.size()]); } private Properties _getProperties() throws Exception { String fileName = "source-formatter.properties"; Properties properties = new Properties(); List<Properties> propertiesList = new ArrayList<Properties>(); int level = 2; if (portalSource) { level = 3; } for (int i = 0; i <= level; i++) { try { InputStream inputStream = new FileInputStream(fileName); Properties props = new Properties(); props.load(inputStream); propertiesList.add(props); } catch (FileNotFoundException fnfe) { } fileName = "../" + fileName; } if (propertiesList.isEmpty()) { return properties; } properties = propertiesList.get(0); if (propertiesList.size() == 1) { return properties; } for (int i = 1; i < propertiesList.size(); i++) { Properties props = propertiesList.get(i); Enumeration<String> enu = (Enumeration<String>) props.propertyNames(); while (enu.hasMoreElements()) { String key = enu.nextElement(); String value = props.getProperty(key); if (Validator.isNull(value)) { continue; } if (key.contains("excludes")) { String existingValue = properties.getProperty(key); if (Validator.isNotNull(existingValue)) { value = existingValue + StringPool.COMMA + value; } properties.put(key, value); } else if (!properties.containsKey(key)) { properties.put(key, value); } } } return properties; } private void _init(boolean useProperties, boolean printErrors, boolean autoFix) throws Exception { _errorMessagesMap = new HashMap<String, List<String>>(); sourceFormatterHelper = new SourceFormatterHelper(useProperties); sourceFormatterHelper.init(); _autoFix = autoFix; _excludes = _getExcludes(); _printErrors = printErrors; _usePortalCompatImport = GetterUtil.getBoolean(getProperty("use.portal.compat.import")); } private boolean _isPortalSource() { if (getFile("portal-impl", 4) != null) { return true; } else { return false; } } private static Map<String, List<String>> _errorMessagesMap = new HashMap<String, List<String>>(); private static boolean _printErrors; private Set<String> _annotationsExclusions; private boolean _autoFix; private Map<String, String> _compatClassNamesMap; private String _copyright; private String[] _excludes; private SourceMismatchException _firstSourceMismatchException; private Set<String> _immutableFieldTypes; private String _mainReleaseVersion; private String _oldCopyright; private Properties _portalLanguageProperties; private Properties _properties; private List<String> _runOutsidePortalExclusions; private boolean _usePortalCompatImport; }