diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 582f55855748..a8a3abec209b 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -1,6 +1,9 @@
+
+
+
@@ -9,6 +12,7 @@
+
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index b3cfcc15afcf..24e1ed775c31 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -364,6 +364,9 @@ project(':hibernate-maven-plugin').projectDir = new File(rootProject.projectDir,
include 'hibernate-ant'
project(':hibernate-ant').projectDir = new File(rootProject.projectDir, "tooling/hibernate-ant")
+include 'hibernate-reveng'
+project(':hibernate-reveng').projectDir = new File(rootProject.projectDir, "tooling/hibernate-reveng")
+
rootProject.children.each { project ->
project.buildFileName = "${project.name}.gradle"
assert project.projectDir.isDirectory()
diff --git a/tooling/hibernate-ant/hibernate-ant.gradle b/tooling/hibernate-ant/hibernate-ant.gradle
index a6af63b9a823..1ddf1e3e5229 100644
--- a/tooling/hibernate-ant/hibernate-ant.gradle
+++ b/tooling/hibernate-ant/hibernate-ant.gradle
@@ -10,5 +10,6 @@ description = 'Annotation Processor to generate JPA 2 static metamodel classes'
dependencies {
compileOnly libs.ant
implementation project( ':hibernate-core' )
+ implementation project( ':hibernate-reveng')
testImplementation libs.ant
}
\ No newline at end of file
diff --git a/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/ConfigurationTask.java b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/ConfigurationTask.java
new file mode 100644
index 000000000000..c0d8c77c065a
--- /dev/null
+++ b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/ConfigurationTask.java
@@ -0,0 +1,134 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.FileSet;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptorFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * @author max
+ *
+ */
+public class ConfigurationTask extends Task {
+
+ List fileSets = new ArrayList();
+ MetadataDescriptor metadataDescriptor;
+ File configurationFile;
+ File propertyFile;
+ protected String entityResolver;
+
+ public ConfigurationTask() {
+ setDescription( "Standard Configuration" );
+ }
+
+ public void addConfiguredFileSet(FileSet fileSet) {
+ fileSets.add( fileSet );
+ }
+
+ public final MetadataDescriptor getMetadataDescriptor() {
+ if ( metadataDescriptor == null ) {
+ metadataDescriptor = createMetadataDescriptor();
+ }
+ return metadataDescriptor;
+ }
+
+ protected MetadataDescriptor createMetadataDescriptor() {
+ return MetadataDescriptorFactory
+ .createNativeDescriptor(
+ configurationFile,
+ getFiles(),
+ loadPropertiesFile() );
+ }
+
+ protected Properties loadPropertiesFile() {
+ if ( propertyFile != null ) {
+ Properties properties = new Properties(); // TODO: should we "inherit" from the ant projects properties ?
+ try (FileInputStream is = new FileInputStream( propertyFile )) {
+ properties.load( is );
+ return properties;
+ }
+ catch (FileNotFoundException e) {
+ throw new BuildException( propertyFile + " not found.", e );
+ }
+ catch (IOException e) {
+ throw new BuildException( "Problem while loading " + propertyFile, e );
+ }
+ }
+ else {
+ return null;
+ }
+ }
+
+
+ protected File[] getFiles() {
+
+ List files = new LinkedList();
+ for ( FileSet fs : fileSets ) {
+
+ DirectoryScanner ds = fs.getDirectoryScanner( getProject() );
+
+ String[] dsFiles = ds.getIncludedFiles();
+ for ( String dsFile : dsFiles ) {
+ File f = new File( dsFile );
+ if ( !f.isFile() ) {
+ f = new File( ds.getBasedir(), dsFile );
+ }
+
+ files.add( f );
+ }
+ }
+
+ return files.toArray( new File[0] );
+ }
+
+
+ public File getConfigurationFile() {
+ return configurationFile;
+ }
+
+ public void setConfigurationFile(File configurationFile) {
+ this.configurationFile = configurationFile;
+ }
+
+ public File getPropertyFile() {
+ return propertyFile;
+ }
+
+ public void setPropertyFile(File propertyFile) {
+ this.propertyFile = propertyFile;
+ }
+
+ public void setEntityResolver(String entityResolverName) {
+ this.entityResolver = entityResolverName;
+ }
+
+ public void setNamingStrategy(String namingStrategy) {
+ log("setting unused naming strategy: " + namingStrategy);
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ ConfigurationTask ct = (ConfigurationTask) super.clone();
+ ct.fileSets.addAll( this.fileSets );
+ ct.metadataDescriptor = this.metadataDescriptor;
+ ct.propertyFile = this.propertyFile;
+ ct.entityResolver = this.entityResolver;
+ return ct;
+ }
+
+}
diff --git a/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/ExporterTask.java b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/ExporterTask.java
new file mode 100644
index 000000000000..831fab886d35
--- /dev/null
+++ b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/ExporterTask.java
@@ -0,0 +1,98 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.Environment;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.PropertySet;
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterConstants;
+
+import java.io.File;
+import java.util.Properties;
+
+/**
+ * @author max
+ *
+ * Is not actually a ant task, but simply just a task part of a HibernateToolTask
+ *
+ */
+public abstract class ExporterTask {
+
+ // refactor out so not dependent on Ant ?
+ protected HibernateToolTask parent;
+ Properties properties;
+ private Path templatePath;
+
+ public ExporterTask(HibernateToolTask parent) {
+ this.parent = parent;
+ this.properties = new Properties();
+ }
+
+
+ public void execute() {
+
+ Exporter exporter = configureExporter(createExporter() );
+ exporter.start();
+
+ }
+
+ protected abstract Exporter createExporter();
+
+ public File getDestdir() {
+ File destdir = (File)this.properties.get(ExporterConstants.DESTINATION_FOLDER);
+ if(destdir==null) {
+ return parent.getDestDir();
+ }
+ else {
+ return destdir;
+ }
+ }
+ public void setDestdir(File destdir) {
+ this.properties.put(ExporterConstants.DESTINATION_FOLDER, destdir);
+ }
+
+ public void setTemplatePath(Path path) {
+ templatePath = path;
+ }
+
+ public void validateParameters() {
+ if(getDestdir()==null) {
+ throw new BuildException("destdir must be set, either locally or on ");
+ }
+ }
+
+ public void addConfiguredPropertySet(PropertySet ps) {
+ properties.putAll(ps.getProperties());
+ }
+
+ public void addConfiguredProperty(Environment.Variable property) {
+ properties.put(property.getKey(), property.getValue());
+ }
+
+ protected Path getTemplatePath() {
+ if(templatePath==null) {
+ return parent.getTemplatePath();
+ }
+ else {
+ return templatePath;
+ }
+ }
+
+
+ abstract String getName();
+
+ protected Exporter configureExporter(Exporter exporter) {
+ Properties prop = new Properties();
+ prop.putAll(parent.getProperties());
+ prop.putAll(properties);
+ exporter.getProperties().putAll(prop);
+ exporter.getProperties().put(ExporterConstants.METADATA_DESCRIPTOR, parent.getMetadataDescriptor());
+ exporter.getProperties().put(ExporterConstants.DESTINATION_FOLDER, getDestdir());
+ exporter.getProperties().put(ExporterConstants.TEMPLATE_PATH, getTemplatePath().list());
+ return exporter;
+ }
+}
diff --git a/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/GenericExporterTask.java b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/GenericExporterTask.java
new file mode 100644
index 000000000000..9b672d29a9c2
--- /dev/null
+++ b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/GenericExporterTask.java
@@ -0,0 +1,80 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterConstants;
+import org.hibernate.tool.reveng.api.export.ExporterFactory;
+import org.hibernate.tool.reveng.api.export.ExporterType;
+
+/**
+ * @author max
+ *
+ */
+public class GenericExporterTask extends ExporterTask {
+
+ public GenericExporterTask(HibernateToolTask parent) {
+ super(parent);
+ }
+
+ String templateName;
+ String exporterClass;
+ String filePattern;
+ String forEach;
+
+ /**
+ * The FilePattern defines the pattern used to generate files.
+ * @param filePattern
+ */
+ public void setFilePattern(String filePattern) {
+ this.filePattern = filePattern;
+ }
+
+ public void setForEach(String forEach) {
+ this.forEach = forEach;
+ }
+
+ public void setTemplate(String templateName) {
+ this.templateName = templateName;
+ }
+
+ public void setExporterClass(String exporterClass) {
+ this.exporterClass = exporterClass;
+ }
+
+ protected Exporter createExporter() {
+ if (exporterClass == null) {
+ return ExporterFactory.createExporter(ExporterType.GENERIC);
+ }
+ else {
+ return ExporterFactory.createExporter(exporterClass);
+ }
+ }
+
+ protected Exporter configureExporter(Exporter exp) {
+ super.configureExporter(exp);
+ if (templateName != null) {
+ exp.getProperties().put(ExporterConstants.TEMPLATE_NAME, templateName);
+ }
+ if (filePattern != null) {
+ exp.getProperties().put(ExporterConstants.FILE_PATTERN, filePattern);
+ }
+ if (forEach != null) {
+ exp.getProperties().put(ExporterConstants.FOR_EACH, forEach);
+ }
+ return exp;
+ }
+
+ public String getName() {
+ StringBuffer buf = new StringBuffer("generic exporter");
+ if(exporterClass!=null) {
+ buf.append( "class: " + exporterClass);
+ }
+ if(templateName!=null) {
+ buf.append( "template: " + templateName);
+ }
+ return buf.toString();
+ }
+}
diff --git a/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2CfgXmlExporterTask.java b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2CfgXmlExporterTask.java
new file mode 100644
index 000000000000..2b79d9cdb0fe
--- /dev/null
+++ b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2CfgXmlExporterTask.java
@@ -0,0 +1,37 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterFactory;
+import org.hibernate.tool.reveng.api.export.ExporterType;
+
+public class Hbm2CfgXmlExporterTask extends ExporterTask {
+
+ private boolean ejb3;
+
+ public Hbm2CfgXmlExporterTask(HibernateToolTask parent) {
+ super(parent);
+ }
+
+ public Exporter createExporter() {
+ return ExporterFactory.createExporter(ExporterType.CFG);
+ }
+
+ public void setEjb3(boolean ejb3) {
+ this.ejb3 = ejb3;
+ }
+
+ public String getName() {
+ return "hbm2cfgxml (Generates hibernate.cfg.xml)";
+ }
+
+ protected Exporter configureExporter(Exporter exporter) {
+ super.configureExporter( exporter );
+ exporter.getProperties().setProperty("ejb3", ""+ejb3);
+ return exporter;
+ }
+
+}
diff --git a/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2DAOExporterTask.java b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2DAOExporterTask.java
new file mode 100644
index 000000000000..af777e9c1ec1
--- /dev/null
+++ b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2DAOExporterTask.java
@@ -0,0 +1,33 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterConstants;
+import org.hibernate.tool.reveng.api.export.ExporterFactory;
+import org.hibernate.tool.reveng.api.export.ExporterType;
+
+/**
+ * @author Dennis Byrne
+ */
+public class Hbm2DAOExporterTask extends Hbm2JavaExporterTask {
+
+ public Hbm2DAOExporterTask(HibernateToolTask parent) {
+ super(parent);
+ }
+
+ protected Exporter createExporter() {
+ Exporter result = ExporterFactory.createExporter(ExporterType.DAO);
+ result.getProperties().putAll(parent.getProperties());
+ result.getProperties().put(ExporterConstants.METADATA_DESCRIPTOR, parent.getMetadataDescriptor());
+ result.getProperties().put(ExporterConstants.DESTINATION_FOLDER, getDestdir());
+ return result;
+ }
+
+ public String getName() {
+ return "hbm2dao (Generates a set of DAOs)";
+ }
+
+}
diff --git a/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2DDLExporterTask.java b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2DDLExporterTask.java
new file mode 100644
index 000000000000..d1aa3484af8e
--- /dev/null
+++ b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2DDLExporterTask.java
@@ -0,0 +1,116 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterConstants;
+import org.hibernate.tool.reveng.api.export.ExporterFactory;
+import org.hibernate.tool.reveng.api.export.ExporterType;
+
+/**
+ * @author max
+ *
+ */
+public class Hbm2DDLExporterTask extends ExporterTask {
+
+ boolean exportToDatabase = true;
+ boolean scriptToConsole = true;
+ boolean schemaUpdate = false;
+ String delimiter = ";";
+ boolean drop = false;
+ boolean create = true;
+ boolean format = false;
+
+ String outputFileName = null;
+ private boolean haltOnError = false;
+
+ public Hbm2DDLExporterTask(HibernateToolTask parent) {
+ super(parent);
+ }
+
+ public String getName() {
+ return "hbm2ddl (Generates database schema)";
+ }
+
+ protected Exporter configureExporter(Exporter exp) {
+ Exporter exporter = super.configureExporter( exp );
+ exporter.getProperties().put(ExporterConstants.EXPORT_TO_DATABASE, exportToDatabase);
+ exporter.getProperties().put(ExporterConstants.EXPORT_TO_CONSOLE, scriptToConsole);
+ exporter.getProperties().put(ExporterConstants.SCHEMA_UPDATE, schemaUpdate);
+ exporter.getProperties().put(ExporterConstants.DELIMITER, delimiter);
+ exporter.getProperties().put(ExporterConstants.DROP_DATABASE, drop);
+ exporter.getProperties().put(ExporterConstants.CREATE_DATABASE, create);
+ exporter.getProperties().put(ExporterConstants.FORMAT, format);
+ if (outputFileName == null) {
+ exporter.getProperties().remove(ExporterConstants.OUTPUT_FILE_NAME);
+ }
+ else {
+ exporter.getProperties().put(ExporterConstants.OUTPUT_FILE_NAME, outputFileName);
+ }
+ exporter.getProperties().put(ExporterConstants.HALT_ON_ERROR, haltOnError);
+ return exporter;
+ }
+
+ protected Exporter createExporter() {
+ Exporter exporter = ExporterFactory.createExporter(ExporterType.DDL);
+ exporter.getProperties().putAll(parent.getProperties());
+ exporter.getProperties().put(ExporterConstants.METADATA_DESCRIPTOR, parent.getProperties());
+ exporter.getProperties().put(ExporterConstants.DESTINATION_FOLDER, parent.getDestDir());
+ return exporter;
+ }
+
+
+ public void setExport(boolean export) {
+ exportToDatabase = export;
+ }
+
+ /**
+ * Run SchemaUpdate instead of SchemaExport
+ */
+ public void setUpdate(boolean update) {
+ this.schemaUpdate = update;
+ }
+
+ /**
+ * Output sql to console ? (default true)
+ */
+ public void setConsole(boolean console) {
+ this.scriptToConsole = console;
+ }
+
+ /**
+ * Format the generated sql
+ */
+ public void setFormat(boolean format) {
+ this.format = format;
+ }
+
+ /**
+ * File out put name (default: empty)
+ */
+ public void setOutputFileName(String fileName) {
+ outputFileName = fileName;
+ }
+
+ public void setDrop(boolean drop) {
+ this.drop = drop;
+ }
+
+ public void setCreate(boolean create) {
+ this.create = create;
+ }
+
+ public void setDelimiter(String delimiter) {
+ this.delimiter = delimiter;
+ }
+
+ public String getDelimiter() {
+ return delimiter;
+ }
+
+ public void setHaltonerror(boolean haltOnError) {
+ this.haltOnError = haltOnError;
+ }
+}
diff --git a/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2DocExporterTask.java b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2DocExporterTask.java
new file mode 100644
index 000000000000..9b42253f065c
--- /dev/null
+++ b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2DocExporterTask.java
@@ -0,0 +1,24 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterFactory;
+import org.hibernate.tool.reveng.api.export.ExporterType;
+
+public class Hbm2DocExporterTask extends ExporterTask {
+
+ public Hbm2DocExporterTask(HibernateToolTask parent) {
+ super(parent);
+ }
+
+ public String getName() {
+ return "hbm2doc (Generates html schema documentation)";
+ }
+
+ protected Exporter createExporter() {
+ return ExporterFactory.createExporter(ExporterType.DOC);
+ }
+}
diff --git a/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2HbmXmlExporterTask.java b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2HbmXmlExporterTask.java
new file mode 100644
index 000000000000..6cf1e96d175b
--- /dev/null
+++ b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2HbmXmlExporterTask.java
@@ -0,0 +1,24 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterFactory;
+import org.hibernate.tool.reveng.api.export.ExporterType;
+
+public class Hbm2HbmXmlExporterTask extends ExporterTask {
+
+ public Hbm2HbmXmlExporterTask(HibernateToolTask parent) {
+ super(parent);
+ }
+
+ protected Exporter createExporter() {
+ return ExporterFactory.createExporter(ExporterType.HBM);
+ }
+
+ public String getName() {
+ return "hbm2hbmxml (Generates a set of hbm.xml files)";
+ }
+}
diff --git a/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2JavaExporterTask.java b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2JavaExporterTask.java
new file mode 100644
index 000000000000..02027228de1d
--- /dev/null
+++ b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/Hbm2JavaExporterTask.java
@@ -0,0 +1,47 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterFactory;
+import org.hibernate.tool.reveng.api.export.ExporterType;
+
+/**
+ * @author max
+ *
+ */
+public class Hbm2JavaExporterTask extends ExporterTask {
+
+ boolean ejb3 = true;
+
+ boolean jdk5 = true;
+
+ public Hbm2JavaExporterTask(HibernateToolTask parent) {
+ super( parent );
+ }
+
+ public void setEjb3(boolean b) {
+ ejb3 = b;
+ }
+
+ public void setJdk5(boolean b) {
+ jdk5 = b;
+ }
+
+ protected Exporter configureExporter(Exporter exp) {
+ super.configureExporter( exp );
+ exp.getProperties().setProperty("ejb3", ""+ejb3);
+ exp.getProperties().setProperty("jdk5", ""+jdk5);
+ return exp;
+ }
+
+ protected Exporter createExporter() {
+ return ExporterFactory.createExporter(ExporterType.JAVA);
+ }
+
+ public String getName() {
+ return "hbm2java (Generates a set of .java files)";
+ }
+}
diff --git a/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/HbmLintExporterTask.java b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/HbmLintExporterTask.java
new file mode 100644
index 000000000000..829111aebdf1
--- /dev/null
+++ b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/HbmLintExporterTask.java
@@ -0,0 +1,26 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterFactory;
+import org.hibernate.tool.reveng.api.export.ExporterType;
+
+public class HbmLintExporterTask extends ExporterTask {
+
+ public HbmLintExporterTask(HibernateToolTask parent) {
+ super( parent );
+ }
+
+ protected Exporter createExporter() {
+ return ExporterFactory.createExporter(ExporterType.HBM_LINT);
+ }
+
+
+ String getName() {
+ return "hbmlint (scans mapping for errors)";
+ }
+
+}
diff --git a/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/HibernateToolTask.java b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/HibernateToolTask.java
new file mode 100644
index 000000000000..4af8a181eae8
--- /dev/null
+++ b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/HibernateToolTask.java
@@ -0,0 +1,293 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Environment;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.PropertySet;
+import org.hibernate.tool.ant.util.ExceptionUtil;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
+import org.hibernate.tool.reveng.internal.util.StringUtil;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * @author max
+ *
+ */
+public class HibernateToolTask extends Task {
+
+ ConfigurationTask configurationTask;
+ File destDir;
+ List generators = new ArrayList();
+ Path classPath;
+ Path templatePath;
+ Properties properties = new Properties();
+
+ public HibernateToolTask() {
+ super();
+ }
+
+ private void checkConfiguration() {
+ if(configurationTask!=null) {
+ throw new BuildException("Only a single configuration is allowed.");
+ }
+ }
+
+ public ConfigurationTask createConfiguration() {
+ checkConfiguration();
+ configurationTask = new ConfigurationTask();
+ return configurationTask;
+ }
+
+
+ public JDBCConfigurationTask createJDBCConfiguration() {
+ checkConfiguration();
+ configurationTask = new JDBCConfigurationTask();
+ return (JDBCConfigurationTask) configurationTask;
+ }
+
+ public JPAConfigurationTask createJpaConfiguration() {
+ checkConfiguration();
+ configurationTask = new JPAConfigurationTask();
+ return (JPAConfigurationTask) configurationTask;
+ }
+
+ public ExporterTask createHbm2DDL() {
+ ExporterTask generator = new Hbm2DDLExporterTask(this);
+ addGenerator( generator );
+ return generator;
+ }
+
+ public ExporterTask createHbmTemplate() {
+ ExporterTask generator = new GenericExporterTask(this);
+ addGenerator( generator );
+ return generator;
+ }
+
+ public ExporterTask createHbm2CfgXml() {
+ ExporterTask generator = new Hbm2CfgXmlExporterTask(this);
+ addGenerator( generator );
+
+ return generator;
+ }
+
+ protected void addGenerator(ExporterTask generator) {
+ generators.add(generator);
+ }
+
+ public ExporterTask createHbm2Java() {
+ ExporterTask generator = new Hbm2JavaExporterTask(this);
+ addGenerator( generator );
+ return generator;
+ }
+
+ public ExporterTask createHbm2HbmXml() {
+ ExporterTask generator= new Hbm2HbmXmlExporterTask(this);
+ addGenerator( generator );
+ return generator;
+ }
+
+ public ExporterTask createHbm2Doc() {
+ ExporterTask generator= new Hbm2DocExporterTask(this);
+ addGenerator( generator );
+ return generator;
+ }
+
+ /*public ExporterTask createHbm2Jsf(){
+ ExporterTask generator= new Hbm2JsfGeneratorTask(this);
+ generators.add(generator);
+ return generator;
+ }*/
+
+ public ExporterTask createHbm2DAO(){
+ ExporterTask generator= new Hbm2DAOExporterTask(this);
+ addGenerator( generator );
+ return generator;
+ }
+
+
+ public QueryExporterTask createQuery() {
+ QueryExporterTask generator = new QueryExporterTask(this);
+ generators.add(generator);
+ return generator;
+ }
+
+ public HbmLintExporterTask createHbmLint() {
+ HbmLintExporterTask generator = new HbmLintExporterTask(this);
+ generators.add(generator);
+ return generator;
+ }
+
+
+ /**
+ * Set the classpath to be used when running the Java class
+ *
+ * @param s an Ant Path object containing the classpath.
+ */
+ public void setClasspath(Path s) {
+ classPath = s;
+ }
+
+
+ /**
+ * Adds a path to the classpath.
+ *
+ * @return created classpath
+ */
+ public Path createClasspath() {
+ classPath = new Path(getProject() );
+ return classPath;
+ }
+
+
+ public void execute() {
+ if(configurationTask==null) {
+ throw new BuildException("No configuration specified. <" + getTaskName() + "> must have one of the following: , , or ");
+ }
+ log("Executing Hibernate Tool with a " + configurationTask.getDescription() );
+ validateParameters();
+ Iterator iterator = generators.iterator();
+
+ AntClassLoader loader = getProject().createClassLoader(classPath);
+
+ ExporterTask generatorTask = null;
+ int count = 1;
+ try {
+ ClassLoader classLoader = this.getClass().getClassLoader();
+ loader.setParent(classLoader ); // if this is not set, classes from the taskdef cannot be found - which is crucial for e.g. annotations.
+ loader.setThreadContextLoader();
+
+ while (iterator.hasNext() ) {
+ generatorTask = iterator.next();
+ log(count++ + ". task: " + generatorTask.getName() );
+ generatorTask.execute();
+ }
+ }
+ catch (RuntimeException re) {
+ reportException(re, count, generatorTask);
+ }
+ finally {
+ if (loader != null) {
+ loader.resetThreadContextLoader();
+ loader.cleanup();
+ }
+ }
+ }
+
+ private void reportException(Throwable re, int count, ExporterTask generatorTask) {
+ log("An exception occurred while running exporter #" + count + ":" + generatorTask, Project.MSG_ERR);
+ log("To get the full stack trace run ant with -verbose", Project.MSG_ERR);
+
+ log(re.toString(), Project.MSG_ERR);
+ StringBuilder ex = new StringBuilder();
+ Throwable cause = re.getCause();
+ while(cause!=null) {
+ ex.append(cause.toString()).append("\n");
+ if(cause==cause.getCause()) {
+ break; // we reached the top.
+ }
+ else {
+ cause=cause.getCause();
+ }
+ }
+ if(!StringUtil.isEmptyOrNull(ex.toString())) {
+ log(ex.toString(), Project.MSG_ERR);
+ }
+
+ String newbieMessage = ExceptionUtil.getProblemSolutionOrCause(re);
+ if(newbieMessage!=null) {
+ log(newbieMessage);
+ }
+
+ if(re instanceof BuildException) {
+ throw (BuildException)re;
+ }
+ else {
+ throw new BuildException(re, getLocation());
+ }
+ }
+
+ private void validateParameters() {
+ if(generators.isEmpty()) {
+ throw new BuildException("No exporters specified in . There has to be at least one specified. An exporter is e.g. or . See documentation for details.", getLocation());
+ }
+ else {
+ for (ExporterTask generatorTask : generators) {
+ generatorTask.validateParameters();
+ }
+ }
+ }
+
+ public File getDestDir() {
+ return destDir;
+ }
+
+ public void setDestDir(File file) {
+ destDir = file;
+ }
+
+ public MetadataDescriptor getMetadataDescriptor() {
+ return configurationTask.getMetadataDescriptor();
+ }
+
+ public void setTemplatePath(Path path) {
+ templatePath = path;
+ }
+
+ public Path getTemplatePath() {
+ if(templatePath==null) {
+ templatePath = new Path(getProject()); // empty path
+ }
+ return templatePath;
+ }
+
+ public Properties getProperties() {
+ Properties p = new Properties();
+ p.putAll(getMetadataDescriptor().getProperties());
+ p.putAll(properties);
+ return p;
+ }
+
+ public void addConfiguredPropertySet(PropertySet ps) {
+ properties.putAll(ps.getProperties());
+ }
+
+ public void addConfiguredProperty(Environment.Variable property) {
+ String key = property.getKey();
+ String value = property.getValue();
+ if (key==null) {
+ log( "Ignoring unnamed task property", Project.MSG_WARN );
+ return;
+ }
+ if (value==null){
+ //This is legal in ANT, make sure we warn properly:
+ log( "Ignoring task property '" +key+"' as no value was specified", Project.MSG_WARN );
+ return;
+ }
+ properties.put( key, value );
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ HibernateToolTask htt = (HibernateToolTask) super.clone();
+ htt.configurationTask = this.configurationTask;
+ htt.destDir = this.destDir;
+ htt.generators.addAll(this.generators);
+ htt.classPath = this.classPath;
+ htt.templatePath = this.templatePath;
+ htt.properties.putAll(this.properties);
+ return htt;
+ }
+
+}
diff --git a/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/JDBCConfigurationTask.java b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/JDBCConfigurationTask.java
new file mode 100644
index 000000000000..67509c315931
--- /dev/null
+++ b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/JDBCConfigurationTask.java
@@ -0,0 +1,133 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+import org.apache.tools.ant.types.Path;
+import org.hibernate.boot.cfgxml.internal.ConfigLoader;
+import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
+import org.hibernate.tool.reveng.api.metadata.MetadataConstants;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptorFactory;
+import org.hibernate.tool.reveng.api.core.RevengSettings;
+import org.hibernate.tool.reveng.api.core.RevengStrategy;
+import org.hibernate.tool.reveng.api.core.RevengStrategyFactory;
+
+import java.io.File;
+import java.util.Map;
+import java.util.Properties;
+
+
+/**
+ * @author max
+ * @author Alexandru Popescu
+ */
+public class JDBCConfigurationTask extends ConfigurationTask {
+
+ boolean preferBasicCompositeIds = true;
+
+ String reverseEngineeringStrategyClass;
+ String packageName;
+ Path revengFiles;
+
+ boolean detectOneToOne = true;
+ boolean detectManyToMany = true;
+ boolean detectOptimisticLock = true;
+
+ public JDBCConfigurationTask() {
+ setDescription("JDBC Configuration (for reverse engineering)");
+ }
+ protected MetadataDescriptor createMetadataDescriptor() {
+ Properties properties = loadProperties();
+ RevengStrategy res = createReverseEngineeringStrategy();
+ properties.put(MetadataConstants.PREFER_BASIC_COMPOSITE_IDS, preferBasicCompositeIds);
+ return MetadataDescriptorFactory
+ .createReverseEngineeringDescriptor(
+ res,
+ properties);
+ }
+
+ private RevengStrategy createReverseEngineeringStrategy() {
+ File[] revengFileList = null;
+ if (revengFiles != null ) {
+ String[] fileNames = revengFiles.list();
+ revengFileList = new File[fileNames.length];
+ for (int i = 0; i < fileNames.length; i++) {
+ revengFileList[i] = new File(fileNames[i]);
+ }
+ }
+
+ RevengStrategy strategy =
+ RevengStrategyFactory.createReverseEngineeringStrategy(
+ reverseEngineeringStrategyClass, revengFileList);
+
+ RevengSettings qqsettings =
+ new RevengSettings(strategy).setDefaultPackageName(packageName)
+ .setDetectManyToMany( detectManyToMany )
+ .setDetectOneToOne( detectOneToOne )
+ .setDetectOptimisticLock( detectOptimisticLock );
+
+ strategy.setSettings(qqsettings);
+
+ return strategy;
+ }
+
+
+ public void setPackageName(String pkgName) {
+ packageName = pkgName;
+ }
+
+ public void setReverseStrategy(String fqn) {
+ reverseEngineeringStrategyClass = fqn;
+ }
+
+ public void setRevEngFile(Path p) {
+ revengFiles = p;
+ }
+
+ public void setPreferBasicCompositeIds(boolean b) {
+ preferBasicCompositeIds = b;
+ }
+
+ public void setDetectOneToOne(boolean b) {
+ detectOneToOne = b;
+ }
+
+ public void setDetectManyToMany(boolean b) {
+ detectManyToMany = b;
+ }
+
+ public void setDetectOptimisticLock(boolean b) {
+ detectOptimisticLock = b;
+ }
+
+ private Map loadCfgXmlFile() {
+ return new ConfigLoader(new BootstrapServiceRegistryBuilder().build())
+ .loadConfigXmlFile(getConfigurationFile())
+ .getConfigurationValues();
+ }
+
+ private Properties loadProperties() {
+ Properties result = new Properties();
+ if (getPropertyFile() != null) {
+ result.putAll(loadPropertiesFile());
+ }
+ if (getConfigurationFile() != null) {
+ result.putAll(loadCfgXmlFile());
+ }
+ return result;
+ }
+
+ public Object clone() throws CloneNotSupportedException {
+ JDBCConfigurationTask jct = (JDBCConfigurationTask) super.clone();
+ jct.preferBasicCompositeIds = this.preferBasicCompositeIds;
+ jct.reverseEngineeringStrategyClass = this.reverseEngineeringStrategyClass;
+ jct.packageName = this.packageName;
+ jct.revengFiles = this.revengFiles;
+ jct.detectOneToOne = this.detectOneToOne;
+ jct.detectManyToMany = this.detectManyToMany;
+ jct.detectOptimisticLock = this.detectOptimisticLock;
+ return jct;
+ }
+}
diff --git a/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/JPAConfigurationTask.java b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/JPAConfigurationTask.java
new file mode 100644
index 000000000000..c1d7b3f752d7
--- /dev/null
+++ b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/JPAConfigurationTask.java
@@ -0,0 +1,68 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+import org.apache.tools.ant.BuildException;
+import org.hibernate.HibernateException;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptorFactory;
+
+import java.io.File;
+import java.util.Properties;
+
+public class JPAConfigurationTask extends ConfigurationTask {
+
+ String persistenceUnit = null;
+
+ public JPAConfigurationTask() {
+ setDescription("JPA Configuration");
+ }
+
+ protected MetadataDescriptor createMetadataDescriptor() {
+ try {
+ Properties overrides = new Properties();
+ Properties p = loadPropertiesFile();
+ if(p!=null) {
+ overrides.putAll( p );
+ }
+ return MetadataDescriptorFactory
+ .createJpaDescriptor(persistenceUnit, overrides);
+ }
+ catch(HibernateException t) {
+ Throwable cause = t.getCause();
+ if (cause != null) {
+ throw new BuildException(cause);
+ }
+ else {
+ throw new BuildException("Problems in creating a configuration for JPA. Have you remembered to add hibernate EntityManager jars to the classpath ?",t);
+ }
+ }
+
+ }
+
+ public String getPersistenceUnit() {
+ return persistenceUnit;
+ }
+
+ public void setPersistenceUnit(String persistenceUnit) {
+ this.persistenceUnit = persistenceUnit;
+ }
+
+ public void setConfigurationFile(File configurationFile) {
+ complain();
+ }
+
+ private void complain() {
+ throw new BuildException("<" + getTaskName() + "> currently only support autodiscovery from META-INF/persistence.xml. Thus setting the configurationfile attribute is not allowed");
+ }
+
+ public Object clone() throws CloneNotSupportedException {
+ JPAConfigurationTask jct = (JPAConfigurationTask) super.clone();
+ jct.persistenceUnit = this.persistenceUnit;
+ return jct;
+ }
+
+
+}
diff --git a/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/JavaFormatterTask.java b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/JavaFormatterTask.java
new file mode 100644
index 000000000000..703312645b8a
--- /dev/null
+++ b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/JavaFormatterTask.java
@@ -0,0 +1,105 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.FileSet;
+import org.hibernate.tool.reveng.api.java.DefaultJavaPrettyPrinterStrategy;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+
+public class JavaFormatterTask extends Task {
+
+ final List fileSets = new ArrayList();
+ boolean failOnError;
+
+ public void addConfiguredFileSet(FileSet fileSet) {
+ fileSets.add(fileSet);
+ }
+
+ private Properties readConfig(File cfgfile) throws IOException {
+ try (BufferedInputStream stream = new BufferedInputStream(new FileInputStream(cfgfile))) {
+ final Properties settings = new Properties();
+ settings.load(stream);
+ return settings;
+ }
+ }
+
+
+ public void execute() throws BuildException {
+
+ File[] files = getFiles();
+
+ int failed = 0;
+
+ if(files.length>0) {
+
+ DefaultJavaPrettyPrinterStrategy formatter = new DefaultJavaPrettyPrinterStrategy();
+ for (File file : files) {
+ try {
+ boolean ok = formatter.formatFile(file);
+ if (!ok) {
+ failed++;
+ getProject().log(this, "Formatting failed - skipping " + file, Project.MSG_WARN);
+ }
+ else {
+ getProject().log(this, "Formatted " + file, Project.MSG_VERBOSE);
+ }
+ }
+ catch (RuntimeException ee) {
+ failed++;
+ if (failOnError) {
+ throw new BuildException("Java formatting failed on " + file, ee);
+ }
+ else {
+ getProject().log(this, "Java formatting failed on " + file + ", " + ee.getLocalizedMessage(), Project.MSG_ERR);
+ }
+ }
+ }
+ }
+
+ getProject().log( this, "Java formatting of " + files.length + " files completed. Skipped " + failed + " file(s).", Project.MSG_INFO );
+
+ }
+
+ private File[] getFiles() {
+
+ List files = new LinkedList();
+ for (FileSet fs : fileSets) {
+
+ DirectoryScanner ds = fs.getDirectoryScanner(getProject());
+
+ String[] dsFiles = ds.getIncludedFiles();
+ for (String dsFile : dsFiles) {
+ File f = new File(dsFile);
+ if (!f.isFile()) {
+ f = new File(ds.getBasedir(), dsFile);
+ }
+
+ files.add(f);
+ }
+ }
+
+ return files.toArray(new File[0]);
+ }
+
+ public Object clone() throws CloneNotSupportedException {
+ JavaFormatterTask jft = (JavaFormatterTask) super.clone();
+ jft.fileSets.addAll(this.fileSets);
+ jft.failOnError = this.failOnError;
+ return jft;
+ }
+
+}
diff --git a/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/QueryExporterTask.java b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/QueryExporterTask.java
new file mode 100644
index 000000000000..558dc5a1bfda
--- /dev/null
+++ b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/QueryExporterTask.java
@@ -0,0 +1,104 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+import org.apache.tools.ant.BuildException;
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterConstants;
+import org.hibernate.tool.reveng.api.export.ExporterFactory;
+import org.hibernate.tool.reveng.api.export.ExporterType;
+import org.hibernate.tool.reveng.internal.util.StringUtil;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class QueryExporterTask extends ExporterTask {
+
+ private String query = "";
+ private String filename;
+ List queries = new ArrayList();
+
+ public QueryExporterTask(HibernateToolTask parent) {
+ super( parent );
+ }
+
+ protected Exporter configureExporter(Exporter exp) {
+ Exporter exporter = super.configureExporter( exp );
+ List queryStrings = new ArrayList();
+ if(!StringUtil.isEmptyOrNull(query)) {
+ queryStrings.add(query);
+ }
+ for (Iterator iter = queries.iterator(); iter.hasNext();) {
+ HQL hql = iter.next();
+ if(!StringUtil.isEmptyOrNull(hql.query)) {
+ queryStrings.add(hql.query);
+ }
+ }
+ exporter.getProperties().put(ExporterConstants.QUERY_LIST, queryStrings);
+ exporter.getProperties().put(ExporterConstants.OUTPUT_FILE_NAME, filename);
+ return exporter;
+ }
+
+ public void validateParameters() {
+ super.validateParameters();
+ if(StringUtil.isEmptyOrNull(query) && queries.isEmpty()) {
+ throw new BuildException("Need to specify at least one query.");
+ }
+
+ for (Iterator iter = queries.iterator(); iter.hasNext();) {
+ HQL hql = iter.next();
+ if(StringUtil.isEmptyOrNull(hql.query)) {
+ throw new BuildException("Query must not be empty");
+ }
+ }
+ }
+ protected Exporter createExporter() {
+ return ExporterFactory.createExporter(ExporterType.QUERY);
+ }
+
+ public void addText(String text) {
+ if(!StringUtil.isEmptyOrNull(text)) {
+ query += trim(text);
+ }
+ }
+
+ static private String trim(String text) {
+ return text.trim();
+ }
+
+ public static class HQL {
+ String query = "";
+ public void addText(String text) {
+ if(!StringUtil.isEmptyOrNull(text)) {
+ query += trim(text);
+ }
+ }
+ }
+
+ public HQL createHql() {
+ HQL hql = new HQL();
+ queries.add(hql);
+ return hql;
+ }
+
+ public void setDestFile(String filename) {
+ this.filename = filename;
+ }
+
+ public void execute() {
+ parent.log("Executing: [" + query + "]");
+ super.execute();
+ }
+ public String getName() {
+ return "query (Executes queries)";
+ }
+
+
+ boolean isNotEmpty(String string) {
+ return string != null && string.length() > 0;
+ }
+
+}
diff --git a/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/util/ExceptionUtil.java b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/util/ExceptionUtil.java
new file mode 100644
index 000000000000..928756c07b91
--- /dev/null
+++ b/tooling/hibernate-ant/src/main/java/org/hibernate/tool/ant/util/ExceptionUtil.java
@@ -0,0 +1,48 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant.util;
+
+import org.hibernate.boot.MappingNotFoundException;
+import org.hibernate.boot.jaxb.Origin;
+
+public class ExceptionUtil {
+
+ public static String getProblemSolutionOrCause(Throwable re) {
+ if(re==null) return null;
+
+ if(re instanceof MappingNotFoundException) {
+ MappingNotFoundException mnf = (MappingNotFoundException)re;
+ Origin origin = mnf.getOrigin();
+ return "A " + origin.getType() + " located at " + origin.getName() + " was not found.\n" +
+ "Check the following:\n" +
+ "\n" +
+ "1) Is the spelling/casing correct ?\n" +
+ "2) Is " + mnf.getOrigin().getName() + " available via the classpath ?\n" +
+ "3) Does it actually exist ?\n";
+ }
+
+ if(re instanceof ClassNotFoundException || re instanceof NoClassDefFoundError) {
+
+ return "A class were not found in the classpath of the Ant task.\n" +
+ "Ensure that the classpath contains the classes needed for Hibernate and your code are in the classpath.\n";
+
+ }
+
+ if(re instanceof UnsupportedClassVersionError) {
+ return "You are most likely running the ant task with a JRE that is older than the JRE required to use the classes.\n" +
+ "e.g. running with JRE 1.3 or 1.4 when using JDK 1.5 annotations is not possible.\n" +
+ "Ensure that you are using a correct JRE.";
+ }
+
+
+
+ if(re.getCause()!=re) {
+ return getProblemSolutionOrCause( re.getCause() );
+ }
+
+ return null;
+ }
+
+}
diff --git a/tooling/hibernate-ant/src/test/java/org/hibernate/tool/ant/Hbm2JavaTestIT.java b/tooling/hibernate-ant/src/test/java/org/hibernate/tool/ant/Hbm2JavaTestIT.java
new file mode 100644
index 000000000000..f1134ef7b38c
--- /dev/null
+++ b/tooling/hibernate-ant/src/test/java/org/hibernate/tool/ant/Hbm2JavaTestIT.java
@@ -0,0 +1,110 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class Hbm2JavaTestIT extends TestTemplate {
+
+ @Test
+ public void testJpaDefault() throws Exception {
+ setHibernateToolTaskXml(
+ """
+ \s
+ \s
+ \s
+ \s
+ """
+ );
+ setDatabaseCreationScript(new String[] {
+ "create table PERSON (ID int not null, NAME varchar(20), primary key (ID))"
+ });
+ createProjectAndBuild();
+ assertFolderExists("generated", 1);
+ assertFileExists("generated/Person.java");
+ String generatedPersonJavaFileContents = getFileContents("generated/Person.java");
+ assertTrue(generatedPersonJavaFileContents.contains("import jakarta.persistence.Entity;"));
+ assertTrue(generatedPersonJavaFileContents.contains("public class Person "));
+ }
+
+ @Test
+ public void testNoAnnotations() throws Exception {
+ setHibernateToolTaskXml(
+ """
+ \s
+ \s
+ \s
+ \s
+ """
+ );
+ setDatabaseCreationScript(new String[] {
+ "create table PERSON (ID int not null, NAME varchar(20), primary key (ID))"
+ });
+ createProjectAndBuild();
+ assertFolderExists("generated", 1);
+ assertFileExists("generated/Person.java");
+ String generatedPersonJavaFileContents = getFileContents("generated/Person.java");
+ assertFalse(generatedPersonJavaFileContents.contains("import jakarta.persistence.Entity;"));
+ assertTrue(generatedPersonJavaFileContents.contains("public class Person "));
+ }
+
+ @Test
+ public void testNoGenerics() throws Exception {
+ setHibernateToolTaskXml(
+ """
+ \s
+ \s
+ \s
+ \s
+ """
+ );
+ setDatabaseCreationScript(new String[] {
+ "create table PERSON (ID int not null, NAME varchar(20), " +
+ "primary key (ID))",
+ "create table ITEM (ID int not null, NAME varchar(20), OWNER_ID int not null, " +
+ "primary key (ID), foreign key (OWNER_ID) references PERSON(ID))"
+ });
+ createProjectAndBuild();
+ assertFolderExists("generated", 2);
+ assertFileExists("generated/Person.java");
+ String generatedPersonJavaFileContents = getFileContents("generated/Person.java");
+ assertTrue(generatedPersonJavaFileContents.contains("public class Person "));
+ assertFalse(generatedPersonJavaFileContents.contains("Set"));
+ assertFileExists("generated/Item.java");
+ String generatedItemJavaFileContents = getFileContents("generated/Item.java");
+ assertTrue(generatedItemJavaFileContents.contains("public class Item "));
+ }
+
+ @Test
+ public void testUseGenerics() throws Exception {
+ setHibernateToolTaskXml(
+ """
+ \s
+ \s
+ \s
+ \s
+ """
+ );
+ setDatabaseCreationScript(new String[] {
+ "create table PERSON (ID int not null, NAME varchar(20), " +
+ "primary key (ID))",
+ "create table ITEM (ID int not null, NAME varchar(20), OWNER_ID int not null, " +
+ "primary key (ID), foreign key (OWNER_ID) references PERSON(ID))"
+ });
+ createProjectAndBuild();
+ assertFolderExists("generated", 2);
+ assertFileExists("generated/Person.java");
+ String generatedPersonJavaFileContents = getFileContents("generated/Person.java");
+ assertTrue(generatedPersonJavaFileContents.contains("public class Person "));
+ assertTrue(generatedPersonJavaFileContents.contains("Set"));
+ assertFileExists("generated/Item.java");
+ String generatedItemJavaFileContents = getFileContents("generated/Item.java");
+ assertTrue(generatedItemJavaFileContents.contains("public class Item "));
+ }
+
+}
diff --git a/tooling/hibernate-ant/src/test/java/org/hibernate/tool/ant/TestTemplate.java b/tooling/hibernate-ant/src/test/java/org/hibernate/tool/ant/TestTemplate.java
new file mode 100644
index 000000000000..1576361b2078
--- /dev/null
+++ b/tooling/hibernate-ant/src/test/java/org/hibernate/tool/ant/TestTemplate.java
@@ -0,0 +1,143 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+import org.apache.tools.ant.DefaultLogger;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.ProjectHelper;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.Statement;
+import java.util.Objects;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public abstract class TestTemplate {
+
+ @TempDir
+ private File projectDir;
+
+ private String hibernateToolTaskXml;
+ private String[] databaseCreationScript;
+
+ protected File getProjectDir() {
+ return projectDir;
+ }
+
+ protected void setHibernateToolTaskXml(String xml) {
+ this.hibernateToolTaskXml = xml;
+ }
+
+ protected void setDatabaseCreationScript(String[] sqls) {
+ this.databaseCreationScript = sqls;
+ }
+
+ protected String constructBuildXmlFileContents() {
+ assertNotNull(hibernateToolTaskXml);
+ return buildXmlFileContents.replace("@hibernateToolTaskXml@", hibernateToolTaskXml);
+ }
+
+ protected String getFileContents(String path) throws Exception {
+ return new String(
+ Files.readAllBytes(
+ new File(getProjectDir(), path).toPath()));
+ }
+
+ protected void createProjectAndBuild() throws Exception {
+ createBuildXmlFile();
+ createDatabase();
+ createHibernatePropertiesFile();
+ runAntBuild();
+ }
+
+ protected void assertFolderExists(String path, int amountOfChildren) {
+ File generatedOutputFolder = new File(getProjectDir(), path);
+ assertTrue(generatedOutputFolder.exists());
+ assertTrue(generatedOutputFolder.isDirectory());
+ assertEquals(amountOfChildren, Objects.requireNonNull(generatedOutputFolder.list()).length);
+ }
+
+ protected void assertFileExists(String path) {
+ File generatedPersonJavaFile = new File(getProjectDir(), path);
+ assertTrue(generatedPersonJavaFile.exists());
+ assertTrue(generatedPersonJavaFile.isFile());
+ }
+
+ private void runAntBuild() {
+ File buildXmlFile = new File(getProjectDir(), "build.xml");
+ Project project = new Project();
+ project.setBaseDir(getProjectDir());
+ project.addBuildListener(getConsoleLogger());
+ ProjectHelper.getProjectHelper().parse(project, buildXmlFile);
+ project.executeTarget(project.getDefaultTarget());
+ }
+
+ private void createBuildXmlFile() throws Exception {
+ File buildXmlFile = new File(getProjectDir(), "build.xml");
+ assertFalse(buildXmlFile.exists());
+ Files.writeString(buildXmlFile.toPath(), constructBuildXmlFileContents());
+ assertTrue(buildXmlFile.exists());
+ }
+
+ private String constructJdbcConnectionString() {
+ return "jdbc:h2:" + getProjectDir().getAbsolutePath() + "/database/test;AUTO_SERVER=TRUE";
+ }
+
+ private void createDatabase() throws Exception {
+ File databaseFile = new File(getProjectDir(), "database/test.mv.db");
+ assertFalse(databaseFile.exists());
+ assertFalse(databaseFile.isFile());
+ Connection connection = DriverManager.getConnection(constructJdbcConnectionString());
+ Statement statement = connection.createStatement();
+ for (String sql : databaseCreationScript) {
+ statement.execute(sql);
+ }
+ statement.close();
+ connection.close();
+ assertTrue(databaseFile.exists());
+ assertTrue(databaseFile.isFile());
+ }
+
+ private void createHibernatePropertiesFile() throws Exception {
+ File hibernatePropertiesFile = new File(getProjectDir(), "hibernate.properties");
+ String hibernatePropertiesFileContents =
+ "hibernate.connection.driver_class=org.h2.Driver\n" +
+ "hibernate.connection.url=" + constructJdbcConnectionString() + "\n" +
+ "hibernate.connection.username=\n" +
+ "hibernate.connection.password=\n" +
+ "hibernate.default_catalog=TEST\n" +
+ "hibernate.default_schema=PUBLIC\n";
+ Files.writeString(hibernatePropertiesFile.toPath(), hibernatePropertiesFileContents);
+ assertTrue(hibernatePropertiesFile.exists());
+ }
+
+ private DefaultLogger getConsoleLogger() {
+ DefaultLogger consoleLogger = new DefaultLogger();
+ consoleLogger.setErrorPrintStream(System.err);
+ consoleLogger.setOutputPrintStream(System.out);
+ consoleLogger.setMessageOutputLevel(Project.MSG_INFO);
+ return consoleLogger;
+ }
+
+ private static final String buildXmlFileContents =
+ """
+ \s
+ \s
+ \s
+ @hibernateToolTaskXml@\
+ \s
+ \s
+ """;
+
+}
diff --git a/tooling/hibernate-ant/src/test/java/org/hibernate/tool/ant/TutorialTest.java b/tooling/hibernate-ant/src/test/java/org/hibernate/tool/ant/TutorialTest.java
new file mode 100644
index 000000000000..77dd7d2edd8a
--- /dev/null
+++ b/tooling/hibernate-ant/src/test/java/org/hibernate/tool/ant/TutorialTest.java
@@ -0,0 +1,31 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.ant;
+
+
+import org.junit.jupiter.api.Test;
+
+public class TutorialTest extends TestTemplate {
+
+ @Test
+ public void testTutorial() throws Exception {
+ setHibernateToolTaskXml(
+ """
+ \s
+ \s
+ \s
+ \s
+ """
+ );
+ setDatabaseCreationScript(new String[] {
+ "create table PERSON (ID int not null, NAME varchar(20), primary key (ID))"
+ });
+ createProjectAndBuild();
+ assertFolderExists("generated-sources", 1);
+ assertFileExists("generated-sources/Person.java");
+ }
+
+
+}
diff --git a/tooling/hibernate-gradle-plugin/hibernate-gradle-plugin.gradle b/tooling/hibernate-gradle-plugin/hibernate-gradle-plugin.gradle
index 7187d8e3929e..14b8d7d480b3 100644
--- a/tooling/hibernate-gradle-plugin/hibernate-gradle-plugin.gradle
+++ b/tooling/hibernate-gradle-plugin/hibernate-gradle-plugin.gradle
@@ -20,6 +20,7 @@ description = "Gradle plugin for integrating Hibernate aspects into your build"
dependencies {
implementation project(':hibernate-core')
+ implementation project(':hibernate-reveng')
implementation libs.byteBuddy
implementation jakartaLibs.jaxbApi
@@ -50,6 +51,13 @@ gradlePlugin {
description = 'Applies Hibernate aspects into the build'
tags = ['hibernate','orm','bytecode','enhancement','bytebuddy']
}
+ hibernate {
+ id = 'org.hibernate.tool.hibernate-tools-gradle'
+ implementationClass = 'org.hibernate.tool.gradle.Plugin'
+ displayName = 'Hibernate Tools Gradle Plugin'
+ description = project.description
+ tags = ['hibernate','tools','reverse engineering','reveng','generation']
+ }
}
}
diff --git a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/Extension.java b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/Extension.java
new file mode 100644
index 000000000000..799309622163
--- /dev/null
+++ b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/Extension.java
@@ -0,0 +1,23 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.gradle;
+
+import org.gradle.api.Project;
+
+public class Extension {
+
+ public String sqlToRun = "";
+ public String hibernateProperties = "hibernate.properties";
+ public String outputFolder = "generated-sources";
+ public String packageName = "";
+ public String revengStrategy = null;
+ public String revengFile = null;
+ public Boolean generateAnnotations = true;
+ public Boolean useGenerics = true;
+ public String templatePath = null;
+
+ public Extension(Project project) {}
+
+}
diff --git a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/Plugin.java b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/Plugin.java
new file mode 100644
index 000000000000..4ab0426e51a7
--- /dev/null
+++ b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/Plugin.java
@@ -0,0 +1,38 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.gradle;
+
+import java.util.Map;
+
+import org.gradle.api.Project;
+import org.hibernate.tool.gradle.task.AbstractTask;
+import org.hibernate.tool.gradle.task.GenerateCfgTask;
+import org.hibernate.tool.gradle.task.GenerateDaoTask;
+import org.hibernate.tool.gradle.task.GenerateHbmTask;
+import org.hibernate.tool.gradle.task.GenerateJavaTask;
+import org.hibernate.tool.gradle.task.RunSqlTask;
+
+public class Plugin implements org.gradle.api.Plugin {
+
+ private static Map> PLUGIN_TASK_MAP = Map.of(
+ "runSql", RunSqlTask.class,
+ "generateJava", GenerateJavaTask.class,
+ "generateCfg", GenerateCfgTask.class,
+ "generateHbm", GenerateHbmTask.class,
+ "generateDao", GenerateDaoTask.class
+ );
+
+ @SuppressWarnings("unchecked")
+ public void apply(Project project) {
+ Extension extension = project.getExtensions().create("hibernateTools", Extension.class, project);
+ for (String key : PLUGIN_TASK_MAP.keySet()) {
+ Class> taskClass = PLUGIN_TASK_MAP.get(key);
+ project.getTasks().register(key, (Class)taskClass);
+ AbstractTask task = (AbstractTask)project.getTasks().getByName(key);
+ task.doFirst(w -> task.initialize(extension));
+ }
+ }
+
+}
diff --git a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/AbstractTask.java b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/AbstractTask.java
new file mode 100644
index 000000000000..598248b08af0
--- /dev/null
+++ b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/AbstractTask.java
@@ -0,0 +1,161 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.gradle.task;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.tools.ant.BuildException;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.ConfigurationContainer;
+import org.gradle.api.artifacts.ResolvedArtifact;
+import org.gradle.api.artifacts.ResolvedConfiguration;
+import org.gradle.api.file.SourceDirectorySet;
+import org.gradle.api.tasks.Internal;
+import org.gradle.api.tasks.SourceSet;
+import org.gradle.api.tasks.SourceSetContainer;
+import org.hibernate.tool.reveng.api.metadata.MetadataConstants;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptorFactory;
+import org.hibernate.tool.reveng.api.core.RevengSettings;
+import org.hibernate.tool.reveng.api.core.RevengStrategy;
+import org.hibernate.tool.reveng.api.core.RevengStrategyFactory;
+import org.hibernate.tool.gradle.Extension;
+
+public abstract class AbstractTask extends DefaultTask {
+
+ @Internal
+ private Extension extension = null;
+
+ @Internal
+ private Properties hibernateProperties = null;
+
+ public void initialize(Extension extension) {
+ this.extension = extension;
+ }
+
+ Extension getExtension() {
+ return this.extension;
+ }
+
+ void perform() {
+ getLogger().lifecycle("Starting Task '" + getName() + "'");
+ ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(
+ new URLClassLoader(
+ resolveProjectClassPath(),
+ oldLoader));
+ doWork();
+ }
+ finally {
+ Thread.currentThread().setContextClassLoader(oldLoader);
+ getLogger().lifecycle("Ending Task '" + getName() + "'");
+ }
+ }
+
+ URL[] resolveProjectClassPath() {
+ try {
+ ConfigurationContainer cc = getProject().getConfigurations();
+ Configuration defaultConf = cc.getByName("compileClasspath");
+ ResolvedConfiguration resolvedConf = defaultConf.getResolvedConfiguration();
+ Set ras = resolvedConf.getResolvedArtifacts();
+ ResolvedArtifact[] resolvedArtifacts = ras.toArray(new ResolvedArtifact[ras.size()]);
+ URL[] urls = new URL[ras.size()];
+ for (int i = 0; i < ras.size(); i++) {
+ urls[i] = resolvedArtifacts[i].getFile().toURI().toURL();
+ }
+ return urls;
+ }
+ catch (MalformedURLException e) {
+ getLogger().error("MalformedURLException while compiling project classpath");
+ throw new BuildException(e);
+ }
+ }
+
+ Properties getHibernateProperties() {
+ if (hibernateProperties == null) {
+ loadPropertiesFile(getPropertyFile());
+ }
+ return hibernateProperties;
+ }
+
+ String getHibernateProperty(String name) {
+ return getHibernateProperties().getProperty(name);
+ }
+
+ MetadataDescriptor createJdbcDescriptor() {
+ RevengStrategy strategy = setupReverseEngineeringStrategy();
+ Properties hibernateProperties = getHibernateProperties();
+ hibernateProperties.put(MetadataConstants.PREFER_BASIC_COMPOSITE_IDS, true);
+ return MetadataDescriptorFactory.createReverseEngineeringDescriptor(strategy, hibernateProperties);
+ }
+
+ @Internal
+ File getOutputFolder() {
+ return new File(getProject().getProjectDir(), getExtension().outputFolder);
+ }
+
+ RevengStrategy setupReverseEngineeringStrategy() {
+ File[] revengFiles = getRevengFiles();
+ RevengStrategy result = RevengStrategyFactory
+ .createReverseEngineeringStrategy(getExtension().revengStrategy, revengFiles);
+ RevengSettings settings = new RevengSettings(result);
+ settings.setDefaultPackageName(getExtension().packageName);
+ result.setSettings(settings);
+ return result;
+ }
+
+ private File getFile(String filename) {
+ SourceSetContainer ssc = getProject().getExtensions().getByType(SourceSetContainer.class);
+ SourceSet ss = ssc.getByName(SourceSet.MAIN_SOURCE_SET_NAME);
+ SourceDirectorySet sds = ss.getResources();
+ for (File f : sds.getFiles()) {
+ if (filename.equals(f.getName())) {
+ return f;
+ }
+ }
+ throw new BuildException("File '" + filename + "' could not be found");
+ }
+
+ private File getPropertyFile() {
+ return getFile(getExtension().hibernateProperties);
+ }
+
+ private File[] getRevengFiles() {
+ String revengFile = getExtension().revengFile;
+ if (revengFile == null) {
+ return null;
+ }
+
+ return new File[] { getFile(revengFile) };
+ }
+
+ private void loadPropertiesFile(File propertyFile) {
+ getLogger().lifecycle("Loading the properties file : " + propertyFile.getPath());
+ try (FileInputStream is = new FileInputStream(propertyFile)) {
+ hibernateProperties = new Properties();
+ hibernateProperties.load(is);
+ getLogger().lifecycle("Properties file is loaded");
+ }
+ catch (FileNotFoundException e) {
+ throw new BuildException(propertyFile + " not found.", e);
+ }
+ catch (IOException e) {
+ throw new BuildException("Problem while loading " + propertyFile, e);
+ }
+ }
+
+ abstract void doWork();
+
+}
diff --git a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/GenerateCfgTask.java b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/GenerateCfgTask.java
new file mode 100644
index 000000000000..69198721e4de
--- /dev/null
+++ b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/GenerateCfgTask.java
@@ -0,0 +1,33 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.gradle.task;
+
+import java.io.File;
+
+import org.gradle.api.tasks.TaskAction;
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterConstants;
+import org.hibernate.tool.reveng.api.export.ExporterFactory;
+import org.hibernate.tool.reveng.api.export.ExporterType;
+
+public class GenerateCfgTask extends AbstractTask {
+
+ @TaskAction
+ public void performTask() {
+ super.perform();
+ }
+
+ void doWork() {
+ getLogger().lifecycle("Creating CFG exporter");
+ Exporter cfgExporter = ExporterFactory.createExporter(ExporterType.CFG);
+ File outputFolder = getOutputFolder();
+ cfgExporter.getProperties().put(ExporterConstants.METADATA_DESCRIPTOR, createJdbcDescriptor());
+ cfgExporter.getProperties().put(ExporterConstants.DESTINATION_FOLDER, outputFolder);
+ getLogger().lifecycle("Starting CFG export to directory: " + outputFolder + "...");
+ cfgExporter.start();
+ getLogger().lifecycle("CFG export finished");
+ }
+
+}
diff --git a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/GenerateDaoTask.java b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/GenerateDaoTask.java
new file mode 100644
index 000000000000..6c990dd31043
--- /dev/null
+++ b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/GenerateDaoTask.java
@@ -0,0 +1,38 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.gradle.task;
+
+import java.io.File;
+
+import org.gradle.api.tasks.TaskAction;
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterConstants;
+import org.hibernate.tool.reveng.api.export.ExporterFactory;
+import org.hibernate.tool.reveng.api.export.ExporterType;
+
+public class GenerateDaoTask extends AbstractTask {
+
+ @TaskAction
+ public void performTask() {
+ super.perform();
+ }
+
+ void doWork() {
+ getLogger().lifecycle("Creating DAO exporter");
+ Exporter hbmExporter = ExporterFactory.createExporter(ExporterType.DAO);
+ File outputFolder = getOutputFolder();
+ hbmExporter.getProperties().put(ExporterConstants.METADATA_DESCRIPTOR, createJdbcDescriptor());
+ hbmExporter.getProperties().put(ExporterConstants.DESTINATION_FOLDER, outputFolder);
+ String templatePath = getExtension().templatePath;
+ if (templatePath != null) {
+ getLogger().lifecycle("Setting template path to: " + templatePath);
+ hbmExporter.getProperties().put(ExporterConstants.TEMPLATE_PATH, new String[] { templatePath });
+ }
+ getLogger().lifecycle("Starting DAO export to directory: " + outputFolder + "...");
+ hbmExporter.start();
+ getLogger().lifecycle("DAO export finished");
+ }
+
+}
diff --git a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/GenerateHbmTask.java b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/GenerateHbmTask.java
new file mode 100644
index 000000000000..8a57a2ce64fa
--- /dev/null
+++ b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/GenerateHbmTask.java
@@ -0,0 +1,38 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.gradle.task;
+
+import java.io.File;
+
+import org.gradle.api.tasks.TaskAction;
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterConstants;
+import org.hibernate.tool.reveng.api.export.ExporterFactory;
+import org.hibernate.tool.reveng.api.export.ExporterType;
+
+public class GenerateHbmTask extends AbstractTask {
+
+ @TaskAction
+ public void performTask() {
+ super.perform();
+ }
+
+ void doWork() {
+ getLogger().lifecycle("Creating HBM exporter");
+ Exporter hbmExporter = ExporterFactory.createExporter(ExporterType.HBM);
+ File outputFolder = getOutputFolder();
+ hbmExporter.getProperties().put(ExporterConstants.METADATA_DESCRIPTOR, createJdbcDescriptor());
+ hbmExporter.getProperties().put(ExporterConstants.DESTINATION_FOLDER, outputFolder);
+ String templatePath = getExtension().templatePath;
+ if (templatePath != null) {
+ getLogger().lifecycle("Setting template path to: " + templatePath);
+ hbmExporter.getProperties().put(ExporterConstants.TEMPLATE_PATH, new String[] { templatePath });
+ }
+ getLogger().lifecycle("Starting HBM export to directory: " + outputFolder + "...");
+ hbmExporter.start();
+ getLogger().lifecycle("HBM export finished");
+ }
+
+}
diff --git a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/GenerateJavaTask.java b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/GenerateJavaTask.java
new file mode 100644
index 000000000000..d1db1e285524
--- /dev/null
+++ b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/GenerateJavaTask.java
@@ -0,0 +1,40 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.gradle.task;
+
+import java.io.File;
+
+import org.gradle.api.tasks.TaskAction;
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterConstants;
+import org.hibernate.tool.reveng.api.export.ExporterFactory;
+import org.hibernate.tool.reveng.api.export.ExporterType;
+
+public class GenerateJavaTask extends AbstractTask {
+
+ @TaskAction
+ public void performTask() {
+ super.perform();
+ }
+
+ void doWork() {
+ getLogger().lifecycle("Creating Java exporter");
+ Exporter pojoExporter = ExporterFactory.createExporter(ExporterType.JAVA);
+ pojoExporter.getProperties().setProperty("ejb3", String.valueOf(getExtension().generateAnnotations));
+ pojoExporter.getProperties().setProperty("jdk5", String.valueOf(getExtension().useGenerics));
+ File outputFolder = getOutputFolder();
+ pojoExporter.getProperties().put(ExporterConstants.METADATA_DESCRIPTOR, createJdbcDescriptor());
+ pojoExporter.getProperties().put(ExporterConstants.DESTINATION_FOLDER, outputFolder);
+ String templatePath = getExtension().templatePath;
+ if (templatePath != null) {
+ getLogger().lifecycle("Setting template path to: " + templatePath);
+ pojoExporter.getProperties().put(ExporterConstants.TEMPLATE_PATH, new String[] { templatePath });
+ }
+ getLogger().lifecycle("Starting Java export to directory: " + outputFolder + "...");
+ pojoExporter.start();
+ getLogger().lifecycle("Java export finished");
+ }
+
+}
diff --git a/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/RunSqlTask.java b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/RunSqlTask.java
new file mode 100644
index 000000000000..302a7aba1a3e
--- /dev/null
+++ b/tooling/hibernate-gradle-plugin/src/main/java/org/hibernate/tool/gradle/task/RunSqlTask.java
@@ -0,0 +1,76 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.gradle.task;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.gradle.api.tasks.TaskAction;
+
+public class RunSqlTask extends AbstractTask {
+
+ @TaskAction
+ public void performTask() {
+ super.perform();
+ }
+
+ void doWork() {
+ registerDriver();
+ runSql();
+ }
+
+ private void registerDriver() {
+ String driverClassName = getHibernateProperty("hibernate.connection.driver_class");
+ getLogger().lifecycle("Registering the database driver: " + driverClassName);
+ try {
+ Class> driverClass = Thread.currentThread().getContextClassLoader().loadClass(driverClassName);
+ Constructor> constructor = driverClass.getDeclaredConstructor();
+ DriverManager.registerDriver(createDelegatingDriver((Driver)constructor.newInstance()));
+ getLogger().lifecycle("Database driver is registered");
+ }
+ catch (Exception e) {
+ getLogger().error("Exception while registering the database driver: " + e.getMessage());
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void runSql() {
+ try {
+ String databaseUrl = getHibernateProperty("hibernate.connection.url");
+ getLogger().lifecycle("Connecting to database: " + databaseUrl);
+ Connection connection = DriverManager
+ .getConnection(databaseUrl, "sa", "");
+ Statement statement = connection.createStatement();
+ getLogger().lifecycle("Running SQL: " + getExtension().sqlToRun);
+ statement.execute(getExtension().sqlToRun);
+ statement.close();
+ connection.close();
+ }
+ catch (SQLException e) {
+ getLogger().error("SQLException");
+ throw new RuntimeException(e);
+ }
+ }
+
+ private Driver createDelegatingDriver(Driver driver) {
+ return (Driver)Proxy.newProxyInstance(
+ DriverManager.class.getClassLoader(),
+ new Class[] { Driver.class},
+ new InvocationHandler() {
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ return method.invoke(driver, args);
+ }
+ });
+ }
+
+}
diff --git a/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/tool/gradle/ExtensionTest.java b/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/tool/gradle/ExtensionTest.java
new file mode 100644
index 000000000000..b5a1f64af837
--- /dev/null
+++ b/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/tool/gradle/ExtensionTest.java
@@ -0,0 +1,26 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.gradle;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+
+public class ExtensionTest {
+
+ @Test
+ void testExtension() {
+ Map extensionFieldMap = new HashMap();
+ for(Field field : Extension.class.getDeclaredFields()) {
+ extensionFieldMap.put(field.getName(), field);
+ }
+ assertNotNull(extensionFieldMap.get("sqlToRun"));
+ }
+
+}
diff --git a/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/tool/gradle/PluginTest.java b/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/tool/gradle/PluginTest.java
new file mode 100644
index 000000000000..84fac8a8cc78
--- /dev/null
+++ b/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/tool/gradle/PluginTest.java
@@ -0,0 +1,29 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.gradle;
+
+import org.gradle.testfixtures.ProjectBuilder;
+import org.gradle.api.Project;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+
+class PluginTest {
+
+ @Test
+ void testApply() {
+ // Create a test project and apply the plugin
+ Project project = ProjectBuilder.builder().build();
+ project.getPlugins().apply("org.hibernate.tool.hibernate-tools-gradle");
+
+ // Verify the result
+ assertNotNull(project.getTasks().findByName("generateJava"));
+ assertNotNull(project.getTasks().findByName("runSql"));
+
+ Object extension = project.getExtensions().getByName("hibernateTools");
+ assertNotNull(extension);
+ assertTrue(extension instanceof Extension);
+ }
+
+}
diff --git a/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/tool/gradle/task/AbstractTaskTest.java b/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/tool/gradle/task/AbstractTaskTest.java
new file mode 100644
index 000000000000..d2191dbf3db5
--- /dev/null
+++ b/tooling/hibernate-gradle-plugin/src/test/java/org/hibernate/tool/gradle/task/AbstractTaskTest.java
@@ -0,0 +1,91 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.gradle.task;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.lang.reflect.Field;
+import java.net.URL;
+
+import org.gradle.api.Project;
+import org.gradle.testfixtures.ProjectBuilder;
+import org.hibernate.tool.reveng.api.core.RevengStrategy;
+import org.hibernate.tool.gradle.Extension;
+import org.hibernate.tool.reveng.internal.core.strategy.AbstractStrategy;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class AbstractTaskTest {
+
+ private static ClassLoader USED_CLASS_LOADER;
+ private static URL[] URLS = new URL[] {};
+
+ private AbstractTask abstractTask = null;
+
+ private Field extensionField = null;
+ private Extension extension = null;
+
+ @BeforeEach
+ void beforeEach() throws Exception {
+ USED_CLASS_LOADER = null;
+ Project project = ProjectBuilder.builder().build();
+ abstractTask = project.getTasks().create("foo", FooTask.class);
+ extensionField = AbstractTask.class.getDeclaredField("extension");
+ extensionField.setAccessible(true);
+ extension = new Extension(project);
+ }
+
+ @Test
+ void testInitialize() throws Exception {
+ assertNull(extensionField.get(abstractTask));
+ abstractTask.initialize(extension);
+ assertSame(extension, extensionField.get(abstractTask));
+ }
+
+ @Test
+ void testGetExtension() throws Exception {
+ assertNull(abstractTask.getExtension());
+ extensionField.set(abstractTask, extension);
+ assertSame(extension, abstractTask.getExtension());
+ }
+
+ @Test
+ void testPerform() {
+ ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+ assertNull(USED_CLASS_LOADER);
+ abstractTask.perform();
+ assertNotNull(USED_CLASS_LOADER);
+ assertNotSame(contextClassLoader, USED_CLASS_LOADER);
+ }
+
+ @Test
+ void testResolveProjectClassPath() {
+ assertSame(URLS, abstractTask.resolveProjectClassPath());
+ }
+
+ @Test
+ public void testSetupReverseEngineeringStrategy() throws Exception {
+ extension.revengStrategy = FooStrategy.class.getName();
+ extensionField.set(abstractTask, extension);
+ RevengStrategy revengStrategy = abstractTask.setupReverseEngineeringStrategy();
+ assertTrue(revengStrategy instanceof FooStrategy);
+ }
+
+ public static class FooStrategy extends AbstractStrategy {}
+
+ public static class FooTask extends AbstractTask {
+ void doWork() {
+ USED_CLASS_LOADER = Thread.currentThread().getContextClassLoader();
+ }
+ URL[] resolveProjectClassPath() {
+ return URLS;
+ }
+ }
+
+}
diff --git a/tooling/hibernate-maven-plugin/hibernate-maven-plugin.gradle b/tooling/hibernate-maven-plugin/hibernate-maven-plugin.gradle
index 852f4af08c1d..6ba87251238c 100644
--- a/tooling/hibernate-maven-plugin/hibernate-maven-plugin.gradle
+++ b/tooling/hibernate-maven-plugin/hibernate-maven-plugin.gradle
@@ -9,6 +9,7 @@ plugins {
}
description = 'Maven plugin to integrate aspects of Hibernate into your build.'
+def h2Version = '2.4.240'
sourceSets {
intTest {
@@ -24,10 +25,12 @@ configurations {
dependencies {
implementation project( ":hibernate-core" )
+ implementation project( ":hibernate-reveng" )
implementation "org.apache.maven:maven-plugin-api:3.9.11"
- implementation "org.apache.maven:maven-project:2.2.1"
+ implementation "org.apache.maven:maven-core:3.9.11"
implementation "org.apache.maven.shared:file-management:3.1.0"
+ implementation "jakarta.xml.bind:jakarta.xml.bind-api:4.0.2"
compileOnly "org.apache.maven.plugin-tools:maven-plugin-tools-annotations:3.15.1"
@@ -38,6 +41,8 @@ dependencies {
intTestRuntimeOnly 'org.apache.maven:maven-compat:3.9.11'
intTestRuntimeOnly 'org.apache.maven.resolver:maven-resolver-transport-http:1.9.24'
intTestRuntimeOnly 'org.apache.maven.resolver:maven-resolver-connector-basic:1.9.24'
+ intTestRuntimeOnly 'com.h2database:h2:' + h2Version
+// intTestRuntimeOnly 'org.slf4j:slf4j-simple:2.0.17'
}
tasks.register('integrationTest', Test) {
@@ -83,8 +88,10 @@ publishingExtension.publications.named("publishedArtifacts") {
integrationTest {
environment "hibernateVersion", project.version
+ environment "h2Version", h2Version
}
-integrationTest.dependsOn rootProject.childProjects.'hibernate-core'.tasks.publishToMavenLocal
+integrationTest.dependsOn ':hibernate-core:publishToMavenLocal'
+integrationTest.dependsOn ':hibernate-reveng:publishToMavenLocal'
integrationTest.dependsOn publishToMavenLocal
check.dependsOn integrationTest
diff --git a/tooling/hibernate-maven-plugin/src/intTest/java/org/hibernate/tool/maven/ExamplesTestIT.java b/tooling/hibernate-maven-plugin/src/intTest/java/org/hibernate/tool/maven/ExamplesTestIT.java
new file mode 100644
index 000000000000..ff6b234fb0dc
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/java/org/hibernate/tool/maven/ExamplesTestIT.java
@@ -0,0 +1,240 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.maven;
+
+import org.apache.maven.cli.MavenCli;
+import org.hibernate.tool.reveng.api.version.Version;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.File;
+import java.net.URL;
+import java.nio.file.Files;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.Statement;
+import java.util.Objects;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+ public class ExamplesTestIT {
+
+ public static final String MVN_HOME = "maven.multiModuleProjectDirectory";
+ private static File baseFolder;
+
+ private File projectFolder;
+
+ @TempDir
+ private File tempFolder;
+
+ private String[] databaseCreationScript = new String[] {
+ // This is the default database which can be overridden per test
+ "create table PERSON (ID int not null, NAME varchar(20), primary key (ID))"
+ };
+
+ @BeforeAll
+ public static void beforeAll() throws Exception {
+ // The needed resource for this test are put in place
+ // in the 'baseFolder' (normally 'target/test-classes')
+ // by the 'build-helper-maven-plugin' execution.
+ // See the 'pom.xml'
+ baseFolder = determineBaseFolder();
+// localRepo = new File(baseFolder.getParentFile(), "local-repo");
+ }
+
+ @Test
+ public void test5MinuteTutorial() throws Exception {
+ prepareProject("5-minute-tutorial");
+ assertNotGeneratedYet("Person.java");
+ runGenerateSources();
+ assertNumberOfGeneratedFiles(1);
+ assertGeneratedContains("Person.java", "public class Person");
+ }
+
+ @Test
+ public void testJpaDefault() throws Exception {
+ prepareProject("hbm2java/jpa-default");
+ assertNotGeneratedYet("Person.java");
+ runGenerateSources();
+ assertNumberOfGeneratedFiles(1);
+ assertGeneratedContains("Person.java","import jakarta.persistence.Entity;");
+ }
+
+ @Test
+ public void testNoAnnotations() throws Exception {
+ prepareProject("hbm2java/no-annotations");
+ assertNotGeneratedYet("Person.java");
+ runGenerateSources();
+ assertNumberOfGeneratedFiles(1);
+ assertGeneratedDoesNotContain("Person.java", "import jakarta.persistence.Entity;");
+ }
+
+ @Test
+ public void testNoGenerics() throws Exception {
+ databaseCreationScript = new String[] {
+ "create table PERSON (ID int not null, NAME varchar(20), primary key (ID))",
+ "create table ITEM (ID int not null, NAME varchar(20), OWNER_ID int not null, " +
+ " primary key (ID), foreign key (OWNER_ID) references PERSON(ID))"
+ };
+ prepareProject("hbm2java/no-generics");
+ assertNotGeneratedYet("Person.java");
+ runGenerateSources();
+ assertNumberOfGeneratedFiles(2);
+ assertGeneratedDoesNotContain("Person.java", "Set");
+ }
+
+ @Test
+ public void testOutputDirectory() throws Exception {
+ System.setProperty("output.dir", "${project.basedir}/generated-classes");
+ prepareProject("hbm2java/output-directory");
+ File outputDirectory = new File(projectFolder, "generated-classes");
+ File personFile = new File(outputDirectory, "Person.java");
+ assertFalse(outputDirectory.exists());
+ assertFalse(personFile.exists());
+ runGenerateSources();
+ assertEquals(1, Objects.requireNonNull( outputDirectory.list() ).length); // 1 file is generated in 'generated-classes'
+ assertTrue(personFile.exists()); // The Person.java file should have been generated
+ }
+
+ @Test
+ public void testTemplatePath() throws Exception {
+ System.setProperty("template.dir", "${project.basedir}/templates");
+ prepareProject("hbm2java/template-path");
+ assertNotGeneratedYet("Person.java");
+ runGenerateSources();
+ assertNumberOfGeneratedFiles(1);
+ assertGeneratedContains("Person.java", "// This is just an example of a custom template");
+ }
+
+ @Test
+ public void testUseGenerics() throws Exception {
+ databaseCreationScript = new String[] {
+ "create table PERSON (ID int not null, NAME varchar(20), primary key (ID))",
+ "create table ITEM (ID int not null, NAME varchar(20), OWNER_ID int not null, " +
+ " primary key (ID), foreign key (OWNER_ID) references PERSON(ID))"
+ };
+ prepareProject("hbm2java/use-generics");
+ assertNotGeneratedYet("Person.java");
+ runGenerateSources();
+ assertNumberOfGeneratedFiles(2);
+ assertGeneratedContains("Person.java", "Set");
+ }
+
+ @Test
+ public void testHbm2OrmSimpleDefault() throws Exception {
+ projectFolder = new File(baseFolder, "hbm2orm/simple-default");
+ File ormXmlFile = new File(projectFolder, "src/main/resources/simple.mapping.xml");
+ assertFalse(ormXmlFile.exists());
+ runMavenCommand( "org.hibernate.orm:hibernate-maven-plugin:" + Version.versionString() + ":hbm2orm");
+ assertTrue(ormXmlFile.exists());
+ String ormXmlContents = Files.readString( ormXmlFile.toPath() );
+ assertTrue(ormXmlContents.contains("entity-mappings"));
+ }
+
+ private void prepareProject(String projectName) throws Exception {
+ projectFolder = new File(baseFolder, projectName);
+ assertTrue(projectFolder.exists());
+ System.setProperty(MVN_HOME, projectFolder.getAbsolutePath());
+ editPomFile(projectFolder);
+ createHibernatePropertiesFile(projectFolder);
+ createDatabase();
+ }
+
+ private void createHibernatePropertiesFile(File projectFolder) throws Exception {
+ File projectResourcesFolder = new File(projectFolder, "src/main/resources");
+ File hibernatePropertiesFile = new File(projectResourcesFolder, "hibernate.properties");
+ String hibernatePropertiesFileContents =
+ "hibernate.connection.driver_class=org.h2.Driver\n" +
+ "hibernate.connection.url=" + constructJdbcConnectionString() + "\n" +
+ "hibernate.connection.username=\n" +
+ "hibernate.connection.password=\n" +
+ "hibernate.default_catalog=TEST\n" +
+ "hibernate.default_schema=PUBLIC\n";
+ Files.writeString(hibernatePropertiesFile.toPath(), hibernatePropertiesFileContents);
+ assertTrue(hibernatePropertiesFile.exists());
+ }
+
+ private void runGenerateSources() {
+ new MavenCli().doMain(
+ new String[]{"generate-sources"},
+ projectFolder.getAbsolutePath(),
+ null,
+ null);
+ }
+
+ private void runMavenCommand(String command) {
+ new MavenCli().doMain(
+ new String[]{ command },
+ projectFolder.getAbsolutePath(),
+ null,
+ null);
+ }
+
+ private void assertNotGeneratedYet(String fileName) {
+ assertFalse(new File(projectFolder, "target/generated-sources/" + fileName).exists());
+ }
+
+ private void assertGeneratedContains(String fileName, String contents) throws Exception {
+ assertTrue(readGeneratedContents(fileName).contains(contents));
+ }
+
+ private void assertGeneratedDoesNotContain(String fileName, String contents) throws Exception {
+ assertFalse(readGeneratedContents(fileName).contains(contents));
+ }
+
+ private void assertNumberOfGeneratedFiles(int amount) {
+ assertEquals(
+ amount,
+ Objects.requireNonNull(
+ new File( projectFolder, "target/generated-sources" ).list() ).length);
+ }
+
+ private String readGeneratedContents(String fileName) throws Exception {
+ File generatedPersonFile = new File(projectFolder, "target/generated-sources/" + fileName);
+ assertTrue(generatedPersonFile.exists());
+ return new String(Files.readAllBytes(generatedPersonFile.toPath()));
+ }
+
+ private static File determineBaseFolder() throws Exception {
+ Class> thisClass = ExamplesTestIT.class;
+ URL markerUrl = thisClass.getResource( "/resource.marker" );
+ assert markerUrl != null;
+ return new File(markerUrl.toURI()).getParentFile();
+ }
+
+ private void createDatabase() throws Exception {
+ File databaseFile = new File(tempFolder, "database/test.mv.db");
+ assertFalse(databaseFile.exists());
+ assertFalse(databaseFile.isFile());
+ Connection connection = DriverManager.getConnection(constructJdbcConnectionString());
+ Statement statement = connection.createStatement();
+ for (String s : databaseCreationScript) {
+ statement.execute(s);
+ }
+ statement.close();
+ connection.close();
+ assertTrue(databaseFile.exists());
+ assertTrue(databaseFile.isFile());
+ }
+
+ private String constructJdbcConnectionString() {
+ return "jdbc:h2:" + tempFolder.getAbsolutePath() + "/database/test;AUTO_SERVER=TRUE";
+ }
+
+ private void editPomFile(File projectFolder) throws Exception {
+ System.out.println("Editing pom file");
+ File pomFile = new File(projectFolder, "pom.xml");
+ assertTrue(pomFile.exists());
+ String pomFileContents = Files.readString( pomFile.toPath() );
+ pomFileContents = pomFileContents
+ .replace( "${h2.version}", System.getenv("h2Version") )
+ .replace( "${hibernate.version}", System.getenv("hibernateVersion") );
+ Files.writeString( pomFile.toPath(), pomFileContents );
+ }
+
+ }
diff --git a/tooling/hibernate-maven-plugin/src/intTest/java/org/hibernate/tool/maven/TransformHbmTestIT.java b/tooling/hibernate-maven-plugin/src/intTest/java/org/hibernate/tool/maven/TransformHbmTestIT.java
new file mode 100644
index 000000000000..6dcbae06da90
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/java/org/hibernate/tool/maven/TransformHbmTestIT.java
@@ -0,0 +1,86 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.maven;
+
+import org.apache.maven.cli.MavenCli;
+import org.hibernate.tool.reveng.api.version.Version;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.File;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Objects;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class TransformHbmTestIT {
+
+ public static final String MVN_HOME = "maven.multiModuleProjectDirectory";
+
+ @TempDir
+ private Path projectPath;
+
+ @Test
+ public void testSimpleHbmTransformation() throws Exception {
+ System.setProperty(MVN_HOME, projectPath.toAbsolutePath().toString());
+ writePomFile();
+ copyHbmFile();
+ runTransformHbmToOrm();
+ }
+
+ private void writePomFile() throws Exception {
+ File pomFile = new File(projectPath.toFile(), "pom.xml");
+ assertFalse(pomFile.exists());
+ Path pomPath = projectPath.resolve("pom.xml");
+ Files.writeString(pomPath, simplePomContents);
+ assertTrue(pomFile.exists());
+ }
+
+ private void copyHbmFile() throws Exception {
+ URL originUrl = getClass().getResource("simple.hbm.xml");
+ assertNotNull(originUrl);
+ Path originPath = Paths.get(Objects.requireNonNull(originUrl).toURI());
+ File destinationDir = new File(projectPath.toFile(), "src/main/resources/");
+ assertTrue(destinationDir.mkdirs());
+ File destinationFile = new File(destinationDir, "simple.hbm.xml");
+ assertFalse(destinationFile.exists());
+ Files.copy(originPath, destinationFile.toPath());
+ assertTrue(destinationFile.exists());
+ }
+
+ private void runTransformHbmToOrm() throws Exception {
+ File destinationDir = new File(projectPath.toFile(), "src/main/resources/");
+ File ormXmlFile = new File(destinationDir, "simple.mapping.xml");
+ assertFalse(ormXmlFile.exists());
+ new MavenCli().doMain(
+ new String[] {
+ "compile",
+ "org.hibernate.orm:hibernate-maven-plugin:" + Version.versionString() + ":hbm2orm"
+ },
+ projectPath.toAbsolutePath().toString(),
+ null,
+ null);
+ // Check the existence of the transformed file
+ assertTrue(ormXmlFile.exists());
+ // Check if it's pretty printed
+ assertTrue(Files.readString(ormXmlFile.toPath()).contains("\n
\n"));
+ }
+
+ private static final String simplePomContents =
+ """
+
+ 4.0.0
+ org.hibernate.tool.maven.test
+ simplest
+ 0.1-SNAPSHOT
+
+ """;
+
+}
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/5-minute-tutorial/README.md b/tooling/hibernate-maven-plugin/src/intTest/resources/5-minute-tutorial/README.md
new file mode 100644
index 000000000000..84a3e34535a9
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/5-minute-tutorial/README.md
@@ -0,0 +1,21 @@
+
+To run this example:
+ - Have [Apache Maven](https://maven.apache.org) installed
+ - Have [H2 Sakila database](https://github.com/hibernate/sakila-h2) running
+ - Issue one of the following commands from a command-line window opened in this folder:
+ - `mvn generate-sources -Dh2.version=${h2.version} -Dproject.version=${hibernate.version}`
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/5-minute-tutorial/pom.xml b/tooling/hibernate-maven-plugin/src/intTest/resources/5-minute-tutorial/pom.xml
new file mode 100644
index 000000000000..44a3d864c273
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/5-minute-tutorial/pom.xml
@@ -0,0 +1,53 @@
+
+
+
+ 4.0.0
+
+ org.hibernate.tool.maven.test
+ five-minute-tutorial
+ 0.0.1-SNAPSHOT
+
+
+
+ com.h2database
+ h2
+ ${h2.version}
+
+
+
+
+
+
+ org.hibernate.orm
+ hibernate-maven-plugin
+ ${hibernate.version}
+
+
+ Entity generation
+ generate-sources
+
+ hbm2java
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/5-minute-tutorial/src/main/resources/hibernate.properties b/tooling/hibernate-maven-plugin/src/intTest/resources/5-minute-tutorial/src/main/resources/hibernate.properties
new file mode 100644
index 000000000000..60b2483a2f2b
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/5-minute-tutorial/src/main/resources/hibernate.properties
@@ -0,0 +1,23 @@
+############################################################################
+# Hibernate Tools, Tooling for your Hibernate Projects #
+# #
+# Copyright 2004-2025 Red Hat, Inc. #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); #
+# you may not use this file except in compliance with the License. #
+# You may obtain a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" basis, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+############################################################################
+hibernate.connection.driver_class=org.h2.Driver
+hibernate.connection.url=jdbc:h2:tcp://localhost/./sakila
+hibernate.connection.username=sa
+hibernate.default_catalog=SAKILA
+hibernate.default_schema=PUBLIC
+
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/jpa-default/README.md b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/jpa-default/README.md
new file mode 100644
index 000000000000..b7b95463cd2f
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/jpa-default/README.md
@@ -0,0 +1,21 @@
+
+To run this example:
+ - Have [Apache Maven](https://maven.apache.org) installed
+ - Have [H2 Sakila database](https://github.com/hibernate/sakila-h2) running
+ - Issue the following commands from a command-line window opened in this folder:
+ `mvn generate-sources -Dh2.version=${h2.version} -Dhibernate.version=${hibernate.version}`
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/jpa-default/pom.xml b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/jpa-default/pom.xml
new file mode 100644
index 000000000000..79e2a4e37f6f
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/jpa-default/pom.xml
@@ -0,0 +1,53 @@
+
+
+
+ 4.0.0
+
+ org.hibernate.tool.maven.test
+ hbm2java-jpa-default
+ 0.0.1-SNAPSHOT
+
+
+
+ com.h2database
+ h2
+ ${h2.version}
+
+
+
+
+
+
+ org.hibernate.orm
+ hibernate-maven-plugin
+ ${hibernate.version}
+
+
+ Entity generation
+ generate-sources
+
+ hbm2java
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/jpa-default/src/main/resources/hibernate.properties b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/jpa-default/src/main/resources/hibernate.properties
new file mode 100644
index 000000000000..60b2483a2f2b
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/jpa-default/src/main/resources/hibernate.properties
@@ -0,0 +1,23 @@
+############################################################################
+# Hibernate Tools, Tooling for your Hibernate Projects #
+# #
+# Copyright 2004-2025 Red Hat, Inc. #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); #
+# you may not use this file except in compliance with the License. #
+# You may obtain a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" basis, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+############################################################################
+hibernate.connection.driver_class=org.h2.Driver
+hibernate.connection.url=jdbc:h2:tcp://localhost/./sakila
+hibernate.connection.username=sa
+hibernate.default_catalog=SAKILA
+hibernate.default_schema=PUBLIC
+
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-annotations/README.md b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-annotations/README.md
new file mode 100644
index 000000000000..b7b95463cd2f
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-annotations/README.md
@@ -0,0 +1,21 @@
+
+To run this example:
+ - Have [Apache Maven](https://maven.apache.org) installed
+ - Have [H2 Sakila database](https://github.com/hibernate/sakila-h2) running
+ - Issue the following commands from a command-line window opened in this folder:
+ `mvn generate-sources -Dh2.version=${h2.version} -Dhibernate.version=${hibernate.version}`
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-annotations/pom.xml b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-annotations/pom.xml
new file mode 100644
index 000000000000..39275e3295cb
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-annotations/pom.xml
@@ -0,0 +1,56 @@
+
+
+
+ 4.0.0
+
+ org.hibernate.tool.maven.test
+ hbm2java-no-annotations
+ 0.0.1-SNAPSHOT
+
+
+
+ com.h2database
+ h2
+ ${h2.version}
+
+
+
+
+
+
+ org.hibernate.orm
+ hibernate-maven-plugin
+ ${hibernate.version}
+
+
+ Entity generation
+ generate-sources
+
+ hbm2java
+
+
+
+
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-annotations/src/main/resources/hibernate.properties b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-annotations/src/main/resources/hibernate.properties
new file mode 100644
index 000000000000..60b2483a2f2b
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-annotations/src/main/resources/hibernate.properties
@@ -0,0 +1,23 @@
+############################################################################
+# Hibernate Tools, Tooling for your Hibernate Projects #
+# #
+# Copyright 2004-2025 Red Hat, Inc. #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); #
+# you may not use this file except in compliance with the License. #
+# You may obtain a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" basis, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+############################################################################
+hibernate.connection.driver_class=org.h2.Driver
+hibernate.connection.url=jdbc:h2:tcp://localhost/./sakila
+hibernate.connection.username=sa
+hibernate.default_catalog=SAKILA
+hibernate.default_schema=PUBLIC
+
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-generics/README.md b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-generics/README.md
new file mode 100644
index 000000000000..b7b95463cd2f
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-generics/README.md
@@ -0,0 +1,21 @@
+
+To run this example:
+ - Have [Apache Maven](https://maven.apache.org) installed
+ - Have [H2 Sakila database](https://github.com/hibernate/sakila-h2) running
+ - Issue the following commands from a command-line window opened in this folder:
+ `mvn generate-sources -Dh2.version=${h2.version} -Dhibernate.version=${hibernate.version}`
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-generics/pom.xml b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-generics/pom.xml
new file mode 100644
index 000000000000..3d5afb66d9a4
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-generics/pom.xml
@@ -0,0 +1,56 @@
+
+
+
+ 4.0.0
+
+ org.hibernate.tool.maven.test
+ hbm2java-no-generics
+ 0.0.1-SNAPSHOT
+
+
+
+ com.h2database
+ h2
+ ${h2.version}
+
+
+
+
+
+
+ org.hibernate.orm
+ hibernate-maven-plugin
+ ${hibernate.version}
+
+
+ Entity generation
+ generate-sources
+
+ hbm2java
+
+
+
+
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-generics/src/main/resources/hibernate.properties b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-generics/src/main/resources/hibernate.properties
new file mode 100644
index 000000000000..60b2483a2f2b
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/no-generics/src/main/resources/hibernate.properties
@@ -0,0 +1,23 @@
+############################################################################
+# Hibernate Tools, Tooling for your Hibernate Projects #
+# #
+# Copyright 2004-2025 Red Hat, Inc. #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); #
+# you may not use this file except in compliance with the License. #
+# You may obtain a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" basis, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+############################################################################
+hibernate.connection.driver_class=org.h2.Driver
+hibernate.connection.url=jdbc:h2:tcp://localhost/./sakila
+hibernate.connection.username=sa
+hibernate.default_catalog=SAKILA
+hibernate.default_schema=PUBLIC
+
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/output-directory/README.md b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/output-directory/README.md
new file mode 100644
index 000000000000..a5b85c8ec89c
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/output-directory/README.md
@@ -0,0 +1,26 @@
+
+To run this example:
+ - Have [Apache Maven](https://maven.apache.org) installed
+ - Have [H2 Sakila database](https://github.com/hibernate/sakila-h2) running
+ - Issue the following command from a command-line window opened in this folder:
+```shell
+mvn generate-sources
+ -Dh2.version=${h2.version}
+ -Dhibernate.version=${hibernate.version}
+ -Doutput.dir=./generated-classes
+```
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/output-directory/pom.xml b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/output-directory/pom.xml
new file mode 100644
index 000000000000..8fbb23eaf45b
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/output-directory/pom.xml
@@ -0,0 +1,56 @@
+
+
+
+ 4.0.0
+
+ org.hibernate.tool.maven.test
+ hbm2java-jpa-default
+ 0.0.1-SNAPSHOT
+
+
+
+ com.h2database
+ h2
+ ${h2.version}
+
+
+
+
+
+
+ org.hibernate.orm
+ hibernate-maven-plugin
+ ${hibernate.version}
+
+
+ Entity generation
+ generate-sources
+
+ hbm2java
+
+
+
+
+ ${output.dir}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/output-directory/src/main/resources/hibernate.properties b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/output-directory/src/main/resources/hibernate.properties
new file mode 100644
index 000000000000..60b2483a2f2b
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/output-directory/src/main/resources/hibernate.properties
@@ -0,0 +1,23 @@
+############################################################################
+# Hibernate Tools, Tooling for your Hibernate Projects #
+# #
+# Copyright 2004-2025 Red Hat, Inc. #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); #
+# you may not use this file except in compliance with the License. #
+# You may obtain a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" basis, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+############################################################################
+hibernate.connection.driver_class=org.h2.Driver
+hibernate.connection.url=jdbc:h2:tcp://localhost/./sakila
+hibernate.connection.username=sa
+hibernate.default_catalog=SAKILA
+hibernate.default_schema=PUBLIC
+
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/template-path/README.md b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/template-path/README.md
new file mode 100644
index 000000000000..fa81c49116cd
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/template-path/README.md
@@ -0,0 +1,26 @@
+
+To run this example:
+ - Have [Apache Maven](https://maven.apache.org) installed
+ - Have [H2 Sakila database](https://github.com/hibernate/sakila-h2) running
+ - Issue the following command from a command-line window opened in this folder:
+```shell
+mvn generate-sources
+ -Dh2.version=${h2.version}
+ -Dhibernate.version=${hibernate.version}
+ -Dtemplate.dir=./templates
+```
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/template-path/pom.xml b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/template-path/pom.xml
new file mode 100644
index 000000000000..50c1cad65a5a
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/template-path/pom.xml
@@ -0,0 +1,56 @@
+
+
+
+ 4.0.0
+
+ org.hibernate.tool.maven.test
+ hbm2java-template-path
+ 0.0.1-SNAPSHOT
+
+
+
+ com.h2database
+ h2
+ ${h2.version}
+
+
+
+
+
+
+ org.hibernate.orm
+ hibernate-maven-plugin
+ ${hibernate.version}
+
+
+ Entity generation
+ generate-sources
+
+ hbm2java
+
+
+
+
+ ${template.dir}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/template-path/src/main/resources/hibernate.properties b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/template-path/src/main/resources/hibernate.properties
new file mode 100644
index 000000000000..60b2483a2f2b
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/template-path/src/main/resources/hibernate.properties
@@ -0,0 +1,23 @@
+############################################################################
+# Hibernate Tools, Tooling for your Hibernate Projects #
+# #
+# Copyright 2004-2025 Red Hat, Inc. #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); #
+# you may not use this file except in compliance with the License. #
+# You may obtain a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" basis, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+############################################################################
+hibernate.connection.driver_class=org.h2.Driver
+hibernate.connection.url=jdbc:h2:tcp://localhost/./sakila
+hibernate.connection.username=sa
+hibernate.default_catalog=SAKILA
+hibernate.default_schema=PUBLIC
+
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/template-path/templates/pojo/Pojo.ftl b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/template-path/templates/pojo/Pojo.ftl
new file mode 100644
index 000000000000..18f3de1a5a29
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/template-path/templates/pojo/Pojo.ftl
@@ -0,0 +1,18 @@
+
+// This is just an example of a custom template
+
+
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/use-generics/README.md b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/use-generics/README.md
new file mode 100644
index 000000000000..b7b95463cd2f
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/use-generics/README.md
@@ -0,0 +1,21 @@
+
+To run this example:
+ - Have [Apache Maven](https://maven.apache.org) installed
+ - Have [H2 Sakila database](https://github.com/hibernate/sakila-h2) running
+ - Issue the following commands from a command-line window opened in this folder:
+ `mvn generate-sources -Dh2.version=${h2.version} -Dhibernate.version=${hibernate.version}`
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/use-generics/pom.xml b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/use-generics/pom.xml
new file mode 100644
index 000000000000..c59fe76a5c83
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/use-generics/pom.xml
@@ -0,0 +1,53 @@
+
+
+
+ 4.0.0
+
+ org.hibernate.tool.maven.test
+ hbm2java-use-generics
+ 0.0.1-SNAPSHOT
+
+
+
+ com.h2database
+ h2
+ ${h2.version}
+
+
+
+
+
+
+ org.hibernate.orm
+ hibernate-maven-plugin
+ ${hibernate.version}
+
+
+ Entity generation
+ generate-sources
+
+ hbm2java
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/use-generics/src/main/resources/hibernate.properties b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/use-generics/src/main/resources/hibernate.properties
new file mode 100644
index 000000000000..60b2483a2f2b
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2java/use-generics/src/main/resources/hibernate.properties
@@ -0,0 +1,23 @@
+############################################################################
+# Hibernate Tools, Tooling for your Hibernate Projects #
+# #
+# Copyright 2004-2025 Red Hat, Inc. #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); #
+# you may not use this file except in compliance with the License. #
+# You may obtain a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" basis, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+############################################################################
+hibernate.connection.driver_class=org.h2.Driver
+hibernate.connection.url=jdbc:h2:tcp://localhost/./sakila
+hibernate.connection.username=sa
+hibernate.default_catalog=SAKILA
+hibernate.default_schema=PUBLIC
+
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/.gitignore b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/.gitignore
new file mode 100644
index 000000000000..34aa788d0e6a
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/.gitignore
@@ -0,0 +1 @@
+*.mapping.xml
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/simple-default/README.md b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/simple-default/README.md
new file mode 100644
index 000000000000..40d4212b989e
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/simple-default/README.md
@@ -0,0 +1,19 @@
+
+To run this example:
+- Have [Apache Maven](https://maven.apache.org) installed
+- Issue the following commands from a command-line window opened in this folder:
+ `mvn org.hibernate.tool:hibernate-tools-maven:${hibernate.version}:hbm2orm`
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/simple-default/pom.xml b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/simple-default/pom.xml
new file mode 100644
index 000000000000..8f2461a63d58
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/simple-default/pom.xml
@@ -0,0 +1,26 @@
+
+
+
+ 4.0.0
+
+ org.hibernate.tool.maven.test
+ hbm2orm-simple-default
+ 0.0.1-SNAPSHOT
+
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/simple-default/src/main/resources/simple.hbm.xml b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/simple-default/src/main/resources/simple.hbm.xml
new file mode 100644
index 000000000000..c45e11bd0102
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/simple-default/src/main/resources/simple.hbm.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/with-user-type/README.md b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/with-user-type/README.md
new file mode 100644
index 000000000000..0b6300de104a
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/with-user-type/README.md
@@ -0,0 +1,19 @@
+
+To run this example:
+- Have [Apache Maven](https://maven.apache.org) installed
+- Issue the following commands from a command-line window opened in this folder:
+ `mvn compile org.hibernate.tool:hibernate-tools-maven:${hibernate.version}:hbm2orm`
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/with-user-type/pom.xml b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/with-user-type/pom.xml
new file mode 100644
index 000000000000..8f2461a63d58
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/with-user-type/pom.xml
@@ -0,0 +1,26 @@
+
+
+
+ 4.0.0
+
+ org.hibernate.tool.maven.test
+ hbm2orm-simple-default
+ 0.0.1-SNAPSHOT
+
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/with-user-type/src/main/java/org/foo/Bar.java b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/with-user-type/src/main/java/org/foo/Bar.java
new file mode 100644
index 000000000000..34baa13968e4
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/with-user-type/src/main/java/org/foo/Bar.java
@@ -0,0 +1,44 @@
+/*
+ * Hibernate Tools, Tooling for your Hibernate Projects
+ *
+ * Copyright 2016-2025 Red Hat, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.foo;
+
+import org.hibernate.usertype.UserType;
+
+public class Bar implements UserType {
+
+ @Override
+ public int getSqlType() {
+ return 0;
+ }
+
+ @Override
+ public Class returnedClass() {
+ return null;
+ }
+
+ @Override
+ public Integer deepCopy(Integer integer) {
+ return 0;
+ }
+
+ @Override
+ public boolean isMutable() {
+ return false;
+ }
+
+}
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/with-user-type/src/main/resources/user-type.hbm.xml b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/with-user-type/src/main/resources/user-type.hbm.xml
new file mode 100644
index 000000000000..aa6eef423b2d
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/hbm2orm/with-user-type/src/main/resources/user-type.hbm.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/org/hibernate/tool/maven/simple.hbm.xml b/tooling/hibernate-maven-plugin/src/intTest/resources/org/hibernate/tool/maven/simple.hbm.xml
new file mode 100644
index 000000000000..c45e11bd0102
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/org/hibernate/tool/maven/simple.hbm.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/resource.marker b/tooling/hibernate-maven-plugin/src/intTest/resources/resource.marker
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/AbstractGenerationMojo.java b/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/AbstractGenerationMojo.java
new file mode 100644
index 000000000000..b71a9914620d
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/AbstractGenerationMojo.java
@@ -0,0 +1,156 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.maven;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Properties;
+
+import org.apache.maven.artifact.DependencyResolutionRequiredException;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptorFactory;
+import org.hibernate.tool.reveng.api.metadata.MetadataConstants;
+import org.hibernate.tool.reveng.api.core.RevengSettings;
+import org.hibernate.tool.reveng.api.core.RevengStrategy;
+import org.hibernate.tool.reveng.api.core.RevengStrategyFactory;
+
+public abstract class AbstractGenerationMojo extends AbstractMojo {
+
+ // For reveng strategy
+ /** The default package name to use when mappings for classes are created. */
+ @Parameter
+ private String packageName;
+
+ /** The name of a property file, e.g. hibernate.properties. */
+ @Parameter
+ private File revengFile;
+
+ /** The class name of the reverse engineering strategy to use.
+ * Extend the DefaultReverseEngineeringStrategy and override the corresponding methods, e.g.
+ * to adapt the generate class names or to provide custom type mappings. */
+ @Parameter
+ private String revengStrategy;
+
+ /** If true, tables which are pure many-to-many link tables will be mapped as such.
+ * A pure many-to-many table is one which primary-key contains exactly two foreign-keys pointing
+ * to other entity tables and has no other columns. */
+ @Parameter(defaultValue = "true")
+ private boolean detectManyToMany;
+
+ /** If true, a one-to-one association will be created for each foreignkey found. */
+ @Parameter(defaultValue = "true")
+ private boolean detectOneToOne;
+
+ /** If true, columns named VERSION or TIMESTAMP with appropriate types will be mapped with the appropriate
+ * optimistic locking corresponding to <version> or <timestamp>. */
+ @Parameter(defaultValue = "true")
+ private boolean detectOptimisticLock;
+
+ /** If true, a collection will be mapped for each foreignkey. */
+ @Parameter(defaultValue = "true")
+ private boolean createCollectionForForeignKey;
+
+ /** If true, a many-to-one association will be created for each foreignkey found. */
+ @Parameter(defaultValue = "true")
+ private boolean createManyToOneForForeignKey;
+
+ // For configuration
+ /** The name of a property file, e.g. hibernate.properties. */
+ @Parameter(defaultValue = "${project.basedir}/src/main/resources/hibernate.properties")
+ private File propertyFile;
+
+ // Not exposed for now
+ private boolean preferBasicCompositeIds = true;
+
+ @Parameter(defaultValue = "${project}", readonly = true, required = true)
+ private MavenProject project;
+
+ public void execute() throws MojoFailureException {
+ ClassLoader original = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(createExporterClassLoader(original));
+ getLog().info("Starting " + this.getClass().getSimpleName() + "...");
+ RevengStrategy strategy = setupReverseEngineeringStrategy();
+ if (propertyFile.exists()) {
+ executeExporter(createJdbcDescriptor(strategy, loadPropertiesFile()));
+ }
+ else {
+ getLog().info("Property file '" + propertyFile + "' cannot be found, aborting...");
+ }
+ getLog().info("Finished " + this.getClass().getSimpleName() + "!");
+ }
+ finally {
+ Thread.currentThread().setContextClassLoader(original);
+ }
+ }
+
+ private RevengStrategy setupReverseEngineeringStrategy() {
+ File[] revengFiles = null;
+ if (revengFile != null) {
+ revengFiles = new File[] { revengFile };
+ }
+ RevengStrategy strategy =
+ RevengStrategyFactory.createReverseEngineeringStrategy(
+ revengStrategy,
+ revengFiles);
+ RevengSettings settings =
+ new RevengSettings(strategy)
+ .setDefaultPackageName(packageName)
+ .setDetectManyToMany(detectManyToMany)
+ .setDetectOneToOne(detectOneToOne)
+ .setDetectOptimisticLock(detectOptimisticLock)
+ .setCreateCollectionForForeignKey(createCollectionForForeignKey)
+ .setCreateManyToOneForForeignKey(createManyToOneForForeignKey);
+ strategy.setSettings(settings);
+ return strategy;
+ }
+
+ private Properties loadPropertiesFile() throws MojoFailureException {
+ try (FileInputStream is = new FileInputStream(propertyFile)) {
+ Properties result = new Properties();
+ result.load(is);
+ return result;
+ }
+ catch (FileNotFoundException e) {
+ throw new MojoFailureException(propertyFile + " not found.", e);
+ }
+ catch (IOException e) {
+ throw new MojoFailureException("Problem while loading " + propertyFile, e);
+ }
+ }
+
+ private MetadataDescriptor createJdbcDescriptor(RevengStrategy strategy, Properties properties) {
+ properties.put(MetadataConstants.PREFER_BASIC_COMPOSITE_IDS, preferBasicCompositeIds);
+ return MetadataDescriptorFactory
+ .createReverseEngineeringDescriptor(
+ strategy,
+ properties);
+ }
+
+ private ClassLoader createExporterClassLoader(ClassLoader parent) {
+ ArrayList urls = new ArrayList();
+ try {
+ for (String cpe : project.getRuntimeClasspathElements()) {
+ urls.add(new File(cpe).toURI().toURL());
+ }
+ }
+ catch (DependencyResolutionRequiredException | MalformedURLException e) {
+ throw new RuntimeException("Problem while constructing project classloader", e);
+ }
+ return new URLClassLoader(urls.toArray(new URL[0]), parent);
+ }
+
+ protected abstract void executeExporter(MetadataDescriptor metadataDescriptor) throws MojoFailureException;
+}
diff --git a/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/GenerateDaoMojo.java b/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/GenerateDaoMojo.java
new file mode 100644
index 000000000000..a84bccb7c5c9
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/GenerateDaoMojo.java
@@ -0,0 +1,63 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.maven;
+
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterConstants;
+import org.hibernate.tool.reveng.api.export.ExporterFactory;
+import org.hibernate.tool.reveng.api.export.ExporterType;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
+
+import java.io.File;
+
+import static org.apache.maven.plugins.annotations.LifecyclePhase.GENERATE_SOURCES;
+
+/**
+ * Mojo to generate Data Access Objects (DAOs) from an existing database.
+ *
+ * See: https://docs.jboss.org/tools/latest/en/hibernatetools/html_single/#d0e4821
+ */
+@Mojo(
+ name = "hbm2dao",
+ defaultPhase = GENERATE_SOURCES,
+ requiresDependencyResolution = ResolutionScope.RUNTIME)
+public class GenerateDaoMojo extends AbstractGenerationMojo {
+
+ /** The directory into which the DAOs will be generated. */
+ @Parameter(defaultValue = "${project.build.directory}/generated-sources/")
+ private File outputDirectory;
+
+ /** Code will contain JPA features, e.g. using annotations from jakarta.persistence
+ * and org.hibernate.annotations. */
+ @Parameter(defaultValue = "false")
+ private boolean ejb3;
+
+ /** Code will contain JDK 5 constructs such as generics and static imports. */
+ @Parameter(defaultValue = "false")
+ private boolean jdk5;
+
+ /** A path used for looking up user-edited templates. */
+ @Parameter
+ private String templatePath;
+
+ protected void executeExporter(MetadataDescriptor metadataDescriptor) {
+ Exporter pojoExporter = ExporterFactory.createExporter(ExporterType.DAO);
+ pojoExporter.getProperties().put(ExporterConstants.METADATA_DESCRIPTOR, metadataDescriptor);
+ pojoExporter.getProperties().put(ExporterConstants.DESTINATION_FOLDER, outputDirectory);
+ if (templatePath != null) {
+ getLog().info("Setting template path to: " + templatePath);
+ pojoExporter.getProperties().put(ExporterConstants.TEMPLATE_PATH, new String[] {templatePath});
+ }
+ pojoExporter.getProperties().setProperty("ejb3", String.valueOf(ejb3));
+ pojoExporter.getProperties().setProperty("jdk5", String.valueOf(jdk5));
+ getLog().info("Starting DAO export to directory: " + outputDirectory + "...");
+ pojoExporter.start();
+ }
+
+
+}
diff --git a/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/GenerateDdlMojo.java b/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/GenerateDdlMojo.java
new file mode 100644
index 000000000000..a35f37066427
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/GenerateDdlMojo.java
@@ -0,0 +1,85 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.maven;
+
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.hibernate.boot.Metadata;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
+import org.hibernate.tool.hbm2ddl.SchemaExport;
+import org.hibernate.tool.schema.TargetType;
+
+import java.io.File;
+import java.util.EnumSet;
+import java.util.Set;
+
+import static org.apache.maven.plugins.annotations.LifecyclePhase.GENERATE_RESOURCES;
+
+/**
+ * Mojo to generate DDL Scripts from an existing database.
+ *
+ * See https://docs.jboss.org/tools/latest/en/hibernatetools/html_single/#d0e4651
+ */
+@Mojo(
+ name = "hbm2ddl",
+ defaultPhase = GENERATE_RESOURCES,
+ requiresDependencyResolution = ResolutionScope.RUNTIME)
+public class GenerateDdlMojo extends AbstractGenerationMojo {
+
+ /** The directory into which the DDLs will be generated. */
+ @Parameter(defaultValue = "${project.build.directory}/generated-resources/")
+ private File outputDirectory;
+
+ /** The default filename of the generated DDL script. */
+ @Parameter(defaultValue = "schema.ddl")
+ private String outputFileName;
+
+ /** The type of output to produce.
+ *
+ *
DATABASE: Export to the database.
+ *
SCRIPT (default): Write to a script file.
+ *
STDOUT: Write to {@link System#out}.
+ *
*/
+ @Parameter(defaultValue = "SCRIPT")
+ private Set targetTypes;
+
+ /**
+ * The DDLs statements to create.
+ *
+ *
NONE: None - duh :P.
+ *
CREATE (default): Create only.
+ *
DROP: Drop only.
+ *
BOTH: Drop and then create.
+ *
+ */
+ @Parameter(defaultValue = "CREATE")
+ private SchemaExport.Action schemaExportAction;
+
+ /** Set the end of statement delimiter. */
+ @Parameter(defaultValue = ";")
+ private String delimiter;
+
+ /** Should we format the sql strings? */
+ @Parameter(defaultValue = "true")
+ private boolean format;
+
+ /** Should we stop once an error occurs? */
+ @Parameter(defaultValue = "true")
+ private boolean haltOnError;
+
+
+ @Override
+ protected void executeExporter(MetadataDescriptor metadataDescriptor) {
+ Metadata metadata = metadataDescriptor.createMetadata();
+
+ SchemaExport export = new SchemaExport();
+ export.setOutputFile(new File(outputDirectory, outputFileName).toString());
+ export.setDelimiter(delimiter);
+ export.setHaltOnError(haltOnError);
+ export.setFormat(format);
+ export.execute(EnumSet.copyOf(this.targetTypes), schemaExportAction, metadata);
+ }
+}
diff --git a/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/GenerateHbmMojo.java b/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/GenerateHbmMojo.java
new file mode 100644
index 000000000000..a619616a0971
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/GenerateHbmMojo.java
@@ -0,0 +1,57 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.maven;
+
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterConstants;
+import org.hibernate.tool.reveng.api.export.ExporterFactory;
+import org.hibernate.tool.reveng.api.export.ExporterType;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
+
+import java.io.File;
+
+import static org.apache.maven.plugins.annotations.LifecyclePhase.GENERATE_SOURCES;
+
+/**
+ * Mojo to generate hbm.xml files from an existing database.
+ *
+ * See: https://docs.jboss.org/tools/latest/en/hibernatetools/html_single/#d0e4821
+ */
+@Mojo(
+ name = "generateHbm",
+ defaultPhase = GENERATE_SOURCES,
+ requiresDependencyResolution = ResolutionScope.RUNTIME)
+public class GenerateHbmMojo extends AbstractGenerationMojo {
+
+ /** The directory into which the DAOs will be generated. */
+ @Parameter(defaultValue = "${project.basedir}/src/main/resources")
+ private File outputDirectory;
+
+ @Parameter
+ private String templatePath;
+
+ protected void executeExporter(MetadataDescriptor metadataDescriptor) throws MojoFailureException {
+ try {
+ Exporter hbmExporter = ExporterFactory.createExporter(ExporterType.HBM);
+ hbmExporter.getProperties().put(ExporterConstants.METADATA_DESCRIPTOR, metadataDescriptor);
+ hbmExporter.getProperties().put(ExporterConstants.DESTINATION_FOLDER, outputDirectory);
+ if (templatePath != null) {
+ getLog().info("Setting template path to: " + templatePath);
+ hbmExporter.getProperties().put(ExporterConstants.TEMPLATE_PATH, new String[] {templatePath});
+ }
+ getLog().info("Starting HBM export to directory: " + outputDirectory + "...");
+ hbmExporter.start();
+ }
+ catch (Exception e) {
+ throw new MojoFailureException( e );
+ }
+ }
+
+
+}
diff --git a/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/GenerateJavaMojo.java b/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/GenerateJavaMojo.java
new file mode 100644
index 000000000000..f8f79fc5ea16
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/GenerateJavaMojo.java
@@ -0,0 +1,65 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.maven;
+
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterConstants;
+import org.hibernate.tool.reveng.api.export.ExporterFactory;
+import org.hibernate.tool.reveng.api.export.ExporterType;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
+
+import java.io.File;
+
+import static org.apache.maven.plugins.annotations.LifecyclePhase.GENERATE_SOURCES;
+
+/**
+ * Mojo to generate Java JPA Entities from an existing database.
+ *
+ * See: https://docs.jboss.org/tools/latest/en/hibernatetools/html_single/#d0e4821
+ */
+@Mojo(
+ name = "hbm2java",
+ defaultPhase = GENERATE_SOURCES,
+ requiresDependencyResolution = ResolutionScope.RUNTIME)
+public class GenerateJavaMojo extends AbstractGenerationMojo {
+
+ /** The directory into which the JPA entities will be generated. */
+ @Parameter(defaultValue = "${project.build.directory}/generated-sources/")
+ private File outputDirectory;
+
+ /** Code will contain JPA features, e.g. using annotations from jakarta.persistence
+ * and org.hibernate.annotations. */
+ @Parameter(defaultValue = "true")
+ private boolean ejb3;
+
+ /** Code will contain JDK 5 constructs such as generics and static imports. */
+ @Parameter(defaultValue = "true")
+ private boolean jdk5;
+
+ /** A path used for looking up user-edited templates. */
+ @Parameter
+ private String templatePath;
+
+ protected void executeExporter(MetadataDescriptor metadataDescriptor) {
+ Exporter pojoExporter = ExporterFactory.createExporter(ExporterType.JAVA);
+ pojoExporter.getProperties().put(ExporterConstants.METADATA_DESCRIPTOR, metadataDescriptor);
+ pojoExporter.getProperties().put(ExporterConstants.DESTINATION_FOLDER, outputDirectory);
+ if (templatePath != null) {
+ getLog().info("Setting template path to: " + templatePath);
+ pojoExporter.getProperties().put(ExporterConstants.TEMPLATE_PATH, new String[] {templatePath});
+ }
+ pojoExporter.getProperties().setProperty("ejb3", String.valueOf(ejb3));
+ pojoExporter.getProperties().setProperty("jdk5", String.valueOf(jdk5));
+ getLog().info("Starting POJO export to directory: " + outputDirectory + "...");
+ pojoExporter.start();
+ }
+
+
+
+
+}
diff --git a/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/TransformHbmMojo.java b/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/TransformHbmMojo.java
new file mode 100644
index 000000000000..6f8956f409e1
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/tool/maven/TransformHbmMojo.java
@@ -0,0 +1,86 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.maven;
+
+import static org.apache.maven.plugins.annotations.LifecyclePhase.GENERATE_RESOURCES;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.maven.artifact.DependencyResolutionRequiredException;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.maven.project.MavenProject;
+
+import org.hibernate.tool.reveng.internal.export.mapping.MappingExporter;
+
+@Mojo(
+ name = "hbm2orm",
+ defaultPhase = GENERATE_RESOURCES,
+ requiresDependencyResolution = ResolutionScope.RUNTIME)
+public class TransformHbmMojo extends AbstractMojo {
+
+ @Parameter(defaultValue = "${project.basedir}/src/main/resources")
+ private File inputFolder;
+
+ @Parameter(defaultValue = "true")
+ private boolean format;
+
+ @Parameter(defaultValue = "${project}", readonly = true, required = true)
+ private MavenProject project;
+
+ @Override
+ public void execute() {
+ ClassLoader original = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(createClassLoader(original));
+ getLog().info("Starting " + this.getClass().getSimpleName() + "...");
+ MappingExporter mappingExporter = new MappingExporter();
+ mappingExporter.setHbmFiles(getHbmFiles(inputFolder));
+ mappingExporter.setFormatResult(format);
+ mappingExporter.start();
+ getLog().info("Finished " + this.getClass().getSimpleName() + "!");
+ }
+ finally {
+ Thread.currentThread().setContextClassLoader(original);
+ }
+ }
+
+ private List getHbmFiles(File f) {
+ List result = new ArrayList<>();
+ if (f.isFile()) {
+ if (f.getName().endsWith("hbm.xml")) {
+ result.add(f);
+ }
+ }
+ else {
+ for (File child : Objects.requireNonNull( f.listFiles() ) ) {
+ result.addAll(getHbmFiles(child));
+ }
+ }
+ return result;
+ }
+
+ private ClassLoader createClassLoader(ClassLoader parent) {
+ ArrayList urls = new ArrayList<>();
+ try {
+ for (String cpe : project.getRuntimeClasspathElements()) {
+ urls.add(new File(cpe).toURI().toURL());
+ }
+ }
+ catch (DependencyResolutionRequiredException | MalformedURLException e) {
+ throw new RuntimeException("Problem while constructing project classloader", e);
+ }
+ return new URLClassLoader(urls.toArray(new URL[0]), parent);
+ }
+
+}
diff --git a/tooling/hibernate-maven-plugin/src/test/java/org/hibernate/tool/maven/GenerateJavaMojoTest.java b/tooling/hibernate-maven-plugin/src/test/java/org/hibernate/tool/maven/GenerateJavaMojoTest.java
new file mode 100644
index 000000000000..336255dcaafd
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/test/java/org/hibernate/tool/maven/GenerateJavaMojoTest.java
@@ -0,0 +1,181 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.maven;
+
+import org.apache.maven.project.MavenProject;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptorFactory;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.nio.file.Files;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.Statement;
+import java.util.Properties;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class GenerateJavaMojoTest {
+
+ private static final String CREATE_PERSON_TABLE =
+ "create table PERSON (ID int not null, NAME varchar(20), primary key (ID))";
+ private static final String CREATE_ITEM_TABLE =
+ "create table ITEM (ID int not null, NAME varchar(20), OWNER_ID int not null, primary key (ID), foreign key (OWNER_ID) references PERSON(ID))";
+ private static final String DROP_ITEM_TABLE =
+ "drop table ITEM";
+ private static final String DROP_PERSON_TABLE =
+ "drop table PERSON";
+
+ @TempDir
+ private File tempDir;
+
+ private File outputDirectory;
+ private GenerateJavaMojo generateJavaMojo;
+
+ @BeforeEach
+ public void beforeEach() throws Exception {
+ createDatabase();
+ createOutputDirectory();
+ createGenerateJavaMojo();
+ }
+
+ @AfterEach
+ public void afterEach() throws Exception {
+ dropDatabase();
+ }
+
+ @Test
+ public void testGenerateAnnotatedJava() throws Exception {
+ File personJavaFile = new File(outputDirectory, "Person.java");
+ // Person.java should not exist
+ assertFalse(personJavaFile.exists());
+ // Set value of field 'ejb3' to 'true' and execute mojo
+ Field ejb3Field = GenerateJavaMojo.class.getDeclaredField("ejb3");
+ ejb3Field.setAccessible(true);
+ ejb3Field.set(generateJavaMojo, true);
+ // Execute mojo
+ generateJavaMojo.executeExporter(createMetadataDescriptor());
+ // Person.java should exist
+ assertTrue(personJavaFile.exists());
+ // Person.java should be an annotated entity
+ byte[] raw = Files.readAllBytes(personJavaFile.toPath());
+ assertTrue(new String(raw).contains("import jakarta.persistence.Entity;"));
+ }
+
+ @Test
+ public void testGenerateNonAnnotatedJava() throws Exception {
+ File personJavaFile = new File(outputDirectory, "Person.java");
+ // Person.java should not exist
+ assertFalse(personJavaFile.exists());
+ // Set value of field 'ejb3' to 'false' and execute mojo
+ Field ejb3Field = GenerateJavaMojo.class.getDeclaredField("ejb3");
+ ejb3Field.setAccessible(true);
+ ejb3Field.set(generateJavaMojo, false);
+ // Execute mojo
+ generateJavaMojo.executeExporter(createMetadataDescriptor());
+ // Person.java should exist
+ assertTrue(personJavaFile.exists());
+ // Person.java should be an annotated entity
+ byte[] raw = Files.readAllBytes(personJavaFile.toPath());
+ assertFalse(new String(raw).contains("import jakarta.persistence.Entity;"));
+ }
+
+ @Test
+ public void testGenerateJavaWithGenerics() throws Exception {
+ File personJavaFile = new File(outputDirectory, "Person.java");
+ // Person.java should not exist
+ assertFalse(personJavaFile.exists());
+ // Set value of field 'jdk5' to 'true' and execute mojo
+ Field jdk5Field = GenerateJavaMojo.class.getDeclaredField("jdk5");
+ jdk5Field.setAccessible(true);
+ jdk5Field.set(generateJavaMojo, true);
+ // Execute mojo
+ generateJavaMojo.executeExporter(createMetadataDescriptor());
+ // Person.java should exist
+ assertTrue(personJavaFile.exists());
+ // Person.java should be an annotated entity
+ byte[] raw = Files.readAllBytes(personJavaFile.toPath());
+ assertTrue(new String(raw).contains("Set"));
+ }
+
+ @Test
+ public void testGenerateJavaWithoutGenerics() throws Exception {
+ File personJavaFile = new File(outputDirectory, "Person.java");
+ // Person.java should not exist
+ assertFalse(personJavaFile.exists());
+ // Set value of field 'jdk5' to 'true' and execute mojo
+ Field jdk5Field = GenerateJavaMojo.class.getDeclaredField("jdk5");
+ jdk5Field.setAccessible(true);
+ jdk5Field.set(generateJavaMojo, false);
+ // Execute mojo
+ generateJavaMojo.executeExporter(createMetadataDescriptor());
+ // Person.java should exist
+ assertTrue(personJavaFile.exists());
+ // Person.java should be an annotated entity
+ byte[] raw = Files.readAllBytes(personJavaFile.toPath());
+ assertFalse(new String(raw).contains("Set"));
+ }
+
+ private void createDatabase() throws Exception {
+ Connection connection = DriverManager.getConnection(constructJdbcConnectionString());
+ Statement statement = connection.createStatement();
+ statement.execute(CREATE_PERSON_TABLE);
+ statement.execute(CREATE_ITEM_TABLE);
+ statement.close();
+ connection.close();
+ }
+
+ private void dropDatabase() throws Exception {
+ Connection connection = DriverManager.getConnection(constructJdbcConnectionString());
+ Statement statement = connection.createStatement();
+ statement.execute(DROP_ITEM_TABLE);
+ statement.execute(DROP_PERSON_TABLE);
+ statement.close();
+ connection.close();
+ }
+
+ private void createGenerateJavaMojo() throws Exception {
+ generateJavaMojo = new GenerateJavaMojo();
+ Field projectField = AbstractGenerationMojo.class.getDeclaredField("project");
+ projectField.setAccessible(true);
+ projectField.set(generateJavaMojo, new MavenProject());
+ Field propertyFileField = AbstractGenerationMojo.class.getDeclaredField("propertyFile");
+ propertyFileField.setAccessible(true);
+ propertyFileField.set(generateJavaMojo, new File(tempDir, "hibernate.properties"));
+ Field outputDirectoryField = GenerateJavaMojo.class.getDeclaredField("outputDirectory");
+ outputDirectoryField.setAccessible(true);
+ outputDirectoryField.set(generateJavaMojo, outputDirectory);
+ }
+
+ private void createOutputDirectory() {
+ outputDirectory = new File(tempDir, "generated");
+ if (!outputDirectory.mkdir()) throw new RuntimeException("Unable to create output directory: " + outputDirectory);
+ }
+
+ private MetadataDescriptor createMetadataDescriptor() {
+ return MetadataDescriptorFactory.createReverseEngineeringDescriptor(
+ null,
+ createProperties());
+ }
+
+ private Properties createProperties() {
+ Properties result = new Properties();
+ result.put("hibernate.connection.url", constructJdbcConnectionString());
+ result.put("hibernate.default_catalog", "TEST");
+ result.put("hibernate.default_schema", "PUBLIC");
+ return result;
+ }
+
+ private String constructJdbcConnectionString() {
+ return "jdbc:h2:" + tempDir.getAbsolutePath() + "/database/test;AUTO_SERVER=TRUE";
+ }
+
+}
diff --git a/tooling/hibernate-reveng/hibernate-reveng.gradle b/tooling/hibernate-reveng/hibernate-reveng.gradle
new file mode 100644
index 000000000000..7dfc076105e6
--- /dev/null
+++ b/tooling/hibernate-reveng/hibernate-reveng.gradle
@@ -0,0 +1,42 @@
+plugins {
+ id "local.publishing-java-module"
+}
+
+description = "Library providing functionality to perform reverse engineering Hibernate related artefacts from an existing database"
+
+sourceSets {
+ legacyTest {
+ compileClasspath += sourceSets.main.output
+ runtimeClasspath += sourceSets.main.output
+ }
+}
+
+configurations {
+ legacyTestImplementation.extendsFrom testImplementation
+ legacyTestRuntimeOnly.extendsFrom testRuntimeOnly
+}
+
+dependencies {
+ implementation project( ':hibernate-core' )
+// implementation project( ':hibernate-ant' )
+ implementation "org.apache.commons:commons-collections4:4.5.0"
+ implementation "com.google.googlejavaformat:google-java-format:1.27.0"
+ implementation "org.freemarker:freemarker:2.3.34"
+ implementation "org.antlr:antlr4-runtime:4.13.2"
+ implementation "jakarta.xml.bind:jakarta.xml.bind-api:4.0.2"
+}
+
+tasks.register('legacyTest', Test) {
+ description = 'Runs legacy tests.'
+ group = 'verification'
+ testClassesDirs = sourceSets.legacyTest.output.classesDirs
+ classpath = sourceSets.legacyTest.runtimeClasspath
+ useJUnitPlatform()
+}
+
+tasks.forbiddenApisLegacyTest {
+ enabled = false
+}
+
+test.dependsOn legacyTest
+
diff --git a/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/Performance/TestCase.java b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/Performance/TestCase.java
new file mode 100644
index 000000000000..0d3abc5092db
--- /dev/null
+++ b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/Performance/TestCase.java
@@ -0,0 +1,50 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.reveng.jdbc2cfg.Performance;
+
+import org.hibernate.boot.Metadata;
+import org.hibernate.mapping.Table;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptorFactory;
+import org.hibernate.tool.reveng.test.utils.JUnitUtil;
+import org.hibernate.tool.reveng.test.utils.JdbcUtil;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author max
+ * @author koen
+ */
+public class TestCase {
+
+ private static final int TABLECOUNT = 200;
+ private static final int COLCOUNT = 10;
+
+ @BeforeEach
+ public void setUp() {
+ JdbcUtil.createDatabase(this);
+ }
+
+ @AfterEach
+ public void tearDown() {
+ JdbcUtil.dropDatabase(this);
+ }
+
+ @Test
+ public void testBasic() {
+ Metadata metadata = MetadataDescriptorFactory
+ .createReverseEngineeringDescriptor(null, null)
+ .createMetadata();
+ JUnitUtil.assertIteratorContainsExactly(
+ "There should be " + TABLECOUNT + " tables!",
+ metadata.collectTableMappings().iterator(),
+ TABLECOUNT);
+ Table tab = metadata.collectTableMappings().iterator().next();
+ assertEquals(COLCOUNT+1, tab.getColumnSpan());
+ }
+
+}
diff --git a/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/PersistentClasses/Item.java b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/PersistentClasses/Item.java
new file mode 100644
index 000000000000..ebd595c73269
--- /dev/null
+++ b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/PersistentClasses/Item.java
@@ -0,0 +1,74 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.reveng.jdbc2cfg.PersistentClasses;
+public class Item {
+
+ Integer childId;
+
+ Orders order;
+ Orders relatedorderId;
+ String name;
+
+ /**
+ * @return Returns the id.
+ */
+ public Integer getChildId() {
+ return childId;
+ }
+ /**
+ * @param id The id to set.
+ */
+ public void setChildId(Integer id) {
+ this.childId = id;
+ }
+ /**
+ * @return Returns the name.
+ */
+ public String getName() {
+ return name;
+ }
+ /**
+ * @param name The name to set.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+ /**
+ * @return Returns the order.
+ */
+ public Orders getOrderId() {
+ return order;
+ }
+ /**
+ * @param order The order to set.
+ */
+ public void setOrderId(Orders order) {
+ this.order = order;
+ }
+ /**
+ * @return Returns the order.
+ */
+ public Orders getOrdersByOrderId() {
+ return order;
+ }
+ /**
+ * @param order The order to set.
+ */
+ public void setOrdersByOrderId(Orders order) {
+ this.order = order;
+ }
+ /**
+ * @return Returns the relatedorderId.
+ */
+ public Orders getOrdersByRelatedOrderId() {
+ return relatedorderId;
+ }
+ /**
+ * @param relatedorderId The relatedorderId to set.
+ */
+ public void setOrdersByRelatedOrderId(Orders relatedorderId) {
+ this.relatedorderId = relatedorderId;
+ }
+}
diff --git a/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/PersistentClasses/Orders.java b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/PersistentClasses/Orders.java
new file mode 100644
index 000000000000..7906f3335af0
--- /dev/null
+++ b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/PersistentClasses/Orders.java
@@ -0,0 +1,79 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.reveng.jdbc2cfg.PersistentClasses;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author max
+ *
+ */
+public class Orders {
+
+ Integer id;
+
+ String name;
+
+ Set items = new HashSet();
+ Set items_1 = new HashSet();
+
+
+ /**
+ * @return Returns the id.
+ */
+ public Integer getId() {
+ return id;
+ }
+
+ /**
+ * @param id
+ * The id to set.
+ */
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ /**
+ * @return Returns the name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name
+ * The name to set.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return Returns the setOfItem.
+ */
+ public Set getItemsForOrderId() {
+ return items;
+ }
+
+ /**
+ * @param items
+ * The setOfItem to set.
+ */
+ public void setItemsForOrderId(Set items) {
+ this.items = items;
+ }
+ /**
+ * @return Returns the setOfItem_1.
+ */
+ public Set getItemsForRelatedOrderId() {
+ return items_1;
+ }
+ /**
+ * @param items_1 The setOfItem_1 to set.
+ */
+ public void setItemsForRelatedOrderId(Set items_1) {
+ this.items_1 = items_1;
+ }
+}
diff --git a/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/PersistentClasses/TestCase.java b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/PersistentClasses/TestCase.java
new file mode 100644
index 000000000000..5f0c22d40528
--- /dev/null
+++ b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/PersistentClasses/TestCase.java
@@ -0,0 +1,169 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.reveng.jdbc2cfg.PersistentClasses;
+
+import org.hibernate.Hibernate;
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+import org.hibernate.boot.Metadata;
+import org.hibernate.cfg.AvailableSettings;
+import org.hibernate.cfg.Environment;
+import org.hibernate.mapping.Collection;
+import org.hibernate.mapping.KeyValue;
+import org.hibernate.mapping.OneToMany;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.Property;
+import org.hibernate.mapping.Set;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptorFactory;
+import org.hibernate.tool.reveng.api.core.RevengSettings;
+import org.hibernate.tool.reveng.internal.core.strategy.AbstractStrategy;
+import org.hibernate.tool.reveng.internal.core.strategy.DefaultStrategy;
+import org.hibernate.tool.reveng.test.utils.JdbcUtil;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * @author max
+ * @author koen
+ */
+public class TestCase {
+
+ private static final String PACKAGE_NAME = "org.hibernate.tool.reveng.jdbc2cfg.PersistentClasses";
+
+ private Metadata metadata = null;
+
+ @BeforeEach
+ public void setUp() {
+ JdbcUtil.createDatabase(this);
+ AbstractStrategy c = new DefaultStrategy();
+ c.setSettings(new RevengSettings(c).setDefaultPackageName(PACKAGE_NAME));
+ metadata = MetadataDescriptorFactory
+ .createReverseEngineeringDescriptor(c, null)
+ .createMetadata();
+ }
+
+ @AfterEach
+ public void tearDown() {
+ JdbcUtil.dropDatabase(this);
+ }
+
+ @Test
+ public void testCreatePersistentClasses() {
+ PersistentClass classMapping = metadata.getEntityBinding(PACKAGE_NAME + ".Orders");
+ assertNotNull(classMapping, "class not found");
+ KeyValue identifier = classMapping.getIdentifier();
+ assertNotNull(identifier);
+ }
+
+ @Test
+ public void testCreateManyToOne() {
+ PersistentClass classMapping = metadata.getEntityBinding(PACKAGE_NAME + ".Item");
+ assertNotNull(classMapping);
+ KeyValue identifier = classMapping.getIdentifier();
+ assertNotNull(identifier);
+ assertEquals(3,classMapping.getPropertyClosureSpan() );
+ Property property = classMapping.getProperty("ordersByRelatedOrderId");
+ assertNotNull(property);
+ property = classMapping.getProperty("ordersByOrderId");
+ assertNotNull(property);
+ }
+
+ @Test
+ public void testCreateOneToMany() {
+ PersistentClass orders = metadata.getEntityBinding(PACKAGE_NAME + ".Orders");
+ Property itemset = orders.getProperty("itemsForRelatedOrderId");
+ Collection col = (Collection) itemset.getValue();
+ OneToMany otm = (OneToMany) col.getElement();
+ assertEquals(PACKAGE_NAME + ".Item", otm.getReferencedEntityName());
+ assertEquals(PACKAGE_NAME + ".Item", otm.getAssociatedClass().getClassName());
+ assertEquals("ORDERS", otm.getTable().getName());
+ assertNotNull(itemset);
+ assertInstanceOf(Set.class, itemset.getValue());
+ }
+
+ @Test
+ public void testBinding() throws HibernateException {
+
+ String schemaToUse = Environment
+ .getProperties()
+ .getProperty(AvailableSettings.DEFAULT_SCHEMA);
+ PersistentClass orders = metadata.getEntityBinding(PACKAGE_NAME + ".Orders");
+ orders.getTable().setSchema(schemaToUse);
+ PersistentClass items = metadata.getEntityBinding(PACKAGE_NAME + ".Item");
+ items.getTable().setSchema(schemaToUse);
+
+ SessionFactory sf = metadata.buildSessionFactory();
+ Session session = sf.openSession();
+ Transaction t = session.beginTransaction();
+
+ Orders order = new Orders();
+ order.setId(1);
+ order.setName("Mickey");
+
+ session.merge(order);
+
+ Item item = addItem(order, 42, "item 42");
+ session.merge(item);
+ session.merge(addItem(order, 43, "x") );
+ session.merge(addItem(order, 44, "y") );
+ session.merge(addItem(order, 45, "z") );
+ session.merge(addItem(order, 46, "w") );
+
+ t.commit();
+ session.close();
+
+ session = sf.openSession();
+ t = session.beginTransaction();
+
+ Item loadeditem = (Item) session.get(PACKAGE_NAME + ".Item", 42);
+
+ assertEquals(item.getName(),loadeditem.getName() );
+ assertEquals(item.getChildId(),loadeditem.getChildId() );
+ assertEquals(item.getOrderId().getId(),loadeditem.getOrderId().getId() );
+
+ assertTrue(loadeditem.getOrderId().getItemsForOrderId().contains(loadeditem) );
+ assertTrue(item.getOrderId().getItemsForOrderId().contains(item) );
+
+ assertEquals(5,item.getOrderId().getItemsForOrderId().size() );
+ assertEquals(5,loadeditem.getOrderId().getItemsForOrderId().size() );
+
+ t.commit();
+ session.close();
+
+ session = sf.openSession();
+ t = session.beginTransaction();
+
+ order = session.getReference(Orders.class, 1);
+ assertFalse(Hibernate.isInitialized(order) );
+ assertFalse(Hibernate.isInitialized(order.getItemsForOrderId() ) );
+
+ order = (Orders) session.createQuery("from " + PACKAGE_NAME + ".Orders", null).getSingleResult();
+
+ assertFalse(Hibernate.isInitialized(order.getItemsForOrderId() ) );
+ t.commit();
+ session.close();
+ sf.close();
+ }
+
+ private Item addItem(Orders m, int itemid, String name) {
+ Item item = new Item();
+ item.setChildId(itemid);
+ item.setOrderId(m);
+ item.setName(name);
+ item.setOrdersByRelatedOrderId(m);
+ m.getItemsForOrderId().add(item);
+ return item;
+ }
+
+}
diff --git a/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/RevEngForeignKey/TestCase.java b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/RevEngForeignKey/TestCase.java
new file mode 100644
index 000000000000..02779b537703
--- /dev/null
+++ b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/RevEngForeignKey/TestCase.java
@@ -0,0 +1,180 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.reveng.jdbc2cfg.RevEngForeignKey;
+
+import org.hibernate.MappingException;
+import org.hibernate.boot.Metadata;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.Property;
+import org.hibernate.mapping.SimpleValue;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptorFactory;
+import org.hibernate.tool.reveng.api.core.RevengStrategy;
+import org.hibernate.tool.reveng.internal.core.strategy.DefaultStrategy;
+import org.hibernate.tool.reveng.internal.core.strategy.OverrideRepository;
+import org.hibernate.tool.reveng.test.utils.JdbcUtil;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+/**
+ * @author max
+ * @author koen
+ */
+public class TestCase {
+
+ private static final String FOREIGN_KEY_TEST_XML = "org/hibernate/tool/reveng/jdbc2cfg/RevEngForeignKey/foreignkeytest.reveng.xml";
+ private static final String BAD_FOREIGNKEY_XML = "org/hibernate/tool/reveng/jdbc2cfg/RevEngForeignKey/badforeignkeytest.reveng.xml";
+
+ @BeforeEach
+ public void setUp() {
+ JdbcUtil.createDatabase(this);
+ }
+
+ @AfterEach
+ public void tearDown() {
+ JdbcUtil.dropDatabase(this);
+ }
+
+ @Test
+ public void testDefaultBiDirectional() {
+ Metadata metadata = MetadataDescriptorFactory
+ .createReverseEngineeringDescriptor(null, null)
+ .createMetadata();
+ PersistentClass project = metadata.getEntityBinding("Project");
+ assertNotNull(project.getProperty("worksOns"));
+ assertNotNull(project.getProperty("employee"));
+ assertEquals(3, project.getPropertyClosureSpan());
+ assertEquals("projectId", project.getIdentifierProperty().getName());
+ PersistentClass employee = metadata.getEntityBinding("Employee");
+ assertNotNull(employee.getProperty("worksOns"));
+ assertNotNull(employee.getProperty("employees"));
+ assertNotNull(employee.getProperty("employee"));
+ assertNotNull(employee.getProperty("projects"));
+ assertEquals(5, employee.getPropertyClosureSpan());
+ assertEquals("id", employee.getIdentifierProperty().getName());
+ PersistentClass worksOn = metadata.getEntityBinding("WorksOn");
+ assertNotNull(worksOn.getProperty("project"));
+ assertNotNull(worksOn.getProperty("employee"));
+ assertEquals(4, worksOn.getPropertyClosureSpan());
+ assertEquals("id", worksOn.getIdentifierProperty().getName());
+ }
+
+ @Test
+ public void testSetAndManyToOne() {
+ OverrideRepository or = new OverrideRepository();
+ or.addResource(FOREIGN_KEY_TEST_XML);
+ RevengStrategy repository = or.getReverseEngineeringStrategy(new DefaultStrategy());
+ Metadata metadata = MetadataDescriptorFactory
+ .createReverseEngineeringDescriptor(repository, null)
+ .createMetadata();
+ PersistentClass project = metadata.getEntityBinding("Project");
+ assertNotNull(project.getProperty("worksOns"));
+ assertPropertyNotExists(project, "employee", "should be removed by reveng.xml");
+ Property property = project.getProperty("teamLead");
+ assertNotNull(property);
+ assertInstanceOf(SimpleValue.class, property.getValue());
+ assertEquals(3, project.getPropertyClosureSpan());
+ assertEquals("projectId", project.getIdentifierProperty().getName());
+ PersistentClass employee = metadata.getEntityBinding("Employee");
+ assertNotNull(employee.getProperty("worksOns"));
+ assertNotNull(employee.getProperty("manager"), "property should be renamed by reveng.xml");
+ assertPropertyNotExists( employee, "employees", "set should be excluded by reveng.xml" );
+ Property setProperty = employee.getProperty("managedProjects");
+ assertNotNull(setProperty, "should be renamed by reveng.xml");
+ assertEquals("delete, update", setProperty.getCascade());
+ assertEquals(4, employee.getPropertyClosureSpan());
+ assertEquals("id", employee.getIdentifierProperty().getName());
+ PersistentClass worksOn = metadata.getEntityBinding("WorksOn");
+ assertNotNull(worksOn.getProperty("project"));
+ assertNotNull(worksOn.getProperty("employee"));
+ assertEquals(4, worksOn.getPropertyClosureSpan());
+ assertEquals("id", worksOn.getIdentifierProperty().getName());
+ }
+
+ @Test
+ public void testOneToOne() {
+ OverrideRepository or = new OverrideRepository();
+ or.addResource(FOREIGN_KEY_TEST_XML);
+ RevengStrategy repository = or.getReverseEngineeringStrategy(new DefaultStrategy());
+ Metadata metadata = MetadataDescriptorFactory
+ .createReverseEngineeringDescriptor(repository, null)
+ .createMetadata();
+ PersistentClass person = metadata.getEntityBinding("Person");
+ PersistentClass addressPerson = metadata.getEntityBinding("AddressPerson");
+ PersistentClass addressMultiPerson = metadata.getEntityBinding("AddressMultiPerson");
+ PersistentClass multiPerson = metadata.getEntityBinding("MultiPerson");
+ assertPropertyNotExists(addressPerson, "person", "should be removed by reveng.xml");
+ assertPropertyNotExists(person, "addressPerson", "should be removed by reveng.xml");
+ Property property = addressMultiPerson.getProperty("renamedOne");
+ assertNotNull(property);
+ assertEquals("delete", property.getCascade(), "Casade should be set to delete by reveng.xml");
+ assertPropertyNotExists(multiPerson, "addressMultiPerson", "should not be there");
+ Property o2o = multiPerson.getProperty("renamedInversedOne");
+ assertNotNull(o2o);
+ assertEquals("update", o2o.getCascade());
+ assertEquals("JOIN", o2o.getValue().getFetchMode().toString());
+ }
+
+ @Test
+ public void testDuplicateForeignKeyDefinition() {
+ try {
+ OverrideRepository or = new OverrideRepository();
+ or.addResource(BAD_FOREIGNKEY_XML);
+ RevengStrategy repository = or.getReverseEngineeringStrategy(new DefaultStrategy());
+ MetadataDescriptorFactory
+ .createReverseEngineeringDescriptor(repository, null)
+ .createMetadata();
+ fail("Should fail because foreign key is already defined in the database"); // maybe we should ignore the definition and only listen to what is overwritten ? For now we error.
+ } catch(MappingException me) {
+ assertTrue(me.getMessage().contains("already defined"));
+ }
+ }
+
+ @Test
+ public void testManyToOneAttributeDefaults() {
+ Metadata metadata = MetadataDescriptorFactory
+ .createReverseEngineeringDescriptor(null, null)
+ .createMetadata();
+ PersistentClass classMapping = metadata.getEntityBinding("Employee");
+ Property property = classMapping.getProperty("employee");
+ assertEquals("none", property.getCascade());
+ assertTrue(property.isUpdateable());
+ assertTrue(property.isInsertable());
+ assertEquals("SELECT", property.getValue().getFetchMode().toString());
+ }
+
+ @Test
+ public void testManyToOneAttributeOverrides() {
+ OverrideRepository or = new OverrideRepository();
+ or.addResource(FOREIGN_KEY_TEST_XML);
+ RevengStrategy repository = or.getReverseEngineeringStrategy(new DefaultStrategy());
+ Metadata metadata = MetadataDescriptorFactory
+ .createReverseEngineeringDescriptor(repository, null)
+ .createMetadata();
+ PersistentClass classMapping = metadata.getEntityBinding("Employee");
+ Property property = classMapping.getProperty("manager");
+ assertEquals("all", property.getCascade());
+ assertFalse(property.isUpdateable());
+ assertFalse(property.isInsertable());
+ assertEquals("JOIN", property.getValue().getFetchMode().toString());
+ }
+
+ private void assertPropertyNotExists(PersistentClass employee, String name, String msg) {
+ try {
+ employee.getProperty(name);
+ fail(msg);
+ } catch(MappingException me) {
+ // excpected
+ }
+ }
+
+}
diff --git a/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/SearchEscapeString/TestCase.java b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/SearchEscapeString/TestCase.java
new file mode 100644
index 000000000000..eb0b44d79fee
--- /dev/null
+++ b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/SearchEscapeString/TestCase.java
@@ -0,0 +1,60 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.reveng.jdbc2cfg.SearchEscapeString;
+
+import org.hibernate.boot.Metadata;
+import org.hibernate.mapping.Table;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptorFactory;
+import org.hibernate.tool.reveng.test.utils.HibernateUtil;
+import org.hibernate.tool.reveng.test.utils.JUnitUtil;
+import org.hibernate.tool.reveng.test.utils.JdbcUtil;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+/**
+ * @author max
+ * @author koen
+ */
+public class TestCase {
+
+ private Metadata metadata = null;
+
+ @BeforeEach
+ public void setUp() {
+ JdbcUtil.createDatabase(this);
+ metadata = MetadataDescriptorFactory
+ .createReverseEngineeringDescriptor(null, null)
+ .createMetadata();
+ }
+
+ @AfterEach
+ public void tearDown() {
+ JdbcUtil.dropDatabase(this);
+ }
+
+ @Test
+ public void testBasic() {
+
+ JUnitUtil.assertIteratorContainsExactly(
+ "There should be 2 tables!",
+ metadata.collectTableMappings().iterator(),
+ 2);
+
+ Table table = HibernateUtil.getTable(metadata, JdbcUtil.toIdentifier(this, "B_TAB" ) );
+ Table table2 = HibernateUtil.getTable(metadata, JdbcUtil.toIdentifier(this, "B2TAB" ) );
+
+ assertNotNull(table);
+ assertNotNull(table2);
+
+ assertEquals(2, table.getColumnSpan());
+ assertEquals(2, table2.getColumnSpan());
+
+ }
+
+}
diff --git a/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/TernarySchema/TestCase.java b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/TernarySchema/TestCase.java
new file mode 100644
index 000000000000..0f240698329f
--- /dev/null
+++ b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/TernarySchema/TestCase.java
@@ -0,0 +1,139 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.reveng.jdbc2cfg.TernarySchema;
+
+import org.hibernate.boot.Metadata;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.Property;
+import org.hibernate.mapping.Set;
+import org.hibernate.tool.reveng.api.export.ExporterConstants;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptorFactory;
+import org.hibernate.tool.reveng.api.core.RevengStrategy.SchemaSelection;
+import org.hibernate.tool.reveng.internal.export.common.DefaultValueVisitor;
+import org.hibernate.tool.reveng.internal.export.hbm.HbmExporter;
+import org.hibernate.tool.reveng.internal.core.strategy.AbstractStrategy;
+import org.hibernate.tool.reveng.test.utils.JUnitUtil;
+import org.hibernate.tool.reveng.test.utils.JdbcUtil;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+/**
+ * @author max
+ * @author koen
+ */
+public class TestCase {
+
+ @TempDir
+ public File outputFolder = new File("output");
+
+ private MetadataDescriptor metadataDescriptor = null;
+
+ @BeforeEach
+ public void setUp() {
+ JdbcUtil.createDatabase(this);
+ AbstractStrategy c = new AbstractStrategy() {
+ public List getSchemaSelections() {
+ List selections = new ArrayList<>();
+ selections.add(createSchemaSelection("HTT"));
+ selections.add(createSchemaSelection("OTHERSCHEMA"));
+ selections.add(createSchemaSelection("THIRDSCHEMA"));
+ return selections;
+ }
+ };
+ metadataDescriptor = MetadataDescriptorFactory
+ .createReverseEngineeringDescriptor(c, null);
+ }
+
+ @AfterEach
+ public void tearDown() {
+ JdbcUtil.dropDatabase(this);
+ }
+
+ @Test
+ public void testTernaryModel() {
+ assertMultiSchema(metadataDescriptor.createMetadata());
+ }
+
+ @Test
+ public void testGeneration() {
+ HbmExporter hme = new HbmExporter();
+ hme.getProperties().put(ExporterConstants.METADATA_DESCRIPTOR, metadataDescriptor);
+ hme.getProperties().put(ExporterConstants.DESTINATION_FOLDER, outputFolder);
+ hme.start();
+ JUnitUtil.assertIsNonEmptyFile( new File(outputFolder, "Role.hbm.xml") );
+ JUnitUtil.assertIsNonEmptyFile( new File(outputFolder, "Member.hbm.xml") );
+ JUnitUtil.assertIsNonEmptyFile( new File(outputFolder, "Plainrole.hbm.xml") );
+ assertEquals(3, Objects.requireNonNull( outputFolder.listFiles() ).length);
+ File[] files = new File[3];
+ files[0] = new File(outputFolder, "Role.hbm.xml");
+ files[1] = new File(outputFolder, "Member.hbm.xml");
+ files[2] = new File(outputFolder, "Plainrole.hbm.xml");
+ assertMultiSchema(MetadataDescriptorFactory
+ .createNativeDescriptor(null, files, null)
+ .createMetadata());
+ }
+
+ private void assertMultiSchema(Metadata metadata) {
+ JUnitUtil.assertIteratorContainsExactly(
+ "There should be three entities!",
+ metadata.getEntityBindings().iterator(),
+ 3);
+ final PersistentClass role = metadata.getEntityBinding("Role");
+ assertNotNull(role);
+ PersistentClass member = metadata.getEntityBinding("Member");
+ assertNotNull(member);
+ PersistentClass plainRole = metadata.getEntityBinding("Plainrole");
+ assertNotNull(plainRole);
+ Property property = role.getProperty("members");
+ assertEquals( "OTHERSCHEMA", role.getTable().getSchema() );
+ assertNotNull(property);
+ property.getValue().accept(new DefaultValueVisitor(true) {
+ public Object accept(Set o) {
+ assertEquals( "THIRDSCHEMA", o.getCollectionTable().getSchema() );
+ return null;
+ }
+ });
+ property = plainRole.getProperty("members");
+ assertEquals( "OTHERSCHEMA", role.getTable().getSchema() );
+ assertNotNull(property);
+ property.getValue().accept(new DefaultValueVisitor(true) {
+ public Object accept(Set o) {
+ // TODO Investigate the ignored test: HBX-1410
+ // For some reason the explicit schema 'HTT' is not reproduced in the many-to-many set in the hbm.xml files
+ // Need to investigate the HBM generation and to try rebuild the metadata with the schema explicitly set
+ // assertEquals("HTT", o.getCollectionTable().getSchema() );
+ return null;
+ }
+ });
+ }
+
+ private SchemaSelection createSchemaSelection(String matchSchema) {
+ return new SchemaSelection() {
+ @Override
+ public String getMatchCatalog() {
+ return null;
+ }
+ @Override
+ public String getMatchSchema() {
+ return matchSchema;
+ }
+ @Override
+ public String getMatchTable() {
+ return null;
+ }
+ };
+ }
+}
diff --git a/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/Versioning/TestCase.java b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/Versioning/TestCase.java
new file mode 100644
index 000000000000..633bdca26b2b
--- /dev/null
+++ b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/jdbc2cfg/Versioning/TestCase.java
@@ -0,0 +1,100 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.reveng.jdbc2cfg.Versioning;
+
+import org.hibernate.boot.Metadata;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.Property;
+import org.hibernate.tool.reveng.api.export.Exporter;
+import org.hibernate.tool.reveng.api.export.ExporterConstants;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptorFactory;
+import org.hibernate.tool.reveng.internal.export.hbm.HbmExporter;
+import org.hibernate.tool.reveng.test.utils.JdbcUtil;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.File;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+/**
+ * To be extended by VersioningForJDK50Test for the JPA generation part
+ * @author max
+ * @author koen
+ */
+public class TestCase {
+
+ private Metadata metadata = null;
+ private MetadataDescriptor metadataDescriptor = null;
+
+ @TempDir
+ public File outputFolder = new File("output");
+
+ @BeforeEach
+ public void setUp() {
+ JdbcUtil.createDatabase(this);
+ metadataDescriptor = MetadataDescriptorFactory
+ .createReverseEngineeringDescriptor(null, null);
+ metadata = metadataDescriptor
+ .createMetadata();
+ }
+
+ @AfterEach
+ public void tearDown() {
+ JdbcUtil.dropDatabase(this);
+ }
+
+ @Test
+ public void testVersion() {
+ PersistentClass cl = metadata.getEntityBinding("WithVersion");
+ Property version = cl.getVersion();
+ assertNotNull(version);
+ assertEquals("version", version.getName());
+ cl = metadata.getEntityBinding("NoVersion");
+ assertNotNull(cl);
+ version = cl.getVersion();
+ assertNull(version);
+ }
+
+ @Test
+ public void testGenerateMappings() {
+ Exporter exporter = new HbmExporter();
+ exporter.getProperties().put(ExporterConstants.METADATA_DESCRIPTOR, metadataDescriptor);
+ exporter.getProperties().put(ExporterConstants.DESTINATION_FOLDER, outputFolder);
+ exporter.start();
+ File[] files = new File[4];
+ files[0] = new File(outputFolder, "WithVersion.hbm.xml");
+ files[1] = new File(outputFolder, "NoVersion.hbm.xml");
+ files[2] = new File(outputFolder, "WithRealTimestamp.hbm.xml");
+ files[3] = new File(outputFolder, "WithFakeTimestamp.hbm.xml");
+ Metadata metadata = MetadataDescriptorFactory
+ .createNativeDescriptor(null, files, null)
+ .createMetadata();
+ PersistentClass cl = metadata.getEntityBinding( "WithVersion" );
+ Property version = cl.getVersion();
+ assertNotNull(version);
+ assertEquals("version", version.getName());
+ cl = metadata.getEntityBinding( "NoVersion" );
+ assertNotNull(cl);
+ version = cl.getVersion();
+ assertNull(version);
+ cl = metadata.getEntityBinding( "WithRealTimestamp" );
+ assertNotNull(cl);
+ version = cl.getVersion();
+ assertNotNull(version);
+ assertEquals("timestamp", version.getType().getName());
+ cl = metadata.getEntityBinding( "WithFakeTimestamp" );
+ assertNotNull(cl);
+ version = cl.getVersion();
+ assertNotNull(version);
+ assertEquals("integer", version.getType().getName());
+ }
+
+}
diff --git a/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/test/utils/ConnectionProvider.java b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/test/utils/ConnectionProvider.java
new file mode 100644
index 000000000000..37a6c0502c35
--- /dev/null
+++ b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/test/utils/ConnectionProvider.java
@@ -0,0 +1,275 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.reveng.test.utils;
+
+import org.hibernate.engine.jdbc.connections.internal.UserSuppliedConnectionProviderImpl;
+
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.CallableStatement;
+import java.sql.Clob;
+import java.sql.NClob;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.RowIdLifetime;
+import java.sql.SQLClientInfoException;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import java.sql.Struct;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Executor;
+
+public class ConnectionProvider extends UserSuppliedConnectionProviderImpl {
+
+ private static final long serialVersionUID = 1L;
+
+ private static Connection CONNECTION = new Connection();
+ private static DatabaseMetaData DATABASE_META_DATA = new DatabaseMetaData();
+
+ @Override public java.sql.Connection getConnection() throws SQLException { return CONNECTION; }
+
+ @Override public void closeConnection(java.sql.Connection conn) throws SQLException {}
+
+ private static class Connection implements java.sql.Connection {
+ @Override public T unwrap(Class iface) throws SQLException { return null; }
+ @Override public boolean isWrapperFor(Class> iface) throws SQLException { return false; }
+ @Override public Statement createStatement() throws SQLException { return null; }
+ @Override public PreparedStatement prepareStatement(String sql) throws SQLException { return null; }
+ @Override public CallableStatement prepareCall(String sql) throws SQLException { return null; }
+ @Override public String nativeSQL(String sql) throws SQLException { return null; }
+ @Override public void setAutoCommit(boolean autoCommit) throws SQLException {}
+ @Override public boolean getAutoCommit() throws SQLException { return false; }
+ @Override public void commit() throws SQLException {}
+ @Override public void rollback() throws SQLException {}
+ @Override public void close() throws SQLException {}
+ @Override public boolean isClosed() throws SQLException { return false; }
+ @Override public DatabaseMetaData getMetaData() throws SQLException { return DATABASE_META_DATA; }
+ @Override public void setReadOnly(boolean readOnly) throws SQLException {}
+ @Override public boolean isReadOnly() throws SQLException { return false; }
+ @Override public void setCatalog(String catalog) throws SQLException {}
+ @Override public String getCatalog() throws SQLException { return null; }
+ @Override public void setTransactionIsolation(int level) throws SQLException {}
+ @Override public int getTransactionIsolation() throws SQLException { return 0; }
+ @Override public SQLWarning getWarnings() throws SQLException { return null; }
+ @Override public void clearWarnings() throws SQLException {}
+ @Override public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { return null; }
+ @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return null; }
+ @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return null; }
+ @Override public Map> getTypeMap() throws SQLException { return null; }
+ @Override public void setTypeMap(Map> map) throws SQLException {}
+ @Override public void setHoldability(int holdability) throws SQLException {}
+ @Override public int getHoldability() throws SQLException { return 0; }
+ @Override public Savepoint setSavepoint() throws SQLException { return null; }
+ @Override public Savepoint setSavepoint(String name) throws SQLException { return null; }
+ @Override public void rollback(Savepoint savepoint) throws SQLException {}
+ @Override public void releaseSavepoint(Savepoint savepoint) throws SQLException {}
+ @Override public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null; }
+ @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null; }
+ @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null; }
+ @Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { return null; }
+ @Override public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { return null; }
+ @Override public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { return null; }
+ @Override public Clob createClob() throws SQLException { return null; }
+ @Override public Blob createBlob() throws SQLException { return null; }
+ @Override public NClob createNClob() throws SQLException { return null; }
+ @Override public SQLXML createSQLXML() throws SQLException { return null; }
+ @Override public boolean isValid(int timeout) throws SQLException { return false;}
+ @Override public void setClientInfo(String name, String value) throws SQLClientInfoException {}
+ @Override public void setClientInfo(Properties properties) throws SQLClientInfoException {}
+ @Override public String getClientInfo(String name) throws SQLException { return null; }
+ @Override public Properties getClientInfo() throws SQLException { return null; }
+ @Override public Array createArrayOf(String typeName, Object[] elements) throws SQLException { return null; }
+ @Override public Struct createStruct(String typeName, Object[] attributes) throws SQLException { return null; }
+ @Override public void setSchema(String schema) throws SQLException {}
+ @Override public String getSchema() throws SQLException { return null; }
+ @Override public void abort(Executor executor) throws SQLException {}
+ @Override public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {}
+ @Override public int getNetworkTimeout() throws SQLException { return 0; }
+ }
+
+ private static class DatabaseMetaData implements java.sql.DatabaseMetaData {
+ @Override public T unwrap(Class iface) throws SQLException { return null; }
+ @Override public boolean isWrapperFor(Class> iface) throws SQLException { return false; }
+ @Override public boolean allProceduresAreCallable() throws SQLException { return false; }
+ @Override public boolean allTablesAreSelectable() throws SQLException { return false; }
+ @Override public String getURL() throws SQLException { return null; }
+ @Override public String getUserName() throws SQLException { return null; }
+ @Override public boolean isReadOnly() throws SQLException { return false; }
+ @Override public boolean nullsAreSortedHigh() throws SQLException { return false; }
+ @Override public boolean nullsAreSortedLow() throws SQLException { return false; }
+ @Override public boolean nullsAreSortedAtStart() throws SQLException { return false; }
+ @Override public boolean nullsAreSortedAtEnd() throws SQLException { return false; }
+ @Override public String getDatabaseProductName() throws SQLException { return null; }
+ @Override public String getDatabaseProductVersion() throws SQLException { return ""; }
+ @Override public String getDriverName() throws SQLException { return null; }
+ @Override public String getDriverVersion() throws SQLException { return null; }
+ @Override public int getDriverMajorVersion() { return 0; }
+ @Override public int getDriverMinorVersion() { return 0; }
+ @Override public boolean usesLocalFiles() throws SQLException { return false; }
+ @Override public boolean usesLocalFilePerTable() throws SQLException { return false; }
+ @Override public boolean supportsMixedCaseIdentifiers() throws SQLException { return false; }
+ @Override public boolean storesUpperCaseIdentifiers() throws SQLException { return false; }
+ @Override public boolean storesLowerCaseIdentifiers() throws SQLException { return false; }
+ @Override public boolean storesMixedCaseIdentifiers() throws SQLException { return false; }
+ @Override public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { return false; }
+ @Override public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { return false; }
+ @Override public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { return false; }
+ @Override public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { return false; }
+ @Override public String getIdentifierQuoteString() throws SQLException { return null; }
+ @Override public String getSQLKeywords() throws SQLException { return null; }
+ @Override public String getNumericFunctions() throws SQLException { return null; }
+ @Override public String getStringFunctions() throws SQLException { return null; }
+ @Override public String getSystemFunctions() throws SQLException { return null; }
+ @Override public String getTimeDateFunctions() throws SQLException { return null; }
+ @Override public String getSearchStringEscape() throws SQLException { return null; }
+ @Override public String getExtraNameCharacters() throws SQLException { return null; }
+ @Override public boolean supportsAlterTableWithAddColumn() throws SQLException { return false; }
+ @Override public boolean supportsAlterTableWithDropColumn() throws SQLException { return false; }
+ @Override public boolean supportsColumnAliasing() throws SQLException { return false; }
+ @Override public boolean nullPlusNonNullIsNull() throws SQLException { return false; }
+ @Override public boolean supportsConvert() throws SQLException { return false; }
+ @Override public boolean supportsConvert(int fromType, int toType) throws SQLException { return false; }
+ @Override public boolean supportsTableCorrelationNames() throws SQLException { return false; }
+ @Override public boolean supportsDifferentTableCorrelationNames() throws SQLException { return false; }
+ @Override public boolean supportsExpressionsInOrderBy() throws SQLException { return false; }
+ @Override public boolean supportsOrderByUnrelated() throws SQLException { return false; }
+ @Override public boolean supportsGroupBy() throws SQLException { return false; }
+ @Override public boolean supportsGroupByUnrelated() throws SQLException { return false; }
+ @Override public boolean supportsGroupByBeyondSelect() throws SQLException { return false; }
+ @Override public boolean supportsLikeEscapeClause() throws SQLException { return false; }
+ @Override public boolean supportsMultipleResultSets() throws SQLException { return false; }
+ @Override public boolean supportsMultipleTransactions() throws SQLException { return false; }
+ @Override public boolean supportsNonNullableColumns() throws SQLException { return false; }
+ @Override public boolean supportsMinimumSQLGrammar() throws SQLException { return false; }
+ @Override public boolean supportsCoreSQLGrammar() throws SQLException { return false; }
+ @Override public boolean supportsExtendedSQLGrammar() throws SQLException { return false; }
+ @Override public boolean supportsANSI92EntryLevelSQL() throws SQLException { return false; }
+ @Override public boolean supportsANSI92IntermediateSQL() throws SQLException { return false; }
+ @Override public boolean supportsANSI92FullSQL() throws SQLException { return false; }
+ @Override public boolean supportsIntegrityEnhancementFacility() throws SQLException { return false; }
+ @Override public boolean supportsOuterJoins() throws SQLException { return false; }
+ @Override public boolean supportsFullOuterJoins() throws SQLException { return false; }
+ @Override public boolean supportsLimitedOuterJoins() throws SQLException { return false; }
+ @Override public String getSchemaTerm() throws SQLException { return null; }
+ @Override public String getProcedureTerm() throws SQLException { return null; }
+ @Override public String getCatalogTerm() throws SQLException { return null; }
+ @Override public boolean isCatalogAtStart() throws SQLException { return false; }
+ @Override public String getCatalogSeparator() throws SQLException { return null; }
+ @Override public boolean supportsSchemasInDataManipulation() throws SQLException { return false; }
+ @Override public boolean supportsSchemasInProcedureCalls() throws SQLException { return false; }
+ @Override public boolean supportsSchemasInTableDefinitions() throws SQLException { return false; }
+ @Override public boolean supportsSchemasInIndexDefinitions() throws SQLException { return false; }
+ @Override public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { return false; }
+ @Override public boolean supportsCatalogsInDataManipulation() throws SQLException { return false; }
+ @Override public boolean supportsCatalogsInProcedureCalls() throws SQLException { return false; }
+ @Override public boolean supportsCatalogsInTableDefinitions() throws SQLException { return false; }
+ @Override public boolean supportsCatalogsInIndexDefinitions() throws SQLException { return false; }
+ @Override public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { return false; }
+ @Override public boolean supportsPositionedDelete() throws SQLException { return false; }
+ @Override public boolean supportsPositionedUpdate() throws SQLException { return false; }
+ @Override public boolean supportsSelectForUpdate() throws SQLException { return false; }
+ @Override public boolean supportsStoredProcedures() throws SQLException { return false; }
+ @Override public boolean supportsSubqueriesInComparisons() throws SQLException { return false; }
+ @Override public boolean supportsSubqueriesInExists() throws SQLException { return false; }
+ @Override public boolean supportsSubqueriesInIns() throws SQLException { return false; }
+ @Override public boolean supportsSubqueriesInQuantifieds() throws SQLException { return false; }
+ @Override public boolean supportsCorrelatedSubqueries() throws SQLException { return false; }
+ @Override public boolean supportsUnion() throws SQLException { return false; }
+ @Override public boolean supportsUnionAll() throws SQLException { return false; }
+ @Override public boolean supportsOpenCursorsAcrossCommit() throws SQLException { return false; }
+ @Override public boolean supportsOpenCursorsAcrossRollback() throws SQLException { return false; }
+ @Override public boolean supportsOpenStatementsAcrossCommit() throws SQLException { return false; }
+ @Override public boolean supportsOpenStatementsAcrossRollback() throws SQLException { return false; }
+ @Override public int getMaxBinaryLiteralLength() throws SQLException { return 0; }
+ @Override public int getMaxCharLiteralLength() throws SQLException { return 0; }
+ @Override public int getMaxColumnNameLength() throws SQLException { return 0; }
+ @Override public int getMaxColumnsInGroupBy() throws SQLException { return 0; }
+ @Override public int getMaxColumnsInIndex() throws SQLException { return 0; }
+ @Override public int getMaxColumnsInOrderBy() throws SQLException { return 0; }
+ @Override public int getMaxColumnsInSelect() throws SQLException { return 0; }
+ @Override public int getMaxColumnsInTable() throws SQLException { return 0; }
+ @Override public int getMaxConnections() throws SQLException { return 0; }
+ @Override public int getMaxCursorNameLength() throws SQLException { return 0; }
+ @Override public int getMaxIndexLength() throws SQLException { return 0; }
+ @Override public int getMaxSchemaNameLength() throws SQLException { return 0; }
+ @Override public int getMaxProcedureNameLength() throws SQLException { return 0; }
+ @Override public int getMaxCatalogNameLength() throws SQLException { return 0; }
+ @Override public int getMaxRowSize() throws SQLException { return 0; }
+ @Override public boolean doesMaxRowSizeIncludeBlobs() throws SQLException { return false; }
+ @Override public int getMaxStatementLength() throws SQLException { return 0; }
+ @Override public int getMaxStatements() throws SQLException { return 0; }
+ @Override public int getMaxTableNameLength() throws SQLException { return 0; }
+ @Override public int getMaxTablesInSelect() throws SQLException { return 0; }
+ @Override public int getMaxUserNameLength() throws SQLException { return 0; }
+ @Override public int getDefaultTransactionIsolation() throws SQLException { return 0; }
+ @Override public boolean supportsTransactions() throws SQLException { return false; }
+ @Override public boolean supportsTransactionIsolationLevel(int level) throws SQLException { return false; }
+ @Override public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { return false; }
+ @Override public boolean supportsDataManipulationTransactionsOnly() throws SQLException { return false; }
+ @Override public boolean dataDefinitionCausesTransactionCommit() throws SQLException { return false; }
+ @Override public boolean dataDefinitionIgnoredInTransactions() throws SQLException { return false; }
+ @Override public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException { return null; }
+ @Override public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException { return null; }
+ @Override public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException { return null; }
+ @Override public ResultSet getSchemas() throws SQLException { return null; }
+ @Override public ResultSet getCatalogs() throws SQLException { return null; }
+ @Override public ResultSet getTableTypes() throws SQLException { return null; }
+ @Override public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { return null; }
+ @Override public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException { return null; }
+ @Override public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { return null; }
+ @Override public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException { return null; }
+ @Override public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException { return null; }
+ @Override public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException { return null; }
+ @Override public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException { return null; }
+ @Override public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException { return null; }
+ @Override public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException { return null; }
+ @Override public ResultSet getTypeInfo() throws SQLException { return null; }
+ @Override public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException { return null; }
+ @Override public boolean supportsResultSetType(int type) throws SQLException { return false; }
+ @Override public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException { return false; }
+ @Override public boolean ownUpdatesAreVisible(int type) throws SQLException { return false; }
+ @Override public boolean ownDeletesAreVisible(int type) throws SQLException { return false; }
+ @Override public boolean ownInsertsAreVisible(int type) throws SQLException { return false; }
+ @Override public boolean othersUpdatesAreVisible(int type) throws SQLException { return false; }
+ @Override public boolean othersDeletesAreVisible(int type) throws SQLException { return false; }
+ @Override public boolean othersInsertsAreVisible(int type) throws SQLException { return false; }
+ @Override public boolean updatesAreDetected(int type) throws SQLException { return false; }
+ @Override public boolean deletesAreDetected(int type) throws SQLException { return false; }
+ @Override public boolean insertsAreDetected(int type) throws SQLException { return false; }
+ @Override public boolean supportsBatchUpdates() throws SQLException { return false; }
+ @Override public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException { return null; }
+ @Override public Connection getConnection() throws SQLException { return CONNECTION; }
+ @Override public boolean supportsSavepoints() throws SQLException { return false; }
+ @Override public boolean supportsNamedParameters() throws SQLException { return false; }
+ @Override public boolean supportsMultipleOpenResults() throws SQLException { return false; }
+ @Override public boolean supportsGetGeneratedKeys() throws SQLException { return false; }
+ @Override public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException { return null; }
+ @Override public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {return null;}
+ @Override public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) throws SQLException { return null; }
+ @Override public boolean supportsResultSetHoldability(int holdability) throws SQLException { return false; }
+ @Override public int getResultSetHoldability() throws SQLException { return 0; }
+ @Override public int getDatabaseMajorVersion() throws SQLException { return 0; }
+ @Override public int getDatabaseMinorVersion() throws SQLException { return 0; }
+ @Override public int getJDBCMajorVersion() throws SQLException { return 0; }
+ @Override public int getJDBCMinorVersion() throws SQLException { return 0; }
+ @Override public int getSQLStateType() throws SQLException { return 0; }
+ @Override public boolean locatorsUpdateCopy() throws SQLException { return false; }
+ @Override public boolean supportsStatementPooling() throws SQLException { return false; }
+ @Override public RowIdLifetime getRowIdLifetime() throws SQLException { return null; }
+ @Override public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { return null; }
+ @Override public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { return false; }
+ @Override public boolean autoCommitFailureClosesAllResultSets() throws SQLException { return false; }
+ @Override public ResultSet getClientInfoProperties() throws SQLException { return null; }
+ @Override public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException { return null; }
+ @Override public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException { return null; }
+ @Override public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { return null; }
+ @Override public boolean generatedKeyAlwaysReturned() throws SQLException { return false; }
+ }
+
+}
diff --git a/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/test/utils/HibernateUtil.java b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/test/utils/HibernateUtil.java
new file mode 100644
index 000000000000..663cf56813e4
--- /dev/null
+++ b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/test/utils/HibernateUtil.java
@@ -0,0 +1,81 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.reveng.test.utils;
+
+import org.hibernate.boot.Metadata;
+import org.hibernate.boot.MetadataSources;
+import org.hibernate.cfg.AvailableSettings;
+import org.hibernate.dialect.DatabaseVersion;
+import org.hibernate.mapping.ForeignKey;
+import org.hibernate.mapping.Table;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptor;
+import org.hibernate.tool.reveng.api.metadata.MetadataDescriptorFactory;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.util.Properties;
+
+public class HibernateUtil {
+
+ public static class Dialect extends org.hibernate.dialect.Dialect {
+ public Dialect() {
+ super((DatabaseVersion)null);
+ }
+ }
+
+ public static ForeignKey getForeignKey(Table table, String fkName) {
+ ForeignKey result = null;
+ for (ForeignKey fk : table.getForeignKeys().values()) {
+ if (fk.getName().equals(fkName)) {
+ result = fk;
+ break;
+ }
+ }
+ return result;
+ }
+
+ public static Table getTable(Metadata metadata, String tabName) {
+ if (metadata != null) {
+ for (Table table : metadata.collectTableMappings()) {
+ if (table.getName().equals(tabName)) {
+ return table;
+ }
+ }
+ }
+ return null;
+ }
+
+ public static MetadataDescriptor initializeMetadataDescriptor(
+ Object test,
+ String[] hbmResourceNames,
+ File hbmFileDir) {
+ ResourceUtil.createResources(test, hbmResourceNames, hbmFileDir);
+ File[] hbmFiles = new File[hbmResourceNames.length];
+ for (int i = 0; i < hbmResourceNames.length; i++) {
+ hbmFiles[i] = new File(hbmFileDir, hbmResourceNames[i]);
+ }
+ Properties properties = new Properties();
+ properties.put(AvailableSettings.DIALECT, Dialect.class.getName());
+ properties.setProperty(AvailableSettings.CONNECTION_PROVIDER, ConnectionProvider.class.getName());
+ return MetadataDescriptorFactory.createNativeDescriptor(null, hbmFiles, properties);
+ }
+
+ public static void addAnnotatedClass(
+ MetadataDescriptor metadataDescriptor,
+ Class> annotatedClass) {
+ try {
+ Field metadataSourcesField = metadataDescriptor
+ .getClass()
+ .getDeclaredField("metadataSources");
+ metadataSourcesField.setAccessible(true);
+ MetadataSources metadataSources =
+ (MetadataSources)metadataSourcesField.get(metadataDescriptor);
+ metadataSources.addAnnotatedClass(annotatedClass);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/test/utils/JUnitUtil.java b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/test/utils/JUnitUtil.java
new file mode 100644
index 000000000000..a9610e608b65
--- /dev/null
+++ b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/test/utils/JUnitUtil.java
@@ -0,0 +1,37 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.reveng.test.utils;
+
+import org.opentest4j.AssertionFailedError;
+
+import java.io.File;
+import java.util.Iterator;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class JUnitUtil {
+
+ public static void assertIteratorContainsExactly(
+ String reason,
+ Iterator> iterator,
+ int expectedAmountOfElements) {
+ int actualAmountOfElements = 0;
+ while (iterator.hasNext() &&
+ actualAmountOfElements <= expectedAmountOfElements) {
+ actualAmountOfElements++;
+ iterator.next();
+ }
+ if (expectedAmountOfElements != actualAmountOfElements) {
+ throw new AssertionFailedError(reason, expectedAmountOfElements, actualAmountOfElements);
+ }
+ }
+
+ public static void assertIsNonEmptyFile(File file) {
+ assertTrue(file.exists(), file + " does not exist");
+ assertTrue(file.isFile(), file + " not a file");
+ assertTrue(file.length()>0, file + " does not have any contents");
+ }
+
+}
diff --git a/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/test/utils/JdbcUtil.java b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/test/utils/JdbcUtil.java
new file mode 100644
index 000000000000..10e8b236ea9c
--- /dev/null
+++ b/tooling/hibernate-reveng/src/legacyTest/java/org/hibernate/tool/reveng/test/utils/JdbcUtil.java
@@ -0,0 +1,206 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.tool.reveng.test.utils;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Properties;
+
+public class JdbcUtil {
+
+ static HashMap