diff --git a/src/main/docs/ant-task.html b/src/main/docs/ant-task.html index ed68ab9f..9395d358 100644 --- a/src/main/docs/ant-task.html +++ b/src/main/docs/ant-task.html @@ -87,6 +87,13 @@
path
defined anywhere else. Should be identical to classpath used for compiling the class files.boolean
false
FileNotFoundException
s related to non-existent JAR entries you can try to work around using this setting.boolean
+ * The default is {@code false}, unless the plugin detects that your build is + * running in the Gradle Daemon (which has this problem), setting the + * default to {@code true} as a consequence. + */ + @Input + public boolean getDisableClassloadingCache() { + return data.disableClassloadingCache; + } + + /** @see #getDisableClassloadingCache */ + public void setDisableClassloadingCache(boolean disableClassloadingCache) { + data.disableClassloadingCache = disableClassloadingCache; + } + /** * List of a custom Java annotations (full class names) that are used in the checked * code to suppress errors. Those annotations must have at least @@ -483,6 +504,7 @@ public void info(String msg) { if (getFailOnMissingClasses()) options.add(FAIL_ON_MISSING_CLASSES); if (!getIgnoreFailures()) options.add(FAIL_ON_VIOLATION); if (getFailOnUnresolvableSignatures()) options.add(FAIL_ON_UNRESOLVABLE_SIGNATURES); + if (getDisableClassloadingCache()) options.add(DISABLE_CLASSLOADING_CACHE); final Checker checker = new Checker(log, loader, options); if (!checker.isSupportedJDK) { diff --git a/src/main/java/de/thetaphi/forbiddenapis/gradle/CheckForbiddenApisExtension.java b/src/main/java/de/thetaphi/forbiddenapis/gradle/CheckForbiddenApisExtension.java index f6c6d346..d02e2641 100644 --- a/src/main/java/de/thetaphi/forbiddenapis/gradle/CheckForbiddenApisExtension.java +++ b/src/main/java/de/thetaphi/forbiddenapis/gradle/CheckForbiddenApisExtension.java @@ -44,7 +44,8 @@ public class CheckForbiddenApisExtension { "failOnUnsupportedJava", "failOnMissingClasses", "failOnUnresolvableSignatures", - "ignoreFailures" + "ignoreFailures", + "disableClassloadingCache" ); public FileCollection signaturesFiles; // initialized by plugin-init.groovy @@ -56,6 +57,7 @@ public class CheckForbiddenApisExtension { public boolean failOnUnsupportedJava = false, failOnMissingClasses = true, failOnUnresolvableSignatures = true, - ignoreFailures = false; + ignoreFailures = false, + disableClassloadingCache = false; } diff --git a/src/main/java/de/thetaphi/forbiddenapis/maven/AbstractCheckMojo.java b/src/main/java/de/thetaphi/forbiddenapis/maven/AbstractCheckMojo.java index 641b3578..7180a1f5 100644 --- a/src/main/java/de/thetaphi/forbiddenapis/maven/AbstractCheckMojo.java +++ b/src/main/java/de/thetaphi/forbiddenapis/maven/AbstractCheckMojo.java @@ -155,6 +155,17 @@ public abstract class AbstractCheckMojo extends AbstractMojo implements Constant @Parameter(required = false, property="forbiddenapis.failOnViolation", defaultValue = "true") private boolean failOnViolation; + /** + * Disable the internal JVM classloading cache when getting bytecode from + * the classpath. This setting slows down checks, but may work around + * issues with other Mojos, that do not close their class loaders. + * If you get {@code FileNotFoundException}s related to non-existent JAR entries + * you can try to work around using this setting. + * @since 2.0 + */ + @Parameter(required = false, defaultValue = "false") + private boolean disableClassloadingCache; + /** * 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. @@ -312,6 +323,7 @@ public void info(String msg) { if (failOnMissingClasses) options.add(FAIL_ON_MISSING_CLASSES); if (failOnViolation) options.add(FAIL_ON_VIOLATION); if (failOnUnresolvableSignatures) options.add(FAIL_ON_UNRESOLVABLE_SIGNATURES); + if (disableClassloadingCache) options.add(DISABLE_CLASSLOADING_CACHE); final Checker checker = new Checker(log, loader, options); if (!checker.isSupportedJDK) { diff --git a/src/main/resources/de/thetaphi/forbiddenapis/gradle/plugin-init.groovy b/src/main/resources/de/thetaphi/forbiddenapis/gradle/plugin-init.groovy index dc574d52..cce9648e 100644 --- a/src/main/resources/de/thetaphi/forbiddenapis/gradle/plugin-init.groovy +++ b/src/main/resources/de/thetaphi/forbiddenapis/gradle/plugin-init.groovy @@ -23,10 +23,19 @@ if (project.plugins.withType(JavaBasePlugin.class).isEmpty()) { throw new PluginInstantiationException('Forbidden-apis only works in projects using the java plugin.'); } +// chck if running in Gradle Daemon? +// see: http://stackoverflow.com/questions/23265217/how-to-know-whether-you-are-running-inside-a-gradle-daemon +boolean isGradleDaemon = System.getProperty('sun.java.command', '').startsWith('org.gradle.launcher.daemon.') || + Thread.currentThread().stackTrace.any { it.className.startsWith 'org.gradle.launcher.daemon.' }; +if (isGradleDaemon) { + project.logger.info('You are running forbidden-apis in the Gradle Daemon; disabling classloading cache to work around resource leak.'); +} + // create Extension for defaults: def extension = project.extensions.create(FORBIDDEN_APIS_EXTENSION_NAME, CheckForbiddenApisExtension.class); extension.with { signaturesFiles = project.files(); + disableClassloadingCache |= isGradleDaemon; } // Define our tasks (one for each SourceSet):