Skip to content

Commit

Permalink
Remove plugin-init.groovy in resources and compile the plugin code wi…
Browse files Browse the repository at this point in the history
…th groovyc (#221)
  • Loading branch information
uschindler committed Mar 12, 2023
1 parent 734fec9 commit 1269a86
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 151 deletions.
18 changes: 16 additions & 2 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,13 @@
<equals arg1="${ivy.version}" arg2="${ivy.install.version}"/>
</condition>
<echo level="warn" taskname="check-ivy" message="${ivy.version-message}"/>
<ivy:cachepath pathid="path.main-build" conf="build" log="${ivy.logging}"/>
<ivy:cachepath pathid="-path.main-build1" conf="build" log="${ivy.logging}"/>
<ivy:cachepath pathid="-path.main-build2" conf="buildgradle" log="${ivy.logging}"/>
<path id="path.main-build">
<!-- order is important as the gradle JAR contains lots of outdated stuff, so should be last! -->
<path refid="-path.main-build1"/>
<path refid="-path.main-build2"/>
</path>
<ivy:cachepath pathid="path.main-bundle" conf="bundle" log="${ivy.logging}"/>
<ivy:cachepath pathid="path.test" conf="test" log="${ivy.logging}"/>
<ivy:cachepath pathid="path.jarjar" conf="jarjar" log="${ivy.logging}"/>
Expand Down Expand Up @@ -255,6 +261,7 @@
<taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpathref="path.jarjar"/>
<taskdef uri="antlib:org.apache.maven.artifact.ant" classpathref="path.tasks"/>
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="path.tasks"/>
<taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc" classpathref="path.tasks"/>
<typedef uri="antlib:org.apache.rat.anttasks" classpathref="path.tasks"/>
<artifact:remoteRepository id="mvn.maven-central.backup" url="${ivy.maven-central.backup}"/>
<!-- Make sure we downloaded Maven, so artifact:mvn can bootstrap itsself -->
Expand Down Expand Up @@ -282,8 +289,15 @@
</sequential>
</macrodef>

<target name="compile" depends="-init" description="Compile">
<target name="compile" depends="-install-tasks" description="Compile main">
<compile module="main" classpathref="path.main-build"/>
<groovyc srcdir="src/main/groovy" destdir="build/main"
indy="true" targetBytecode="${jdk.version}" encoding="${build.encoding}">
<classpath>
<path refid="path.main-build"/>
<pathelement path="build/main"/>
</classpath>
</groovyc>
</target>

<target name="compile-tools" depends="compile" description="Compile tools">
Expand Down
7 changes: 4 additions & 3 deletions ivy.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@
]>
<ivy-module version="2.0">
<info organisation="de.thetaphi" module="forbiddenapis"/>
<configurations defaultconfmapping="build-&gt;*;bundle-&gt;*;test-&gt;*;buildtools-&gt;*;jarjar-&gt;*">
<configurations defaultconfmapping="build-&gt;*;buildgradle-&gt;*;bundle-&gt;*;test-&gt;*;buildtools-&gt;*;jarjar-&gt;*">
<conf name="build" transitive="false" visibility="private" />
<conf name="buildgradle" transitive="false" visibility="private" />
<conf name="bundle" transitive="false" visibility="private" />
<conf name="test" transitive="false" visibility="private" />
<conf name="buildtools" transitive="false" visibility="private" />
Expand All @@ -35,10 +36,10 @@
<dependency org="org.apache.maven" name="maven-plugin-api" rev="&maven.version;" conf="build"/>
<dependency org="org.apache.maven" name="maven-artifact" rev="&maven.version;" conf="build"/>
<dependency org="org.apache.maven.plugin-tools" name="maven-plugin-annotations" rev="3.4" conf="build"/>
<dependency org="dev.gradleplugins" name="gradle-api" rev="&gradle.version;" conf="build"/>
<dependency org="org.slf4j" name="slf4j-api" rev="1.7.7" conf="build"/>
<dependency org="dev.gradleplugins" name="gradle-api" rev="&gradle.version;" conf="buildgradle"/>
<!-- Gradle also needs Groovy, but we need it as build tool, too: -->
<dependency org="org.codehaus.groovy" name="groovy-all" rev="2.4.17" conf="build,buildtools"/>
<dependency org="org.codehaus.groovy" name="groovy-all" rev="2.4.21" conf="build,buildtools"/>
<!-- ASM minimal (latest version) required: -->
<dependency org="org.ow2.asm" name="asm" rev="&asm.version;" conf="build,bundle,buildtools"/>
<dependency org="org.ow2.asm" name="asm-commons" rev="&asm.version;" conf="build,bundle,buildtools"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* (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.
*/

package de.thetaphi.forbiddenapis.gradle;

import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.util.GradleVersion;

/**
* Forbiddenapis Gradle Plugin (requires at least Gradle v3.2)
* @since 2.0
*/
public class ForbiddenApisPlugin extends ForbiddenApisPluginBase {

@Override
public void apply(Project project) {
if (GradleVersion.current().compareTo(MIN_GRADLE_VERSION) < 0) {
throw new GradleException("Forbiddenapis plugin requires at least " + MIN_GRADLE_VERSION + ", running version is " + GradleVersion.current());
}

project.plugins.apply(JavaBasePlugin.class);

// create Extension for defaults:
def extension = project.extensions.create(FORBIDDEN_APIS_EXTENSION_NAME, CheckForbiddenApisExtension.class, project);

// Create a convenience task for all checks (this does not conflict with extension, as it has higher priority in DSL):
def forbiddenTask = TASK_AVOIDANCE_AVAILABLE ? project.tasks.register(FORBIDDEN_APIS_TASK_NAME) : project.tasks.create(FORBIDDEN_APIS_TASK_NAME)
forbiddenTask.configure {
description = "Runs forbidden-apis checks.";
group = JavaBasePlugin.VERIFICATION_GROUP;
}

// Gradle is buggy with it's JavaVersion enum: We use majorVersion property before Java 11 (6,7,8,9,10) and for later we use toString() to be future-proof:
Closure targetCompatibilityGetter = { (project.targetCompatibility?.hasProperty('java11Compatible') && project.targetCompatibility?.java11Compatible) ?
project.targetCompatibility.toString() : project.targetCompatibility?.majorVersion };

// Define our tasks (one for each SourceSet):
project.sourceSets.all{ sourceSet ->
String sourceSetTaskName = sourceSet.getTaskName(FORBIDDEN_APIS_TASK_NAME, null);
def sourceSetTask = TASK_AVOIDANCE_AVAILABLE ? project.tasks.register(sourceSetTaskName, CheckForbiddenApis.class) :
project.tasks.create(sourceSetTaskName, CheckForbiddenApis.class);
def templateClassesDirs = project.files();
def templateClasspath = project.files();
sourceSetTask.configure {
description = "Runs forbidden-apis checks on '${sourceSet.name}' classes.";
dependsOn(sourceSet.output);
outputs.upToDateWhen { true }
def taskData = internalTaskData()
conventionMapping.with{
FORBIDDEN_APIS_EXTENSION_PROPS.each{ key ->
map(key, {
def item = taskData[key]
if (item instanceof ConfigurableFileCollection) {
return item.from(extension[key])
} else if (item instanceof Collection) {
item.addAll(extension[key])
return item
}
return extension[key]
})
}
classesDirs = { templateClassesDirs.from(sourceSet.output.hasProperty('classesDirs') ? sourceSet.output.classesDirs : sourceSet.output.classesDir) }
classpath = { templateClasspath.from(sourceSet.compileClasspath) }
targetCompatibility = targetCompatibilityGetter
}
}
forbiddenTask.configure {
dependsOn(sourceSetTask)
}
}

// Add our task as dependency to chain
def checkTask = TASK_AVOIDANCE_AVAILABLE ? project.tasks.named(JavaBasePlugin.CHECK_TASK_NAME) : project.tasks.getByName(JavaBasePlugin.CHECK_TASK_NAME);
checkTask.configure { it.dependsOn(forbiddenTask) };
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ public CheckForbiddenApisExtension(Project project) {
failOnUnresolvableSignatures = true,
ignoreFailures = false,
ignoreSignaturesOfMissingClasses = false,
disableClassloadingCache = ForbiddenApisPlugin.DEFAULT_DISABLE_CLASSLOADING_CACHE;
disableClassloadingCache = ForbiddenApisPluginBase.DEFAULT_DISABLE_CLASSLOADING_CACHE;

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,21 @@

package de.thetaphi.forbiddenapis.gradle;

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyCodeSource;
import groovy.util.DelegatingScript;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.customizers.ImportCustomizer;
import org.gradle.api.GradleException;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.util.GradleVersion;

/**
* Forbiddenapis Gradle Plugin (requires at least Gradle v3.2)
* @since 2.0
*/
public class ForbiddenApisPlugin implements Plugin<Project> {
abstract class ForbiddenApisPluginBase implements Plugin<Project> {

private static final Logger LOG = Logging.getLogger(ForbiddenApisPlugin.class);
private static final Logger LOG = Logging.getLogger(ForbiddenApisPluginBase.class);

/** Name of the base task that depends on one for every SourceSet. */
public static final String FORBIDDEN_APIS_TASK_NAME = "forbiddenApis";
Expand All @@ -69,45 +54,12 @@ public class ForbiddenApisPlugin implements Plugin<Project> {
/** True, if this version of Gradle supports task avoidance API (&gt;=v4.9). */
public static final boolean TASK_AVOIDANCE_AVAILABLE = GradleVersion.current().compareTo(GradleVersion.version("4.9")) >= 0;

/** All properties that our ForbiddenApisExtension provides. Used by plugin init script to create convention mapping. */
public static final List<String> FORBIDDEN_APIS_EXTENSION_PROPS = determineExtensionProps();
/** All properties that our ForbiddenApisExtension provides. Used to create convention mapping. */
protected static final List<String> FORBIDDEN_APIS_EXTENSION_PROPS = determineExtensionProps();

/** Java Package that contains the Gradle Daemon (needed to detect it on startup). */
private static final String GRADLE_DAEMON_PACKAGE = "org.gradle.launcher.daemon.";

/** Resource with Groovy script that initializes the plugin. */
private static final String PLUGIN_INIT_SCRIPT = "plugin-init.groovy";

/** Compiled class instance of the plugin init script, an instance is executed per {@link #apply(Project)} */
private static final Class<? extends DelegatingScript> COMPILED_SCRIPT = loadScript();

private static Class<? extends DelegatingScript> loadScript() {
final ImportCustomizer importCustomizer = new ImportCustomizer().addStarImports(ForbiddenApisPlugin.class.getPackage().getName());
final CompilerConfiguration configuration = new CompilerConfiguration().addCompilationCustomizers(importCustomizer);
configuration.setScriptBaseClass(DelegatingScript.class.getName());
configuration.setSourceEncoding(StandardCharsets.UTF_8.name());
final URL scriptUrl = ForbiddenApisPlugin.class.getResource(PLUGIN_INIT_SCRIPT);
if (scriptUrl == null) {
throw new RuntimeException("Cannot find resource with script: " + PLUGIN_INIT_SCRIPT);
}
return AccessController.doPrivileged(new PrivilegedAction<Class<? extends DelegatingScript>>() {
@Override
public Class<? extends DelegatingScript> run() {
try {
// We don't close the classloader, as we may need it later when loading other classes from inside script:
@SuppressWarnings("resource") final GroovyClassLoader loader =
new GroovyClassLoader(ForbiddenApisPlugin.class.getClassLoader(), configuration);
final GroovyCodeSource csrc = new GroovyCodeSource(scriptUrl);
@SuppressWarnings("unchecked") final Class<? extends DelegatingScript> clazz =
loader.parseClass(csrc, false).asSubclass(DelegatingScript.class);
return clazz;
} catch (Exception e) {
throw new RuntimeException("Cannot compile Groovy script: " + PLUGIN_INIT_SCRIPT, e);
}
}
});
}

private static List<String> determineExtensionProps() {
final List<String> props = new ArrayList<>();
for (final Field f : CheckForbiddenApisExtension.class.getDeclaredFields()) {
Expand Down Expand Up @@ -140,20 +92,4 @@ private static boolean detectAndLogGradleDaemon() {
return daemon;
}

@Override
public void apply(Project project) {
if (GradleVersion.current().compareTo(MIN_GRADLE_VERSION) < 0) {
throw new GradleException("Forbiddenapis plugin requires at least " + MIN_GRADLE_VERSION + ", running version is " + GradleVersion.current());
}
final DelegatingScript script;
try {
script = COMPILED_SCRIPT.newInstance();
} catch (Exception e) {
throw new GradleException("Cannot instantiate Groovy script to apply forbiddenapis plugin.", e);
}
script.setDelegate(this);
script.setProperty("project", project);
script.run();
}

}

This file was deleted.

0 comments on commit 1269a86

Please sign in to comment.