Skip to content

Add "failOnViolation" setting to optionally fail builds #62

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 9, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/main/docs/ant-task.html
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ <h2>Parameters</h2>
<td>Fail the build if a signature is not resolving. If this parameter is set to to false, then such signatures are silently ignored.</td>
</tr>

<tr>
<td>failOnViolation</td>
<td><code>boolean</code></td>
<td><code>true</code></td>
<td>Fail the build if violations have been found. If this parameter is set to <code>false</code>, then the build will continue even if violations have been found.</td>
</tr>

<tr>
<td>internalRuntimeForbidden</td>
<td><code>boolean</code></td>
Expand Down
11 changes: 9 additions & 2 deletions src/main/java/de/thetaphi/forbiddenapis/AbstractCheckMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,14 @@ public abstract class AbstractCheckMojo extends AbstractMojo {
*/
@Parameter(required = false, defaultValue = "true")
private boolean failOnUnresolvableSignatures;


/**
* Fail the build if violations have been found. Defaults to {@code true}.
* @since 1.9
*/
@Parameter(required = false, property="forbiddenapis.failOnViolation", defaultValue = "true")
private boolean failOnViolation;

/**
* The default compiler target version used to expand references to bundled JDK signatures.
* E.g., if you use "jdk-deprecated", it will expand to this version.
Expand Down Expand Up @@ -200,7 +207,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
ClassLoader.getSystemClassLoader();

try {
final Checker checker = new Checker(loader, internalRuntimeForbidden, failOnMissingClasses, failOnUnresolvableSignatures) {
final Checker checker = new Checker(loader, internalRuntimeForbidden, failOnMissingClasses, failOnViolation, failOnUnresolvableSignatures) {
@Override
protected void logError(String msg) {
log.error(msg);
Expand Down
11 changes: 10 additions & 1 deletion src/main/java/de/thetaphi/forbiddenapis/AntTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public final class AntTask extends Task {
private boolean restrictClassFilename = true;
private boolean failOnMissingClasses = true;
private boolean failOnUnresolvableSignatures = true;
private boolean failOnViolation = true;
private boolean ignoreEmptyFileset = false;

@Override
Expand All @@ -76,7 +77,7 @@ public void execute() throws BuildException {
classFiles.setProject(getProject());
apiSignatures.setProject(getProject());

final Checker checker = new Checker(loader, internalRuntimeForbidden, failOnMissingClasses, failOnUnresolvableSignatures) {
final Checker checker = new Checker(loader, internalRuntimeForbidden, failOnMissingClasses, failOnViolation, failOnUnresolvableSignatures) {
@Override
protected void logError(String msg) {
log(msg, Project.MSG_ERR);
Expand Down Expand Up @@ -325,4 +326,12 @@ public void setIgnoreEmptyFileSet(boolean ignoreEmptyFileset) {
this.ignoreEmptyFileset = ignoreEmptyFileset;
}

/**
* Fail the build if violations have been found. If this parameter is set to {@code false},
* then the build will continue even if violations have been found.
* Defaults to {@code true}.
*/
public void setFailOnViolation(boolean failOnViolation) {
this.failOnViolation = failOnViolation;
}
}
7 changes: 4 additions & 3 deletions src/main/java/de/thetaphi/forbiddenapis/Checker.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public abstract class Checker implements RelatedClassLookup {
final Set<File> bootClassPathJars;
final Set<String> bootClassPathDirs;
final ClassLoader loader;
final boolean internalRuntimeForbidden, failOnMissingClasses, defaultFailOnUnresolvableSignatures;
final boolean internalRuntimeForbidden, failOnMissingClasses, failOnViolation, defaultFailOnUnresolvableSignatures;

// key is the internal name (slashed):
final Map<String,ClassSignature> classesToCheck = new HashMap<String,ClassSignature>();
Expand All @@ -86,10 +86,11 @@ public abstract class Checker implements RelatedClassLookup {
protected abstract void logWarn(String msg);
protected abstract void logInfo(String msg);

public Checker(ClassLoader loader, boolean internalRuntimeForbidden, boolean failOnMissingClasses, boolean defaultFailOnUnresolvableSignatures) {
public Checker(ClassLoader loader, boolean internalRuntimeForbidden, boolean failOnMissingClasses, boolean failOnViolation, boolean defaultFailOnUnresolvableSignatures) {
this.loader = loader;
this.internalRuntimeForbidden = internalRuntimeForbidden;
this.failOnMissingClasses = failOnMissingClasses;
this.failOnViolation = failOnViolation;
this.defaultFailOnUnresolvableSignatures = defaultFailOnUnresolvableSignatures;
this.start = System.currentTimeMillis();

Expand Down Expand Up @@ -439,7 +440,7 @@ public final void run() throws ForbiddenApiException {
final String message = String.format(Locale.ENGLISH,
"Scanned %d (and %d related) class file(s) for forbidden API invocations (in %.2fs), %d error(s).",
classesToCheck.size(), classesToCheck.isEmpty() ? 0 : classpathClassCache.size(), (System.currentTimeMillis() - start) / 1000.0, errors);
if (errors > 0) {
if (failOnViolation && errors > 0) {
logError(message);
throw new ForbiddenApiException("Check for forbidden API calls failed, see log.");
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/de/thetaphi/forbiddenapis/CliMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ public void run() throws ExitException {
final URLClassLoader loader = URLClassLoader.newInstance(urls, ClassLoader.getSystemClassLoader());
try {
final Checker checker = new Checker(loader, cmd.hasOption(internalruntimeforbiddenOpt.getLongOpt()),
!cmd.hasOption(allowmissingclassesOpt.getLongOpt()), !cmd.hasOption(allowunresolvablesignaturesOpt.getLongOpt())) {
!cmd.hasOption(allowmissingclassesOpt.getLongOpt()), true, !cmd.hasOption(allowunresolvablesignaturesOpt.getLongOpt())) {
@Override
protected void logError(String msg) {
CliMain.this.logError(msg);
Expand Down
40 changes: 40 additions & 0 deletions src/test/antunit/TestFailOnViolation.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* (C) Copyright Uwe Schindler (Generics Policeman) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
-->
<project xmlns:au="antlib:org.apache.ant.antunit">

<fileset id="main.classes" dir="${antunit.main.classes}"/>

<target name="testFailOnViolation">
<au:expectfailure expectedMessage="Check for forbidden API calls failed, see log">
<forbiddenapis classpathref="path.all">
<fileset refid="main.classes"/>
java.awt.Color @ Color is disallowed, thats not bad, because ANT has no colors...
java.lang.String @ You are crazy that you disallow strings
</forbiddenapis>
</au:expectfailure>
<au:assertLogContains level="error" text="java.lang.String [You are crazy that you disallow strings]"/>
</target>

<target name="testDoNotFailOnViolation">
<forbiddenapis classpathref="path.all" failOnViolation="false">
<fileset refid="main.classes"/>
java.awt.Color @ Color is disallowed, thats not bad, because ANT has no colors...
java.lang.String @ You are crazy that you disallow strings
</forbiddenapis>
<au:assertLogContains level="error" text="java.lang.String [You are crazy that you disallow strings]"/>
</target>
</project>
10 changes: 10 additions & 0 deletions src/test/antunit/TestMavenMojo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@
</au:expectfailure>
<au:assertLogContains text="You are crazy that you disallow strings"/>
</target>

<target name="testFailOnViolation">
<artifact:mvn pom="${antunit.fake-pom}" mavenVersion="${maven.version}" failonerror="true" fork="true">
<arg value="${groupId}:${artifactId}:${version}:check"/>
<syspropertyset refid="injected-properties"/>
<sysproperty key="antunit.failOnViolation" value="false"/>
<sysproperty key="antunit.signatures" value="java.lang.String @ You are crazy that you disallow strings"/>
</artifact:mvn>
<au:assertLogContains text="You are crazy that you disallow strings"/>
</target>

<target name="testFailOnUnresolveableSignaturesMaven2">
<au:expectfailure>
Expand Down
1 change: 1 addition & 0 deletions src/test/antunit/pom-generator.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
<configuration>
<internalRuntimeForbidden>true</internalRuntimeForbidden>
<failOnUnresolvableSignatures>${antunit.failOnUnresolvableSignatures}</failOnUnresolvableSignatures>
<failOnViolation>${antunit.failOnViolation}</failOnViolation>
<bundledSignatures>
<bundledSignature>jdk-unsafe</bundledSignature>
<bundledSignature>jdk-deprecated</bundledSignature>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public final class CheckerSetupTest {
@SuppressForbidden
static final class MyChecker extends Checker {
public MyChecker() {
super(ClassLoader.getSystemClassLoader(), true, true, true);
super(ClassLoader.getSystemClassLoader(), true, true, true, true);
}

@Override
Expand Down