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 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); }
@Override public void visitToken(DetailAST detailAST) { List<DetailAST> methodCallASTList = DetailASTUtil.getAllChildTokens(detailAST, TokenTypes.METHOD_CALL, true); for (DetailAST methodCallAST : methodCallASTList) { List<DetailAST> childMethodCallASTList = DetailASTUtil.getAllChildTokens(methodCallAST, TokenTypes.METHOD_CALL, true); // Only check the method that is first in the chain if (!childMethodCallASTList.isEmpty()) { continue; } String chainedMethodNames = _getChainedMethodNames(methodCallAST); if (!chainedMethodNames.contains(StringPool.PERIOD)) { continue; } _checkMethodName(chainedMethodNames, "getClass", methodCallAST, detailAST); if (StringUtil.count(chainedMethodNames, StringPool.PERIOD) == 1) { continue; } if (chainedMethodNames.contains("concat.concat.concat")) { log(methodCallAST.getLineNo(), MSG_AVOID_TOO_MANY_CONCAT); continue; } if (!chainedMethodNames.contains("concat.concat") && !chainedMethodNames.matches(_chainingAllowedFormat)) { log( methodCallAST.getLineNo(), MSG_AVOID_CHAINING_MULTIPLE, DetailASTUtil.getMethodName(methodCallAST)); } } }
@Override protected void doUpgrade() throws Exception { Connection con = null; PreparedStatement ps = null; ResultSet rs = null; try { con = DataAccess.getConnection(); ps = con.prepareStatement(_GET_LAYOUT); rs = ps.executeQuery(); while (rs.next()) { long plid = rs.getLong("plid"); String typeSettings = rs.getString("typeSettings"); String newTypeSettings = typeSettings; Matcher matcher = _pattern.matcher(typeSettings); while (matcher.find()) { String nestedColumnIds = matcher.group(); int underlineCount = StringUtil.count(nestedColumnIds, StringPool.UNDERLINE); if (underlineCount == _UNDERLINE_COUNT) { String newNestedColumnIds = nestedColumnIds.replaceAll(_pattern.pattern(), "_$1_$2"); newTypeSettings = newTypeSettings.replaceAll(nestedColumnIds, newNestedColumnIds); } } if (!newTypeSettings.equals(typeSettings)) { updateLayout(plid, newTypeSettings); } } } finally { DataAccess.cleanUp(con, ps, rs); } }
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 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 formatJSP(String fileName, String absolutePath, String content) throws IOException { StringBundler sb = new StringBundler(); UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(new UnsyncStringReader(content)); int lineCount = 0; String line = null; String previousLine = StringPool.BLANK; String currentAttributeAndValue = null; String previousAttribute = null; String previousAttributeAndValue = null; boolean readAttributes = false; String currentException = null; String previousException = null; boolean hasUnsortedExceptions = false; boolean javaSource = false; while ((line = unsyncBufferedReader.readLine()) != null) { lineCount++; if (!fileName.contains("jsonw") || !fileName.endsWith("action.jsp")) { line = trimLine(line, false); } if (line.contains("<aui:button ") && line.contains("type=\"button\"")) { processErrorMessage(fileName, "aui:button " + fileName + " " + lineCount); } if (line.contains("debugger.")) { processErrorMessage(fileName, "debugger " + fileName + " " + lineCount); } String trimmedLine = StringUtil.trimLeading(line); String trimmedPreviousLine = StringUtil.trimLeading(previousLine); checkStringBundler(trimmedLine, fileName, lineCount); checkEmptyCollection(trimmedLine, fileName, lineCount); if (trimmedLine.equals("<%") || trimmedLine.equals("<%!")) { javaSource = true; } else if (trimmedLine.equals("%>")) { javaSource = false; } if (javaSource || trimmedLine.contains("<%= ")) { checkInefficientStringMethods(line, fileName, absolutePath, lineCount); } if (javaSource && portalSource && !isExcluded(_unusedVariablesExclusions, fileName, lineCount) && !_jspContents.isEmpty() && hasUnusedVariable(fileName, trimmedLine)) { processErrorMessage(fileName, "Unused variable: " + fileName + " " + lineCount); } if (!trimmedLine.equals("%>") && line.contains("%>") && !line.contains("--%>") && !line.contains(" %>")) { line = StringUtil.replace(line, "%>", " %>"); } if (line.contains("<%=") && !line.contains("<%= ")) { line = StringUtil.replace(line, "<%=", "<%= "); } if (trimmedPreviousLine.equals("%>") && Validator.isNotNull(line) && !trimmedLine.equals("-->")) { sb.append("\n"); } else if (Validator.isNotNull(previousLine) && !trimmedPreviousLine.equals("<!--") && trimmedLine.equals("<%")) { sb.append("\n"); } else if (trimmedPreviousLine.equals("<%") && Validator.isNull(line)) { continue; } else if (trimmedPreviousLine.equals("<%") && trimmedLine.startsWith("//")) { sb.append("\n"); } else if (Validator.isNull(previousLine) && trimmedLine.equals("%>") && (sb.index() > 2)) { String lineBeforePreviousLine = sb.stringAt(sb.index() - 3); if (!lineBeforePreviousLine.startsWith("//")) { sb.setIndex(sb.index() - 1); } } if ((trimmedLine.startsWith("if (") || trimmedLine.startsWith("else if (") || trimmedLine.startsWith("while (")) && trimmedLine.endsWith(") {")) { checkIfClauseParentheses(trimmedLine, fileName, lineCount); } if (readAttributes) { if (!trimmedLine.startsWith(StringPool.FORWARD_SLASH) && !trimmedLine.startsWith(StringPool.GREATER_THAN)) { int pos = trimmedLine.indexOf(StringPool.EQUAL); if (pos != -1) { String attribute = trimmedLine.substring(0, pos); if (!trimmedLine.endsWith(StringPool.APOSTROPHE) && !trimmedLine.endsWith(StringPool.GREATER_THAN) && !trimmedLine.endsWith(StringPool.QUOTE)) { processErrorMessage(fileName, "attribute: " + fileName + " " + lineCount); readAttributes = false; } else if (trimmedLine.endsWith(StringPool.APOSTROPHE) && !trimmedLine.contains(StringPool.QUOTE)) { line = StringUtil.replace(line, StringPool.APOSTROPHE, StringPool.QUOTE); readAttributes = false; } else if (Validator.isNotNull(previousAttribute)) { if (!isAttributName(attribute) && !attribute.startsWith(StringPool.LESS_THAN)) { processErrorMessage(fileName, "attribute: " + fileName + " " + lineCount); readAttributes = false; } else if (Validator.isNull(previousAttributeAndValue) && (previousAttribute.compareTo(attribute) > 0)) { previousAttributeAndValue = previousLine; currentAttributeAndValue = line; } } if (!readAttributes) { previousAttribute = null; previousAttributeAndValue = null; } else { previousAttribute = attribute; } } } else { previousAttribute = null; readAttributes = false; } } if (!hasUnsortedExceptions) { int i = line.indexOf("<liferay-ui:error exception=\"<%="); if (i != -1) { currentException = line.substring(i + 33); if (Validator.isNotNull(previousException) && (previousException.compareTo(currentException) > 0)) { hasUnsortedExceptions = true; } } if (!hasUnsortedExceptions) { previousException = currentException; currentException = null; } } if (trimmedLine.startsWith(StringPool.LESS_THAN) && !trimmedLine.startsWith("<%") && !trimmedLine.startsWith("<!")) { if (!trimmedLine.contains(StringPool.GREATER_THAN) && !trimmedLine.contains(StringPool.SPACE)) { readAttributes = true; } else { line = sortAttributes(fileName, line, lineCount, true); } } if (!trimmedLine.contains(StringPool.DOUBLE_SLASH) && !trimmedLine.startsWith(StringPool.STAR)) { while (trimmedLine.contains(StringPool.TAB)) { line = StringUtil.replaceLast(line, StringPool.TAB, StringPool.SPACE); trimmedLine = StringUtil.replaceLast(trimmedLine, StringPool.TAB, StringPool.SPACE); } while (trimmedLine.contains(StringPool.DOUBLE_SPACE) && !trimmedLine.contains(StringPool.QUOTE + StringPool.DOUBLE_SPACE) && !fileName.endsWith(".vm")) { line = StringUtil.replaceLast(line, StringPool.DOUBLE_SPACE, StringPool.SPACE); trimmedLine = StringUtil.replaceLast(trimmedLine, StringPool.DOUBLE_SPACE, StringPool.SPACE); } } if (!fileName.endsWith("/touch.jsp")) { int x = line.indexOf("<%@ include file"); if (x != -1) { x = line.indexOf(StringPool.QUOTE, x); int y = line.indexOf(StringPool.QUOTE, x + 1); if (y != -1) { String includeFileName = line.substring(x + 1, y); Matcher matcher = _jspIncludeFilePattern.matcher(includeFileName); if (!matcher.find()) { processErrorMessage(fileName, "include: " + fileName + " " + lineCount); } } } } line = replacePrimitiveWrapperInstantiation(fileName, line, lineCount); previousLine = line; sb.append(line); sb.append("\n"); } unsyncBufferedReader.close(); content = sb.toString(); if (content.endsWith("\n")) { content = content.substring(0, content.length() - 1); } content = formatTaglibQuotes(fileName, content, StringPool.QUOTE); content = formatTaglibQuotes(fileName, content, StringPool.APOSTROPHE); if (Validator.isNotNull(previousAttributeAndValue)) { content = StringUtil.replaceFirst( content, previousAttributeAndValue + "\n" + currentAttributeAndValue, currentAttributeAndValue + "\n" + previousAttributeAndValue); } if (hasUnsortedExceptions) { if ((StringUtil.count(content, currentException) > 1) || (StringUtil.count(content, previousException) > 1)) { processErrorMessage(fileName, "unsorted exceptions: " + fileName); } else { content = StringUtil.replaceFirst(content, previousException, currentException); content = StringUtil.replaceLast(content, currentException, previousException); } } return content; }
/** * @author Wesley Gong * @author Bijan Vakili * @author Douglas Wong * @author Brian Wing Shun Chan */ public class UpgradeNestedPortlets extends UpgradeProcess { @Override protected void doUpgrade() throws Exception { Connection con = null; PreparedStatement ps = null; ResultSet rs = null; try { con = DataAccess.getConnection(); ps = con.prepareStatement(_GET_LAYOUT); rs = ps.executeQuery(); while (rs.next()) { long plid = rs.getLong("plid"); String typeSettings = rs.getString("typeSettings"); String newTypeSettings = typeSettings; Matcher matcher = _pattern.matcher(typeSettings); while (matcher.find()) { String nestedColumnIds = matcher.group(); int underlineCount = StringUtil.count(nestedColumnIds, StringPool.UNDERLINE); if (underlineCount == _UNDERLINE_COUNT) { String newNestedColumnIds = nestedColumnIds.replaceAll(_pattern.pattern(), "_$1_$2"); newTypeSettings = newTypeSettings.replaceAll(nestedColumnIds, newNestedColumnIds); } } if (!newTypeSettings.equals(typeSettings)) { updateLayout(plid, newTypeSettings); } } } finally { DataAccess.cleanUp(con, ps, rs); } } protected void updateLayout(long plid, String typeSettings) throws Exception { Connection con = null; PreparedStatement ps = null; try { con = DataAccess.getConnection(); ps = con.prepareStatement("update Layout set typeSettings = ? where plid = " + plid); ps.setString(1, typeSettings); ps.executeUpdate(); } finally { DataAccess.cleanUp(con, ps); } } private static final String _GET_LAYOUT = "select plid, typeSettings from Layout where typeSettings like " + "'%nested-column-ids=" + PortletKeys.NESTED_PORTLETS + PortletConstants.INSTANCE_SEPARATOR + "%'"; private static final int _UNDERLINE_COUNT = StringUtil.count(PortletConstants.INSTANCE_SEPARATOR, StringPool.UNDERLINE) + 1; private static Pattern _pattern = Pattern.compile( "(" + PortletKeys.NESTED_PORTLETS + PortletConstants.INSTANCE_SEPARATOR + "[^_,\\s=]+_)([^_,\\s=]+)"); }