Skip to content

Commit d507e3f

Browse files
committed
SONARJAVA-1212 Extract JavaProperties Helper from AvoidDESCheck
1 parent 6d79358 commit d507e3f

3 files changed

Lines changed: 219 additions & 36 deletions

File tree

java-checks/src/main/java/org/sonar/java/checks/AvoidDESCheck.java

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,17 @@
2323
import org.sonar.api.server.rule.RulesDefinition;
2424
import org.sonar.check.Priority;
2525
import org.sonar.check.Rule;
26+
import org.sonar.java.checks.helpers.JavaPropertiesHelper;
2627
import org.sonar.java.checks.methods.AbstractMethodDetection;
2728
import org.sonar.java.checks.methods.MethodMatcher;
2829
import org.sonar.java.model.LiteralUtils;
29-
import org.sonar.plugins.java.api.semantic.Symbol;
3030
import org.sonar.plugins.java.api.tree.ExpressionTree;
31-
import org.sonar.plugins.java.api.tree.IdentifierTree;
3231
import org.sonar.plugins.java.api.tree.LiteralTree;
3332
import org.sonar.plugins.java.api.tree.MethodInvocationTree;
3433
import org.sonar.plugins.java.api.tree.Tree;
3534
import org.sonar.squidbridge.annotations.SqaleConstantRemediation;
3635
import org.sonar.squidbridge.annotations.SqaleSubCharacteristic;
3736

38-
import javax.annotation.CheckForNull;
39-
4037
import java.util.List;
4138

4239
@Rule(
@@ -56,10 +53,9 @@ protected List<MethodMatcher> getMethodInvocationMatchers() {
5653
@Override
5754
protected void onMethodInvocationFound(MethodInvocationTree mit) {
5855
ExpressionTree firstArg = mit.arguments().get(0);
59-
if (firstArg.is(Tree.Kind.IDENTIFIER)) {
60-
firstArg = retrievedPropertyDefaultValue((IdentifierTree) firstArg);
61-
} else if (firstArg.is(Tree.Kind.METHOD_INVOCATION)) {
62-
firstArg = retrievedPropertyDefaultValue((MethodInvocationTree) firstArg);
56+
ExpressionTree defaultPropertyValue = JavaPropertiesHelper.retrievedPropertyDefaultValue(firstArg);
57+
if (defaultPropertyValue != null) {
58+
firstArg = defaultPropertyValue;
6359
}
6460
if (firstArg != null && firstArg.is(Tree.Kind.STRING_LITERAL)) {
6561
String algo = LiteralUtils.trimQuotes(((LiteralTree) firstArg).value());
@@ -74,34 +70,6 @@ private void checkIssue(Tree tree, String algorithm) {
7470
}
7571
}
7672

77-
@CheckForNull
78-
private static ExpressionTree retrievedPropertyDefaultValue(IdentifierTree firstArg) {
79-
Symbol symbol = firstArg.symbol();
80-
if (symbol.usages().size() == 1) {
81-
ExpressionTree initializer = ((Symbol.VariableSymbol) symbol).declaration().initializer();
82-
if (initializer != null && initializer.is(Tree.Kind.METHOD_INVOCATION)) {
83-
return retrievedPropertyDefaultValue((MethodInvocationTree) initializer);
84-
}
85-
}
86-
return null;
87-
}
88-
89-
@CheckForNull
90-
private static ExpressionTree retrievedPropertyDefaultValue(MethodInvocationTree mit) {
91-
if (isGetPropertyWithDefaultValue(mit)) {
92-
return mit.arguments().get(1);
93-
}
94-
return null;
95-
}
96-
97-
private static boolean isGetPropertyWithDefaultValue(MethodInvocationTree mit) {
98-
Symbol symbol = mit.symbol();
99-
if (symbol.owner().type().is("java.util.Properties")) {
100-
return "getProperty".equals(symbol.name()) && mit.arguments().size() == 2;
101-
}
102-
return false;
103-
}
104-
10573
private static boolean isExcludedAlgorithm(String algorithm) {
10674
return "DES".equals(algorithm) || "DESede".equals(algorithm);
10775
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* SonarQube Java
3+
* Copyright (C) 2012 SonarSource
4+
* sonarqube@googlegroups.com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public
17+
* License along with this program; if not, write to the Free Software
18+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
19+
*/
20+
package org.sonar.java.checks.helpers;
21+
22+
import org.sonar.plugins.java.api.semantic.Symbol;
23+
import org.sonar.plugins.java.api.tree.ExpressionTree;
24+
import org.sonar.plugins.java.api.tree.IdentifierTree;
25+
import org.sonar.plugins.java.api.tree.MethodInvocationTree;
26+
import org.sonar.plugins.java.api.tree.Tree;
27+
28+
import javax.annotation.CheckForNull;
29+
30+
public class JavaPropertiesHelper {
31+
32+
private JavaPropertiesHelper() {
33+
}
34+
35+
/**
36+
* If the provided expression is an {@link IdentifierTree} or a {@link MethodInvocationTree}, it will check if it used to retrieve
37+
* a property with a default value provided (using {@link java.util.Properties#getProperty(String, String)}).
38+
* @param expression
39+
* @return null The default value of the getProperty method invocation, or null if the expression is not of the expected kind
40+
* or if is not used to retrieve a property with a default value.
41+
* .
42+
*/
43+
@CheckForNull
44+
public static ExpressionTree retrievedPropertyDefaultValue(ExpressionTree expression) {
45+
if (expression.is(Tree.Kind.IDENTIFIER)) {
46+
return retrievedPropertyDefaultValue((IdentifierTree) expression);
47+
} else if (expression.is(Tree.Kind.METHOD_INVOCATION)) {
48+
return retrievedPropertyDefaultValue((MethodInvocationTree) expression);
49+
}
50+
return null;
51+
}
52+
53+
@CheckForNull
54+
private static ExpressionTree retrievedPropertyDefaultValue(IdentifierTree identifier) {
55+
Symbol symbol = identifier.symbol();
56+
if (symbol.usages().size() == 1) {
57+
ExpressionTree initializer = ((Symbol.VariableSymbol) symbol).declaration().initializer();
58+
if (initializer != null && initializer.is(Tree.Kind.METHOD_INVOCATION)) {
59+
return retrievedPropertyDefaultValue((MethodInvocationTree) initializer);
60+
}
61+
}
62+
return null;
63+
}
64+
65+
@CheckForNull
66+
private static ExpressionTree retrievedPropertyDefaultValue(MethodInvocationTree mit) {
67+
if (isGetPropertyWithDefaultValue(mit)) {
68+
return mit.arguments().get(1);
69+
}
70+
return null;
71+
}
72+
73+
private static boolean isGetPropertyWithDefaultValue(MethodInvocationTree mit) {
74+
Symbol symbol = mit.symbol();
75+
if (symbol.owner().type().is("java.util.Properties")) {
76+
return "getProperty".equals(symbol.name()) && mit.arguments().size() == 2;
77+
}
78+
return false;
79+
}
80+
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* SonarQube Java
3+
* Copyright (C) 2012 SonarSource
4+
* sonarqube@googlegroups.com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public
17+
* License along with this program; if not, write to the Free Software
18+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
19+
*/
20+
package org.sonar.java.checks.helpers;
21+
22+
import com.google.common.base.Charsets;
23+
import com.google.common.collect.Lists;
24+
import com.sonar.sslr.api.typed.ActionParser;
25+
import org.junit.Test;
26+
import org.sonar.java.ast.parser.JavaParser;
27+
import org.sonar.java.resolve.SemanticModel;
28+
import org.sonar.plugins.java.api.tree.ClassTree;
29+
import org.sonar.plugins.java.api.tree.CompilationUnitTree;
30+
import org.sonar.plugins.java.api.tree.ExpressionStatementTree;
31+
import org.sonar.plugins.java.api.tree.ExpressionTree;
32+
import org.sonar.plugins.java.api.tree.MethodInvocationTree;
33+
import org.sonar.plugins.java.api.tree.MethodTree;
34+
import org.sonar.plugins.java.api.tree.StatementTree;
35+
import org.sonar.plugins.java.api.tree.Tree;
36+
37+
import java.io.File;
38+
import java.lang.reflect.Constructor;
39+
40+
import static org.fest.assertions.Assertions.assertThat;
41+
42+
public class JavaPropertiesHelperTest {
43+
44+
private final ActionParser<Tree> p = JavaParser.createParser(Charsets.UTF_8);
45+
46+
@Test
47+
public void private_constructor() throws Exception {
48+
Constructor<JavaPropertiesHelper> constructor = JavaPropertiesHelper.class.getDeclaredConstructor();
49+
assertThat(constructor.isAccessible()).isFalse();
50+
constructor.setAccessible(true);
51+
constructor.newInstance();
52+
}
53+
54+
@Test
55+
public void null_if_not_get_property() throws Exception {
56+
ExpressionTree tree = firstExpression("void foo(java.util.Properties props){ props.setProperty(\"myKey\", \"myValue\"); }");
57+
ExpressionTree defaultValue = JavaPropertiesHelper.retrievedPropertyDefaultValue(tree);
58+
assertThat(defaultValue).isNull();
59+
60+
tree = firstExpression("void foo(){ System.out.println(); }");
61+
defaultValue = JavaPropertiesHelper.retrievedPropertyDefaultValue(tree);
62+
assertThat(defaultValue).isNull();
63+
}
64+
65+
@Test
66+
public void null_if_get_property_without_default_value() throws Exception {
67+
ExpressionTree tree = firstExpression("void foo(java.util.Properties props){ props.getProperty(\"myKey\"); }");
68+
ExpressionTree defaultValue = JavaPropertiesHelper.retrievedPropertyDefaultValue(tree);
69+
assertThat(defaultValue).isNull();
70+
}
71+
72+
@Test
73+
public void null_if_not_identifier_or_method_invocation() throws Exception {
74+
ExpressionTree tree = firstExpression("void foo(int a){ a++; }");
75+
ExpressionTree defaultValue = JavaPropertiesHelper.retrievedPropertyDefaultValue(tree);
76+
assertThat(defaultValue).isNull();
77+
}
78+
79+
@Test
80+
public void retrieve_default_value_on_method_invocation() throws Exception {
81+
ExpressionTree tree = firstExpression("void foo(java.util.Properties props){ props.getProperty(\"myKey\", \"defaultValue\"); }");
82+
ExpressionTree defaultValue = JavaPropertiesHelper.retrievedPropertyDefaultValue(tree);
83+
assertThat(defaultValue).isNotNull();
84+
assertThat(defaultValue.is(Tree.Kind.STRING_LITERAL)).isTrue();
85+
}
86+
87+
@Test
88+
public void retrieve_default_value_on_identifier() throws Exception {
89+
ExpressionTree tree = firstExpression(
90+
"void foo(String prop){ foo(myValue); } "
91+
+ "java.util.Properties props = new java.util.Properties();"
92+
+ "String myValue = props.getProperty(\"myKey\", \"defaultValue\");");
93+
ExpressionTree defaultValue = JavaPropertiesHelper.retrievedPropertyDefaultValue(((MethodInvocationTree) tree).arguments().get(0));
94+
assertThat(defaultValue).isNotNull();
95+
assertThat(defaultValue.is(Tree.Kind.STRING_LITERAL)).isTrue();
96+
}
97+
98+
@Test
99+
public void null_if_variable_used_more_than_once() throws Exception {
100+
ExpressionTree tree = firstExpression(
101+
"void foo(String prop){ foo(myValue); myValue = 0; } "
102+
+ "java.util.Properties props = new java.util.Properties();"
103+
+ "String myValue = props.getProperty(\"myKey\", \"defaultValue\");");
104+
ExpressionTree defaultValue = JavaPropertiesHelper.retrievedPropertyDefaultValue(((MethodInvocationTree) tree).arguments().get(0));
105+
assertThat(defaultValue).isNull();
106+
}
107+
108+
@Test
109+
public void null_if_variable_not_initialized() throws Exception {
110+
ExpressionTree tree = firstExpression(
111+
"void foo(String prop){ foo(myValue);} "
112+
+ "String myValue;");
113+
ExpressionTree defaultValue = JavaPropertiesHelper.retrievedPropertyDefaultValue(((MethodInvocationTree) tree).arguments().get(0));
114+
assertThat(defaultValue).isNull();
115+
}
116+
117+
@Test
118+
public void null_if_variable_not_initilialized_method_invocation() throws Exception {
119+
ExpressionTree tree = firstExpression(
120+
"void foo(String prop){ foo(myValue);} "
121+
+ "java.util.Properties props = new java.util.Properties();"
122+
+ "String myValue = \"hello\";");
123+
ExpressionTree defaultValue = JavaPropertiesHelper.retrievedPropertyDefaultValue(((MethodInvocationTree) tree).arguments().get(0));
124+
assertThat(defaultValue).isNull();
125+
}
126+
127+
private ExpressionTree firstExpression(String code) {
128+
CompilationUnitTree compilationUnitTree = (CompilationUnitTree) p.parse("class A { " + code + "}");
129+
SemanticModel.createFor(compilationUnitTree, Lists.<File>newArrayList());
130+
ClassTree firstType = (ClassTree) compilationUnitTree.types().get(0);
131+
StatementTree firstStatement = ((MethodTree) firstType.members().get(0)).block().body().get(0);
132+
return ((ExpressionStatementTree) firstStatement).expression();
133+
}
134+
135+
}

0 commit comments

Comments
 (0)