Extending existing jar task with support for enhancing(signing) the generated artifact


(detelinyordanov) #1

Hi Everyone,

I’m working on a plugin to support signing of Jar artifacts (using Java’s jarsigner) and I managed to get it working but I’m wondering whether my implementation is following Gradle’s best practices. My idea is to extend the standard ‘jar’ task adding a separate action responsible for signing the artifact. I decided to use this approach because signing must be done in place, and if it was a separate task to sign the jar, this would have caused the jar task to always execute (since its output will always change). I’m not sure this was the right approach, any other suggestions are welcome, but since I already implemented it, it raised a couple of questions that I would like to discuss. My intention was to allow users to configure the signing via a project-level signing extension, but also have a task-level extension, which allows to override the project-level settings. To achieve this, I did the following:

  • defined a ‘JarSigningExtension’ class - created a project-level JarSigningExtension instance - whenever a Jar task is configured for signing, a separate task-level JarSigningExtension instance is created on the task, and it is configured (using convention mapping) to use the defaults signing settings from the project-level extension

The latter is done by manually registering/mapping all properties of the project-level extension as convention values on the task-level extension.

My question is whether this approach makes sense and if it is possible to achieve same thing in a cleaner way - I could probably further improve this by listing and mapping all properties via reflection, but there could be some utility class that allows this - considering both extensions are instances of one and the same extension class?

By the way, the plugin would also register all JarSigningExtension properties as task inputs - by using ‘task.inputs.property(‘jarSigning’, { //return all signing extension property values using reflection })’ I’m wondering whether there is some annotation support for this - e.g. to annotate the JarSigningExtension class so that the annotated properties are automatically added as inputs when the extension is created on the task instance?

Any comments or suggestions how to improve the plugin are greatly appreciated!

Thanks,

Detelin


(Peter Niederwieser) #2

Sounds pretty good. It’s customary to use convention mapping to link one extension to another. Inputs and outputs of task classes can be declared by annotating them with with org.gradle.api.tasks.Input and similar annotations in the same package. This also works for nested properties (see @Nested). I don’t think it can be made to work with extensions though. Usually, extension properties are ultimately mapped to task properties, so there is no need to annotate the extension properties.

The big question is whether signing should be its own task. If at all possible, this would clearly be the preferred approach. Extending a task by adding another task action is troublesome. Why must be signing be done in place?


(detelinyordanov) #3

Because I thought it is not a good idea to create a separate signed artifact. The goal would be that the primary artifact gets signed, however I was wondering whether/how this could be done in another task - to accomplish this, the plugin would have to also remove the already declared published artifact and replace it with a new one (or probably reconfigure the existing?) - do you think this is possible?

Regards,

Detelin


How do I depend on/publish the signed .jar instead of the unsigned .jar?
(Peter Niederwieser) #4

I think it’s better to create a separate artifact. Overwriting another task’s output feels wrong to me. I’d rather reconfigure the project to, say, publish the signed artifact instead of the unsigned one. Also, there might still be some use for the unsigned artifact. I’d only consider overwriting if I hit a road block with this approach.