forked from LiveRamp/pmd_extensions
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Ben Podgursky
committed
Jun 30, 2014
0 parents
commit 4078d83
Showing
8 changed files
with
518 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>com.liveramp</groupId> | ||
<artifactId>pmd_extensions</artifactId> | ||
<version>1.0-SNAPSHOT</version> | ||
<packaging>jar</packaging> | ||
|
||
<name>pmd_extensions</name> | ||
|
||
<properties> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
</properties> | ||
|
||
<repositories> | ||
<repository> | ||
<id>liveramp-repositories</id> | ||
<name>Liveramp Repositories</name> | ||
<url>http://repository.liveramp.com/artifactory/liveramp-repositories</url> | ||
<snapshots> | ||
<enabled>true</enabled> | ||
<updatePolicy>always</updatePolicy> | ||
</snapshots> | ||
</repository> | ||
</repositories> | ||
|
||
<distributionManagement> | ||
<snapshotRepository> | ||
<id>artifactory.liveramp.net</id> | ||
<name>artifactory.liveramp.net-snapshots</name> | ||
<url>http://repository.liveramp.com/artifactory/libs-snapshot-local</url> | ||
</snapshotRepository> | ||
<repository> | ||
<id>repository.liveramp.com</id> | ||
<name>repository.liveramp.com-releases</name> | ||
<url>http://repository.liveramp.com/artifactory/libs-release-local</url> | ||
</repository> | ||
</distributionManagement> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>net.sourceforge.pmd</groupId> | ||
<artifactId>pmd</artifactId> | ||
<version>5.0.5</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.guava</groupId> | ||
<artifactId>guava</artifactId> | ||
<version>13.0.1</version> | ||
</dependency> | ||
</dependencies> | ||
</project> |
73 changes: 73 additions & 0 deletions
73
src/main/java/com/liveramp/pmd_extensions/BlacklistClassUsages.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package com.liveramp.pmd_extensions; | ||
|
||
import java.util.List; | ||
|
||
import com.google.common.collect.Lists; | ||
import net.sourceforge.pmd.RuleContext; | ||
import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression; | ||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; | ||
import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration; | ||
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; | ||
import net.sourceforge.pmd.lang.rule.properties.StringProperty; | ||
|
||
/** | ||
* Prevent a class from being instantiated or imported. See example usage in example_ruleset.xml | ||
* | ||
* TODO prevent it from being used statically fully qualified | ||
*/ | ||
public class BlacklistClassUsages extends AbstractJavaRule { | ||
private static final String LIST_NAME = "BlacklistedClasses"; | ||
|
||
public BlacklistClassUsages(){ | ||
definePropertyDescriptor(new StringProperty(LIST_NAME, "List of classes to blacklist", "", 0)); | ||
} | ||
|
||
@Override | ||
public void start(RuleContext ctx) { | ||
List<String> blacklistedClasses = Lists.newArrayList(); | ||
Object prop = getProperty(getPropertyDescriptor(LIST_NAME)); | ||
for (String className : prop.toString().split(",")) { | ||
blacklistedClasses.add(className.trim()); | ||
} | ||
ctx.setAttribute(LIST_NAME, blacklistedClasses); | ||
} | ||
|
||
private static List<String> getFromContext(Object data){ | ||
RuleContext ctx = (RuleContext)data; | ||
return (List<String>)ctx.getAttribute(LIST_NAME); | ||
} | ||
|
||
/** | ||
* Check whether the class was imported | ||
*/ | ||
@Override | ||
public Object visit(ASTImportDeclaration node, Object data) { | ||
|
||
String img = node.jjtGetChild(0).getImage(); | ||
for (String blacklistedClass : getFromContext(data)) { | ||
if (img.startsWith(blacklistedClass)) { | ||
addViolation(data, node); | ||
} | ||
} | ||
return data; | ||
} | ||
|
||
/** | ||
* Check if the class was instantiated | ||
*/ | ||
@Override | ||
public Object visit(ASTAllocationExpression node, Object data) { | ||
|
||
if (!(node.jjtGetChild(0) instanceof ASTClassOrInterfaceType)) { | ||
return data; | ||
} | ||
|
||
for (String blockedClass : getFromContext(data)) { | ||
if (PmdHelper.isSubclass((ASTClassOrInterfaceType) node.jjtGetChild(0), blockedClass)){ | ||
addViolation(data, node); | ||
} | ||
} | ||
|
||
return data; | ||
} | ||
} |
127 changes: 127 additions & 0 deletions
127
src/main/java/com/liveramp/pmd_extensions/BlacklistMethods.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
package com.liveramp.pmd_extensions; | ||
|
||
import java.util.List; | ||
|
||
import com.google.common.collect.Lists; | ||
import net.sourceforge.pmd.RuleContext; | ||
import net.sourceforge.pmd.lang.ast.Node; | ||
import net.sourceforge.pmd.lang.java.ast.ASTName; | ||
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; | ||
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; | ||
import net.sourceforge.pmd.lang.java.ast.TypeNode; | ||
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; | ||
import net.sourceforge.pmd.lang.java.symboltable.NameOccurrence; | ||
import net.sourceforge.pmd.lang.rule.properties.StringProperty; | ||
|
||
/** | ||
* Fail any build which uses certain methods on particular classes. Example configuration in rule set: | ||
* | ||
<property name="BlacklistedMethods" value=" | ||
java.lang.String:getBytes:0, | ||
java.nio.ByteBuffer:array, | ||
"/> | ||
* Here, the getBytes method on String with arity 0 is banned, and the array method on ByteBuffer (with any arity) | ||
* is banned | ||
*/ | ||
public class BlacklistMethods extends AbstractJavaRule { | ||
private static final String LIST_NAME = "BlacklistedMethods"; | ||
|
||
public BlacklistMethods() { | ||
definePropertyDescriptor(new StringProperty(LIST_NAME, "List of methods to blacklist", "", 0)); | ||
} | ||
|
||
@Override | ||
public void start(RuleContext ctx) { | ||
List<BlacklistedCall> blockedCalls = Lists.newArrayList(); | ||
Object prop = getProperty(getPropertyDescriptor(LIST_NAME)); | ||
for (String reference : prop.toString().split(",")) { | ||
blockedCalls.add(parseRef(reference.trim())); | ||
} | ||
ctx.setAttribute(LIST_NAME, blockedCalls); | ||
} | ||
|
||
private BlacklistedCall parseRef(String s){ | ||
String[] parts = s.split(":"); | ||
if(parts.length == 2){ | ||
return new BlacklistedCall(parts[0], parts[1]); | ||
} | ||
if(parts.length == 3){ | ||
return new BlacklistedCall(parts[0], parts[1], Integer.parseInt(parts[2])); | ||
} | ||
throw new RuntimeException("Cannot parse method reference: "+s+"!"); | ||
} | ||
|
||
public Object visit(ASTVariableDeclaratorId node, Object data) { | ||
List<BlacklistedCall> blockedCalls = getFromContext(data); | ||
|
||
for (BlacklistedCall call : blockedCalls) { | ||
String ruleClass = call.getRuleClass(); | ||
|
||
if (PmdHelper.isSubclass(node, ruleClass)) { | ||
boolean isArray = node.isArray(); | ||
for (NameOccurrence occ : node.getUsages()) { | ||
NameOccurrence qualifier = occ.getNameForWhichThisIsAQualifier(); | ||
|
||
if (qualifier != null) { | ||
String ruleMethodName = call.getRuleMethodName(); | ||
|
||
if (!isArray && qualifier.getImage().equals(ruleMethodName)) { | ||
Integer argumentCount = call.getArgumentCount(); | ||
|
||
if (argumentCount == null || argumentCount == qualifier.getArgumentCount()) { | ||
addViolation(data, occ.getLocation(), | ||
"Blacklisted method call: "+ ruleClass +"."+ ruleMethodName +"{"+ argumentCount +"}"); | ||
} | ||
} | ||
// I don't know what this case catches... | ||
else if (isArray | ||
&& qualifier.getLocation() != null | ||
&& !ASTName.class.equals(qualifier.getLocation().getClass()) | ||
&& qualifier.getImage().equals(ruleMethodName)) { | ||
addViolation(data, occ.getLocation()); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return data; | ||
} | ||
|
||
private static List<BlacklistedCall> getFromContext(Object data){ | ||
RuleContext ctx = (RuleContext)data; | ||
return (List<BlacklistedCall>)ctx.getAttribute(LIST_NAME); | ||
} | ||
|
||
/** | ||
* Check for static methods | ||
*/ | ||
@Override | ||
public Object visit(ASTPrimaryPrefix node, Object data) { | ||
|
||
if (node.jjtGetNumChildren() == 0) { | ||
return data; | ||
} | ||
|
||
Node node1 = node.jjtGetChild(0); | ||
String image = node1.getImage(); | ||
|
||
if(image == null){ | ||
return data; | ||
} | ||
|
||
for (BlacklistedCall blacklistedCall : getFromContext(data)) { | ||
if (node1 instanceof TypeNode) { | ||
TypeNode tn = (TypeNode) node1; | ||
if (PmdHelper.isSubclass(tn, blacklistedCall.getRuleClass())) { | ||
if (image.equals(blacklistedCall.getImportedStaticImage()) | ||
|| image.equals(blacklistedCall.getFullStaticImage())) { | ||
addViolation(data, node); | ||
} | ||
} | ||
} | ||
} | ||
|
||
return data; | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
src/main/java/com/liveramp/pmd_extensions/BlacklistedCall.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package com.liveramp.pmd_extensions; | ||
|
||
public class BlacklistedCall { | ||
|
||
private final String ruleClass; | ||
private final String ruleClassName; | ||
private final String ruleMethodName; | ||
private final Integer argumentCount; | ||
|
||
private final String staticImported; | ||
private final String staticFull; | ||
|
||
public BlacklistedCall(String ruleClass, String ruleMethodName) { | ||
this(ruleClass, ruleMethodName, null); | ||
} | ||
|
||
public BlacklistedCall(String ruleClass, String ruleMethodName, Integer argumentCount) { | ||
this.ruleClass = ruleClass; | ||
this.ruleMethodName = ruleMethodName; | ||
this.argumentCount = argumentCount; | ||
|
||
String[] parts = ruleClass.split("\\."); | ||
if(parts.length < 1){ | ||
throw new RuntimeException("Unrecognized classname: "+ruleClass); | ||
} | ||
ruleClassName = parts[parts.length-1]; | ||
|
||
this.staticImported = ruleClassName+"."+ruleMethodName; | ||
this.staticFull = ruleClass+"."+ruleMethodName; | ||
|
||
} | ||
|
||
public String getRuleClass() { | ||
return ruleClass; | ||
} | ||
|
||
public String getRuleMethodName() { | ||
return ruleMethodName; | ||
} | ||
|
||
public Integer getArgumentCount() { | ||
return argumentCount; | ||
} | ||
|
||
public String getRuleClassName() { | ||
return ruleClassName; | ||
} | ||
|
||
public String getImportedStaticImage() { | ||
return staticImported; | ||
} | ||
|
||
public String getFullStaticImage(){ | ||
return staticFull; | ||
} | ||
} |
Oops, something went wrong.