Skip to content

Commit d635b0e

Browse files
committed
Make plugin register the task rather than relying on doLast and project references
1 parent a00c017 commit d635b0e

File tree

5 files changed

+72
-69
lines changed

5 files changed

+72
-69
lines changed

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version-injection-plugin
44
Gradle plugin used by Hibernate to inject project version into compiled classes
55

66
To use you'd simply apply the plugin (after making sure it is added to your buildscript classpath):
7-
```
7+
```groovy
88
buildscript {
99
...
1010
dependencies {
@@ -16,9 +16,12 @@ apply plugin: 'version-injection'
1616
```
1717

1818
Then, you'd configure it. Configuration mainly involves naming the Class member to inject the project version into:
19-
```
19+
```groovy
2020
versionInjection {
21-
into( 'com.acme.Version', 'getVersionString' )
21+
version.set('version')
22+
targetMembers.set(List.of(
23+
member('com.acme.Version', 'getVersionString')
24+
))
2225
}
2326
```
2427

src/main/java/org/hibernate/build/gradle/inject/InjectionPlugin.java

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525

2626
import org.gradle.api.Plugin;
2727
import org.gradle.api.Project;
28-
import org.gradle.api.Task;
28+
import org.gradle.api.plugins.JavaPluginExtension;
29+
import org.gradle.api.tasks.TaskProvider;
2930

3031
/**
3132
* Mainly used to apply the InjectionAction to the main compileJava task
@@ -39,15 +40,23 @@ public class InjectionPlugin implements Plugin<Project> {
3940
public void apply(Project project) {
4041
project.getPluginManager().apply( "java" );
4142

42-
// Allow user to configure
43-
final InjectionSpec injectionSpec = new InjectionSpec( project );
44-
project.getExtensions().add( EXTENSION_NAME, injectionSpec );
43+
final InjectionSpec injectionSpec = project.getExtensions().create( EXTENSION_NAME, InjectionSpec.class, project );
4544

46-
// The action to run after compilation
47-
final InjectionAction injectionAction = new InjectionAction( injectionSpec );
48-
final Task compileJava = project.getTasks().getByName( "compileJava" );
49-
compileJava.getInputs().property( "version-injection-targets", injectionSpec.getTargetMembers() );
50-
compileJava.doLast( injectionAction );
45+
final TaskProvider<InjectionTask> injectionTaskProvider = project.getTasks().register(
46+
InjectionTask.TASK_NAME, InjectionTask.class, task -> {
47+
JavaPluginExtension javaExtension = (JavaPluginExtension) project.getExtensions().getByName( "java" );
48+
49+
task.getVersion().set( injectionSpec.getVersion() );
50+
task.getInjectionTargets().set( injectionSpec.getTargetMembers() );
51+
52+
task.getClasspath().setFrom(
53+
javaExtension.getSourceSets().getByName( "main" ).getOutput().getClassesDirs()
54+
);
55+
56+
task.dependsOn( project.getTasks().named( "compileJava" ) );
57+
}
58+
);
59+
project.getTasks().named( "classes" ).configure( classes -> classes.dependsOn( injectionTaskProvider ) );
5160
}
5261

5362
}

src/main/java/org/hibernate/build/gradle/inject/InjectionSpec.java

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,20 @@
33
import javax.inject.Inject;
44

55
import org.gradle.api.Project;
6-
import org.gradle.api.model.ObjectFactory;
76
import org.gradle.api.provider.ListProperty;
7+
import org.gradle.api.provider.Property;
88

99
/**
1010
* @author Steve Ebersole
1111
*/
12-
public class InjectionSpec {
13-
private final ListProperty<TargetMember> targetMembers;
12+
public abstract class InjectionSpec {
1413

15-
@Inject
16-
public InjectionSpec(ObjectFactory objects) {
17-
targetMembers = objects.listProperty( TargetMember.class );
18-
}
14+
public abstract Property<String> getVersion();
1915

20-
public InjectionSpec(Project project) {
21-
this( project.getObjects() );
22-
}
16+
public abstract ListProperty<TargetMember> getTargetMembers();
2317

24-
public ListProperty<TargetMember> getTargetMembers() {
25-
return targetMembers;
26-
}
27-
28-
public void into(String className, String member) {
29-
into( new TargetMember( className, member ) );
18+
@Inject
19+
public InjectionSpec(Project project) {
3020
}
3121

32-
private void into(TargetMember targetMember) {
33-
targetMembers.add( targetMember );
34-
}
3522
}

src/main/java/org/hibernate/build/gradle/inject/InjectionAction.java renamed to src/main/java/org/hibernate/build/gradle/inject/InjectionTask.java

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
import java.net.URLClassLoader;
3434
import java.util.ArrayList;
3535

36+
import org.slf4j.Logger;
37+
import org.slf4j.LoggerFactory;
38+
3639
import javassist.ClassPool;
3740
import javassist.CtClass;
3841
import javassist.CtField;
@@ -43,64 +46,62 @@
4346
import javassist.bytecode.ClassFile;
4447
import javassist.bytecode.ConstantAttribute;
4548
import javassist.bytecode.FieldInfo;
46-
import org.gradle.api.Action;
47-
import org.gradle.api.Project;
48-
import org.gradle.api.Task;
49-
import org.gradle.api.tasks.SourceSet;
50-
import org.gradle.api.tasks.SourceSetContainer;
51-
52-
import org.slf4j.Logger;
53-
import org.slf4j.LoggerFactory;
49+
import org.gradle.api.DefaultTask;
50+
import org.gradle.api.file.ConfigurableFileCollection;
51+
import org.gradle.api.provider.ListProperty;
52+
import org.gradle.api.provider.Property;
53+
import org.gradle.api.tasks.Input;
54+
import org.gradle.api.tasks.InputFiles;
55+
import org.gradle.api.tasks.TaskAction;
5456

5557
/**
56-
* Responsible for coordinating the actual injection of project version. Runs as a Gradle Action (doLast typically
57-
* to the main CompileJava task)
58+
* Responsible for coordinating the actual injection of project version.
5859
*
5960
* @author Steve Ebersole
6061
*/
61-
public class InjectionAction implements Action<Task> {
62-
private static final Logger log = LoggerFactory.getLogger( InjectionAction.class );
62+
public abstract class InjectionTask extends DefaultTask {
63+
static final String TASK_NAME = "injectVersion";
64+
private static final Logger log = LoggerFactory.getLogger( InjectionTask.class );
6365

6466
private LoaderClassPath loaderClassPath;
6567
private ClassPool classPool;
6668

67-
private final InjectionSpec injectionSpec;
69+
@InputFiles
70+
abstract ConfigurableFileCollection getClasspath();
6871

69-
public InjectionAction(InjectionSpec injectionSpec) {
70-
this.injectionSpec = injectionSpec;
71-
}
72+
@Input
73+
public abstract Property<String> getVersion();
74+
75+
@Input
76+
public abstract ListProperty<TargetMember> getInjectionTargets();
7277

73-
@Override
74-
public void execute(Task task) {
75-
final ClassLoader runtimeScopeClassLoader = buildRuntimeScopeClassLoader( task.getProject() );
78+
@TaskAction
79+
public void execute() {
80+
final ClassLoader runtimeScopeClassLoader = buildRuntimeScopeClassLoader();
7681
loaderClassPath = new LoaderClassPath( runtimeScopeClassLoader );
7782
classPool = new ClassPool( true );
7883
classPool.appendClassPath( loaderClassPath );
7984

80-
performInjections( task.getProject() );
85+
performInjections();
8186
}
8287

83-
private ClassLoader buildRuntimeScopeClassLoader(Project project) {
88+
private ClassLoader buildRuntimeScopeClassLoader() {
8489
final ArrayList<URL> classPathUrls = new ArrayList<>();
85-
final SourceSet mainSourceSet = project
86-
.getExtensions()
87-
.getByType( SourceSetContainer.class )
88-
.getByName( SourceSet.MAIN_SOURCE_SET_NAME );
89-
for ( File file : mainSourceSet.getRuntimeClasspath() ) {
90+
getClasspath().forEach( file -> {
9091
try {
9192
classPathUrls.add( file.toURI().toURL() );
9293
}
9394
catch (MalformedURLException e) {
9495
throw new InjectionException( "Could not determine artifact URL [" + file.getPath() + "]", e );
9596
}
96-
}
97+
} );
9798
return new URLClassLoader( classPathUrls.toArray( URL[]::new ), getClass().getClassLoader() );
9899
}
99100

100-
private void performInjections(Project project) {
101-
final String projectVersion = project.getVersion().toString();
101+
private void performInjections() {
102+
final String projectVersion = getVersion().get();
102103

103-
for ( TargetMember targetMember : injectionSpec.getTargetMembers().get() ) {
104+
for ( TargetMember targetMember : getInjectionTargets().get() ) {
104105
resolveInjectionTarget( targetMember ).inject( projectVersion );
105106
}
106107
}
@@ -113,7 +114,7 @@ private InjectionTarget resolveInjectionTarget(TargetMember targetMember) {
113114
CtField field = ctClass.getField( targetMember.getMemberName() );
114115
return new FieldInjectionTarget( targetMember, ctClass, field );
115116
}
116-
catch( NotFoundException ignore ) {
117+
catch (NotFoundException ignore) {
117118
}
118119

119120
// see if it is a method...
@@ -133,7 +134,7 @@ private InjectionTarget resolveInjectionTarget(TargetMember targetMember) {
133134
// finally throw an exception
134135
throw new InjectionException( "Unknown member [" + targetMember.getQualifiedName() + "]" );
135136
}
136-
catch ( Throwable e ) {
137+
catch (Throwable e) {
137138
throw new InjectionException( "Unable to resolve class [" + targetMember.getClassName() + "]", e );
138139
}
139140
}
@@ -146,14 +147,13 @@ private interface InjectionTarget {
146147
* Inject the given value per this target's strategy.
147148
*
148149
* @param value The value to inject.
149-
*
150150
* @throws org.hibernate.build.gradle.inject.InjectionException Indicates a problem performing the injection.
151151
*/
152152
void inject(String value);
153153
}
154154

155155
private abstract class BaseInjectionTarget implements InjectionTarget {
156-
@SuppressWarnings( {"UnusedDeclaration"})
156+
@SuppressWarnings({ "UnusedDeclaration" })
157157
private final TargetMember targetMember;
158158
private final CtClass ctClass;
159159
private final File classFileLocation;
@@ -164,7 +164,7 @@ protected BaseInjectionTarget(TargetMember targetMember, CtClass ctClass) {
164164
try {
165165
classFileLocation = new File( loaderClassPath.find( targetMember.getClassName() ).toURI() );
166166
}
167-
catch ( Throwable e ) {
167+
catch (Throwable e) {
168168
throw new InjectionException( "Unable to resolve class file path", e );
169169
}
170170
}
@@ -205,7 +205,7 @@ private class FieldInjectionTarget extends BaseInjectionTarget {
205205
private FieldInjectionTarget(TargetMember targetMember, CtClass ctClass, CtField ctField) {
206206
super( targetMember, ctClass );
207207
this.ctField = ctField;
208-
if ( ! Modifier.isStatic( ctField.getModifiers() ) ) {
208+
if ( !Modifier.isStatic( ctField.getModifiers() ) ) {
209209
throw new InjectionException( "Field is not static [" + targetMember.getQualifiedName() + "]" );
210210
}
211211
}
@@ -237,7 +237,7 @@ protected void doInjection(String value) {
237237
try {
238238
ctMethod.setBody( "{return \"" + value + "\";}" );
239239
}
240-
catch ( Throwable t ) {
240+
catch (Throwable t) {
241241
throw new InjectionException( "Unable to replace method body", t );
242242
}
243243
}

src/main/java/org/hibernate/build/gradle/inject/TargetMember.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,15 @@ public class TargetMember implements Serializable {
3333
private final String className;
3434
private final String memberName;
3535

36-
public TargetMember(String className, String memberName) {
36+
private TargetMember(String className, String memberName) {
3737
this.className = className;
3838
this.memberName = memberName;
3939
}
4040

41+
public static TargetMember member(String className, String memberName) {
42+
return new TargetMember( className, memberName );
43+
}
44+
4145
public String getClassName() {
4246
return className;
4347
}

0 commit comments

Comments
 (0)