Skip to content

Commit bd4a652

Browse files
committed
Merge Hibernate Tools into ORM : Add the Reveng Maven Mojos
1 parent 762d20f commit bd4a652

File tree

7 files changed

+600
-2
lines changed

7 files changed

+600
-2
lines changed

tooling/hibernate-maven-plugin/hibernate-maven-plugin.gradle

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@ configurations {
2626

2727
dependencies {
2828
implementation project( ":hibernate-core" )
29+
implementation project( ":hibernate-reveng" )
2930

3031
implementation "org.apache.maven:maven-plugin-api:3.9.11"
31-
implementation "org.apache.maven:maven-project:2.2.1"
32+
implementation "org.apache.maven:maven-core:3.9.11"
3233
implementation "org.apache.maven.shared:file-management:3.1.0"
34+
implementation "jakarta.xml.bind:jakarta.xml.bind-api:4.0.2"
3335

3436
compileOnly "org.apache.maven.plugin-tools:maven-plugin-tools-annotations:3.15.1"
3537

@@ -104,6 +106,7 @@ integrationTest {
104106
environment "hibernateVersion", project.version
105107
}
106108

107-
integrationTest.dependsOn rootProject.childProjects.'hibernate-core'.tasks.publishToMavenLocal
109+
integrationTest.dependsOn ':hibernate-core:publishToMavenLocal'
110+
integrationTest.dependsOn ':hibernate-reveng:publishToMavenLocal'
108111
integrationTest.dependsOn publishToMavenLocal
109112
check.dependsOn integrationTest
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.tool.maven;
6+
7+
import java.io.File;
8+
import java.io.FileInputStream;
9+
import java.io.FileNotFoundException;
10+
import java.io.IOException;
11+
import java.net.MalformedURLException;
12+
import java.net.URL;
13+
import java.net.URLClassLoader;
14+
import java.util.ArrayList;
15+
import java.util.Properties;
16+
17+
import org.apache.maven.artifact.DependencyResolutionRequiredException;
18+
import org.apache.maven.plugin.AbstractMojo;
19+
import org.apache.maven.plugin.MojoFailureException;
20+
import org.apache.maven.plugins.annotations.Parameter;
21+
import org.apache.maven.project.MavenProject;
22+
import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
23+
import org.hibernate.tool.reveng.api.metadata.MetadataDescriptorFactory;
24+
import org.hibernate.tool.reveng.api.metadata.MetadataConstants;
25+
import org.hibernate.tool.reveng.api.core.RevengSettings;
26+
import org.hibernate.tool.reveng.api.core.RevengStrategy;
27+
import org.hibernate.tool.reveng.api.core.RevengStrategyFactory;
28+
29+
public abstract class AbstractGenerationMojo extends AbstractMojo {
30+
31+
// For reveng strategy
32+
/** The default package name to use when mappings for classes are created. */
33+
@Parameter
34+
private String packageName;
35+
36+
/** The name of a property file, e.g. hibernate.properties. */
37+
@Parameter
38+
private File revengFile;
39+
40+
/** The class name of the reverse engineering strategy to use.
41+
* Extend the DefaultReverseEngineeringStrategy and override the corresponding methods, e.g.
42+
* to adapt the generate class names or to provide custom type mappings. */
43+
@Parameter
44+
private String revengStrategy;
45+
46+
/** If true, tables which are pure many-to-many link tables will be mapped as such.
47+
* A pure many-to-many table is one which primary-key contains exactly two foreign-keys pointing
48+
* to other entity tables and has no other columns. */
49+
@Parameter(defaultValue = "true")
50+
private boolean detectManyToMany;
51+
52+
/** If true, a one-to-one association will be created for each foreignkey found. */
53+
@Parameter(defaultValue = "true")
54+
private boolean detectOneToOne;
55+
56+
/** If true, columns named VERSION or TIMESTAMP with appropriate types will be mapped with the appropriate
57+
* optimistic locking corresponding to <version> or <timestamp>. */
58+
@Parameter(defaultValue = "true")
59+
private boolean detectOptimisticLock;
60+
61+
/** If true, a collection will be mapped for each foreignkey. */
62+
@Parameter(defaultValue = "true")
63+
private boolean createCollectionForForeignKey;
64+
65+
/** If true, a many-to-one association will be created for each foreignkey found. */
66+
@Parameter(defaultValue = "true")
67+
private boolean createManyToOneForForeignKey;
68+
69+
// For configuration
70+
/** The name of a property file, e.g. hibernate.properties. */
71+
@Parameter(defaultValue = "${project.basedir}/src/main/resources/hibernate.properties")
72+
private File propertyFile;
73+
74+
// Not exposed for now
75+
private boolean preferBasicCompositeIds = true;
76+
77+
@Parameter(defaultValue = "${project}", readonly = true, required = true)
78+
private MavenProject project;
79+
80+
public void execute() throws MojoFailureException {
81+
ClassLoader original = Thread.currentThread().getContextClassLoader();
82+
try {
83+
Thread.currentThread().setContextClassLoader(createExporterClassLoader(original));
84+
getLog().info("Starting " + this.getClass().getSimpleName() + "...");
85+
RevengStrategy strategy = setupReverseEngineeringStrategy();
86+
if (propertyFile.exists()) {
87+
executeExporter(createJdbcDescriptor(strategy, loadPropertiesFile()));
88+
}
89+
else {
90+
getLog().info("Property file '" + propertyFile + "' cannot be found, aborting...");
91+
}
92+
getLog().info("Finished " + this.getClass().getSimpleName() + "!");
93+
}
94+
finally {
95+
Thread.currentThread().setContextClassLoader(original);
96+
}
97+
}
98+
99+
private RevengStrategy setupReverseEngineeringStrategy() {
100+
File[] revengFiles = null;
101+
if (revengFile != null) {
102+
revengFiles = new File[] { revengFile };
103+
}
104+
RevengStrategy strategy =
105+
RevengStrategyFactory.createReverseEngineeringStrategy(
106+
revengStrategy,
107+
revengFiles);
108+
RevengSettings settings =
109+
new RevengSettings(strategy)
110+
.setDefaultPackageName(packageName)
111+
.setDetectManyToMany(detectManyToMany)
112+
.setDetectOneToOne(detectOneToOne)
113+
.setDetectOptimisticLock(detectOptimisticLock)
114+
.setCreateCollectionForForeignKey(createCollectionForForeignKey)
115+
.setCreateManyToOneForForeignKey(createManyToOneForForeignKey);
116+
strategy.setSettings(settings);
117+
return strategy;
118+
}
119+
120+
private Properties loadPropertiesFile() throws MojoFailureException {
121+
try (FileInputStream is = new FileInputStream(propertyFile)) {
122+
Properties result = new Properties();
123+
result.load(is);
124+
return result;
125+
}
126+
catch (FileNotFoundException e) {
127+
throw new MojoFailureException(propertyFile + " not found.", e);
128+
}
129+
catch (IOException e) {
130+
throw new MojoFailureException("Problem while loading " + propertyFile, e);
131+
}
132+
}
133+
134+
private MetadataDescriptor createJdbcDescriptor(RevengStrategy strategy, Properties properties) {
135+
properties.put(MetadataConstants.PREFER_BASIC_COMPOSITE_IDS, preferBasicCompositeIds);
136+
return MetadataDescriptorFactory
137+
.createReverseEngineeringDescriptor(
138+
strategy,
139+
properties);
140+
}
141+
142+
private ClassLoader createExporterClassLoader(ClassLoader parent) {
143+
ArrayList<URL> urls = new ArrayList<URL>();
144+
try {
145+
for (String cpe : project.getRuntimeClasspathElements()) {
146+
urls.add(new File(cpe).toURI().toURL());
147+
}
148+
}
149+
catch (DependencyResolutionRequiredException | MalformedURLException e) {
150+
throw new RuntimeException("Problem while constructing project classloader", e);
151+
}
152+
return new URLClassLoader(urls.toArray(new URL[0]), parent);
153+
}
154+
155+
protected abstract void executeExporter(MetadataDescriptor metadataDescriptor) throws MojoFailureException;
156+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.tool.maven;
6+
7+
import org.apache.maven.plugins.annotations.Mojo;
8+
import org.apache.maven.plugins.annotations.Parameter;
9+
import org.apache.maven.plugins.annotations.ResolutionScope;
10+
import org.hibernate.tool.reveng.api.export.Exporter;
11+
import org.hibernate.tool.reveng.api.export.ExporterConstants;
12+
import org.hibernate.tool.reveng.api.export.ExporterFactory;
13+
import org.hibernate.tool.reveng.api.export.ExporterType;
14+
import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
15+
16+
import java.io.File;
17+
18+
import static org.apache.maven.plugins.annotations.LifecyclePhase.GENERATE_SOURCES;
19+
20+
/**
21+
* Mojo to generate Data Access Objects (DAOs) from an existing database.
22+
* <p>
23+
* See: https://docs.jboss.org/tools/latest/en/hibernatetools/html_single/#d0e4821
24+
*/
25+
@Mojo(
26+
name = "hbm2dao",
27+
defaultPhase = GENERATE_SOURCES,
28+
requiresDependencyResolution = ResolutionScope.RUNTIME)
29+
public class GenerateDaoMojo extends AbstractGenerationMojo {
30+
31+
/** The directory into which the DAOs will be generated. */
32+
@Parameter(defaultValue = "${project.build.directory}/generated-sources/")
33+
private File outputDirectory;
34+
35+
/** Code will contain JPA features, e.g. using annotations from jakarta.persistence
36+
* and org.hibernate.annotations. */
37+
@Parameter(defaultValue = "false")
38+
private boolean ejb3;
39+
40+
/** Code will contain JDK 5 constructs such as generics and static imports. */
41+
@Parameter(defaultValue = "false")
42+
private boolean jdk5;
43+
44+
/** A path used for looking up user-edited templates. */
45+
@Parameter
46+
private String templatePath;
47+
48+
protected void executeExporter(MetadataDescriptor metadataDescriptor) {
49+
Exporter pojoExporter = ExporterFactory.createExporter(ExporterType.DAO);
50+
pojoExporter.getProperties().put(ExporterConstants.METADATA_DESCRIPTOR, metadataDescriptor);
51+
pojoExporter.getProperties().put(ExporterConstants.DESTINATION_FOLDER, outputDirectory);
52+
if (templatePath != null) {
53+
getLog().info("Setting template path to: " + templatePath);
54+
pojoExporter.getProperties().put(ExporterConstants.TEMPLATE_PATH, new String[] {templatePath});
55+
}
56+
pojoExporter.getProperties().setProperty("ejb3", String.valueOf(ejb3));
57+
pojoExporter.getProperties().setProperty("jdk5", String.valueOf(jdk5));
58+
getLog().info("Starting DAO export to directory: " + outputDirectory + "...");
59+
pojoExporter.start();
60+
}
61+
62+
63+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.tool.maven;
6+
7+
import org.apache.maven.plugins.annotations.Mojo;
8+
import org.apache.maven.plugins.annotations.Parameter;
9+
import org.apache.maven.plugins.annotations.ResolutionScope;
10+
import org.hibernate.boot.Metadata;
11+
import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
12+
import org.hibernate.tool.hbm2ddl.SchemaExport;
13+
import org.hibernate.tool.schema.TargetType;
14+
15+
import java.io.File;
16+
import java.util.EnumSet;
17+
import java.util.Set;
18+
19+
import static org.apache.maven.plugins.annotations.LifecyclePhase.GENERATE_RESOURCES;
20+
21+
/**
22+
* Mojo to generate DDL Scripts from an existing database.
23+
* <p>
24+
* See https://docs.jboss.org/tools/latest/en/hibernatetools/html_single/#d0e4651
25+
*/
26+
@Mojo(
27+
name = "hbm2ddl",
28+
defaultPhase = GENERATE_RESOURCES,
29+
requiresDependencyResolution = ResolutionScope.RUNTIME)
30+
public class GenerateDdlMojo extends AbstractGenerationMojo {
31+
32+
/** The directory into which the DDLs will be generated. */
33+
@Parameter(defaultValue = "${project.build.directory}/generated-resources/")
34+
private File outputDirectory;
35+
36+
/** The default filename of the generated DDL script. */
37+
@Parameter(defaultValue = "schema.ddl")
38+
private String outputFileName;
39+
40+
/** The type of output to produce.
41+
* <ul>
42+
* <li>DATABASE: Export to the database.</li>
43+
* <li>SCRIPT (default): Write to a script file.</li>
44+
* <li>STDOUT: Write to {@link System#out}.</li>
45+
* </ul> */
46+
@Parameter(defaultValue = "SCRIPT")
47+
private Set<TargetType> targetTypes;
48+
49+
/**
50+
* The DDLs statements to create.
51+
* <ul>
52+
* <li>NONE: None - duh :P.</li>
53+
* <li>CREATE (default): Create only.</li>
54+
* <li>DROP: Drop only.</li>
55+
* <li>BOTH: Drop and then create.</li>
56+
* </ul>
57+
*/
58+
@Parameter(defaultValue = "CREATE")
59+
private SchemaExport.Action schemaExportAction;
60+
61+
/** Set the end of statement delimiter. */
62+
@Parameter(defaultValue = ";")
63+
private String delimiter;
64+
65+
/** Should we format the sql strings? */
66+
@Parameter(defaultValue = "true")
67+
private boolean format;
68+
69+
/** Should we stop once an error occurs? */
70+
@Parameter(defaultValue = "true")
71+
private boolean haltOnError;
72+
73+
74+
@Override
75+
protected void executeExporter(MetadataDescriptor metadataDescriptor) {
76+
Metadata metadata = metadataDescriptor.createMetadata();
77+
78+
SchemaExport export = new SchemaExport();
79+
export.setOutputFile(new File(outputDirectory, outputFileName).toString());
80+
export.setDelimiter(delimiter);
81+
export.setHaltOnError(haltOnError);
82+
export.setFormat(format);
83+
export.execute(EnumSet.copyOf(this.targetTypes), schemaExportAction, metadata);
84+
}
85+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.tool.maven;
6+
7+
import org.apache.maven.plugin.MojoFailureException;
8+
import org.apache.maven.plugins.annotations.Mojo;
9+
import org.apache.maven.plugins.annotations.Parameter;
10+
import org.apache.maven.plugins.annotations.ResolutionScope;
11+
import org.hibernate.tool.reveng.api.export.Exporter;
12+
import org.hibernate.tool.reveng.api.export.ExporterConstants;
13+
import org.hibernate.tool.reveng.api.export.ExporterFactory;
14+
import org.hibernate.tool.reveng.api.export.ExporterType;
15+
import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
16+
17+
import java.io.File;
18+
19+
import static org.apache.maven.plugins.annotations.LifecyclePhase.GENERATE_SOURCES;
20+
21+
/**
22+
* Mojo to generate hbm.xml files from an existing database.
23+
* <p>
24+
* See: https://docs.jboss.org/tools/latest/en/hibernatetools/html_single/#d0e4821
25+
*/
26+
@Mojo(
27+
name = "generateHbm",
28+
defaultPhase = GENERATE_SOURCES,
29+
requiresDependencyResolution = ResolutionScope.RUNTIME)
30+
public class GenerateHbmMojo extends AbstractGenerationMojo {
31+
32+
/** The directory into which the DAOs will be generated. */
33+
@Parameter(defaultValue = "${project.basedir}/src/main/resources")
34+
private File outputDirectory;
35+
36+
@Parameter
37+
private String templatePath;
38+
39+
protected void executeExporter(MetadataDescriptor metadataDescriptor) throws MojoFailureException {
40+
try {
41+
Exporter hbmExporter = ExporterFactory.createExporter(ExporterType.HBM);
42+
hbmExporter.getProperties().put(ExporterConstants.METADATA_DESCRIPTOR, metadataDescriptor);
43+
hbmExporter.getProperties().put(ExporterConstants.DESTINATION_FOLDER, outputDirectory);
44+
if (templatePath != null) {
45+
getLog().info("Setting template path to: " + templatePath);
46+
hbmExporter.getProperties().put(ExporterConstants.TEMPLATE_PATH, new String[] {templatePath});
47+
}
48+
getLog().info("Starting HBM export to directory: " + outputDirectory + "...");
49+
hbmExporter.start();
50+
}
51+
catch (Exception e) {
52+
throw new MojoFailureException( e );
53+
}
54+
}
55+
56+
57+
}

0 commit comments

Comments
 (0)