Skip to content

Commit

Permalink
Merge pull request #62 from joschi/optional-fail
Browse files Browse the repository at this point in the history
Add "failOnViolation" setting to optionally fail builds
  • Loading branch information
uschindler committed Aug 9, 2015
2 parents 331eac4 + 8466a8d commit 24c39a3
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 8 deletions.
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

0 comments on commit 24c39a3

Please sign in to comment.