1 package de.juplo.plugins.hibernate;
4 import com.pyx4j.log4j.MavenLogAppender;
6 import java.io.FileInputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
10 import java.net.URLClassLoader;
11 import java.security.NoSuchAlgorithmException;
12 import java.util.Collections;
13 import java.util.HashSet;
14 import java.util.Iterator;
15 import java.util.LinkedList;
16 import java.util.List;
18 import java.util.Map.Entry;
19 import java.util.Properties;
21 import java.util.regex.Matcher;
22 import java.util.regex.Pattern;
23 import javax.persistence.Embeddable;
24 import javax.persistence.Entity;
25 import javax.persistence.MappedSuperclass;
26 import javax.persistence.spi.PersistenceUnitTransactionType;
27 import org.apache.maven.artifact.Artifact;
28 import org.apache.maven.model.Resource;
29 import org.apache.maven.plugin.AbstractMojo;
30 import org.apache.maven.plugin.MojoExecutionException;
31 import org.apache.maven.plugin.MojoFailureException;
32 import org.apache.maven.project.MavenProject;
33 import org.hibernate.boot.MetadataBuilder;
34 import org.hibernate.boot.MetadataSources;
35 import org.hibernate.boot.cfgxml.internal.ConfigLoader;
36 import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
37 import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
38 import org.hibernate.boot.registry.BootstrapServiceRegistry;
39 import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
40 import org.hibernate.boot.registry.StandardServiceRegistry;
41 import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
42 import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
43 import org.hibernate.boot.registry.selector.spi.StrategySelector;
44 import org.hibernate.boot.spi.MetadataImplementor;
45 import static org.hibernate.cfg.AvailableSettings.DIALECT;
46 import static org.hibernate.cfg.AvailableSettings.DRIVER;
47 import static org.hibernate.cfg.AvailableSettings.FORMAT_SQL;
48 import static org.hibernate.cfg.AvailableSettings.HBM2DLL_CREATE_NAMESPACES;
49 import static org.hibernate.cfg.AvailableSettings.IMPLICIT_NAMING_STRATEGY;
50 import static org.hibernate.cfg.AvailableSettings.PASS;
51 import static org.hibernate.cfg.AvailableSettings.PHYSICAL_NAMING_STRATEGY;
52 import static org.hibernate.cfg.AvailableSettings.SHOW_SQL;
53 import static org.hibernate.cfg.AvailableSettings.USER;
54 import static org.hibernate.cfg.AvailableSettings.URL;
55 import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
56 import org.hibernate.internal.util.config.ConfigurationException;
57 import static org.hibernate.jpa.AvailableSettings.JDBC_DRIVER;
58 import static org.hibernate.jpa.AvailableSettings.JDBC_PASSWORD;
59 import static org.hibernate.jpa.AvailableSettings.JDBC_URL;
60 import static org.hibernate.jpa.AvailableSettings.JDBC_USER;
61 import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
62 import org.hibernate.jpa.boot.internal.PersistenceXmlParser;
63 import org.hibernate.jpa.boot.spi.ProviderChecker;
64 import org.scannotation.AnnotationDB;
68 * Baseclass with common attributes and methods.
70 * @phase process-classes
72 * @requiresDependencyResolution runtime
74 public abstract class AbstractSchemaMojo extends AbstractMojo
76 public final static String EXPORT = "hibernate.schema.export";
77 public final static String DELIMITER = "hibernate.schema.delimiter";
78 public final static String OUTPUTDIRECTORY = "project.build.outputDirectory";
79 public final static String SCAN_DEPENDENCIES = "hibernate.schema.scan.dependencies";
80 public final static String SCAN_TESTCLASSES = "hibernate.schema.scan.test_classes";
81 public final static String TEST_OUTPUTDIRECTORY = "project.build.testOutputDirectory";
82 public final static String SKIPPED = "hibernate.schema.skipped";
84 private final static Pattern SPLIT = Pattern.compile("[^,\\s]+");
90 * Only needed internally.
92 * @parameter property="project"
96 private MavenProject project;
101 * Only needed internally.
103 * @parameter property="project.build.directory"
107 String buildDirectory;
110 /** Parameters to configure the genaration of the SQL *********************/
113 * Export the database-schma to the database.
114 * If set to <code>false</code>, only the SQL-script is created and the
115 * database is not touched.
117 * <strong>Important:</strong>
118 * This configuration value can only be configured through the
119 * <code>pom.xml</code>, or by the definition of a system-property, because
120 * it is not known by Hibernate nor JPA and, hence, not picked up from
121 * their configuration!
123 * @parameter property="hibernate.schema.export" default-value="true"
131 * If set to <code>true</code>, the execution is skipped.
133 * A skipped execution is signaled via the maven-property
134 * <code>${hibernate.export.skipped}</code>.
136 * The execution is skipped automatically, if no modified or newly added
137 * annotated classes are found and the dialect was not changed.
139 * <strong>Important:</strong>
140 * This configuration value can only be configured through the
141 * <code>pom.xml</code>, or by the definition of a system-property, because
142 * it is not known by Hibernate nor JPA and, hence, not picked up from
143 * their configuration!
145 * @parameter property="hibernate.schema.skip" default-value="${maven.test.skip}"
148 private boolean skip;
153 * Force execution, even if no modified or newly added annotated classes
154 * where found and the dialect was not changed.
156 * <code>skip</code> takes precedence over <code>force</code>.
158 * <strong>Important:</strong>
159 * This configuration value can only be configured through the
160 * <code>pom.xml</code>, or by the definition of a system-property, because
161 * it is not known by Hibernate nor JPA and, hence, not picked up from
162 * their configuration!
164 * @parameter property="hibernate.schema.force" default-value="false"
167 private boolean force;
172 * @parameter property="hibernate.dialect"
175 private String dialect;
178 * Delimiter in output-file.
180 * <strong>Important:</strong>
181 * This configuration value can only be configured through the
182 * <code>pom.xml</code>, or by the definition of a system-property, because
183 * it is not known by Hibernate nor JPA and, hence, not picked up from
184 * their configuration!
186 * @parameter property="hibernate.schema.delimiter" default-value=";"
192 * Show the generated SQL in the command-line output.
194 * @parameter property="hibernate.show_sql"
200 * Format output-file.
202 * @parameter property="hibernate.format_sql"
208 * Specifies whether to automatically create also the database schema/catalog.
210 * @parameter property="hibernate.hbm2dll.create_namespaces" default-value="false"
213 Boolean createNamespaces;
216 * Implicit naming strategy
218 * @parameter property="hibernate.implicit_naming_strategy"
221 private String implicitNamingStrategy;
224 * Physical naming strategy
226 * @parameter property="hibernate.physical_naming_strategy"
229 private String physicalNamingStrategy;
232 * Classes-Directory to scan.
234 * This parameter defaults to the maven build-output-directory for classes.
235 * Additionally, all dependencies are scanned for annotated classes.
237 * <strong>Important:</strong>
238 * This configuration value can only be configured through the
239 * <code>pom.xml</code>, or by the definition of a system-property, because
240 * it is not known by Hibernate nor JPA and, hence, not picked up from
241 * their configuration!
243 * @parameter property="project.build.outputDirectory"
246 private String outputDirectory;
249 * Dependency-Scopes, that should be scanned for annotated classes.
251 * By default, only dependencies in the scope <code>compile</code> are
252 * scanned for annotated classes. Multiple scopes can be seperated by
253 * white space or commas.
255 * If you do not want any dependencies to be scanned for annotated
256 * classes, set this parameter to <code>none</code>.
258 * The plugin does not scan for annotated classes in transitive
259 * dependencies. If some of your annotated classes are hidden in a
260 * transitive dependency, you can simply add that dependency explicitly.
262 * @parameter property="hibernate.schema.scan.dependencies" default-value="compile"
265 private String scanDependencies;
268 * Whether to scan test-classes too, or not.
270 * If this parameter is set to <code>true</code> the test-classes of the
271 * artifact will be scanned for hibernate-annotated classes additionally.
273 * <strong>Important:</strong>
274 * This configuration value can only be configured through the
275 * <code>pom.xml</code>, or by the definition of a system-property, because
276 * it is not known by Hibernate nor JPA and, hence, not picked up from
277 * their configuration!
279 * @parameter property="hibernate.schema.scan.test_classes" default-value="false"
282 private Boolean scanTestClasses;
285 * Test-Classes-Directory to scan.
287 * This parameter defaults to the maven build-output-directory for
290 * This parameter is only used, when <code>scanTestClasses</code> is set
291 * to <code>true</code>!
293 * <strong>Important:</strong>
294 * This configuration value can only be configured through the
295 * <code>pom.xml</code>, or by the definition of a system-property, because
296 * it is not known by Hibernate nor JPA and, hence, not picked up from
297 * their configuration!
299 * @parameter property="project.build.testOutputDirectory"
302 private String testOutputDirectory;
305 /** Conection parameters *************************************************/
310 * @parameter property="hibernate.connection.driver_class"
313 private String driver;
318 * @parameter property="hibernate.connection.url"
326 * @parameter property="hibernate.connection.username"
329 private String username;
334 * @parameter property="hibernate.connection.password"
337 private String password;
340 /** Parameters to locate configuration sources ****************************/
343 * Path to a file or name of a ressource with hibernate properties.
344 * If this parameter is specified, the plugin will try to load configuration
345 * values from a file with the given path or a ressource on the classpath with
346 * the given name. If both fails, the execution of the plugin will fail.
348 * If this parameter is not set the plugin will load configuration values
349 * from a ressource named <code>hibernate.properties</code> on the classpath,
350 * if it is present, but will not fail if there is no such ressource.
352 * During ressource-lookup, the test-classpath takes precedence.
357 private String hibernateProperties;
360 * Path to Hibernate configuration file (.cfg.xml).
361 * If this parameter is specified, the plugin will try to load configuration
362 * values from a file with the given path or a ressource on the classpath with
363 * the given name. If both fails, the execution of the plugin will fail.
365 * If this parameter is not set the plugin will load configuration values
366 * from a ressource named <code>hibernate.cfg.xml</code> on the classpath,
367 * if it is present, but will not fail if there is no such ressource.
369 * During ressource-lookup, the test-classpath takes precedence.
371 * Settings in this file will overwrite settings in the properties file.
376 private String hibernateConfig;
379 * Name of the persistence-unit.
380 * If this parameter is specified, the plugin will try to load configuration
381 * values from a persistence-unit with the specified name. If no such
382 * persistence-unit can be found, the plugin will throw an exception.
384 * If this parameter is not set and there is only one persistence-unit
385 * available, that unit will be used automatically. But if this parameter is
386 * not set and there are multiple persistence-units available on,
387 * the class-path, the execution of the plugin will fail.
389 * Settings in this file will overwrite settings in the properties or the
390 * configuration file.
395 private String persistenceUnit;
398 * List of Hibernate-Mapping-Files (XML).
399 * Multiple files can be separated with white-spaces and/or commas.
401 * @parameter property="hibernate.mapping"
404 private String mappings;
408 public final void execute(String filename)
410 MojoFailureException,
411 MojoExecutionException
415 getLog().info("Execution of hibernate-maven-plugin was skipped!");
416 project.getProperties().setProperty(SKIPPED, "true");
420 ModificationTracker tracker;
423 tracker = new ModificationTracker(buildDirectory, filename, getLog());
425 catch (NoSuchAlgorithmException e)
427 throw new MojoFailureException("Digest-Algorithm MD5 is missing!", e);
430 SimpleConnectionProvider connectionProvider =
431 new SimpleConnectionProvider(getLog());
435 /** Start extended logging */
436 MavenLogAppender.startPluginLog(this);
438 /** Load checksums for old mapping and configuration */
441 /** Create the ClassLoader */
442 URLClassLoader classLoader = createClassLoader();
444 /** Create a BootstrapServiceRegistry with the created ClassLoader */
445 BootstrapServiceRegistry bootstrapServiceRegitry =
446 new BootstrapServiceRegistryBuilder()
447 .applyClassLoader(classLoader)
449 ClassLoaderService classLoaderService =
450 bootstrapServiceRegitry.getService(ClassLoaderService.class);
452 Properties properties = new Properties();
453 ConfigLoader configLoader = new ConfigLoader(bootstrapServiceRegitry);
455 /** Loading and merging configuration */
456 properties.putAll(loadProperties(configLoader));
457 properties.putAll(loadConfig(configLoader));
458 properties.putAll(loadPersistenceUnit(classLoaderService, properties));
460 /** Overwriting/Completing configuration */
461 configure(properties, tracker);
463 /** Check configuration for modifications */
464 if(tracker.track(properties))
465 getLog().debug("Configuration has changed.");
467 getLog().debug("Configuration unchanged.");
469 /** Configure Hibernate */
470 StandardServiceRegistry serviceRegistry =
471 new StandardServiceRegistryBuilder(bootstrapServiceRegitry)
472 .applySettings(properties)
473 .addService(ConnectionProvider.class, connectionProvider)
477 MetadataSources sources = new MetadataSources(serviceRegistry);
478 addAnnotatedClasses(sources, classLoaderService, tracker);
479 addMappings(sources, tracker);
481 /** Skip execution, if mapping and configuration is unchanged */
482 if (!tracker.modified())
485 "Mapping and configuration unchanged."
488 getLog().info("Schema generation is forced!");
491 getLog().info("Skipping schema generation!");
492 project.getProperties().setProperty(SKIPPED, "true");
498 /** Create a connection, if sufficient configuration infromation is available */
499 connectionProvider.open(classLoaderService, properties);
501 MetadataBuilder metadataBuilder = sources.getMetadataBuilder();
503 StrategySelector strategySelector =
504 serviceRegistry.getService(StrategySelector.class);
506 if (properties.containsKey(IMPLICIT_NAMING_STRATEGY))
508 metadataBuilder.applyImplicitNamingStrategy(
509 strategySelector.resolveStrategy(
510 ImplicitNamingStrategy.class,
511 properties.getProperty(IMPLICIT_NAMING_STRATEGY)
516 if (properties.containsKey(PHYSICAL_NAMING_STRATEGY))
518 metadataBuilder.applyPhysicalNamingStrategy(
519 strategySelector.resolveStrategy(
520 PhysicalNamingStrategy.class,
521 properties.getProperty(PHYSICAL_NAMING_STRATEGY)
527 * Change class-loader of current thread.
528 * This is necessary, because still not all parts of Hibernate 5 use
529 * the newly introduced ClassLoaderService and will fail otherwise!
531 Thread thread = Thread.currentThread();
532 ClassLoader contextClassLoader = thread.getContextClassLoader();
535 thread.setContextClassLoader(classLoader);
536 build((MetadataImplementor)metadataBuilder.build());
540 thread.setContextClassLoader(contextClassLoader);
545 /** Remember mappings and configuration */
548 /** Close the connection - if one was opened */
549 connectionProvider.close();
551 /** Stop Log-Capturing */
552 MavenLogAppender.endPluginLog(this);
557 abstract void build(MetadataImplementor metadata)
559 MojoFailureException,
560 MojoExecutionException;
563 private URLClassLoader createClassLoader() throws MojoExecutionException
567 getLog().debug("Creating ClassLoader for project-dependencies...");
568 List<String> classpathFiles = project.getCompileClasspathElements();
570 classpathFiles.addAll(project.getTestClasspathElements());
571 List<URL> urls = new LinkedList<URL>();
573 file = new File(testOutputDirectory);
576 getLog().info("creating test-output-directory: " + testOutputDirectory);
579 urls.add(file.toURI().toURL());
580 file = new File(outputDirectory);
583 getLog().info("creating output-directory: " + outputDirectory);
586 urls.add(file.toURI().toURL());
587 for (String pathElement : classpathFiles)
589 getLog().debug("Dependency: " + pathElement);
590 urls.add(new File(pathElement).toURI().toURL());
594 urls.toArray(new URL[urls.size()]),
595 getClass().getClassLoader()
600 getLog().error("Error while creating ClassLoader!", e);
601 throw new MojoExecutionException(e.getMessage());
605 private Map loadProperties(ConfigLoader configLoader)
607 MojoExecutionException
609 /** Try to read configuration from properties-file */
610 if (hibernateProperties == null)
614 return configLoader.loadProperties("hibernate.properties");
616 catch (ConfigurationException e)
618 getLog().debug(e.getMessage());
619 return Collections.EMPTY_MAP;
626 File file = new File(hibernateProperties);
629 getLog().info("Reading settings from file " + hibernateProperties + "...");
630 return configLoader.loadProperties(file);
633 return configLoader.loadProperties(hibernateProperties);
635 catch (ConfigurationException e)
637 getLog().error("Error while reading properties!", e);
638 throw new MojoExecutionException(e.getMessage());
643 private Map loadConfig(ConfigLoader configLoader)
644 throws MojoExecutionException
646 /** Try to read configuration from configuration-file */
647 if (hibernateConfig == null)
653 .loadConfigXmlResource("hibernate.cfg.xml")
654 .getConfigurationValues();
656 catch (ConfigurationException e)
658 getLog().debug(e.getMessage());
659 return Collections.EMPTY_MAP;
666 File file = new File(hibernateConfig);
669 getLog().info("Reading configuration from file " + hibernateConfig + "...");
670 return configLoader.loadConfigXmlFile(file).getConfigurationValues();
675 .loadConfigXmlResource(hibernateConfig)
676 .getConfigurationValues();
678 catch (ConfigurationException e)
680 getLog().error("Error while reading configuration!", e);
681 throw new MojoExecutionException(e.getMessage());
686 private void configure(Properties properties, ModificationTracker tracker)
687 throws MojoFailureException
690 * Special treatment for the configuration-value "export": if it is
691 * switched to "true", the genearation fo the schema should be forced!
693 if (tracker.check(EXPORT, export.toString()) && export)
697 * Configure the generation of the SQL.
698 * Overwrite values from properties-file if the configuration parameter is
699 * known to Hibernate.
701 dialect = configure(properties, dialect, DIALECT);
702 tracker.track(DELIMITER, delimiter); // << not reflected in hibernate configuration!
703 format = configure(properties, format, FORMAT_SQL);
704 createNamespaces = configure(properties, createNamespaces, HBM2DLL_CREATE_NAMESPACES);
705 implicitNamingStrategy = configure(properties, implicitNamingStrategy, IMPLICIT_NAMING_STRATEGY);
706 physicalNamingStrategy = configure(properties, physicalNamingStrategy, PHYSICAL_NAMING_STRATEGY);
707 tracker.track(OUTPUTDIRECTORY, outputDirectory); // << not reflected in hibernate configuration!
708 tracker.track(SCAN_DEPENDENCIES, scanDependencies); // << not reflected in hibernate configuration!
709 tracker.track(SCAN_TESTCLASSES, scanTestClasses.toString()); // << not reflected in hibernate configuration!
710 tracker.track(TEST_OUTPUTDIRECTORY, testOutputDirectory); // << not reflected in hibernate configuration!
713 * Special treatment for the configuration-value "show": a change of its
714 * configured value should not lead to a regeneration of the database
718 show = Boolean.valueOf(properties.getProperty(SHOW_SQL));
720 properties.setProperty(SHOW_SQL, show.toString());
723 * Configure the connection parameters.
724 * Overwrite values from properties-file.
726 driver = configure(properties, driver, DRIVER, JDBC_DRIVER);
727 url = configure(properties, url, URL, JDBC_URL);
728 username = configure(properties, username, USER, JDBC_USER);
729 password = configure(properties, password, PASS, JDBC_PASSWORD);
731 if (properties.isEmpty())
733 getLog().error("No properties set!");
734 throw new MojoFailureException("Hibernate configuration is missing!");
737 getLog().info("Gathered hibernate-configuration (turn on debugging for details):");
738 for (Entry<Object,Object> entry : properties.entrySet())
739 getLog().info(" " + entry.getKey() + " = " + entry.getValue());
742 private String configure(
743 Properties properties,
746 String alternativeKey
749 value = configure(properties, value, key);
751 return properties.getProperty(alternativeKey);
753 if (properties.containsKey(alternativeKey))
756 "Ignoring property " + alternativeKey + "=" +
757 properties.getProperty(alternativeKey) + " in favour for property " +
758 key + "=" + properties.getProperty(key)
760 properties.remove(alternativeKey);
762 return properties.getProperty(alternativeKey);
765 private String configure(Properties properties, String value, String key)
769 if (properties.containsKey(key))
771 "Overwriting property " + key + "=" + properties.getProperty(key) +
772 " with the value " + value
775 getLog().debug("Using the value " + value + " for property " + key);
776 properties.setProperty(key, value);
778 return properties.getProperty(key);
781 private boolean configure(Properties properties, Boolean value, String key)
785 if (properties.containsKey(key))
787 "Overwriting property " + key + "=" + properties.getProperty(key) +
788 " with the value " + value
791 getLog().debug("Using the value " + value + " for property " + key);
792 properties.setProperty(key, value.toString());
794 return Boolean.valueOf(properties.getProperty(key));
797 private void addMappings(MetadataSources sources, ModificationTracker tracker)
798 throws MojoFailureException
800 getLog().debug("Adding explicitly configured mappings...");
801 if (mappings != null)
805 for (String filename : mappings.split("[\\s,]+"))
807 // First try the filename as absolute/relative path
808 File file = new File(filename);
811 // If the file was not found, search for it in the resource-directories
812 for (Resource resource : project.getResources())
814 file = new File(resource.getDirectory() + File.separator + filename);
821 if (file.isDirectory())
822 // TODO: add support to read all mappings under a directory
823 throw new MojoFailureException(file.getAbsolutePath() + " is a directory");
824 if (tracker.track(filename, new FileInputStream(file)))
825 getLog().debug("Found new or modified mapping-file: " + filename);
827 getLog().debug("mapping-file unchanged: " + filename);
829 sources.addFile(file);
832 throw new MojoFailureException("File " + filename + " could not be found in any of the configured resource-directories!");
835 catch (IOException e)
837 throw new MojoFailureException("Cannot calculate MD5 sums!", e);
842 private void addAnnotatedClasses(
843 MetadataSources sources,
844 ClassLoaderService classLoaderService,
845 ModificationTracker tracker
848 MojoFailureException,
849 MojoExecutionException
854 AnnotationDB db = new AnnotationDB();
857 dir = new File(outputDirectory);
860 getLog().info("Scanning directory " + dir.getAbsolutePath() + " for annotated classes...");
861 URL dirUrl = dir.toURI().toURL();
862 db.scanArchives(dirUrl);
867 dir = new File(testOutputDirectory);
870 getLog().info("Scanning directory " + dir.getAbsolutePath() + " for annotated classes...");
871 URL dirUrl = dir.toURI().toURL();
872 db.scanArchives(dirUrl);
876 if (scanDependencies != null)
878 Matcher matcher = SPLIT.matcher(scanDependencies);
879 while (matcher.find())
881 getLog().info("Scanning dependencies for scope " + matcher.group());
882 for (Artifact artifact : project.getDependencyArtifacts())
884 if (!artifact.getScope().equalsIgnoreCase(matcher.group()))
886 if (artifact.getFile() == null)
888 getLog().warn("Cannot scan dependency " + artifact.getId() + ": no JAR-file available!");
891 getLog().info("Scanning dependency " + artifact.getId() + " for annotated classes...");
892 db.scanArchives(artifact.getFile().toURI().toURL());
897 Set<String> classes = new HashSet<String>();
898 if (db.getAnnotationIndex().containsKey(Entity.class.getName()))
899 classes.addAll(db.getAnnotationIndex().get(Entity.class.getName()));
900 if (db.getAnnotationIndex().containsKey(MappedSuperclass.class.getName()))
901 classes.addAll(db.getAnnotationIndex().get(MappedSuperclass.class.getName()));
902 if (db.getAnnotationIndex().containsKey(Embeddable.class.getName()))
903 classes.addAll(db.getAnnotationIndex().get(Embeddable.class.getName()));
905 Set<String> packages = new HashSet<String>();
907 for (String name : classes)
909 Class<?> annotatedClass = classLoaderService.classForName(name);
910 String packageName = annotatedClass.getPackage().getName();
911 if (!packages.contains(packageName))
914 annotatedClass.getResourceAsStream("package-info.class");
917 // No compiled package-info available: no package-level annotations!
918 getLog().debug("Package " + packageName + " is not annotated.");
922 if (tracker.track(packageName, is))
923 getLog().debug("New or modified package: " + packageName);
925 getLog().debug("Unchanged package: " + packageName);
926 getLog().info("Adding annotated package " + packageName);
927 sources.addPackage(packageName);
929 packages.add(packageName);
931 String resourceName = annotatedClass.getName();
933 resourceName.substring(
934 resourceName.lastIndexOf(".") + 1,
935 resourceName.length()
939 .getResourceAsStream(resourceName);
940 if (tracker.track(name, is))
941 getLog().debug("New or modified class: " + name);
943 getLog().debug("Unchanged class: " + name);
944 getLog().info("Adding annotated class " + annotatedClass);
945 sources.addAnnotatedClass(annotatedClass);
950 getLog().error("Error while scanning!", e);
951 throw new MojoFailureException(e.getMessage());
955 private Properties loadPersistenceUnit(
956 ClassLoaderService classLoaderService,
957 Properties properties
962 PersistenceXmlParser parser =
963 new PersistenceXmlParser(
965 PersistenceUnitTransactionType.RESOURCE_LOCAL
968 List<ParsedPersistenceXmlDescriptor> units = parser.doResolve(properties);
970 if (persistenceUnit == null)
972 switch (units.size())
975 getLog().info("Found no META-INF/persistence.xml.");
976 return new Properties();
978 getLog().info("Using persistence-unit " + units.get(0).getName());
979 return units.get(0).getProperties();
981 StringBuilder builder = new StringBuilder();
982 builder.append("No name provided and multiple persistence units found: ");
983 Iterator<ParsedPersistenceXmlDescriptor> it = units.iterator();
984 builder.append(it.next().getName());
987 builder.append(", ");
988 builder.append(it.next().getName());
991 throw new MojoFailureException(builder.toString());
995 for (ParsedPersistenceXmlDescriptor unit : units)
997 getLog().debug("Found persistence-unit " + unit.getName());
998 if (!unit.getName().equals(persistenceUnit))
1001 // See if we (Hibernate) are the persistence provider
1002 if (!ProviderChecker.isProvider(unit, properties))
1004 getLog().debug("Wrong provider: " + unit.getProviderClassName());
1008 getLog().info("Using persistence-unit " + unit.getName());
1009 return unit.getProperties();
1012 throw new MojoFailureException("Could not find persistence-unit " + persistenceUnit);