- * This parameter defaults to the maven build-output-directory for classes.
- * Additionally, all dependencies are scanned for annotated classes.
- *
- * @parameter property="project.build.outputDirectory"
- * @since 1.0
- */
- private String outputDirectory;
-
- /**
- * Whether to scan test-classes too, or not.
- *
- * If this parameter is set to true the test-classes of the
- * artifact will be scanned for hibernate-annotated classes additionally.
- *
- * @parameter property="hibernate.export.scan_testclasses" default-value="false"
- * @since 1.0.1
- */
- private boolean scanTestClasses;
-
- /**
- * Dependency-Scopes, that should be scanned for annotated classes.
- *
- * By default, only dependencies in the scope compile are
- * scanned for annotated classes. Multiple scopes can be seperated by
- * white space or commas.
- *
- * If you do not want any dependencies to be scanned for annotated
- * classes, set this parameter to none.
- *
- * The plugin does not scan for annotated classes in transitive
- * dependencies. If some of your annotated classes are hidden in a
- * transitive dependency, you can simply add that dependency explicitly.
- *
- * @parameter property="hibernate.export.scan_dependencies" default-value="compile"
- * @since 1.0.3
- */
- private String scanDependencies;
-
- /**
- * Test-Classes-Directory to scan.
- *
- * This parameter defaults to the maven build-output-directory for
- * test-classes.
- *
- * This parameter is only used, when scanTestClasses is set
- * to true!
- *
- * @parameter property="project.build.testOutputDirectory"
- * @since 1.0.2
- */
- private String testOutputDirectory;
-
- /**
- * Skip execution
- *
- * If set to true, the execution is skipped.
- *
- * A skipped execution is signaled via the maven-property
- * ${hibernate.export.skipped}.
- *
- * The execution is skipped automatically, if no modified or newly added
- * annotated classes are found and the dialect was not changed.
- *
- * @parameter property="hibernate.skip" default-value="${maven.test.skip}"
- * @since 1.0
- */
- private boolean skip;
-
- /**
- * Force execution
- *
- * Force execution, even if no modified or newly added annotated classes
- * where found and the dialect was not changed.
- *
- * skip takes precedence over force.
- *
- * @parameter property="hibernate.export.force" default-value="false"
- * @since 1.0
- */
- private boolean force;
-
- /**
- * SQL-Driver name.
- *
- * @parameter property="hibernate.connection.driver_class"
- * @since 1.0
- */
- private String driverClassName;
-
- /**
- * Database URL.
- *
- * @parameter property="hibernate.connection.url"
- * @since 1.0
- */
- private String url;
-
- /**
- * Database username
- *
- * @parameter property="hibernate.connection.username"
- * @since 1.0
- */
- private String username;
-
- /**
- * Database password
- *
- * @parameter property="hibernate.connection.password"
- * @since 1.0
- */
- private String password;
-
- /**
- * Hibernate dialect.
- *
- * @parameter property="hibernate.dialect"
- * @since 1.0
- */
- private String hibernateDialect;
-
- /**
- * Hibernate Naming Strategy
- *
- * @parameter property="hibernate.ejb.naming_strategy"
- * @since 1.0.2
- */
- private String hibernateNamingStrategy;
-
- /**
- * Path to Hibernate properties file.
- * If this parameter is not set the plugin will try to load the configuration
- * from a file hibernate.properties on the classpath. The
- * test-classpath takes precedence.
- *
- * @parameter
- * @since 1.0
- */
- private String hibernateProperties;
-
- /**
- * Path to Hibernate configuration file (.cfg.xml).
- * Settings in this file will overwrite settings in the properties file.
- * If this parameter is not set the plugin will try to load the configuration
- * from a file hibernate.cfg.xml on the classpath. The
- * test-classpath takes precedence.
- *
- * @parameter
- * @since 1.1.0
- */
- private String hibernateConfig;
-
- /**
- * Name of the persistence-unit.
- * If there is only one persistence-unit available, that unit will be used
- * automatically.
- * Settings in this file will overwrite settings in the properties or the
- * configuration file.
- *
- * @parameter
- * @since 1.1.0
- */
- private String persistenceUnit;
-
- /**
- * List of Hibernate-Mapping-Files (XML).
- * Multiple files can be separated with white-spaces and/or commas.
- *
- * @parameter property="hibernate.mapping"
- * @since 1.0.2
- */
- private String hibernateMapping;
-
- /**
- * Target of execution:
- *
- *
NONE only export schema to SQL-script (forces execution, signals skip)
SCRIPT export schema to SQL-script and print it to STDOUT
- *
BOTH
- *
- *
- * A database connection is only needed for EXPORT and BOTH, but a
- * Hibernate-Dialect must always be chosen.
- *
- * @parameter property="hibernate.export.target" default-value="EXPORT"
- * @since 1.0
- */
- private String target;
-
- /**
- * Type of execution.
- *
- *
NONE do nothing - just validate the configuration
- *
CREATE create database-schema
- *
DROP drop database-schema
- *
BOTH (DEFAULT!)
- *
- *
- * If NONE is choosen, no databaseconnection is needed.
- *
- * @parameter property="hibernate.export.type" default-value="BOTH"
- * @since 1.0
- */
- private String type;
-
- /**
- * Output file.
- *
- * @parameter property="hibernate.export.schema.filename" default-value="${project.build.directory}/schema.sql"
- * @since 1.0
- */
- private String outputFile;
-
- /**
- * Delimiter in output-file.
- *
- * @parameter property="hibernate.export.schema.delimiter" default-value=";"
- * @since 1.0
- */
- private String delimiter;
-
- /**
- * Format output-file.
- *
- * @parameter property="hibernate.export.schema.format" default-value="true"
- * @since 1.0
- */
- private boolean format;
-
- /**
- * Generate envers schema for auditing tables.
- *
- * @parameter property="hibernate.export.envers" default-value="true"
- * @since 1.0.3
- */
- private boolean envers;
-
-
- @Override
- public void execute()
- throws
- MojoFailureException,
- MojoExecutionException
- {
- if (skip)
- {
- getLog().info("Execution of hibernate4-maven-plugin:export was skipped!");
- project.getProperties().setProperty(EXPORT_SKIPPED_PROPERTY, "true");
- return;
- }
-
- Map md5s;
- boolean modified = false;
- File saved = new File(buildDirectory + File.separator + MD5S);
-
- if (saved.isFile() && saved.length() > 0)
- {
- try
- {
- FileInputStream fis = new FileInputStream(saved);
- ObjectInputStream ois = new ObjectInputStream(fis);
- md5s = (HashMap)ois.readObject();
- ois.close();
- }
- catch (Exception e)
- {
- md5s = new HashMap();
- getLog().warn("Cannot read timestamps from saved: " + e);
- }
- }
- else
- {
- md5s = new HashMap();
- try
- {
- saved.createNewFile();
- }
- catch (IOException e)
- {
- getLog().debug("Cannot create file \"" + saved.getPath() + "\" for timestamps: " + e);
- }
- }
-
- URLClassLoader classLoader = null;
- try
- {
- getLog().debug("Creating ClassLoader for project-dependencies...");
- List classpathFiles = project.getCompileClasspathElements();
- if (scanTestClasses)
- classpathFiles.addAll(project.getTestClasspathElements());
- List urls = new LinkedList();
- File file;
- file = new File(testOutputDirectory);
- if (!file.exists())
- {
- getLog().info("creating test-output-directory: " + testOutputDirectory);
- file.mkdirs();
- }
- urls.add(file.toURI().toURL());
- file = new File(outputDirectory);
- if (!file.exists())
- {
- getLog().info("creating output-directory: " + outputDirectory);
- file.mkdirs();
- }
- urls.add(file.toURI().toURL());
- for (String pathElement : classpathFiles)
- {
- getLog().debug("Dependency: " + pathElement);
- urls.add(new File(pathElement).toURI().toURL());
- }
- classLoader =
- new URLClassLoader(
- urls.toArray(new URL[urls.size()]),
- getClass().getClassLoader()
- );
- }
- catch (Exception e)
- {
- getLog().error("Error while creating ClassLoader!", e);
- throw new MojoExecutionException(e.getMessage());
- }
-
- Set> classes =
- new TreeSet>(
- new Comparator>() {
- @Override
- public int compare(Class> a, Class> b)
- {
- return a.getName().compareTo(b.getName());
- }
- }
- );
-
- try
- {
- AnnotationDB db = new AnnotationDB();
- File dir = new File(outputDirectory);
- if (dir.exists())
- {
- getLog().info("Scanning directory " + outputDirectory + " for annotated classes...");
- URL dirUrl = dir.toURI().toURL();
- db.scanArchives(dirUrl);
- }
- if (scanTestClasses)
- {
- dir = new File(testOutputDirectory);
- if (dir.exists())
- {
- getLog().info("Scanning directory " + testOutputDirectory + " for annotated classes...");
- URL dirUrl = dir.toURI().toURL();
- db.scanArchives(dirUrl);
- }
- }
- if (scanDependencies != null)
- {
- Matcher matcher = split.matcher(scanDependencies);
- while (matcher.find())
- {
- getLog().info("Scanning dependencies for scope " + matcher.group());
- for (Artifact artifact : project.getDependencyArtifacts())
- {
- if (!artifact.getScope().equalsIgnoreCase(matcher.group()))
- continue;
- if (artifact.getFile() == null)
- {
- getLog().warn(
- "Cannot scan dependency " +
- artifact.getId() +
- ": no JAR-file available!"
- );
- continue;
- }
- getLog().info(
- "Scanning dependency " +
- artifact.getId() +
- " for annotated classes..."
- );
- db.scanArchives(artifact.getFile().toURI().toURL());
- }
- }
- }
-
- Set classNames = new HashSet();
- if (db.getAnnotationIndex().containsKey(Entity.class.getName()))
- classNames.addAll(db.getAnnotationIndex().get(Entity.class.getName()));
- if (db.getAnnotationIndex().containsKey(MappedSuperclass.class.getName()))
- classNames.addAll(db.getAnnotationIndex().get(MappedSuperclass.class.getName()));
- if (db.getAnnotationIndex().containsKey(Embeddable.class.getName()))
- classNames.addAll(db.getAnnotationIndex().get(Embeddable.class.getName()));
-
- MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
- for (String name : classNames)
- {
- Class> annotatedClass = classLoader.loadClass(name);
- classes.add(annotatedClass);
- String resourceName = annotatedClass.getName();
- resourceName = resourceName.substring(resourceName.lastIndexOf(".") + 1, resourceName.length()) + ".class";
- InputStream is =
- annotatedClass
- .getResourceAsStream(resourceName);
- byte[] buffer = new byte[1024*4]; // copy data in 4MB-chunks
- int i;
- while((i = is.read(buffer)) > -1)
- digest.update(buffer, 0, i);
- is.close();
- byte[] bytes = digest.digest();
- BigInteger bi = new BigInteger(1, bytes);
- String newMd5 = String.format("%0" + (bytes.length << 1) + "x", bi);
- String oldMd5 = !md5s.containsKey(name) ? "" : md5s.get(name);
- if (!newMd5.equals(oldMd5))
- {
- getLog().debug("Found new or modified annotated class: " + name);
- modified = true;
- md5s.put(name, newMd5);
- }
- else
- {
- getLog().debug(oldMd5 + " -> class unchanged: " + name);
- }
- }
- }
- catch (ClassNotFoundException e)
- {
- getLog().error("Error while adding annotated classes!", e);
- throw new MojoExecutionException(e.getMessage());
- }
- catch (Exception e)
- {
- getLog().error("Error while scanning!", e);
- throw new MojoFailureException(e.getMessage());
- }
-
-
- ValidationConfiguration config = new ValidationConfiguration();
- // Clear unused system-properties
- config.setProperties(new Properties());
-
-
- ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
- StandardServiceRegistryImpl registry = null;
- MavenLogAppender.startPluginLog(this);
-
- try
- {
- /**
- * Change class-loader of current thread, so that hibernate can
- * see all dependencies!
- */
- Thread.currentThread().setContextClassLoader(classLoader);
-
-
- /** Try to read configuration from properties-file */
- try
- {
- if (hibernateProperties == null)
- {
- URL url = classLoader.findResource("hibernate.properties");
- if (url == null)
- {
- getLog().info("No hibernate.properties on the classpath!");
- }
- else
- {
- getLog().info("Reading settings from hibernate.properties on the classpath.");
- Properties properties = new Properties();
- properties.load(url.openStream());
- config.setProperties(properties);
- }
- }
- else
- {
- File file = new File(hibernateProperties);
- if (file.exists())
- {
- getLog().info("Reading settings from file " + hibernateProperties + "...");
- Properties properties = new Properties();
- properties.load(new FileInputStream(file));
- config.setProperties(properties);
- }
- else
- getLog().info("No hibernate-properties-file found! (Checked path: " + hibernateProperties + ")");
- }
- }
- catch (IOException e)
- {
- getLog().error("Error while reading properties!", e);
- throw new MojoExecutionException(e.getMessage());
- }
-
- /** Try to read configuration from configuration-file */
- try
- {
- if (hibernateConfig == null)
- {
- URL url = classLoader.findResource("hibernate.cfg.xml");
- if (url == null)
- {
- getLog().info("No hibernate.cfg.xml on the classpath!");
- }
- else
- {
- getLog().info("Reading settings from hibernate.cfg.xml on the classpath.");
- config.configure(url);
- }
- }
- else
- {
- File file = new File(hibernateConfig);
- if (file.exists())
- {
- getLog().info("Reading configuration from file " + hibernateConfig + "...");
- config.configure(file);
- }
- else
- getLog().info("No hibernate-configuration-file found! (Checked path: " + hibernateConfig + ")");
- }
- }
- catch (Exception e)
- {
- getLog().error("Error while reading configuration!", e);
- throw new MojoExecutionException(e.getMessage());
- }
-
- ParsedPersistenceXmlDescriptor persistenceUnitDescriptor =
- getPersistenceUnitDescriptor(
- persistenceUnit,
- config.getProperties(),
- new MavenProjectClassLoaderService(classLoader)
- );
- if (persistenceUnitDescriptor != null)
- config.setProperties(persistenceUnitDescriptor.getProperties());
-
-
- /** Overwrite values from properties-file or set, if given */
-
- if (driverClassName != null)
- {
- if (config.getProperties().containsKey(DRIVER_CLASS))
- getLog().debug(
- "Overwriting property " +
- DRIVER_CLASS + "=" + config.getProperty(DRIVER_CLASS) +
- " with the value " + driverClassName
- );
- else
- getLog().debug("Using the value " + driverClassName);
- config.setProperty(DRIVER_CLASS, driverClassName);
- }
- if (config.getProperty(DRIVER_CLASS) == null)
- {
- String driver = config.getProperty(JPA_DRIVER);
- if (driver != null)
- {
- getLog().info(
- DRIVER_CLASS +
- " is not set. Borrow setting from " +
- JPA_DRIVER +
- ": " +
- driver);
- config.setProperty(DRIVER_CLASS, driver);
- }
- }
-
- if (url != null)
- {
- if (config.getProperties().containsKey(URL))
- getLog().debug(
- "Overwriting property " +
- URL + "=" + config.getProperty(URL) +
- " with the value " + url
- );
- else
- getLog().debug("Using the value " + url);
- config.setProperty(URL, url);
- }
- if (config.getProperty(URL) == null)
- {
- String url = config.getProperty(JPA_URL);
- if (url != null)
- {
- getLog().info(
- URL +
- " is not set. Borrow setting from " +
- JPA_URL +
- ": " +
- url);
- config.setProperty(URL, url);
- }
- }
-
- if (username != null)
- {
- if (config.getProperties().containsKey(USERNAME))
- getLog().debug(
- "Overwriting property " +
- USERNAME + "=" + config.getProperty(USERNAME) +
- " with the value " + username
- );
- else
- getLog().debug("Using the value " + username);
- config.setProperty(USERNAME, username);
- }
- if (config.getProperty(USERNAME) == null)
- {
- String username = config.getProperty(JPA_USERNAME);
- if (username != null)
- {
- getLog().info(
- USERNAME +
- " is not set. Borrow setting from " +
- JPA_USERNAME +
- ": " +
- username);
- config.setProperty(USERNAME, username);
- }
- }
-
- if (password != null)
- {
- if (config.getProperties().containsKey(PASSWORD))
- getLog().debug(
- "Overwriting property " +
- PASSWORD + "=" + config.getProperty(PASSWORD) +
- " with value " + password
- );
- else
- getLog().debug("Using value " + password + " for property " + PASSWORD);
- config.setProperty(PASSWORD, password);
- }
- if (config.getProperty(PASSWORD) == null)
- {
- String password = config.getProperty(JPA_PASSWORD);
- if (password != null)
- {
- getLog().info(
- PASSWORD +
- " is not set. Borrow setting from " +
- JPA_PASSWORD +
- ": " +
- password);
- config.setProperty(PASSWORD, password);
- }
- }
-
- if (hibernateDialect != null)
- {
- if (config.getProperties().containsKey(DIALECT))
- getLog().debug(
- "Overwriting property " +
- DIALECT + "=" + config.getProperty(DIALECT) +
- " with value " + hibernateDialect
- );
- else
- getLog().debug(
- "Using value " + hibernateDialect + " for property " + DIALECT
- );
- config.setProperty(DIALECT, hibernateDialect);
- }
-
- if ( hibernateNamingStrategy != null )
- {
- if ( config.getProperties().contains(NAMING_STRATEGY))
- getLog().debug(
- "Overwriting property " +
- NAMING_STRATEGY + "=" + config.getProperty(NAMING_STRATEGY) +
- " with value " + hibernateNamingStrategy
- );
- else
- getLog().debug(
- "Using value " + hibernateNamingStrategy + " for property " +
- NAMING_STRATEGY
- );
- config.setProperty(NAMING_STRATEGY, hibernateNamingStrategy);
- }
-
- /** The generated SQL varies with the dialect! */
- if (md5s.containsKey(DIALECT))
- {
- String dialect = config.getProperty(DIALECT);
- if (md5s.get(DIALECT).equals(dialect))
- getLog().debug("SQL-dialect unchanged.");
- else
- {
- modified = true;
- if (dialect == null)
- {
- getLog().debug("SQL-dialect was unset.");
- md5s.remove(DIALECT);
- }
- else
- {
- getLog().debug("SQL-dialect changed: " + dialect);
- md5s.put(DIALECT, dialect);
- }
- }
- }
- else
- {
- String dialect = config.getProperty(DIALECT);
- if (dialect != null)
- {
- modified = true;
- md5s.put(DIALECT, config.getProperty(DIALECT));
- }
- }
-
- /** The generated SQL varies with the envers-configuration */
- if (md5s.get(ENVERS) != null)
- {
- if (md5s.get(ENVERS).equals(Boolean.toString(envers)))
- getLog().debug("Envers-Configuration unchanged. Enabled: " + envers);
- else
- {
- getLog().debug("Envers-Configuration changed. Enabled: " + envers);
- modified = true;
- md5s.put(ENVERS, Boolean.toString(envers));
- }
- }
- else
- {
- modified = true;
- md5s.put(ENVERS, Boolean.toString(envers));
- }
-
- if (config.getProperties().isEmpty())
- {
- getLog().error("No properties set!");
- throw new MojoFailureException("Hibernate configuration is missing!");
- }
-
- getLog().info("Gathered hibernate-configuration (turn on debugging for details):");
- for (Entry