Skip to content

Commit c8c25c3

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

File tree

5 files changed

+71
-67
lines changed

5 files changed

+71
-67
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: 36 additions & 35 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,63 @@
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
/**
5658
* Responsible for coordinating the actual injection of project version. Runs as a Gradle Action (doLast typically
5759
* to the main CompileJava task)
5860
*
5961
* @author Steve Ebersole
6062
*/
61-
public class InjectionAction implements Action<Task> {
62-
private static final Logger log = LoggerFactory.getLogger( InjectionAction.class );
63+
public abstract class InjectionTask extends DefaultTask {
64+
static final String TASK_NAME = "injectVersion";
65+
private static final Logger log = LoggerFactory.getLogger( InjectionTask.class );
6366

6467
private LoaderClassPath loaderClassPath;
6568
private ClassPool classPool;
6669

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

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

73-
@Override
74-
public void execute(Task task) {
75-
final ClassLoader runtimeScopeClassLoader = buildRuntimeScopeClassLoader( task.getProject() );
79+
@TaskAction
80+
public void execute() {
81+
final ClassLoader runtimeScopeClassLoader = buildRuntimeScopeClassLoader();
7682
loaderClassPath = new LoaderClassPath( runtimeScopeClassLoader );
7783
classPool = new ClassPool( true );
7884
classPool.appendClassPath( loaderClassPath );
7985

80-
performInjections( task.getProject() );
86+
performInjections();
8187
}
8288

83-
private ClassLoader buildRuntimeScopeClassLoader(Project project) {
89+
private ClassLoader buildRuntimeScopeClassLoader() {
8490
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() ) {
91+
getClasspath().forEach( file -> {
9092
try {
9193
classPathUrls.add( file.toURI().toURL() );
9294
}
9395
catch (MalformedURLException e) {
9496
throw new InjectionException( "Could not determine artifact URL [" + file.getPath() + "]", e );
9597
}
96-
}
98+
} );
9799
return new URLClassLoader( classPathUrls.toArray( URL[]::new ), getClass().getClassLoader() );
98100
}
99101

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

103-
for ( TargetMember targetMember : injectionSpec.getTargetMembers().get() ) {
105+
for ( TargetMember targetMember : getInjectionTargets().get() ) {
104106
resolveInjectionTarget( targetMember ).inject( projectVersion );
105107
}
106108
}
@@ -113,7 +115,7 @@ private InjectionTarget resolveInjectionTarget(TargetMember targetMember) {
113115
CtField field = ctClass.getField( targetMember.getMemberName() );
114116
return new FieldInjectionTarget( targetMember, ctClass, field );
115117
}
116-
catch( NotFoundException ignore ) {
118+
catch (NotFoundException ignore) {
117119
}
118120

119121
// see if it is a method...
@@ -133,7 +135,7 @@ private InjectionTarget resolveInjectionTarget(TargetMember targetMember) {
133135
// finally throw an exception
134136
throw new InjectionException( "Unknown member [" + targetMember.getQualifiedName() + "]" );
135137
}
136-
catch ( Throwable e ) {
138+
catch (Throwable e) {
137139
throw new InjectionException( "Unable to resolve class [" + targetMember.getClassName() + "]", e );
138140
}
139141
}
@@ -146,14 +148,13 @@ private interface InjectionTarget {
146148
* Inject the given value per this target's strategy.
147149
*
148150
* @param value The value to inject.
149-
*
150151
* @throws org.hibernate.build.gradle.inject.InjectionException Indicates a problem performing the injection.
151152
*/
152153
void inject(String value);
153154
}
154155

155156
private abstract class BaseInjectionTarget implements InjectionTarget {
156-
@SuppressWarnings( {"UnusedDeclaration"})
157+
@SuppressWarnings({ "UnusedDeclaration" })
157158
private final TargetMember targetMember;
158159
private final CtClass ctClass;
159160
private final File classFileLocation;
@@ -164,7 +165,7 @@ protected BaseInjectionTarget(TargetMember targetMember, CtClass ctClass) {
164165
try {
165166
classFileLocation = new File( loaderClassPath.find( targetMember.getClassName() ).toURI() );
166167
}
167-
catch ( Throwable e ) {
168+
catch (Throwable e) {
168169
throw new InjectionException( "Unable to resolve class file path", e );
169170
}
170171
}
@@ -205,7 +206,7 @@ private class FieldInjectionTarget extends BaseInjectionTarget {
205206
private FieldInjectionTarget(TargetMember targetMember, CtClass ctClass, CtField ctField) {
206207
super( targetMember, ctClass );
207208
this.ctField = ctField;
208-
if ( ! Modifier.isStatic( ctField.getModifiers() ) ) {
209+
if ( !Modifier.isStatic( ctField.getModifiers() ) ) {
209210
throw new InjectionException( "Field is not static [" + targetMember.getQualifiedName() + "]" );
210211
}
211212
}
@@ -237,7 +238,7 @@ protected void doInjection(String value) {
237238
try {
238239
ctMethod.setBody( "{return \"" + value + "\";}" );
239240
}
240-
catch ( Throwable t ) {
241+
catch (Throwable t) {
241242
throw new InjectionException( "Unable to replace method body", t );
242243
}
243244
}

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)