Skip to content

Commit

Permalink
HSEARCH-3319 WIP: maven plugin to generate "metamodel classes" while …
Browse files Browse the repository at this point in the history
…compiling in the same module ...
  • Loading branch information
marko-bekhta committed May 28, 2024
1 parent 75911f7 commit 30f9d6a
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 11 deletions.
2 changes: 2 additions & 0 deletions metamodel/generator-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
<deploy.skip>false</deploy.skip>
<enforcer.dependencyconvergence.skip>true</enforcer.dependencyconvergence.skip>
<java.module.name>org.hibernate.search.metamodel.generator.plugin</java.module.name>
<forbiddenapis.skip>true</forbiddenapis.skip>
<checkstyle.skip>true</checkstyle.skip>
</properties>

<dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,28 @@
*/
package org.hibernate.search.metamodel.generator.plugin;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.stream.Collectors;

import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;

import org.hibernate.SessionFactory;
import org.hibernate.search.engine.backend.metamodel.IndexDescriptor;
Expand All @@ -25,6 +38,7 @@
import org.hibernate.search.util.impl.integrationtest.backend.lucene.LuceneBackendConfiguration;
import org.hibernate.search.util.impl.integrationtest.mapper.orm.OrmSetupHelper;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
Expand All @@ -43,9 +57,17 @@ public class HibernateSearchMetamodelGeneratorMojo extends AbstractMojo {
@Parameter(property = "annotatedTypes")
List<String> annotatedTypes;

@Parameter(property = "packagesToCompile")
List<String> packagesToCompile;

@Parameter(property = "properties")
Properties properties;

@Parameter(property = "sameModuleCompile", defaultValue = "false")
boolean sameModuleCompile;

private URLClassLoader classLoader;

@Override
public void execute() throws MojoExecutionException, MojoFailureException {
getLog().info( "Hibernate Search Metamodel Generator" );
Expand All @@ -60,8 +82,6 @@ public void execute() throws MojoExecutionException, MojoFailureException {

Path generatedMetamodelLocation =
Path.of( project.getBuild().getOutputDirectory() ).resolveSibling( "generated-metamodel-sources" );
project.addCompileSourceRoot( generatedMetamodelLocation.toString() );


try ( SessionFactory sessionFactory = setupContext.setup( annotatedTypes() ) ) {
SearchMapping mapping = Search.mapping( sessionFactory );
Expand All @@ -75,7 +95,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
getLog().info( "Indexed entities: " + indexedEntities );

}

project.addCompileSourceRoot( generatedMetamodelLocation.toString() );
}
}

Expand Down Expand Up @@ -112,18 +132,79 @@ private void createClass(SearchIndexedEntity<?> indexedEntity, Path root) {
}

private Class<?>[] annotatedTypes() {
try {
Class<?>[] types = new Class<?>[annotatedTypes.size()];
for ( int i = 0; i < annotatedTypes.size(); i++ ) {
types[i] = Class.forName( annotatedTypes.get( i ) );
if ( sameModuleCompile ) {
try {
List<Path> roots = new ArrayList<>();
List<Path> classes = new ArrayList<>();
for ( String compileSourceRoot : this.project.getCompileSourceRoots() ) {
Path root = Path.of( compileSourceRoot );
roots.add( root );

for ( String pkg : packagesToCompile ) {
Path path = root.resolve( Path.of( pkg.replace( ".", FileSystems.getDefault().getSeparator() ) ) );
if ( Files.exists( path ) ) {
Files.list( path ).filter( f -> f.getFileName().toString().endsWith( ".java" ) )
.forEach( classes::add );
}
}
}

Path output = Path.of( project.getBuild().getOutputDirectory() )
.resolveSibling( "generated-metamodel-pre-compiled-classes" );
Files.createDirectories( output );

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager( null, null, null );
fileManager.setLocationFromPaths( StandardLocation.SOURCE_PATH, roots );
fileManager.setLocation( StandardLocation.CLASS_PATH, getDependenciesAsFiles() );
fileManager.setLocationFromPaths( StandardLocation.CLASS_OUTPUT, List.of( output ) );

Iterable<? extends JavaFileObject> toCompile = fileManager.getJavaFileObjectsFromPaths( classes );

DiagnosticCollector<JavaFileObject> diagnostic = new DiagnosticCollector<>();
JavaCompiler.CompilationTask task =
compiler.getTask( null, fileManager, diagnostic, List.of(), null, toCompile );

task.call();

classLoader = new URLClassLoader( "hibernate-search-generator",
new URL[] { output.toUri().toURL() }, this.getClass().getClassLoader() );
Thread.currentThread().setContextClassLoader( classLoader );

Class<?>[] types = new Class<?>[annotatedTypes.size()];
for ( int i = 0; i < annotatedTypes.size(); i++ ) {
types[i] = classLoader.loadClass( annotatedTypes.get( i ) );
}
return types;

}
catch (IOException | ClassNotFoundException e) {
throw new RuntimeException( e );
}
return types;
}
catch (ClassNotFoundException e) {
throw new RuntimeException( e );
else {
try {
Class<?>[] types = new Class<?>[annotatedTypes.size()];
for ( int i = 0; i < annotatedTypes.size(); i++ ) {
types[i] = Class.forName( annotatedTypes.get( i ) );
}
return types;
}
catch (ClassNotFoundException e) {
throw new RuntimeException( e );
}
}
}

private Collection<File> getDependenciesAsFiles() {
project.setArtifactFilter( artifact -> true );
project.setArtifacts( null );
return project.getArtifacts()
.stream()
.map( Artifact::getFile )
.collect( Collectors.toList() );
}

private boolean hasOrmMapper(List<Dependency> dependencies) {
for ( Dependency dependency : dependencies ) {
if ( "hibernate-search-mapper-orm".equals( dependency.getArtifactId() ) ) {
Expand Down
2 changes: 1 addition & 1 deletion metamodel/generator-test/generation/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<!-- This is a publicly distributed module that should be published: -->
<deploy.skip>false</deploy.skip>
<java.module.name>org.hibernate.search.metamodel.generator.test</java.module.name>
<org.hibernate.search.integrationtest.orm.database.kind>h2</org.hibernate.search.integrationtest.orm.database.kind>
<checkstyle.skip>true</checkstyle.skip>
</properties>

<dependencies>
Expand Down
28 changes: 28 additions & 0 deletions metamodel/generator-test/model/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<!-- This is a publicly distributed module that should be published: -->
<deploy.skip>false</deploy.skip>
<java.module.name>org.hibernate.search.metamodel.generator</java.module.name>
<checkstyle.skip>true</checkstyle.skip>
</properties>

<dependencies>
Expand Down Expand Up @@ -65,6 +66,33 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-metamodel-generator-plugin</artifactId>
<version>${project.version}</version>
<executions>
<execution>
<id>generate</id>
<goals>
<goal>generate-metamodel</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<sameModuleCompile>true</sameModuleCompile>
<annotatedTypes>
<type>org.hibernate.search.metamodel.generator.model.MyEntity</type>
<type>org.hibernate.search.metamodel.generator.model.MyProgrammaticEntity</type>
</annotatedTypes>
<packagesToCompile>
<package>org.hibernate.search.metamodel.generator.model</package>
</packagesToCompile>
<properties>
<hibernate.search.mapping.configurer>org.hibernate.search.metamodel.generator.model.MyConfigurer</hibernate.search.mapping.configurer>
</properties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

0 comments on commit 30f9d6a

Please sign in to comment.