import com.pyx4j.log4j.MavenLogAppender;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.NoSuchAlgorithmException;
+import java.time.ZonedDateTime;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
*/
public abstract class AbstractSchemaMojo extends AbstractMojo
{
- public final static String EXPORT = "hibernate.schema.export";
+ public final static String EXECUTE = "hibernate.schema.execute";
public final static String OUTPUTDIRECTORY = "project.build.outputDirectory";
public final static String SCAN_CLASSES = "hibernate.schema.scan.classes";
public final static String SCAN_DEPENDENCIES = "hibernate.schema.scan.dependencies";
public final static String SCAN_TESTCLASSES = "hibernate.schema.scan.test_classes";
public final static String TEST_OUTPUTDIRECTORY = "project.build.testOutputDirectory";
public final static String SKIPPED = "hibernate.schema.skipped";
+ public final static String SCRIPT = "hibernate.schema.script";
private final static Pattern SPLIT = Pattern.compile("[^,\\s]+");
/** Parameters to configure the genaration of the SQL *********************/
/**
- * Export the database-schma to the database.
+ * Excecute the generated SQL.
* If set to <code>false</code>, only the SQL-script is created and the
* database is not touched.
* <p>
* it is not known by Hibernate nor JPA and, hence, not picked up from
* their configuration!
*
- * @parameter property="hibernate.schema.export" default-value="true"
+ * @parameter property="hibernate.schema.execute" default-value="true"
* @since 2.0
*/
- private Boolean export;
+ private Boolean execute;
/**
* Skip execution
private boolean skip;
/**
- * Force execution
+ * Force generation/execution
* <p>
- * Force execution, even if no modified or newly added annotated classes
- * where found and the dialect was not changed.
+ * Force the generation and (if configured) the execution of the SQL, even if
+ * no modified or newly added annotated classes where found and the
+ * configuration was not changed.
* <p>
* <code>skip</code> takes precedence over <code>force</code>.
* <p>
/** Check, that the outputfile is writable */
final File output = getOutputFile(filename);
+ /** Check, if the outputfile is missing or was changed */
+ checkOutputFile(output, tracker);
/** Configure Hibernate */
final StandardServiceRegistry serviceRegistry =
/** Skip execution, if mapping and configuration is unchanged */
if (!tracker.modified())
{
- getLog().info(
- "Mapping and configuration unchanged."
- );
+ getLog().info("Mapping and configuration unchanged.");
if (force)
- getLog().info("Schema generation is forced!");
+ getLog().info("Generation/execution is forced!");
else
{
getLog().info("Skipping schema generation!");
}
+ /** Truncate output file */
+ try
+ {
+ new FileOutputStream(output).getChannel().truncate(0).close();
+ }
+ catch (IOException e)
+ {
+ String error =
+ "Error while truncating " + output.getAbsolutePath() + ": "
+ + e.getMessage();
+ getLog().warn(error);
+ throw new MojoExecutionException(error);
+ }
+
/** Create a connection, if sufficient configuration infromation is available */
connectionProvider.open(classLoaderService, properties);
SchemaManagementToolCoordinator
.buildExecutionOptions(settings, handler);
final EnumSet<TargetType> targetTypes = EnumSet.of(TargetType.SCRIPT);
- if (export)
+ if (execute)
targetTypes.add(TargetType.DATABASE);
TargetDescriptor target = new TargetDescriptor()
{
{
thread.setContextClassLoader(classLoader);
build((MetadataImplementor)metadataBuilder.build(), options, target);
+ if (handler.getExceptions().size() > 0)
+ {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Hibernate failed:");
+ for (Exception e : handler.getExceptions())
+ {
+ builder.append("\n * ");
+ builder.append(e.getMessage());
+ AbstractSchemaMojo.printStrackTrace(builder, e);
+ builder.append("\n");
+ }
+ String error = builder.toString();
+ getLog().error(error);
+ throw new MojoFailureException(error);
+ }
}
finally
{
thread.setContextClassLoader(contextClassLoader);
- for (Exception e : handler.getExceptions())
- getLog().error(e.getMessage());
+ /** Track, the content of the generated script */
+ checkOutputFile(output, tracker);
}
}
catch (MojoExecutionException e)
throws MojoFailureException
{
/**
- * Special treatment for the configuration-value "export": if it is
+ * Special treatment for the configuration-value "execute": if it is
* switched to "true", the genearation fo the schema should be forced!
*/
- if (tracker.check(EXPORT, export.toString()) && export)
+ if (tracker.check(EXECUTE, execute.toString()) && execute)
+ {
+ getLog().info(
+ "hibernate.schema.execute was switched on: " +
+ "forcing generation/execution of SQL"
+ );
tracker.touch();
+ }
+ configure(properties, execute, EXECUTE);
/**
* Configure the generation of the SQL.
configure(properties, createNamespaces, HBM2DLL_CREATE_NAMESPACES);
configure(properties, implicitNamingStrategy, IMPLICIT_NAMING_STRATEGY);
configure(properties, physicalNamingStrategy, PHYSICAL_NAMING_STRATEGY);
- tracker.track(OUTPUTDIRECTORY, outputDirectory); // << not reflected in hibernate configuration!
- tracker.track(SCAN_DEPENDENCIES, scanDependencies); // << not reflected in hibernate configuration!
- tracker.track(SCAN_TESTCLASSES, scanTestClasses.toString()); // << not reflected in hibernate configuration!
- tracker.track(TEST_OUTPUTDIRECTORY, testOutputDirectory); // << not reflected in hibernate configuration!
+ configure(properties, outputDirectory, OUTPUTDIRECTORY);
+ configure(properties, scanDependencies, SCAN_DEPENDENCIES);
+ configure(properties, scanTestClasses, SCAN_TESTCLASSES);
+ configure(properties, testOutputDirectory, TEST_OUTPUTDIRECTORY);
/**
* Special treatment for the configuration-value "show": a change of its
throw new MojoFailureException("Hibernate configuration is missing!");
}
- getLog().info("Gathered hibernate-configuration (turn on debugging for details):");
+ getLog().info("Gathered configuration:");
for (Entry<Object,Object> entry : properties.entrySet())
getLog().info(" " + entry.getKey() + " = " + entry.getValue());
}
if (value != null)
{
if (properties.containsKey(key))
- getLog().info(
- "Overwriting property " + key + "=\"" +
- properties.getProperty(key) +
- "\" with value \"" + value + "\""
- );
+ {
+ if (!properties.getProperty(key).equals(value))
+ {
+ getLog().info(
+ "Overwriting property " + key + "=\"" +
+ properties.getProperty(key) +
+ "\" with value \"" + value + "\""
+ );
+ properties.setProperty(key, value);
+ }
+ }
else
+ {
getLog().debug("Using value \"" + value + "\" for property " + key);
- properties.setProperty(key, value);
+ properties.setProperty(key, value);
+ }
}
}
return output;
}
+ private void checkOutputFile(File output, ModificationTracker tracker)
+ throws
+ MojoExecutionException
+ {
+ try
+ {
+ if (output.exists())
+ tracker.track(SCRIPT, new FileInputStream(output));
+ else
+ tracker.track(SCRIPT, ZonedDateTime.now().toString());
+ }
+ catch (IOException e)
+ {
+ String error =
+ "Error while checking the generated script: " + e.getMessage();
+ getLog().error(error);
+ throw new MojoExecutionException(error);
+ }
+ }
+
private void addMappings(MetadataSources sources, ModificationTracker tracker)
throws MojoFailureException
{
{
try
{
- File dir = new File(outputDirectory);
+ File dir = new File(path);
if (dir.exists())
{
getLog().info("Adding " + dir.getAbsolutePath() + " to the list of roots to scan...");
urls.add(dir.toURI().toURL());
}
+ else
+ getLog().warn(
+ "the directory cannot be scanned for annotated classes, " +
+ "because it does not exist: " +
+ dir.getAbsolutePath()
+ );
}
catch (MalformedURLException e)
{
throw new MojoFailureException("Could not find persistence-unit " + persistenceUnit);
}
+
+
+ public static void printStrackTrace(StringBuilder builder, Throwable t)
+ {
+ while (t != null)
+ {
+ builder.append("\n\tCause: ");
+ builder.append(t.getMessage() == null ? "" : t.getMessage().replaceAll("\\s+", " "));
+ for (StackTraceElement trace : t.getStackTrace())
+ {
+ builder.append("\n\t");
+ builder.append(trace.getClassName());
+ builder.append(".");
+ builder.append(trace.getMethodName());
+ builder.append("():");
+ builder.append(trace.getLineNumber());
+ }
+ t = t.getCause();
+ }
+ }
}