I'm trying to create a Gradle plugin in Java that has property extensions (not conventions, as this is apparently the old, wrong way). For the record, I'm working with Gradle 1.6 on a Linux machine (Ubuntu 12.04).
I've gotten as far as figuring out that the this should be done in the Plugin class definition. Here is A way of adding an extension. Create an extension class that contains your properties:
public class MyPluginExtensions {
File sourceDir;
File outputDir;
public MyPluginExtensions(Project project) {
this.project = project;
sourceDir = new File(project.getProjectDir(), "src");
outputDir = new File(project.getBuildDir(), "out");
}
}
Now add these extensions to the project in the main plugin class:
public class MyPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
Map<String,Object> taskInfo = new HashMap<String,Object>();
taskInfo.put("type", MyPluginTask.class);
taskInfo.put("description", "Generates blah from blah.");
taskInfo.put("group", "Blah");
Task myPluginTask = project.task(taskInfo, "myPluginTask");
// Define conventions and attach them to tasks
MyPluginExtensions extensions = new MyPluginExtensions(project);
myPluginTask.getExtensions().add(
"sourceDir",
extensions.sourceDir);
myPluginTask.getExtensions().add(
"outputDir",
extensions.outputDir);
}
}
This approach, however, doesn't seem to be correct. A new project property is shows up in the project.ext
namespace. I expect to be able to address the plugin extensions as:
in my build.gradle:
myPluginTask.sourceDir = file('the/main/src')
myPluginTask.outputDir = file('the/output')
However, when I put such things in a gradle script that uses my plugin and try to set this property, gradle tells me I can't set it:
* What went wrong:
A problem occurred evaluating script.
> There's an extension registered with name 'sourceDir'. You should not reassign it via a property setter.
So, what's the right way to add property extensions for a task in a Java-based Gradle plugin?
EDIT:
Based on some other SO posts, I tried just adding my extensions object in one shot:
// first attempt:
//myPluginTask.getExtensions().add("sourceDir", extensions.sourceDir);
//myPluginTask.getExtensions().add("outputDir",extensions.outputDir);
// second attempt
myPluginTask.getExtensions().add("myPluginTask", extensions);
This appears to work. However, Gradle is now complaining that I've added a dynamic property:
Deprecated dynamic property: "sourceDir" on "task ':myPluginTask'", value: "/Users/jfer...".
So, again, what's the right way to add a plugin extension property?
EDIT 2
So, taking yet another shot at this, I'm adding the extension to the project object and using the create method instead:
// first attempt:
//myPluginTask.getExtensions().add("sourceDir", extensions.sourceDir);
//myPluginTask.getExtensions().add("outputDir",extensions.outputDir);
// second attempt
// myPluginTask.getExtensions().add("myPluginTask", extensions);
// third attempt
project.getExtensions().create("myPluginTask", MyPluginExtensions.class, project);
However, this fails for a couple of reasons:
project.myPluginPropExt.propertyName
and instead adds it in the project namespace (e.g., project.propertyName
) which is not correct and causes Gradle to throw a bunch of "deprecated dynamic property" warnings.So here is a solution to my problem:
public class MyPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
Map<String,Object> taskInfo = new HashMap<String,Object>();
taskInfo.put("type", MyPluginTask.class);
taskInfo.put("description", "Generates blah from blah.");
taskInfo.put("group", "Blah");
Task myPluginTask = project.task(taskInfo, "myPluginTask");
// Define conventions and attach them to tasks
MyPluginExtensions extensions = new MyPluginExtensions(project);
// the magic extension code:
project.getExtensions().add("myPluginName", extensions);
}
}
Now I can set a value for one of the extension properties in my gradle.build file like so (and I don't get a warning about adding deprecated dynamic properties):
myPluginName.sourceDir = file('the/main/src')
The final trick is to get this value in my Plugin's task:
public class MyPluginTask extends DefaultTask {
@TaskAction
public void action() {
MyPluginExtensions extensions = (MyPluginExtensions) getProject()
.getExtensions().findByName("myPluginName");
System.out.println("sourceDir value: " + extensions.sourceDir);
}
}
This works, but what annoys me about this solution is that I want to be able to put the extension properties in the same namespace as the task (e.g., myPluginTask.sourceDir
) which I have seen in groovy-based plugins, but this apparently is not supported or just doesn't work.
In the meantime, hope this helps someone else.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With