From fd7cca8fdc5c56ff9919c797f0cff1cfbc5fb5f9 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Wed, 8 Jun 2022 16:28:15 -0500 Subject: [PATCH] HHH-15314 - Hibernate Gradle plugin is not working for Kotlin projects --- .../tooling/gradle/HibernateOrmPlugin.java | 83 ++++- .../orm/tooling/gradle/HibernateOrmSpec.java | 138 +++++--- .../gradle/enhance/EnhancementHelper.java | 2 +- .../metamodel/JpaMetamodelGenerationSpec.java | 20 +- .../metamodel/JpaMetamodelGenerationTask.java | 320 +++++------------- .../metamodel/PersistenceUnitInfoImpl.java | 131 +++++++ .../metamodel/model/GenerationOptions.java | 22 ++ .../model/JpaStaticMetamodelGenerator.java | 20 +- .../metamodel/model/MetamodelClass.java | 14 +- ...mPluginTest.java => JavaProjectTests.java} | 100 +----- .../tooling/gradle/KotlinProjectTests.java | 150 ++++++++ .../orm/tooling/gradle/TestHelper.java | 34 ++ .../projects/simple-kotlin/build.gradle | 5 +- .../src/main/kotlin/TheEntity.kt | 2 + .../resources/projects/simple/build.gradle | 5 +- .../simple/src/main/java/TheEntity.java | 3 + 16 files changed, 637 insertions(+), 412 deletions(-) create mode 100644 tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/PersistenceUnitInfoImpl.java create mode 100644 tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/model/GenerationOptions.java rename tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/orm/tooling/gradle/{HibernateOrmPluginTest.java => JavaProjectTests.java} (59%) create mode 100644 tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/orm/tooling/gradle/KotlinProjectTests.java create mode 100644 tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/orm/tooling/gradle/TestHelper.java diff --git a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/HibernateOrmPlugin.java b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/HibernateOrmPlugin.java index fc5394529a..a2ff441fc8 100644 --- a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/HibernateOrmPlugin.java +++ b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/HibernateOrmPlugin.java @@ -13,12 +13,17 @@ import org.gradle.api.Task; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.plugins.JvmEcosystemPlugin; import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.TaskProvider; import org.gradle.api.tasks.compile.AbstractCompile; +import org.gradle.api.tasks.compile.JavaCompile; import org.hibernate.orm.tooling.gradle.enhance.EnhancementHelper; import org.hibernate.orm.tooling.gradle.metamodel.JpaMetamodelGenerationTask; import static org.hibernate.orm.tooling.gradle.Helper.determineCompileSourceSetName; +import static org.hibernate.orm.tooling.gradle.HibernateOrmSpec.HIBERNATE; +import static org.hibernate.orm.tooling.gradle.metamodel.JpaMetamodelGenerationTask.COMPILE_META_TASK_NAME; +import static org.hibernate.orm.tooling.gradle.metamodel.JpaMetamodelGenerationTask.GEN_TASK_NAME; /** * Hibernate ORM Gradle plugin @@ -33,26 +38,29 @@ public class HibernateOrmPlugin implements Plugin { final HibernateOrmSpec ormDsl = project.getExtensions().create( HibernateOrmSpec.DSL_NAME, HibernateOrmSpec.class, project ); prepareEnhancement( ormDsl, project ); + prepareModelGen( ormDsl, project ); + prepareHbmTransformation( ormDsl, project ); - JpaMetamodelGenerationTask.apply( ormDsl, ormDsl.getSourceSetProperty().get(), project ); -// project.getDependencies().add( -// "implementation", -// ormDsl.getHibernateVersionProperty().map( (ormVersion) -> Character.isDigit( ormVersion.charAt( 0 ) ) -// ? "org.hibernate.orm:hibernate-core:" + ormVersion -// : null -// ) -// ); + //noinspection ConstantConditions + project.getDependencies().add( + "implementation", + ormDsl.getUseSameVersion().map( (use) -> use + ? "org.hibernate.orm:hibernate-core:" + HibernateVersion.version + : null + ) + ); } private void prepareEnhancement(HibernateOrmSpec ormDsl, Project project) { project.getGradle().getTaskGraph().whenReady( (graph) -> { - if ( !ormDsl.getSupportEnhancementProperty().get() ) { + if ( !ormDsl.isEnhancementEnabled() ) { return; } + graph.getAllTasks().forEach( (task) -> { if ( task instanceof AbstractCompile ) { - final SourceSet sourceSetLocal = ormDsl.getSourceSetProperty().get(); + final SourceSet sourceSetLocal = ormDsl.getSourceSet().get(); final String compiledSourceSetName = determineCompileSourceSetName( task.getName() ); if ( !sourceSetLocal.getName().equals( compiledSourceSetName ) ) { @@ -60,7 +68,7 @@ public class HibernateOrmPlugin implements Plugin { } final AbstractCompile compileTask = (AbstractCompile) task; - //noinspection Convert2Lambda + //noinspection Convert2Lambda,NullableProblems task.doLast( new Action<>() { @Override public void execute(Task t) { @@ -70,10 +78,59 @@ public class HibernateOrmPlugin implements Plugin { EnhancementHelper.enhance( classesDirectory, classLoader, ormDsl, project ); } } ); - - task.finalizedBy( this ); } } ); } ); } + + private void prepareModelGen(HibernateOrmSpec ormDsl, Project project) { + final TaskProvider modelCompileTaskRef = project.getTasks().register( COMPILE_META_TASK_NAME, JavaCompile.class, (modelCompileTask) -> { + modelCompileTask.onlyIf( (t) -> ormDsl.isMetamodelGenerationEnabled() ); + + modelCompileTask.setGroup( HIBERNATE ); + modelCompileTask.setDescription( "Compiles the JPA static metamodel generated by `" + GEN_TASK_NAME + "`" ); + } ); + + project.getTasks().register( GEN_TASK_NAME, JpaMetamodelGenerationTask.class, (genTask) -> { + genTask.onlyIf( (t) -> ormDsl.isMetamodelGenerationEnabled() ); + + if ( !ormDsl.isMetamodelGenerationEnabled() ) { + return; + } + + genTask.injectSourceSet( ormDsl.getSourceSet() ); + genTask.getGenerationOutputDirectory().set( ormDsl.getJpaMetamodel().getGenerationOutputDirectory() ); + + final JavaCompile modelCompileTask = modelCompileTaskRef.get(); + + final SourceSet sourceSet = ormDsl.getSourceSet().get(); + sourceSet.getAllSource().minus( sourceSet.getAllSource() ).forEach( (dir) -> { + final String language = dir.getName(); + final String languageCompileTaskName = sourceSet.getCompileTaskName( language ); + final AbstractCompile languageCompileTask = (AbstractCompile) project.getTasks().getByName( languageCompileTaskName ); + genTask.dependsOn( languageCompileTask ); + + modelCompileTask.setSourceCompatibility( languageCompileTask.getSourceCompatibility() ); + modelCompileTask.setTargetCompatibility( languageCompileTask.getTargetCompatibility() ); + genTask.injectJavaVersion( languageCompileTask.getSourceCompatibility() ); + + modelCompileTask.finalizedBy( modelCompileTask ); + } ); + + genTask.dependsOn( sourceSet.getProcessResourcesTaskName() ); + + genTask.finalizedBy( modelCompileTask ); + modelCompileTask.dependsOn( genTask ); + modelCompileTask.source( project.files( ormDsl.getJpaMetamodel().getGenerationOutputDirectory() ) ); + modelCompileTask.getDestinationDirectory().set( ormDsl.getJpaMetamodel().getCompileOutputDirectory() ); + + modelCompileTask.setClasspath( + project.getConfigurations().getByName( "runtimeClasspath" ).plus( sourceSet.getRuntimeClasspath() ) + ); + } ); + } + + private void prepareHbmTransformation(HibernateOrmSpec ormDsl, Project project) { + + } } diff --git a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/HibernateOrmSpec.java b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/HibernateOrmSpec.java index 1b349828ae..38cb107b9f 100644 --- a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/HibernateOrmSpec.java +++ b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/HibernateOrmSpec.java @@ -14,6 +14,7 @@ import org.gradle.api.plugins.ExtensionAware; import org.gradle.api.plugins.ExtensionContainer; import org.gradle.api.plugins.JavaPluginExtension; import org.gradle.api.provider.Property; +import org.gradle.api.provider.Provider; import org.gradle.api.tasks.SourceSet; import org.hibernate.orm.tooling.gradle.enhance.EnhancementSpec; @@ -27,34 +28,29 @@ public abstract class HibernateOrmSpec implements ExtensionAware { public static final String DSL_NAME = HIBERNATE; - private final Property hibernateVersionProperty; + private EnhancementSpec enhancementDsl; + private JpaMetamodelGenerationSpec jpaMetamodelDsl; + + private final Property useSameVersion; private final Project project; private final Property sourceSetProperty; - private final Property supportEnhancementProperty; - private final Property supportJpaMetamodelProperty; - private final EnhancementSpec enhancementDsl; - private final JpaMetamodelGenerationSpec jpaMetamodelDsl; + private final Provider enhancementDslAccess; + private final Provider jpaMetamodelDslAccess; @Inject public HibernateOrmSpec(Project project) { this.project = project; - hibernateVersionProperty = project.getObjects().property( String.class ); - hibernateVersionProperty.convention( HibernateVersion.version ); + useSameVersion = project.getObjects().property( Boolean.class ); + useSameVersion.convention( true ); sourceSetProperty = project.getObjects().property( SourceSet.class ); sourceSetProperty.convention( mainSourceSet( project ) ); - supportEnhancementProperty = project.getObjects().property( Boolean.class ); - supportEnhancementProperty.convention( true ); - - supportJpaMetamodelProperty = project.getObjects().property( Boolean.class ); - supportJpaMetamodelProperty.convention( true ); - - enhancementDsl = getExtensions().create( EnhancementSpec.DSL_NAME, EnhancementSpec.class, this, project ); - jpaMetamodelDsl = getExtensions().create( JpaMetamodelGenerationSpec.DSL_NAME, JpaMetamodelGenerationSpec.class, this, project ); + enhancementDslAccess = project.provider( () -> enhancementDsl ); + jpaMetamodelDslAccess = project.provider( () -> jpaMetamodelDsl ); } private static SourceSet mainSourceSet(Project project) { @@ -66,68 +62,126 @@ public abstract class HibernateOrmSpec implements ExtensionAware { return javaPluginExtension.getSourceSets().getByName( name ); } - public Property getHibernateVersionProperty() { - return hibernateVersionProperty; + /** + * Should the plugin inject a dependency on the same version of `hibernate-core` + * as the version of this plugin? The dependency is added to the `implementation` + * {@link org.gradle.api.artifacts.Configuration}. + *

+ * Defaults to {@code true}. If overriding and performing enhancement, be aware + * that Hibernate generally only supports using classes enhanced using matching + * versions between tooling and runtime. In other words, be careful. + */ + public Property getUseSameVersion() { + return useSameVersion; } - public void hibernateVersion(String version) { - setHibernateVersion( version ); + /** + * @see #getUseSameVersion() + */ + public void setUseSameVersion(boolean value) { + useSameVersion.set( value ); } - public void setHibernateVersion(String version) { - hibernateVersionProperty.set( version ); + /** + * @see #getUseSameVersion() + */ + public void useSameVersion() { + useSameVersion.set( true ); } - public Property getSourceSetProperty() { + /** + * The source-set containing the domain model. Defaults to the `main` source-set + */ + public Property getSourceSet() { return sourceSetProperty; } + /** + * @see #getSourceSet() + */ public void setSourceSet(String name) { setSourceSet( resolveSourceSet( name, project ) ); } + /** + * @see #getSourceSet() + */ public void setSourceSet(SourceSet sourceSet) { sourceSetProperty.set( sourceSet ); } + /** + * @see #getSourceSet() + */ public void sourceSet(String name) { setSourceSet( resolveSourceSet( name, project ) ); } + /** + * @see #getSourceSet() + */ public void sourceSet(SourceSet sourceSet) { setSourceSet( sourceSet ); } - public Property getSupportEnhancementProperty() { - return supportEnhancementProperty; - } + /** + * DSL extension for configuring bytecode enhancement. Also acts as the trigger for + * opting into bytecode enhancement + */ + public EnhancementSpec getEnhancement() { + if ( enhancementDsl == null ) { + enhancementDsl = getExtensions().create( EnhancementSpec.DSL_NAME, EnhancementSpec.class, this, project ); + } - public void disableEnhancement() { - supportEnhancementProperty.set( false ); - } - - public Property getSupportJpaMetamodelProperty() { - return supportJpaMetamodelProperty; - } - - public void disableJpaMetamodel() { - supportJpaMetamodelProperty.set( false ); - } - - public EnhancementSpec getEnhancementSpec() { return enhancementDsl; } - public void enhancement(Action action) { - action.execute( enhancementDsl ); + /** + * Provider access to {@link #getEnhancement()} + */ + public Provider getEnhancementDslAccess() { + return enhancementDslAccess; } - public JpaMetamodelGenerationSpec getJpaMetamodelSpec() { + public boolean isEnhancementEnabled() { + return enhancementDsl != null; + } + + /** + * @see #getEnhancement() + */ + public void enhancement(Action action) { + action.execute( getEnhancement() ); + } + + /** + * DSL extension for configuring JPA static metamodel generation. Also acts as the trigger for + * opting into the generation + */ + public JpaMetamodelGenerationSpec getJpaMetamodel() { + if ( jpaMetamodelDsl == null ) { + jpaMetamodelDsl = getExtensions().create( JpaMetamodelGenerationSpec.DSL_NAME, JpaMetamodelGenerationSpec.class, this, project ); + } return jpaMetamodelDsl; } + + /** + * Provider access to {@link #getJpaMetamodel()} + */ + public Provider getJpaMetamodelDslAccess() { + return jpaMetamodelDslAccess; + } + + public boolean isMetamodelGenerationEnabled() { + return jpaMetamodelDsl != null; + } + + /** + * @see #getJpaMetamodel() + */ public void jpaMetamodel(Actionaction) { - action.execute( jpaMetamodelDsl ); + action.execute( getJpaMetamodel() ); } @Override diff --git a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/enhance/EnhancementHelper.java b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/enhance/EnhancementHelper.java index 67f17f30d5..4af900eea4 100644 --- a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/enhance/EnhancementHelper.java +++ b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/enhance/EnhancementHelper.java @@ -89,7 +89,7 @@ public class EnhancementHelper { } public static Enhancer generateEnhancer(ClassLoader classLoader, HibernateOrmSpec ormDsl) { - final EnhancementSpec enhancementDsl = ormDsl.getEnhancementSpec(); + final EnhancementSpec enhancementDsl = ormDsl.getEnhancement(); final EnhancementContext enhancementContext = new DefaultEnhancementContext() { @Override diff --git a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/JpaMetamodelGenerationSpec.java b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/JpaMetamodelGenerationSpec.java index 5a5daef65c..9a2ba7c1cb 100644 --- a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/JpaMetamodelGenerationSpec.java +++ b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/JpaMetamodelGenerationSpec.java @@ -12,11 +12,11 @@ import javax.inject.Inject; import org.gradle.api.JavaVersion; import org.gradle.api.Project; import org.gradle.api.file.DirectoryProperty; -import org.gradle.api.plugins.JavaPluginConvention; import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider; import org.gradle.api.provider.SetProperty; import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.SourceSetContainer; import org.gradle.api.tasks.compile.JavaCompile; import org.hibernate.orm.tooling.gradle.HibernateOrmSpec; @@ -37,7 +37,6 @@ public class JpaMetamodelGenerationSpec { private final Provider targetJavaVersionAccess; @Inject - @SuppressWarnings( "UnstableApiUsage" ) public JpaMetamodelGenerationSpec(HibernateOrmSpec ormDsl, Project project) { this.project = project; @@ -57,16 +56,13 @@ public class JpaMetamodelGenerationSpec { project.getLayout().getBuildDirectory().dir( "classes/java/" + JPA_METAMODEL ) ); - targetJavaVersionAccess = project.provider( - () -> { - final JavaPluginConvention javaPluginConvention = project.getConvention().findPlugin( JavaPluginConvention.class ); - assert javaPluginConvention != null; - final SourceSet sourceSet = javaPluginConvention.getSourceSets().getByName( SourceSet.MAIN_SOURCE_SET_NAME ); - final String compileTaskName = sourceSet.getCompileJavaTaskName(); - final JavaCompile compileTask = (JavaCompile) project.getTasks().getByName( compileTaskName ); - return JavaVersion.toVersion( compileTask.getTargetCompatibility() ); - } - ); + targetJavaVersionAccess = project.provider( () -> { + final SourceSetContainer sourceSets = project.getExtensions().getByType( SourceSetContainer.class ); + final SourceSet sourceSet = sourceSets.getByName( SourceSet.MAIN_SOURCE_SET_NAME ); + final String compileTaskName = sourceSet.getCompileJavaTaskName(); + final JavaCompile compileTask = (JavaCompile) project.getTasks().getByName( compileTaskName ); + return JavaVersion.toVersion( compileTask.getTargetCompatibility() ); + } ); } public Provider getTargetJavaVersionAccess() { diff --git a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/JpaMetamodelGenerationTask.java b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/JpaMetamodelGenerationTask.java index 1782bd970e..7ccdf12a64 100644 --- a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/JpaMetamodelGenerationTask.java +++ b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/JpaMetamodelGenerationTask.java @@ -8,42 +8,33 @@ package org.hibernate.orm.tooling.gradle.metamodel; import java.io.File; import java.net.MalformedURLException; -import java.net.URI; import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.List; +import java.util.Arrays; import java.util.Properties; import javax.inject.Inject; -import javax.sql.DataSource; import org.gradle.api.DefaultTask; -import org.gradle.api.GradleException; +import org.gradle.api.JavaVersion; import org.gradle.api.Project; -import org.gradle.api.Task; import org.gradle.api.file.ConfigurableFileTree; +import org.gradle.api.file.Directory; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.file.FileCollection; +import org.gradle.api.provider.Property; +import org.gradle.api.provider.Provider; +import org.gradle.api.provider.SetProperty; +import org.gradle.api.tasks.Input; import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.SkipWhenEmpty; import org.gradle.api.tasks.SourceSet; -import org.gradle.api.tasks.SourceSetOutput; import org.gradle.api.tasks.TaskAction; -import org.gradle.api.tasks.compile.JavaCompile; import org.hibernate.cfg.AvailableSettings; -import org.hibernate.jpa.HibernatePersistenceProvider; import org.hibernate.orm.tooling.gradle.Helper; import org.hibernate.orm.tooling.gradle.HibernateOrmSpec; +import org.hibernate.orm.tooling.gradle.metamodel.model.GenerationOptions; import org.hibernate.orm.tooling.gradle.metamodel.model.JpaStaticMetamodelGenerator; -import org.hibernate.orm.tooling.gradle.metamodel.model.MetamodelClass; - -import jakarta.persistence.SharedCacheMode; -import jakarta.persistence.ValidationMode; -import jakarta.persistence.spi.ClassTransformer; -import jakarta.persistence.spi.PersistenceUnitInfo; -import jakarta.persistence.spi.PersistenceUnitTransactionType; import static org.hibernate.orm.tooling.gradle.HibernateOrmSpec.HIBERNATE; @@ -56,86 +47,114 @@ import static org.hibernate.orm.tooling.gradle.HibernateOrmSpec.HIBERNATE; * classes based on annotations. This task accounts for both classes and XML mappings */ public class JpaMetamodelGenerationTask extends DefaultTask { - public static final String DSL_NAME = "generateJpaMetamodel"; - public static final String COMPILE_DSL_NAME = "compileJpaMetamodel"; + public static final String GEN_TASK_NAME = "generateJpaMetamodel"; + public static final String COMPILE_META_TASK_NAME = "compileJpaMetamodel"; + private final DirectoryProperty generationOutputDirectory; + + private final Property sourceSetProperty; + private final Property applyGeneratedAnnotation; + private final SetProperty suppressions; + + private final Property javaVersion; - private final HibernateOrmSpec ormSpec; - private final DirectoryProperty resourcesOutputDir; - private final SourceSet mainSourceSet; @Inject - @SuppressWarnings( "UnstableApiUsage" ) - public JpaMetamodelGenerationTask( - HibernateOrmSpec ormSpec, - SourceSet mainSourceSet, - JavaCompile mainCompileTask, - Project project) { - this.ormSpec = ormSpec; - dependsOn( mainCompileTask ); + public JpaMetamodelGenerationTask() { + setGroup( HIBERNATE ); + setDescription( "Generates the JPA 'static metamodel'" ); - this.mainSourceSet = mainSourceSet; + sourceSetProperty = getProject().getObjects().property( SourceSet.class ); - final SourceSetOutput mainSourceSetOutput = mainSourceSet.getOutput(); + generationOutputDirectory = getProject().getObjects().directoryProperty(); - resourcesOutputDir = project.getObjects().directoryProperty(); - resourcesOutputDir.set( project.getLayout().dir( project.provider( mainSourceSetOutput::getResourcesDir ) ) ); + applyGeneratedAnnotation = getProject().getObjects().property( Boolean.class ); + applyGeneratedAnnotation.convention( true ); + suppressions = getProject().getObjects().setProperty( String.class ); + suppressions.convention( Arrays.asList( "raw", "deprecation" ) ); + + javaVersion = getProject().getObjects().property( JavaVersion.class ); + javaVersion.convention( JavaVersion.current() ); } - @InputFiles - @SkipWhenEmpty - public FileCollection getJavaClassDirs() { - return mainSourceSet.getOutput(); + public void injectSourceSet(Provider sourceSetAccess) { + sourceSetProperty.set( sourceSetAccess ); } - @InputFiles - @SkipWhenEmpty - public DirectoryProperty getResourcesOutputDir() { - // for access to XML mappings - return resourcesOutputDir; + public void injectJavaVersion(Object version) { + javaVersion.set( JavaVersion.toVersion( version ) ); } @OutputDirectory public DirectoryProperty getGenerationOutputDirectory() { - return ormSpec.getJpaMetamodelSpec().getGenerationOutputDirectory(); + return generationOutputDirectory; + } + + @InputFiles + @SkipWhenEmpty + public FileCollection getSources() { + return sourceSetProperty.get().getOutput(); + } + + @Input + public Property getApplyGeneratedAnnotation() { + return applyGeneratedAnnotation; + } + + @Input + public SetProperty getSuppressions() { + return suppressions; } @TaskAction public void generateJpaMetamodel() { - final ClassLoader classLoader = determineUnitClassLoader( getProject(), mainSourceSet ); + final ClassLoader classLoader = Helper.toClassLoader( sourceSetProperty.get().getOutput() ); final PersistenceUnitInfoImpl unitInfo = new PersistenceUnitInfoImpl( determineUnitUrl(), generateIntegrationSettings(), classLoader ); - getJavaClassDirs().forEach( - classesDir -> { - final ConfigurableFileTree files = getProject().fileTree( classesDir ); - files.forEach( - file -> { - if ( file.getName().endsWith( ".class" ) ) { - final String className = Helper.determineClassName( classesDir, file ); - unitInfo.addManagedClassName( className ); - } - else if ( isMappingFile( file ) ) { - unitInfo.addMappingFile( file.getName() ); - } - } - ); - } - ); - resourcesOutputDir.getAsFileTree().forEach( - file -> { - if ( isMappingFile( file ) ) { - unitInfo.addMappingFile( file.getName() ); - } + getSources().forEach( (dir) -> { + final ConfigurableFileTree files = getProject().fileTree( dir ); + files.forEach( (file) -> { + if ( file.getName().endsWith( ".class" ) ) { + final String className = Helper.determineClassName( dir, file ); + unitInfo.addManagedClassName( className ); } - ); + else if ( isMappingFile( file ) ) { + unitInfo.addMappingFile( file.getName() ); + } + } ); + } ); - JpaStaticMetamodelGenerator.processMetamodel( unitInfo, ormSpec.getJpaMetamodelSpec() ); + JpaStaticMetamodelGenerator.processMetamodel( unitInfo, createGenerationOptions() ); + } + + private GenerationOptions createGenerationOptions() { + return new GenerationOptions() { + @Override + public Provider getGenerationDirectory() { + return generationOutputDirectory; + } + + @Override + public Provider getApplyGeneratedAnnotation() { + return applyGeneratedAnnotation; + } + + @Override + public SetProperty getSuppressions() { + return suppressions; + } + + @Override + public Provider getTargetJavaVersionAccess() { + return javaVersion; + } + }; } private URL determineUnitUrl() { @@ -148,25 +167,6 @@ public class JpaMetamodelGenerationTask extends DefaultTask { } } - @SuppressWarnings( "UnstableApiUsage" ) - private static ClassLoader determineUnitClassLoader(Project project, SourceSet mainSourceSet) { - final String compileJavaTaskName = mainSourceSet.getCompileJavaTaskName(); - final JavaCompile javaCompileTask = (JavaCompile) project.getTasks().getByName( compileJavaTaskName ); - final URL projectClassesDirUrl = toUrl( javaCompileTask.getDestinationDirectory().get().getAsFile() ); - - return new URLClassLoader( new URL[] { projectClassesDirUrl }, MetamodelClass.class.getClassLoader() ); - } - - private static URL toUrl(File file) { - final URI uri = file.toURI(); - try { - return uri.toURL(); - } - catch (MalformedURLException e) { - throw new GradleException( "Could not convert classpath entry into URL : " + file.getAbsolutePath(), e ); - } - } - private Properties generateIntegrationSettings() { final Properties settings = new Properties(); @@ -186,151 +186,7 @@ public class JpaMetamodelGenerationTask extends DefaultTask { return fileName.endsWith( ".hbm.xml" ) || fileName.endsWith( ".orm.xml" ); } - private static class PersistenceUnitInfoImpl implements PersistenceUnitInfo { - private final URL unitRoot; - private final Properties properties; - private final ClassLoader classLoader; - private final List managedClassNames = new ArrayList<>(); - private final List mappingFileNames = new ArrayList<>(); - - public PersistenceUnitInfoImpl(URL unitRoot, Properties properties, ClassLoader classLoader) { - this.unitRoot = unitRoot; - this.properties = properties; - this.classLoader = classLoader; - } - - @Override - public String getPersistenceUnitName() { - return "jpa-static-metamodel-gen"; - } - - @Override - public URL getPersistenceUnitRootUrl() { - return unitRoot; - } - - @Override - public Properties getProperties() { - return properties; - } - - @Override - public ClassLoader getClassLoader() { - return classLoader; - } - - @Override - public List getManagedClassNames() { - return managedClassNames; - } - - public void addManagedClassName(String className) { - getManagedClassNames().add( className ); - } - - @Override - public List getMappingFileNames() { - return mappingFileNames; - } - - public void addMappingFile(String fileName) { - getMappingFileNames().add( fileName ); - } - - - - - - @Override - public String getPersistenceProviderClassName() { - return HibernatePersistenceProvider.class.getName(); - } - - @Override - public PersistenceUnitTransactionType getTransactionType() { - return null; - } - - @Override - public DataSource getJtaDataSource() { - return null; - } - - @Override - public DataSource getNonJtaDataSource() { - return null; - } - - @Override - public List getJarFileUrls() { - return null; - } - - @Override - public boolean excludeUnlistedClasses() { - return true; - } - - @Override - public SharedCacheMode getSharedCacheMode() { - return null; - } - - @Override - public ValidationMode getValidationMode() { - return null; - } - - @Override - public String getPersistenceXMLSchemaVersion() { - return null; - } - - @Override - public void addTransformer(ClassTransformer transformer) { - - } - - @Override - public ClassLoader getNewTempClassLoader() { - return null; - } - } - - @SuppressWarnings( "UnstableApiUsage" ) - public static void apply(HibernateOrmSpec pluginDsl, SourceSet mainSourceSet, Project project) { - final String mainCompileTaskName = mainSourceSet.getCompileJavaTaskName(); - final JavaCompile mainCompileTask = (JavaCompile) project.getTasks().getByName( mainCompileTaskName ); - final Task compileResourcesTask = project.getTasks().getByName( "processResources" ); - - final JpaMetamodelGenerationTask genTask = project.getTasks().create( - DSL_NAME, - JpaMetamodelGenerationTask.class, - pluginDsl, - mainSourceSet, - mainCompileTask, - project - ); - genTask.setGroup( HIBERNATE ); - genTask.setDescription( "Generates the JPA 'static metamodel'" ); - genTask.onlyIf( (t) -> pluginDsl.getSupportJpaMetamodelProperty().getOrElse( true ) ); - - genTask.dependsOn( mainCompileTask ); - genTask.dependsOn( compileResourcesTask ); - - final JavaCompile compileJpaMetamodelTask = project.getTasks().create( COMPILE_DSL_NAME, JavaCompile.class ); - compileJpaMetamodelTask.setGroup( HIBERNATE ); - compileJpaMetamodelTask.setDescription( "Compiles the JPA static metamodel generated by `" + DSL_NAME + "`" ); - compileJpaMetamodelTask.setSourceCompatibility( mainCompileTask.getSourceCompatibility() ); - compileJpaMetamodelTask.setTargetCompatibility( mainCompileTask.getTargetCompatibility() ); - genTask.finalizedBy( compileJpaMetamodelTask ); - mainCompileTask.finalizedBy( compileJpaMetamodelTask ); - compileJpaMetamodelTask.dependsOn( genTask ); - compileJpaMetamodelTask.source( project.files( pluginDsl.getJpaMetamodelSpec().getGenerationOutputDirectory() ) ); - compileJpaMetamodelTask.getDestinationDirectory().set( pluginDsl.getJpaMetamodelSpec().getCompileOutputDirectory() ); - compileJpaMetamodelTask.setClasspath( - project.getConfigurations().getByName( "runtimeClasspath" ).plus( mainSourceSet.getRuntimeClasspath() ) - ); + public static void apply(HibernateOrmSpec pluginDsl, Project project) { } } diff --git a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/PersistenceUnitInfoImpl.java b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/PersistenceUnitInfoImpl.java new file mode 100644 index 0000000000..7f2af12591 --- /dev/null +++ b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/PersistenceUnitInfoImpl.java @@ -0,0 +1,131 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html. + */ +package org.hibernate.orm.tooling.gradle.metamodel; + +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import javax.sql.DataSource; + +import org.hibernate.jpa.HibernatePersistenceProvider; + +import jakarta.persistence.SharedCacheMode; +import jakarta.persistence.ValidationMode; +import jakarta.persistence.spi.ClassTransformer; +import jakarta.persistence.spi.PersistenceUnitInfo; +import jakarta.persistence.spi.PersistenceUnitTransactionType; + +/** + * @author Steve Ebersole + */ +class PersistenceUnitInfoImpl implements PersistenceUnitInfo { + private final URL unitRoot; + private final Properties properties; + private final ClassLoader classLoader; + private final List managedClassNames = new ArrayList<>(); + private final List mappingFileNames = new ArrayList<>(); + + public PersistenceUnitInfoImpl(URL unitRoot, Properties properties, ClassLoader classLoader) { + this.unitRoot = unitRoot; + this.properties = properties; + this.classLoader = classLoader; + } + + @Override + public String getPersistenceUnitName() { + return "jpa-static-metamodel-gen"; + } + + @Override + public URL getPersistenceUnitRootUrl() { + return unitRoot; + } + + @Override + public Properties getProperties() { + return properties; + } + + @Override + public ClassLoader getClassLoader() { + return classLoader; + } + + @Override + public List getManagedClassNames() { + return managedClassNames; + } + + public void addManagedClassName(String className) { + getManagedClassNames().add( className ); + } + + @Override + public List getMappingFileNames() { + return mappingFileNames; + } + + public void addMappingFile(String fileName) { + getMappingFileNames().add( fileName ); + } + + @Override + public String getPersistenceProviderClassName() { + return HibernatePersistenceProvider.class.getName(); + } + + @Override + public PersistenceUnitTransactionType getTransactionType() { + return null; + } + + @Override + public DataSource getJtaDataSource() { + return null; + } + + @Override + public DataSource getNonJtaDataSource() { + return null; + } + + @Override + public List getJarFileUrls() { + return null; + } + + @Override + public boolean excludeUnlistedClasses() { + return true; + } + + @Override + public SharedCacheMode getSharedCacheMode() { + return null; + } + + @Override + public ValidationMode getValidationMode() { + return null; + } + + @Override + public String getPersistenceXMLSchemaVersion() { + return null; + } + + @Override + public void addTransformer(ClassTransformer transformer) { + + } + + @Override + public ClassLoader getNewTempClassLoader() { + return null; + } +} diff --git a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/model/GenerationOptions.java b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/model/GenerationOptions.java new file mode 100644 index 0000000000..7f26bb2ad0 --- /dev/null +++ b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/model/GenerationOptions.java @@ -0,0 +1,22 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html. + */ +package org.hibernate.orm.tooling.gradle.metamodel.model; + +import org.gradle.api.JavaVersion; +import org.gradle.api.file.Directory; +import org.gradle.api.provider.Provider; +import org.gradle.api.provider.SetProperty; + +/** + * @author Steve Ebersole + */ +public interface GenerationOptions { + Provider getGenerationDirectory(); + Provider getApplyGeneratedAnnotation(); + SetProperty getSuppressions(); + Provider getTargetJavaVersionAccess(); +} diff --git a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/model/JpaStaticMetamodelGenerator.java b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/model/JpaStaticMetamodelGenerator.java index fd0eaa3f91..4165b2966c 100644 --- a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/model/JpaStaticMetamodelGenerator.java +++ b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/model/JpaStaticMetamodelGenerator.java @@ -11,7 +11,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.Set; -import jakarta.persistence.spi.PersistenceUnitInfo; import org.gradle.api.file.Directory; import org.gradle.api.file.RegularFile; @@ -23,22 +22,24 @@ import org.hibernate.mapping.Component; import org.hibernate.mapping.MappedSuperclass; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; -import org.hibernate.orm.tooling.gradle.metamodel.JpaMetamodelGenerationSpec; + +import jakarta.persistence.spi.PersistenceUnitInfo; public class JpaStaticMetamodelGenerator { + public static void processMetamodel( PersistenceUnitInfo persistenceUnitInfo, - JpaMetamodelGenerationSpec spec) { + GenerationOptions options) { EntityManagerFactoryBuilder target = Bootstrap.getEntityManagerFactoryBuilder( persistenceUnitInfo, Collections.emptyMap() ); try { - new JpaStaticMetamodelGenerator( spec, target.metadata() ).process(); + new JpaStaticMetamodelGenerator( options, target.metadata() ).process(); } finally { target.cancel(); } } - private final JpaMetamodelGenerationSpec spec; + private final GenerationOptions options; private final MetadataImplementor metadata; private final Directory generationOutputDirectory; @@ -46,10 +47,10 @@ public class JpaStaticMetamodelGenerator { private final Set processedDomainTypeNames = new HashSet<>(); - private JpaStaticMetamodelGenerator(JpaMetamodelGenerationSpec spec, MetadataImplementor metadata) { - this.spec = spec; + private JpaStaticMetamodelGenerator(GenerationOptions options, MetadataImplementor metadata) { + this.options = options; this.metadata = metadata; - this.generationOutputDirectory = spec.getGenerationOutputDirectory().get(); + this.generationOutputDirectory = options.getGenerationDirectory().get(); this.objectFactory = new ObjectFactory( metadata ); } @@ -94,10 +95,9 @@ public class JpaStaticMetamodelGenerator { final RegularFile metamodelClassJavaFile = generationOutputDirectory.file( metamodelClassJavaFileName ); final File metamodelClassJavaFileAsFile = metamodelClassJavaFile.getAsFile(); - metamodelClass.writeToFile( metamodelClassJavaFileAsFile, spec ); + metamodelClass.writeToFile( metamodelClassJavaFileAsFile, options ); } - @SuppressWarnings( "unchecked" ) private void handleEmbeddable(Component embeddedValueMapping) { final MetamodelClass metamodelClass = objectFactory.metamodelClass( embeddedValueMapping ); handleManagedClass( metamodelClass, embeddedValueMapping.getPropertyIterator() ); diff --git a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/model/MetamodelClass.java b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/model/MetamodelClass.java index 28a17ba59b..c3ddce2e38 100644 --- a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/model/MetamodelClass.java +++ b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/orm/tooling/gradle/metamodel/model/MetamodelClass.java @@ -24,8 +24,6 @@ import java.util.TreeSet; import org.gradle.api.GradleException; import org.gradle.api.JavaVersion; -import org.hibernate.orm.tooling.gradle.metamodel.JpaMetamodelGenerationSpec; - import static java.lang.Character.LINE_SEPARATOR; /** @@ -59,14 +57,14 @@ public class MetamodelClass { attributes.add( attribute ); } - public void writeToFile(File outputFile, JpaMetamodelGenerationSpec spec) { + public void writeToFile(File outputFile, GenerationOptions options) { prepareOutputFile( outputFile ); final Path path = outputFile.toPath(); try ( final BufferedWriter writer = Files.newBufferedWriter( path, StandardCharsets.UTF_8, StandardOpenOption.WRITE ) ) { - renderClassPreamble( writer, spec ); + renderClassPreamble( writer, options ); writer.write( LINE_SEPARATOR ); writer.write( "public abstract class " + metamodelClassName ); @@ -96,7 +94,7 @@ public class MetamodelClass { } } - private void renderClassPreamble(BufferedWriter writer, JpaMetamodelGenerationSpec spec) throws IOException { + private void renderClassPreamble(BufferedWriter writer, GenerationOptions options) throws IOException { final String nowFormatted = DateFormat.getDateInstance().format( new Date() ); writer.write( "// Generated by Hibernate ORM Gradle tooling - " + nowFormatted ); @@ -113,8 +111,8 @@ public class MetamodelClass { writer.write( LINE_SEPARATOR ); // first, the generated annotation - if ( spec.getApplyGeneratedAnnotation().getOrElse( true ) ) { - final JavaVersion javaVersion = spec.getTargetJavaVersionAccess().getOrElse( JavaVersion.current() ); + if ( options.getApplyGeneratedAnnotation().getOrElse( true ) ) { + final JavaVersion javaVersion = options.getTargetJavaVersionAccess().getOrElse( JavaVersion.current() ); final String qualifiedAnnotationName = javaVersion.isJava9Compatible() ? "javax.annotation.processing.Generated" : "jakarta.annotation.Generated"; @@ -130,7 +128,7 @@ public class MetamodelClass { writer.write( LINE_SEPARATOR ); } - final Set suppressions = spec.getSuppressions().getOrElse( Collections.emptySet() ); + final Set suppressions = options.getSuppressions().getOrElse( Collections.emptySet() ); if ( ! suppressions.isEmpty() ) { writer.write( "@SuppressWarnings( { " ); for ( String suppression : suppressions ) { diff --git a/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/orm/tooling/gradle/HibernateOrmPluginTest.java b/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/orm/tooling/gradle/JavaProjectTests.java similarity index 59% rename from tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/orm/tooling/gradle/HibernateOrmPluginTest.java rename to tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/orm/tooling/gradle/JavaProjectTests.java index 41813c3d21..16b07d2c46 100644 --- a/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/orm/tooling/gradle/HibernateOrmPluginTest.java +++ b/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/orm/tooling/gradle/JavaProjectTests.java @@ -14,13 +14,9 @@ import org.gradle.testkit.runner.BuildTask; import org.gradle.testkit.runner.GradleRunner; import org.gradle.testkit.runner.TaskOutcome; -import org.hibernate.engine.spi.Managed; - import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import org.assertj.core.api.Condition; - import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -29,15 +25,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; * * @author Steve Ebersole */ -class HibernateOrmPluginTest { - private static final Condition SUCCESS = new Condition<>( - (taskOutcome) -> taskOutcome == TaskOutcome.SUCCESS, - "task succeeded" - ); - private static final Condition UP_TO_DATE = new Condition<>( - (taskOutcome) -> taskOutcome == TaskOutcome.UP_TO_DATE, - "task up-to-date" - ); +class JavaProjectTests { @Test public void testEnhancement(@TempDir Path projectDir) throws Exception { @@ -59,13 +47,8 @@ class HibernateOrmPluginTest { // make sure the class is enhanced final File classesDir = new File( projectDir.toFile(), "build/classes/java/main" ); final ClassLoader classLoader = Helper.toClassLoader( classesDir ); - verifyEnhanced( classLoader, "TheEmbeddable" ); - verifyEnhanced( classLoader, "TheEntity" ); - } - - private void verifyEnhanced(ClassLoader classLoader, String className) throws Exception { - final Class loadedClass = classLoader.loadClass( className ); - assertThat( Managed.class ).isAssignableFrom( loadedClass ); + TestHelper.verifyEnhanced( classLoader, "TheEmbeddable" ); + TestHelper.verifyEnhanced( classLoader, "TheEntity" ); } @Test @@ -89,7 +72,7 @@ class HibernateOrmPluginTest { // make sure the class is enhanced final File classesDir = new File( projectDir.toFile(), "build/classes/java/main" ); final ClassLoader classLoader = Helper.toClassLoader( classesDir ); - verifyEnhanced( classLoader, "TheEntity" ); + TestHelper.verifyEnhanced( classLoader, "TheEntity" ); } { @@ -108,7 +91,7 @@ class HibernateOrmPluginTest { // and again final File classesDir = new File( projectDir.toFile(), "build/classes/java/main" ); final ClassLoader classLoader = Helper.toClassLoader( classesDir ); - verifyEnhanced( classLoader, "TheEntity" ); + TestHelper.verifyEnhanced( classLoader, "TheEntity" ); } } @@ -127,10 +110,10 @@ class HibernateOrmPluginTest { final BuildTask task = result.task( ":generateJpaMetamodel" ); assertThat( task ).isNotNull(); assertThat( task.getOutcome() ).isEqualTo( TaskOutcome.SUCCESS ); + assertThat( new File( projectDir.toFile(), "build/classes/java/jpaMetamodel" ) ).exists(); } @Test -// @Disabled( "up-to-date checking not working" ) public void testJpaMetamodelGenUpToDate(@TempDir Path projectDir) { Copier.copyProject( "simple/build.gradle", projectDir ); @@ -147,6 +130,7 @@ class HibernateOrmPluginTest { final BuildTask task = result.task( ":generateJpaMetamodel" ); assertThat( task ).isNotNull(); assertThat( task.getOutcome() ).isEqualTo( TaskOutcome.SUCCESS ); + assertThat( new File( projectDir.toFile(), "build/classes/java/jpaMetamodel" ) ).exists(); } { @@ -162,75 +146,7 @@ class HibernateOrmPluginTest { final BuildTask task2 = result2.task( ":generateJpaMetamodel" ); assertThat( task2 ).isNotNull(); assertThat( task2.getOutcome() ).isEqualTo( TaskOutcome.UP_TO_DATE ); + assertThat( new File( projectDir.toFile(), "build/classes/java/jpaMetamodel" ) ).exists(); } } - - @Test - public void testEnhanceKotlinModel(@TempDir Path projectDir) throws Exception { - Copier.copyProject( "simple-kotlin/build.gradle", projectDir ); - - final GradleRunner gradleRunner = GradleRunner.create() - .withProjectDir( projectDir.toFile() ) - .withPluginClasspath() - .withDebug( true ) - .withArguments( "clean", "compileKotlin", "--stacktrace", "--no-build-cache" ) - .forwardOutput(); - - final BuildResult result = gradleRunner.build(); - final BuildTask task = result.task( ":compileKotlin" ); - assertThat( task ).isNotNull(); - assertThat( task.getOutcome() ).isEqualTo( TaskOutcome.SUCCESS ); - - // make sure the class is enhanced - final File classesDir = new File( projectDir.toFile(), "build/classes/kotlin/main" ); - final ClassLoader classLoader = Helper.toClassLoader( classesDir ); - verifyEnhanced( classLoader, "TheEntity" ); - } - - @Test - public void testEnhanceKotlinModelUpToDate(@TempDir Path projectDir) throws Exception { - Copier.copyProject( "simple-kotlin/build.gradle", projectDir ); - - { - System.out.println( "First execution ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" ); - - final GradleRunner gradleRunner = GradleRunner.create() - .withProjectDir( projectDir.toFile() ) - .withPluginClasspath() - .withDebug( true ) - .withArguments( "clean", "compileKotlin", "--stacktrace", "--no-build-cache" ) - .forwardOutput(); - - final BuildResult result = gradleRunner.build(); - final BuildTask task = result.task( ":compileKotlin" ); - assertThat( task ).isNotNull(); - assertThat( task.getOutcome() ).isEqualTo( TaskOutcome.SUCCESS ); - - // make sure the class is enhanced - final File classesDir = new File( projectDir.toFile(), "build/classes/kotlin/main" ); - final ClassLoader classLoader = Helper.toClassLoader( classesDir ); - verifyEnhanced( classLoader, "TheEntity" ); - } - { - System.out.println( "Second execution ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" ); - - final GradleRunner gradleRunner = GradleRunner.create() - .withProjectDir( projectDir.toFile() ) - .withPluginClasspath() - .withDebug( true ) - .withArguments( "compileKotlin", "--stacktrace", "--no-build-cache" ) - .forwardOutput(); - - final BuildResult result = gradleRunner.build(); - final BuildTask task = result.task( ":compileKotlin" ); - assertThat( task ).isNotNull(); - assertThat( task.getOutcome() ).isEqualTo( TaskOutcome.UP_TO_DATE ); - - // make sure the class is enhanced - final File classesDir = new File( projectDir.toFile(), "build/classes/kotlin/main" ); - final ClassLoader classLoader = Helper.toClassLoader( classesDir ); - verifyEnhanced( classLoader, "TheEntity" ); - } - - } } diff --git a/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/orm/tooling/gradle/KotlinProjectTests.java b/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/orm/tooling/gradle/KotlinProjectTests.java new file mode 100644 index 0000000000..4574c529a3 --- /dev/null +++ b/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/orm/tooling/gradle/KotlinProjectTests.java @@ -0,0 +1,150 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html. + */ +package org.hibernate.orm.tooling.gradle; + +import java.io.File; +import java.nio.file.Path; + +import org.gradle.testkit.runner.BuildResult; +import org.gradle.testkit.runner.BuildTask; +import org.gradle.testkit.runner.GradleRunner; +import org.gradle.testkit.runner.TaskOutcome; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.hibernate.orm.tooling.gradle.TestHelper.verifyEnhanced; + +/** + * @author Steve Ebersole + */ +public class KotlinProjectTests { + + @Test + public void testEnhanceModel(@TempDir Path projectDir) throws Exception { + Copier.copyProject( "simple-kotlin/build.gradle", projectDir ); + + final GradleRunner gradleRunner = GradleRunner.create() + .withProjectDir( projectDir.toFile() ) + .withPluginClasspath() + .withDebug( true ) + .withArguments( "clean", "compileKotlin", "--stacktrace", "--no-build-cache" ) + .forwardOutput(); + + final BuildResult result = gradleRunner.build(); + final BuildTask task = result.task( ":compileKotlin" ); + assertThat( task ).isNotNull(); + assertThat( task.getOutcome() ).isEqualTo( TaskOutcome.SUCCESS ); + + // make sure the class is enhanced + final File classesDir = new File( projectDir.toFile(), "build/classes/kotlin/main" ); + final ClassLoader classLoader = Helper.toClassLoader( classesDir ); + verifyEnhanced( classLoader, "TheEntity" ); + } + + @Test + public void testEnhanceModelUpToDate(@TempDir Path projectDir) throws Exception { + Copier.copyProject( "simple-kotlin/build.gradle", projectDir ); + + { + System.out.println( "First execution ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" ); + + final GradleRunner gradleRunner = GradleRunner.create() + .withProjectDir( projectDir.toFile() ) + .withPluginClasspath() + .withDebug( true ) + .withArguments( "clean", "compileKotlin", "--stacktrace", "--no-build-cache" ) + .forwardOutput(); + + final BuildResult result = gradleRunner.build(); + final BuildTask task = result.task( ":compileKotlin" ); + assertThat( task ).isNotNull(); + assertThat( task.getOutcome() ).isEqualTo( TaskOutcome.SUCCESS ); + + // make sure the class is enhanced + final File classesDir = new File( projectDir.toFile(), "build/classes/kotlin/main" ); + final ClassLoader classLoader = Helper.toClassLoader( classesDir ); + verifyEnhanced( classLoader, "TheEntity" ); + } + { + System.out.println( "Second execution ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" ); + + final GradleRunner gradleRunner = GradleRunner.create() + .withProjectDir( projectDir.toFile() ) + .withPluginClasspath() + .withDebug( true ) + .withArguments( "compileKotlin", "--stacktrace", "--no-build-cache" ) + .forwardOutput(); + + final BuildResult result = gradleRunner.build(); + final BuildTask task = result.task( ":compileKotlin" ); + assertThat( task ).isNotNull(); + assertThat( task.getOutcome() ).isEqualTo( TaskOutcome.UP_TO_DATE ); + + // make sure the class is enhanced + final File classesDir = new File( projectDir.toFile(), "build/classes/kotlin/main" ); + final ClassLoader classLoader = Helper.toClassLoader( classesDir ); + verifyEnhanced( classLoader, "TheEntity" ); + } + } + + @Test + public void testJpaMetamodelGen(@TempDir Path projectDir) { + Copier.copyProject( "simple-kotlin/build.gradle", projectDir ); + + final GradleRunner gradleRunner = GradleRunner.create() + .withProjectDir( projectDir.toFile() ) + .withPluginClasspath() + .withDebug( true ) + .withArguments( "clean", "generateJpaMetamodel", "--stacktrace", "--no-build-cache" ) + .forwardOutput(); + + final BuildResult result = gradleRunner.build(); + final BuildTask task = result.task( ":generateJpaMetamodel" ); + assertThat( task ).isNotNull(); + assertThat( task.getOutcome() ).isEqualTo( TaskOutcome.SUCCESS ); + assertThat( new File( projectDir.toFile(), "build/classes/java/jpaMetamodel" ) ).exists(); + } + + @Test + public void testJpaMetamodelGenUpToDate(@TempDir Path projectDir) { + Copier.copyProject( "simple-kotlin/build.gradle", projectDir ); + + { + System.out.println( "First execution ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" ); + final GradleRunner gradleRunner = GradleRunner.create() + .withProjectDir( projectDir.toFile() ) + .withPluginClasspath() + .withDebug( true ) + .withArguments( "clean", "generateJpaMetamodel", "--stacktrace", "--no-build-cache" ) + .forwardOutput(); + + final BuildResult result = gradleRunner.build(); + final BuildTask task = result.task( ":generateJpaMetamodel" ); + assertThat( task ).isNotNull(); + assertThat( task.getOutcome() ).isEqualTo( TaskOutcome.SUCCESS ); + assertThat( new File( projectDir.toFile(), "build/classes/java/jpaMetamodel" ) ).exists(); + } + + { + System.out.println( "Second execution ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" ); + final GradleRunner gradleRunner2 = GradleRunner.create() + .withProjectDir( projectDir.toFile() ) + .withPluginClasspath() + .withDebug( true ) + .withArguments( "generateJpaMetamodel", "--stacktrace", "--no-build-cache" ) + .forwardOutput(); + + final BuildResult result2 = gradleRunner2.build(); + final BuildTask task2 = result2.task( ":generateJpaMetamodel" ); + assertThat( task2 ).isNotNull(); + assertThat( task2.getOutcome() ).isEqualTo( TaskOutcome.UP_TO_DATE ); + assertThat( new File( projectDir.toFile(), "build/classes/java/jpaMetamodel" ) ).exists(); + } + } +} diff --git a/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/orm/tooling/gradle/TestHelper.java b/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/orm/tooling/gradle/TestHelper.java new file mode 100644 index 0000000000..093767e83e --- /dev/null +++ b/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/orm/tooling/gradle/TestHelper.java @@ -0,0 +1,34 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html. + */ +package org.hibernate.orm.tooling.gradle; + +import org.gradle.testkit.runner.TaskOutcome; + +import org.hibernate.engine.spi.Managed; + +import org.assertj.core.api.Condition; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +/** + * @author Steve Ebersole + */ +public class TestHelper { + private static final Condition SUCCESS = new Condition<>( + (taskOutcome) -> taskOutcome == TaskOutcome.SUCCESS, + "task succeeded" + ); + private static final Condition UP_TO_DATE = new Condition<>( + (taskOutcome) -> taskOutcome == TaskOutcome.UP_TO_DATE, + "task up-to-date" + ); + + public static void verifyEnhanced(ClassLoader classLoader, String className) throws Exception { + final Class loadedClass = classLoader.loadClass( className ); + assertThat( Managed.class ).isAssignableFrom( loadedClass ); + } +} diff --git a/tooling/hibernate-gradle-plugin/src/test/resources/projects/simple-kotlin/build.gradle b/tooling/hibernate-gradle-plugin/src/test/resources/projects/simple-kotlin/build.gradle index 2ac1c7350a..7e19c6dfe7 100644 --- a/tooling/hibernate-gradle-plugin/src/test/resources/projects/simple-kotlin/build.gradle +++ b/tooling/hibernate-gradle-plugin/src/test/resources/projects/simple-kotlin/build.gradle @@ -20,10 +20,13 @@ repositories { } dependencies { - implementation 'jakarta.persistence:jakarta.persistence-api:3.0.0' + implementation 'org.hibernate.orm:hibernate-core:6.1.0.Final' } hibernate { + // to get using the same version to work, we'd have to install hibernate-core into maven local prior to running these. + // suck we won't be able to adequately test this part, but + useSameVersion = false enhancement { lazyInitialization( true ) dirtyTracking = true diff --git a/tooling/hibernate-gradle-plugin/src/test/resources/projects/simple-kotlin/src/main/kotlin/TheEntity.kt b/tooling/hibernate-gradle-plugin/src/test/resources/projects/simple-kotlin/src/main/kotlin/TheEntity.kt index a532385287..1a5d539003 100644 --- a/tooling/hibernate-gradle-plugin/src/test/resources/projects/simple-kotlin/src/main/kotlin/TheEntity.kt +++ b/tooling/hibernate-gradle-plugin/src/test/resources/projects/simple-kotlin/src/main/kotlin/TheEntity.kt @@ -1,7 +1,9 @@ import jakarta.persistence.Entity; import jakarta.persistence.Id; +import org.hibernate.annotations.BatchSize @Entity +@BatchSize(size = 20) class TheEntity ( @Id var id: Long? = null, diff --git a/tooling/hibernate-gradle-plugin/src/test/resources/projects/simple/build.gradle b/tooling/hibernate-gradle-plugin/src/test/resources/projects/simple/build.gradle index bf093f8223..8eb0381d47 100644 --- a/tooling/hibernate-gradle-plugin/src/test/resources/projects/simple/build.gradle +++ b/tooling/hibernate-gradle-plugin/src/test/resources/projects/simple/build.gradle @@ -20,10 +20,13 @@ repositories { } dependencies { - implementation 'jakarta.persistence:jakarta.persistence-api:3.0.0' + implementation 'org.hibernate.orm:hibernate-core:6.1.0.Final' } hibernate { + // to get using the same version to work, we'd have to install hibernate-core into maven local prior to running these. + // suck we won't be able to adequately test this part, but + useSameVersion = false enhancement { lazyInitialization( true ) dirtyTracking = true diff --git a/tooling/hibernate-gradle-plugin/src/test/resources/projects/simple/src/main/java/TheEntity.java b/tooling/hibernate-gradle-plugin/src/test/resources/projects/simple/src/main/java/TheEntity.java index 43a82b8d95..b5d9eb5eea 100644 --- a/tooling/hibernate-gradle-plugin/src/test/resources/projects/simple/src/main/java/TheEntity.java +++ b/tooling/hibernate-gradle-plugin/src/test/resources/projects/simple/src/main/java/TheEntity.java @@ -12,9 +12,12 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToMany; +import org.hibernate.annotations.BatchSize; + import java.util.Set; @Entity +@BatchSize( size = 20 ) public class TheEntity { @Id private Integer id;