X-Git-Url: https://juplo.de/gitweb/?a=blobdiff_plain;f=dist%2Fhibernate-maven-plugin-2.0.0%2Fxref%2Fde%2Fjuplo%2Fplugins%2Fhibernate%2FAbstractSchemaMojo.html;fp=dist%2Fhibernate-maven-plugin-2.0.0%2Fxref%2Fde%2Fjuplo%2Fplugins%2Fhibernate%2FAbstractSchemaMojo.html;h=16fa7a9e710331e959c3b34a8a2724d35266c4f4;hb=a53595184bd6e57bdc45292cc92c393c4e2dfe6e;hp=0000000000000000000000000000000000000000;hpb=c48c9ee0e9faa89a4c0a5323b367b9f5a6abe602;p=website diff --git a/dist/hibernate-maven-plugin-2.0.0/xref/de/juplo/plugins/hibernate/AbstractSchemaMojo.html b/dist/hibernate-maven-plugin-2.0.0/xref/de/juplo/plugins/hibernate/AbstractSchemaMojo.html new file mode 100644 index 00000000..16fa7a9e --- /dev/null +++ b/dist/hibernate-maven-plugin-2.0.0/xref/de/juplo/plugins/hibernate/AbstractSchemaMojo.html @@ -0,0 +1,1191 @@ + + + +AbstractSchemaMojo xref + + + +
View Javadoc
+1   package de.juplo.plugins.hibernate;
+2   
+3   
+4   import com.pyx4j.log4j.MavenLogAppender;
+5   import java.io.File;
+6   import java.io.FileInputStream;
+7   import java.io.IOException;
+8   import java.io.InputStream;
+9   import java.net.MalformedURLException;
+10  import java.net.URL;
+11  import java.security.NoSuchAlgorithmException;
+12  import java.util.Collections;
+13  import java.util.HashSet;
+14  import java.util.Iterator;
+15  import java.util.LinkedHashSet;
+16  import java.util.List;
+17  import java.util.Map;
+18  import java.util.Map.Entry;
+19  import java.util.Properties;
+20  import java.util.Set;
+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.cfgxml.spi.LoadedConfig;
+37  import org.hibernate.boot.cfgxml.spi.MappingReference;
+38  import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
+39  import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
+40  import org.hibernate.boot.registry.BootstrapServiceRegistry;
+41  import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
+42  import org.hibernate.boot.registry.StandardServiceRegistry;
+43  import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
+44  import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
+45  import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
+46  import org.hibernate.boot.registry.selector.spi.StrategySelector;
+47  import org.hibernate.boot.spi.MetadataImplementor;
+48  import static org.hibernate.cfg.AvailableSettings.DIALECT;
+49  import static org.hibernate.cfg.AvailableSettings.DRIVER;
+50  import static org.hibernate.cfg.AvailableSettings.FORMAT_SQL;
+51  import static org.hibernate.cfg.AvailableSettings.HBM2DLL_CREATE_NAMESPACES;
+52  import static org.hibernate.cfg.AvailableSettings.IMPLICIT_NAMING_STRATEGY;
+53  import static org.hibernate.cfg.AvailableSettings.PASS;
+54  import static org.hibernate.cfg.AvailableSettings.PHYSICAL_NAMING_STRATEGY;
+55  import static org.hibernate.cfg.AvailableSettings.SHOW_SQL;
+56  import static org.hibernate.cfg.AvailableSettings.USER;
+57  import static org.hibernate.cfg.AvailableSettings.URL;
+58  import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
+59  import org.hibernate.internal.util.config.ConfigurationException;
+60  import static org.hibernate.jpa.AvailableSettings.JDBC_DRIVER;
+61  import static org.hibernate.jpa.AvailableSettings.JDBC_PASSWORD;
+62  import static org.hibernate.jpa.AvailableSettings.JDBC_URL;
+63  import static org.hibernate.jpa.AvailableSettings.JDBC_USER;
+64  import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
+65  import org.hibernate.jpa.boot.internal.PersistenceXmlParser;
+66  import org.hibernate.jpa.boot.spi.ProviderChecker;
+67  import org.scannotation.AnnotationDB;
+68  
+69  
+70  /**
+71   * Baseclass with common attributes and methods.
+72   *
+73   * @phase process-classes
+74   * @threadSafe
+75   * @requiresDependencyResolution runtime
+76   */
+77  public abstract class AbstractSchemaMojo extends AbstractMojo
+78  {
+79    public final static String EXPORT = "hibernate.schema.export";
+80    public final static String DELIMITER = "hibernate.schema.delimiter";
+81    public final static String OUTPUTDIRECTORY = "project.build.outputDirectory";
+82    public final static String SCAN_CLASSES = "hibernate.schema.scan.classes";
+83    public final static String SCAN_DEPENDENCIES = "hibernate.schema.scan.dependencies";
+84    public final static String SCAN_TESTCLASSES = "hibernate.schema.scan.test_classes";
+85    public final static String TEST_OUTPUTDIRECTORY = "project.build.testOutputDirectory";
+86    public final static String SKIPPED = "hibernate.schema.skipped";
+87  
+88    private final static Pattern SPLIT = Pattern.compile("[^,\\s]+");
+89  
+90    private final Set<String> packages = new HashSet<String>();
+91  
+92    /**
+93     * The maven project.
+94     * <p>
+95     * Only needed internally.
+96     *
+97     * @parameter property="project"
+98     * @required
+99     * @readonly
+100    */
+101   private MavenProject project;
+102 
+103   /**
+104    * Build-directory.
+105    * <p>
+106    * Only needed internally.
+107    *
+108    * @parameter property="project.build.directory"
+109    * @required
+110    * @readonly
+111    */
+112   String buildDirectory;
+113 
+114 
+115   /** Parameters to configure the genaration of the SQL *********************/
+116 
+117   /**
+118    * Export the database-schma to the database.
+119    * If set to <code>false</code>, only the SQL-script is created and the
+120    * database is not touched.
+121    * <p>
+122    * <strong>Important:</strong>
+123    * This configuration value can only be configured through the
+124    * <code>pom.xml</code>, or by the definition of a system-property, because
+125    * it is not known by Hibernate nor JPA and, hence, not picked up from
+126    * their configuration!
+127    *
+128    * @parameter property="hibernate.schema.export" default-value="true"
+129    * @since 2.0
+130    */
+131   Boolean export;
+132 
+133   /**
+134    * Skip execution
+135    * <p>
+136    * If set to <code>true</code>, the execution is skipped.
+137    * <p>
+138    * A skipped execution is signaled via the maven-property
+139    * <code>${hibernate.schema.skipped}</code>.
+140    * <p>
+141    * The execution is skipped automatically, if no modified or newly added
+142    * annotated classes are found and the dialect was not changed.
+143    * <p>
+144    * <strong>Important:</strong>
+145    * This configuration value can only be configured through the
+146    * <code>pom.xml</code>, or by the definition of a system-property, because
+147    * it is not known by Hibernate nor JPA and, hence, not picked up from
+148    * their configuration!
+149    *
+150    * @parameter property="hibernate.schema.skip" default-value="${maven.test.skip}"
+151    * @since 1.0
+152    */
+153   private boolean skip;
+154 
+155   /**
+156    * Force execution
+157    * <p>
+158    * Force execution, even if no modified or newly added annotated classes
+159    * where found and the dialect was not changed.
+160    * <p>
+161    * <code>skip</code> takes precedence over <code>force</code>.
+162    * <p>
+163    * <strong>Important:</strong>
+164    * This configuration value can only be configured through the
+165    * <code>pom.xml</code>, or by the definition of a system-property, because
+166    * it is not known by Hibernate nor JPA and, hence, not picked up from
+167    * their configuration!
+168    *
+169    * @parameter property="hibernate.schema.force" default-value="false"
+170    * @since 1.0
+171    */
+172   private boolean force;
+173 
+174   /**
+175    * Hibernate dialect.
+176    *
+177    * @parameter property="hibernate.dialect"
+178    * @since 1.0
+179    */
+180   private String dialect;
+181 
+182   /**
+183    * Delimiter in output-file.
+184    * <p>
+185    * <strong>Important:</strong>
+186    * This configuration value can only be configured through the
+187    * <code>pom.xml</code>, or by the definition of a system-property, because
+188    * it is not known by Hibernate nor JPA and, hence, not picked up from
+189    * their configuration!
+190    *
+191    * @parameter property="hibernate.schema.delimiter" default-value=";"
+192    * @since 1.0
+193    */
+194   String delimiter;
+195 
+196   /**
+197    * Show the generated SQL in the command-line output.
+198    *
+199    * @parameter property="hibernate.show_sql"
+200    * @since 1.0
+201    */
+202   Boolean show;
+203 
+204   /**
+205    * Format output-file.
+206    *
+207    * @parameter property="hibernate.format_sql"
+208    * @since 1.0
+209    */
+210   Boolean format;
+211 
+212   /**
+213    * Specifies whether to automatically create also the database schema/catalog.
+214    *
+215    * @parameter property="hibernate.hbm2dll.create_namespaces" default-value="false"
+216    * @since 2.0
+217    */
+218   Boolean createNamespaces;
+219 
+220   /**
+221    * Implicit naming strategy
+222    *
+223    * @parameter property="hibernate.implicit_naming_strategy"
+224    * @since 2.0
+225    */
+226   private String implicitNamingStrategy;
+227 
+228   /**
+229    * Physical naming strategy
+230    *
+231    * @parameter property="hibernate.physical_naming_strategy"
+232    * @since 2.0
+233    */
+234   private String physicalNamingStrategy;
+235 
+236   /**
+237    * Wether the project should be scanned for annotated-classes, or not
+238    * <p>
+239    * This parameter is intended to allow overwriting of the parameter
+240    * <code>exclude-unlisted-classes</code> of a <code>persistence-unit</code>.
+241    * If not specified, it defaults to <code>true</code>
+242    *
+243    * @parameter property="hibernate.schema.scan.classes"
+244    * @since 2.0
+245    */
+246   private Boolean scanClasses;
+247 
+248   /**
+249    * Classes-Directory to scan.
+250    * <p>
+251    * This parameter defaults to the maven build-output-directory for classes.
+252    * Additionally, all dependencies are scanned for annotated classes.
+253    * <p>
+254    * <strong>Important:</strong>
+255    * This configuration value can only be configured through the
+256    * <code>pom.xml</code>, or by the definition of a system-property, because
+257    * it is not known by Hibernate nor JPA and, hence, not picked up from
+258    * their configuration!
+259    *
+260    * @parameter property="project.build.outputDirectory"
+261    * @since 1.0
+262    */
+263   private String outputDirectory;
+264 
+265   /**
+266    * Dependency-Scopes, that should be scanned for annotated classes.
+267    * <p>
+268    * By default, only dependencies in the scope <code>compile</code> are
+269    * scanned for annotated classes. Multiple scopes can be seperated by
+270    * white space or commas.
+271    * <p>
+272    * If you do not want any dependencies to be scanned for annotated
+273    * classes, set this parameter to <code>none</code>.
+274    * <p>
+275    * The plugin does not scan for annotated classes in transitive
+276    * dependencies. If some of your annotated classes are hidden in a
+277    * transitive dependency, you can simply add that dependency explicitly.
+278    *
+279    * @parameter property="hibernate.schema.scan.dependencies" default-value="compile"
+280    * @since 1.0.3
+281    */
+282   private String scanDependencies;
+283 
+284   /**
+285    * Whether to scan the test-branch of the project for annotated classes, or
+286    * not.
+287    * <p>
+288    * If this parameter is set to <code>true</code> the test-classes of the
+289    * artifact will be scanned for hibernate-annotated classes additionally.
+290    * <p>
+291    * <strong>Important:</strong>
+292    * This configuration value can only be configured through the
+293    * <code>pom.xml</code>, or by the definition of a system-property, because
+294    * it is not known by Hibernate nor JPA and, hence, not picked up from
+295    * their configuration!
+296    *
+297    * @parameter property="hibernate.schema.scan.test_classes" default-value="false"
+298    * @since 1.0.1
+299    */
+300   private Boolean scanTestClasses;
+301 
+302   /**
+303    * Test-Classes-Directory to scan.
+304    * <p>
+305    * This parameter defaults to the maven build-output-directory for
+306    * test-classes.
+307    * <p>
+308    * This parameter is only used, when <code>scanTestClasses</code> is set
+309    * to <code>true</code>!
+310    * <p>
+311    * <strong>Important:</strong>
+312    * This configuration value can only be configured through the
+313    * <code>pom.xml</code>, or by the definition of a system-property, because
+314    * it is not known by Hibernate nor JPA and, hence, not picked up from
+315    * their configuration!
+316    *
+317    * @parameter property="project.build.testOutputDirectory"
+318    * @since 1.0.2
+319    */
+320   private String testOutputDirectory;
+321 
+322 
+323   /** Conection parameters *************************************************/
+324 
+325   /**
+326    * SQL-Driver name.
+327    *
+328    * @parameter property="hibernate.connection.driver_class"
+329    * @since 1.0
+330    */
+331   private String driver;
+332 
+333   /**
+334    * Database URL.
+335    *
+336    * @parameter property="hibernate.connection.url"
+337    * @since 1.0
+338    */
+339   private String url;
+340 
+341   /**
+342    * Database username
+343    *
+344    * @parameter property="hibernate.connection.username"
+345    * @since 1.0
+346    */
+347   private String username;
+348 
+349   /**
+350    * Database password
+351    *
+352    * @parameter property="hibernate.connection.password"
+353    * @since 1.0
+354    */
+355   private String password;
+356 
+357 
+358   /** Parameters to locate configuration sources ****************************/
+359 
+360   /**
+361    * Path to a file or name of a ressource with hibernate properties.
+362    * If this parameter is specified, the plugin will try to load configuration
+363    * values from a file with the given path or a ressource on the classpath with
+364    * the given name. If both fails, the execution of the plugin will fail.
+365    * <p>
+366    * If this parameter is not set the plugin will load configuration values
+367    * from a ressource named <code>hibernate.properties</code> on the classpath,
+368    * if it is present, but will not fail if there is no such ressource.
+369    * <p>
+370    * During ressource-lookup, the test-classpath takes precedence.
+371    *
+372    * @parameter
+373    * @since 1.0
+374    */
+375   private String hibernateProperties;
+376 
+377   /**
+378    * Path to Hibernate configuration file (.cfg.xml).
+379    * If this parameter is specified, the plugin will try to load configuration
+380    * values from a file with the given path or a ressource on the classpath with
+381    * the given name. If both fails, the execution of the plugin will fail.
+382    * <p>
+383    * If this parameter is not set the plugin will load configuration values
+384    * from a ressource named <code>hibernate.cfg.xml</code> on the classpath,
+385    * if it is present, but will not fail if there is no such ressource.
+386    * <p>
+387    * During ressource-lookup, the test-classpath takes precedence.
+388    * <p>
+389    * Settings in this file will overwrite settings in the properties file.
+390    *
+391    * @parameter
+392    * @since 1.1.0
+393    */
+394   private String hibernateConfig;
+395 
+396   /**
+397    * Name of the persistence-unit.
+398    * If this parameter is specified, the plugin will try to load configuration
+399    * values from a persistence-unit with the specified name. If no such
+400    * persistence-unit can be found, the plugin will throw an exception.
+401    * <p>
+402    * If this parameter is not set and there is only one persistence-unit
+403    * available, that unit will be used automatically. But if this parameter is
+404    * not set and there are multiple persistence-units available on,
+405    * the class-path, the execution of the plugin will fail.
+406    * <p>
+407    * Settings in this file will overwrite settings in the properties or the
+408    * configuration file.
+409    *
+410    * @parameter
+411    * @since 1.1.0
+412    */
+413   private String persistenceUnit;
+414 
+415   /**
+416    * List of Hibernate-Mapping-Files (XML).
+417    * Multiple files can be separated with white-spaces and/or commas.
+418    *
+419    * @parameter property="hibernate.mapping"
+420    * @since 1.0.2
+421    */
+422   private String mappings;
+423 
+424 
+425 
+426   public final void execute(String filename)
+427     throws
+428       MojoFailureException,
+429       MojoExecutionException
+430   {
+431     if (skip)
+432     {
+433       getLog().info("Execution of hibernate-maven-plugin was skipped!");
+434       project.getProperties().setProperty(SKIPPED, "true");
+435       return;
+436     }
+437 
+438     ModificationTracker tracker;
+439     try
+440     {
+441       tracker = new ModificationTracker(buildDirectory, filename, getLog());
+442     }
+443     catch (NoSuchAlgorithmException e)
+444     {
+445       throw new MojoFailureException("Digest-Algorithm MD5 is missing!", e);
+446     }
+447 
+448     SimpleConnectionProvider connectionProvider =
+449         new SimpleConnectionProvider(getLog());
+450 
+451     try
+452     {
+453       /** Start extended logging */
+454       MavenLogAppender.startPluginLog(this);
+455 
+456       /** Load checksums for old mapping and configuration */
+457       tracker.load();
+458 
+459       /** Create the ClassLoader */
+460       MutableClassLoader classLoader = createClassLoader();
+461 
+462       /** Create a BootstrapServiceRegistry with the created ClassLoader */
+463       BootstrapServiceRegistry bootstrapServiceRegitry =
+464           new BootstrapServiceRegistryBuilder()
+465               .applyClassLoader(classLoader)
+466               .build();
+467       ClassLoaderService classLoaderService =
+468           bootstrapServiceRegitry.getService(ClassLoaderService.class);
+469 
+470       Properties properties = new Properties();
+471       ConfigLoader configLoader = new ConfigLoader(bootstrapServiceRegitry);
+472 
+473       /** Loading and merging configuration */
+474       properties.putAll(loadProperties(configLoader));
+475       LoadedConfig config = loadConfig(configLoader);
+476       if (config != null)
+477         properties.putAll(config.getConfigurationValues());
+478       ParsedPersistenceXmlDescriptor unit =
+479           loadPersistenceUnit(classLoaderService, properties);
+480       if (unit != null)
+481         properties.putAll(unit.getProperties());
+482 
+483       /** Overwriting/Completing configuration */
+484       configure(properties, tracker);
+485 
+486       /** Check configuration for modifications */
+487       if(tracker.track(properties))
+488         getLog().debug("Configuration has changed.");
+489       else
+490         getLog().debug("Configuration unchanged.");
+491 
+492       /** Configure Hibernate */
+493       StandardServiceRegistry serviceRegistry =
+494           new StandardServiceRegistryBuilder(bootstrapServiceRegitry)
+495               .applySettings(properties)
+496               .addService(ConnectionProvider.class, connectionProvider)
+497               .build();
+498       MetadataSources sources = new MetadataSources(serviceRegistry);
+499 
+500       /** Add the remaining class-path-elements */
+501       completeClassPath(classLoader);
+502 
+503       /** Apply mappings from hibernate-configuration, if present */
+504       if (config != null)
+505       {
+506         for (MappingReference mapping : config.getMappingReferences())
+507           mapping.apply(sources);
+508       }
+509 
+510       Set<String> classes;
+511       if (unit == null)
+512       {
+513         /** No persistent unit: default behaviour */
+514         if (scanClasses == null)
+515           scanClasses = true;
+516         Set<URL> urls = new HashSet<URL>();
+517         if (scanClasses)
+518           addRoot(urls, outputDirectory);
+519         if (scanTestClasses)
+520           addRoot(urls, testOutputDirectory);
+521         addDependencies(urls);
+522         classes = scanUrls(urls);
+523       }
+524       else
+525       {
+526         /** Follow configuration in persisten unit */
+527         if (scanClasses == null)
+528           scanClasses = !unit.isExcludeUnlistedClasses();
+529         Set<URL> urls = new HashSet<URL>();
+530         if (scanClasses)
+531         {
+532           /**
+533            * Scan the root of the persiten unit and configured jars for
+534            * annotated classes
+535            */
+536           urls.add(unit.getPersistenceUnitRootUrl());
+537           for (URL url : unit.getJarFileUrls())
+538             urls.add(url);
+539         }
+540         if (scanTestClasses)
+541           addRoot(urls, testOutputDirectory);
+542         classes = scanUrls(urls);
+543         for (String className : unit.getManagedClassNames())
+544           classes.add(className);
+545         /**
+546          * Add mappings from the default mapping-file
+547          * <code>META-INF/orm.xml</code>, if present
+548          */
+549         try
+550         {
+551           InputStream is = classLoader.getResourceAsStream("META-INF/orm.xml");
+552           if (is != null)
+553           {
+554             getLog().info("Adding default JPA-XML-mapping from META-INF/orm.xml");
+555             tracker.track("META-INF/orm.xml", is);
+556             sources.addResource("META-INF/orm.xml");
+557           }
+558           /**
+559            * Add mappings from files, that are explicitly configured in the
+560            * persistence unit
+561            */
+562           for (String mapping : unit.getMappingFileNames())
+563           {
+564             getLog().info("Adding explicitly configured mapping from " + mapping);
+565             tracker.track(mapping, classLoader.getResourceAsStream(mapping));
+566             sources.addResource(mapping);
+567           }
+568         }
+569         catch (IOException e)
+570         {
+571           throw new MojoFailureException("Error reading XML-mappings", e);
+572         }
+573       }
+574 
+575       /** Add the configured/collected annotated classes */
+576       for (String className : classes)
+577         addAnnotated(className, sources, classLoaderService, tracker);
+578 
+579       /** Add explicitly configured classes */
+580       addMappings(sources, tracker);
+581 
+582       /** Skip execution, if mapping and configuration is unchanged */
+583       if (!tracker.modified())
+584       {
+585         getLog().info(
+586             "Mapping and configuration unchanged."
+587             );
+588         if (force)
+589           getLog().info("Schema generation is forced!");
+590         else
+591         {
+592           getLog().info("Skipping schema generation!");
+593           project.getProperties().setProperty(SKIPPED, "true");
+594           return;
+595         }
+596       }
+597 
+598 
+599       /** Create a connection, if sufficient configuration infromation is available */
+600       connectionProvider.open(classLoaderService, properties);
+601 
+602       MetadataBuilder metadataBuilder = sources.getMetadataBuilder();
+603 
+604       StrategySelector strategySelector =
+605           serviceRegistry.getService(StrategySelector.class);
+606 
+607       if (properties.containsKey(IMPLICIT_NAMING_STRATEGY))
+608       {
+609         metadataBuilder.applyImplicitNamingStrategy(
+610             strategySelector.resolveStrategy(
+611                 ImplicitNamingStrategy.class,
+612                 properties.getProperty(IMPLICIT_NAMING_STRATEGY)
+613                 )
+614             );
+615       }
+616 
+617       if (properties.containsKey(PHYSICAL_NAMING_STRATEGY))
+618       {
+619         metadataBuilder.applyPhysicalNamingStrategy(
+620             strategySelector.resolveStrategy(
+621                 PhysicalNamingStrategy.class,
+622                 properties.getProperty(PHYSICAL_NAMING_STRATEGY)
+623                 )
+624             );
+625       }
+626 
+627       /**
+628        * Change class-loader of current thread.
+629        * This is necessary, because still not all parts of Hibernate 5 use
+630        * the newly introduced ClassLoaderService and will fail otherwise!
+631        */
+632       Thread thread = Thread.currentThread();
+633       ClassLoader contextClassLoader = thread.getContextClassLoader();
+634       try
+635       {
+636         thread.setContextClassLoader(classLoader);
+637         build((MetadataImplementor)metadataBuilder.build());
+638       }
+639       finally
+640       {
+641         thread.setContextClassLoader(contextClassLoader);
+642       }
+643     }
+644     catch (MojoExecutionException e)
+645     {
+646       tracker.failed();
+647       throw e;
+648     }
+649     catch (MojoFailureException e)
+650     {
+651       tracker.failed();
+652       throw e;
+653     }
+654     catch (RuntimeException e)
+655     {
+656       tracker.failed();
+657       throw e;
+658     }
+659     finally
+660     {
+661       /** Remember mappings and configuration */
+662       tracker.save();
+663 
+664       /** Close the connection - if one was opened */
+665       connectionProvider.close();
+666 
+667       /** Stop Log-Capturing */
+668       MavenLogAppender.endPluginLog(this);
+669     }
+670   }
+671 
+672 
+673   abstract void build(MetadataImplementor metadata)
+674     throws
+675       MojoFailureException,
+676       MojoExecutionException;
+677 
+678 
+679   private MutableClassLoader createClassLoader() throws MojoExecutionException
+680   {
+681     try
+682     {
+683       getLog().debug("Creating ClassLoader for project-dependencies...");
+684       LinkedHashSet<URL> urls = new LinkedHashSet<URL>();
+685       File file;
+686 
+687       file = new File(testOutputDirectory);
+688       if (!file.exists())
+689       {
+690         getLog().info("Creating test-output-directory: " + testOutputDirectory);
+691         file.mkdirs();
+692       }
+693       urls.add(file.toURI().toURL());
+694 
+695       file = new File(outputDirectory);
+696       if (!file.exists())
+697       {
+698         getLog().info("Creating output-directory: " + outputDirectory);
+699         file.mkdirs();
+700       }
+701       urls.add(file.toURI().toURL());
+702 
+703       return new MutableClassLoader(urls, getLog());
+704     }
+705     catch (Exception e)
+706     {
+707       getLog().error("Error while creating ClassLoader!", e);
+708       throw new MojoExecutionException(e.getMessage());
+709     }
+710   }
+711 
+712   private void completeClassPath(MutableClassLoader classLoader)
+713       throws
+714         MojoExecutionException
+715   {
+716     try
+717     {
+718       getLog().debug("Completing class-paths of the ClassLoader for project-dependencies...");
+719       List<String> classpathFiles = project.getCompileClasspathElements();
+720       if (scanTestClasses)
+721         classpathFiles.addAll(project.getTestClasspathElements());
+722       LinkedHashSet<URL> urls = new LinkedHashSet<URL>();
+723       for (String pathElement : classpathFiles)
+724       {
+725         getLog().debug("Dependency: " + pathElement);
+726         urls.add(new File(pathElement).toURI().toURL());
+727       }
+728       classLoader.add(urls);
+729     }
+730     catch (Exception e)
+731     {
+732       getLog().error("Error while creating ClassLoader!", e);
+733       throw new MojoExecutionException(e.getMessage());
+734     }
+735   }
+736 
+737   private Map loadProperties(ConfigLoader configLoader)
+738       throws
+739         MojoExecutionException
+740   {
+741     /** Try to read configuration from properties-file */
+742     if (hibernateProperties == null)
+743     {
+744       try
+745       {
+746         return configLoader.loadProperties("hibernate.properties");
+747       }
+748       catch (ConfigurationException e)
+749       {
+750         getLog().debug(e.getMessage());
+751         return Collections.EMPTY_MAP;
+752       }
+753     }
+754     else
+755     {
+756       try
+757       {
+758         File file = new File(hibernateProperties);
+759         if (file.exists())
+760         {
+761           getLog().info("Reading settings from file " + hibernateProperties + "...");
+762           return configLoader.loadProperties(file);
+763         }
+764         else
+765           return configLoader.loadProperties(hibernateProperties);
+766       }
+767       catch (ConfigurationException e)
+768       {
+769         getLog().error("Error while reading properties!", e);
+770         throw new MojoExecutionException(e.getMessage());
+771       }
+772     }
+773   }
+774 
+775   private LoadedConfig loadConfig(ConfigLoader configLoader)
+776       throws MojoExecutionException
+777   {
+778     /** Try to read configuration from configuration-file */
+779     if (hibernateConfig == null)
+780     {
+781       try
+782       {
+783         return configLoader.loadConfigXmlResource("hibernate.cfg.xml");
+784       }
+785       catch (ConfigurationException e)
+786       {
+787         getLog().debug(e.getMessage());
+788         return null;
+789       }
+790     }
+791     else
+792     {
+793       try
+794       {
+795         File file = new File(hibernateConfig);
+796         if (file.exists())
+797         {
+798           getLog().info("Reading configuration from file " + hibernateConfig + "...");
+799           return configLoader.loadConfigXmlFile(file);
+800         }
+801         else
+802         {
+803           return configLoader.loadConfigXmlResource(hibernateConfig);
+804         }
+805       }
+806       catch (ConfigurationException e)
+807       {
+808         getLog().error("Error while reading configuration!", e);
+809         throw new MojoExecutionException(e.getMessage());
+810       }
+811     }
+812   }
+813 
+814   private void configure(Properties properties, ModificationTracker tracker)
+815       throws MojoFailureException
+816   {
+817     /**
+818      * Special treatment for the configuration-value "export": if it is
+819      * switched to "true", the genearation fo the schema should be forced!
+820      */
+821     if (tracker.check(EXPORT, export.toString()) && export)
+822       tracker.touch();
+823 
+824     /**
+825      * Configure the generation of the SQL.
+826      * Overwrite values from properties-file if the configuration parameter is
+827      * known to Hibernate.
+828      */
+829     dialect = configure(properties, dialect, DIALECT);
+830     tracker.track(DELIMITER, delimiter); // << not reflected in hibernate configuration!
+831     format = configure(properties, format, FORMAT_SQL);
+832     createNamespaces = configure(properties, createNamespaces, HBM2DLL_CREATE_NAMESPACES);
+833     implicitNamingStrategy = configure(properties, implicitNamingStrategy, IMPLICIT_NAMING_STRATEGY);
+834     physicalNamingStrategy = configure(properties, physicalNamingStrategy, PHYSICAL_NAMING_STRATEGY);
+835     tracker.track(OUTPUTDIRECTORY, outputDirectory); // << not reflected in hibernate configuration!
+836     tracker.track(SCAN_DEPENDENCIES, scanDependencies); // << not reflected in hibernate configuration!
+837     tracker.track(SCAN_TESTCLASSES, scanTestClasses.toString()); // << not reflected in hibernate configuration!
+838     tracker.track(TEST_OUTPUTDIRECTORY, testOutputDirectory); // << not reflected in hibernate configuration!
+839 
+840     /**
+841      * Special treatment for the configuration-value "show": a change of its
+842      * configured value should not lead to a regeneration of the database
+843      * schama!
+844      */
+845     if (show == null)
+846       show = Boolean.valueOf(properties.getProperty(SHOW_SQL));
+847     else
+848       properties.setProperty(SHOW_SQL, show.toString());
+849 
+850     /**
+851      * Configure the connection parameters.
+852      * Overwrite values from properties-file.
+853      */
+854     driver = configure(properties, driver, DRIVER, JDBC_DRIVER);
+855     url = configure(properties, url, URL, JDBC_URL);
+856     username = configure(properties, username, USER, JDBC_USER);
+857     password = configure(properties, password, PASS, JDBC_PASSWORD);
+858 
+859     if (properties.isEmpty())
+860     {
+861       getLog().error("No properties set!");
+862       throw new MojoFailureException("Hibernate configuration is missing!");
+863     }
+864 
+865     getLog().info("Gathered hibernate-configuration (turn on debugging for details):");
+866     for (Entry<Object,Object> entry : properties.entrySet())
+867       getLog().info("  " + entry.getKey() + " = " + entry.getValue());
+868   }
+869 
+870   private String configure(
+871       Properties properties,
+872       String value,
+873       String key,
+874       String alternativeKey
+875       )
+876   {
+877     value = configure(properties, value, key);
+878     if (value == null)
+879       return properties.getProperty(alternativeKey);
+880 
+881     if (properties.containsKey(alternativeKey))
+882     {
+883       getLog().warn(
+884           "Ignoring property " + alternativeKey + "=" +
+885           properties.getProperty(alternativeKey) + " in favour for property " +
+886           key + "=" + properties.getProperty(key)
+887           );
+888       properties.remove(alternativeKey);
+889     }
+890     return properties.getProperty(alternativeKey);
+891   }
+892 
+893   private String configure(Properties properties, String value, String key)
+894   {
+895     if (value != null)
+896     {
+897       if (properties.containsKey(key))
+898         getLog().debug(
+899             "Overwriting property " + key + "=" + properties.getProperty(key) +
+900             " with the value " + value
+901             );
+902       else
+903         getLog().debug("Using the value " + value + " for property " + key);
+904       properties.setProperty(key, value);
+905     }
+906     return properties.getProperty(key);
+907   }
+908 
+909   private boolean configure(Properties properties, Boolean value, String key)
+910   {
+911     if (value != null)
+912     {
+913       if (properties.containsKey(key))
+914         getLog().debug(
+915             "Overwriting property " + key + "=" + properties.getProperty(key) +
+916             " with the value " + value
+917             );
+918       else
+919         getLog().debug("Using the value " + value + " for property " + key);
+920       properties.setProperty(key, value.toString());
+921     }
+922     return Boolean.valueOf(properties.getProperty(key));
+923   }
+924 
+925   private void addMappings(MetadataSources sources, ModificationTracker tracker)
+926       throws MojoFailureException
+927   {
+928     getLog().debug("Adding explicitly configured mappings...");
+929     if (mappings != null)
+930     {
+931       try
+932       {
+933         for (String filename : mappings.split("[\\s,]+"))
+934         {
+935           // First try the filename as absolute/relative path
+936           File file = new File(filename);
+937           if (!file.exists())
+938           {
+939             // If the file was not found, search for it in the resource-directories
+940             for (Resource resource : project.getResources())
+941             {
+942               file = new File(resource.getDirectory() + File.separator + filename);
+943               if (file.exists())
+944                 break;
+945             }
+946           }
+947           if (file.exists())
+948           {
+949             if (file.isDirectory())
+950               // TODO: add support to read all mappings under a directory
+951               throw new MojoFailureException(file.getAbsolutePath() + " is a directory");
+952             if (tracker.track(filename, new FileInputStream(file)))
+953               getLog().debug("Found new or modified mapping-file: " + filename);
+954             else
+955               getLog().debug("Mapping-file unchanged: " + filename);
+956 
+957             sources.addFile(file);
+958           }
+959           else
+960             throw new MojoFailureException("File " + filename + " could not be found in any of the configured resource-directories!");
+961         }
+962       }
+963       catch (IOException e)
+964       {
+965         throw new MojoFailureException("Cannot calculate MD5 sums!", e);
+966       }
+967     }
+968   }
+969 
+970   private void addRoot(Set<URL> urls, String path) throws MojoFailureException
+971   {
+972     try
+973     {
+974       File dir = new File(outputDirectory);
+975       if (dir.exists())
+976       {
+977         getLog().info("Adding " + dir.getAbsolutePath() + " to the list of roots to scan...");
+978         urls.add(dir.toURI().toURL());
+979       }
+980     }
+981     catch (MalformedURLException e)
+982     {
+983       getLog().error("error while adding the project-root to the list of roots to scan!", e);
+984       throw new MojoFailureException(e.getMessage());
+985     }
+986   }
+987 
+988   private void addDependencies(Set<URL> urls) throws MojoFailureException
+989   {
+990     try
+991     {
+992       if (scanDependencies != null)
+993       {
+994         Matcher matcher = SPLIT.matcher(scanDependencies);
+995         while (matcher.find())
+996         {
+997           getLog().info("Adding dependencies from scope " + matcher.group() + " to the list of roots to scan");
+998           for (Artifact artifact : project.getDependencyArtifacts())
+999           {
+1000             if (!artifact.getScope().equalsIgnoreCase(matcher.group()))
+1001               continue;
+1002             if (artifact.getFile() == null)
+1003             {
+1004               getLog().warn("Cannot add dependency " + artifact.getId() + ": no JAR-file available!");
+1005               continue;
+1006             }
+1007             getLog().info("Adding dependencies from scope " + artifact.getId() + " to the list of roots to scan");
+1008             urls.add(artifact.getFile().toURI().toURL());
+1009           }
+1010         }
+1011       }
+1012     }
+1013     catch (MalformedURLException e)
+1014     {
+1015       getLog().error("Error while adding dependencies to the list of roots to scan!", e);
+1016       throw new MojoFailureException(e.getMessage());
+1017     }
+1018   }
+1019 
+1020   private Set<String> scanUrls(Set<URL> scanRoots)
+1021       throws
+1022         MojoFailureException
+1023   {
+1024     try
+1025     {
+1026       AnnotationDB db = new AnnotationDB();
+1027       for (URL root : scanRoots)
+1028         db.scanArchives(root);
+1029 
+1030       Set<String> classes = new HashSet<String>();
+1031       if (db.getAnnotationIndex().containsKey(Entity.class.getName()))
+1032         classes.addAll(db.getAnnotationIndex().get(Entity.class.getName()));
+1033       if (db.getAnnotationIndex().containsKey(MappedSuperclass.class.getName()))
+1034         classes.addAll(db.getAnnotationIndex().get(MappedSuperclass.class.getName()));
+1035       if (db.getAnnotationIndex().containsKey(Embeddable.class.getName()))
+1036         classes.addAll(db.getAnnotationIndex().get(Embeddable.class.getName()));
+1037 
+1038       return classes;
+1039     }
+1040     catch (Exception e)
+1041     {
+1042       getLog().error("Error while scanning!", e);
+1043       throw new MojoFailureException(e.getMessage());
+1044     }
+1045   }
+1046 
+1047   private void addAnnotated(
+1048       String name,
+1049       MetadataSources sources,
+1050       ClassLoaderService classLoaderService,
+1051       ModificationTracker tracker
+1052       )
+1053       throws
+1054         MojoFailureException,
+1055         MojoExecutionException
+1056   {
+1057     try
+1058     {
+1059       getLog().info("Adding annotated resource: " + name);
+1060       String packageName;
+1061 
+1062       try
+1063       {
+1064         Class<?> annotatedClass = classLoaderService.classForName(name);
+1065         String resourceName = annotatedClass.getName();
+1066         resourceName =
+1067             resourceName.substring(
+1068                 resourceName.lastIndexOf(".") + 1,
+1069                 resourceName.length()
+1070                 ) + ".class";
+1071         InputStream is = annotatedClass.getResourceAsStream(resourceName);
+1072         if (tracker.track(name, is))
+1073           getLog().debug("New or modified class: " + name);
+1074         else
+1075           getLog().debug("Unchanged class: " + name);
+1076         sources.addAnnotatedClass(annotatedClass);
+1077         packageName = annotatedClass.getPackage().getName();
+1078       }
+1079       catch(ClassLoadingException e)
+1080       {
+1081         packageName = name;
+1082       }
+1083 
+1084       while (packageName != null)
+1085       {
+1086         if (packages.contains(packageName))
+1087           return;
+1088         String resource = packageName.replace('.', '/') + "/package-info.class";
+1089         InputStream is = classLoaderService.locateResourceStream(resource);
+1090         if (is == null)
+1091         {
+1092           // No compiled package-info available: no package-level annotations!
+1093           getLog().debug("Package " + packageName + " is not annotated.");
+1094         }
+1095         else
+1096         {
+1097           if (tracker.track(packageName, is))
+1098             getLog().debug("New or modified package: " + packageName);
+1099           else
+1100            getLog().debug("Unchanged package: " + packageName);
+1101           getLog().info("Adding annotations from package " + packageName);
+1102           sources.addPackage(packageName);
+1103         }
+1104         packages.add(packageName);
+1105         int i = packageName.lastIndexOf('.');
+1106         if (i < 0)
+1107           packageName = null;
+1108         else
+1109           packageName = packageName.substring(0,i);
+1110       }
+1111     }
+1112     catch (Exception e)
+1113     {
+1114       getLog().error("Error while adding the annotated class " + name, e);
+1115       throw new MojoFailureException(e.getMessage());
+1116     }
+1117   }
+1118 
+1119   private ParsedPersistenceXmlDescriptor loadPersistenceUnit(
+1120       ClassLoaderService classLoaderService,
+1121       Properties properties
+1122       )
+1123       throws
+1124         MojoFailureException
+1125   {
+1126     PersistenceXmlParser parser =
+1127         new PersistenceXmlParser(
+1128             classLoaderService,
+1129             PersistenceUnitTransactionType.RESOURCE_LOCAL
+1130              );
+1131 
+1132     List<ParsedPersistenceXmlDescriptor> units = parser.doResolve(properties);
+1133 
+1134     if (persistenceUnit == null)
+1135     {
+1136       switch (units.size())
+1137       {
+1138         case 0:
+1139           getLog().info("Found no META-INF/persistence.xml.");
+1140           return null;
+1141         case 1:
+1142           getLog().info("Using persistence-unit " + units.get(0).getName());
+1143           return units.get(0);
+1144         default:
+1145           StringBuilder builder = new StringBuilder();
+1146           builder.append("No name provided and multiple persistence units found: ");
+1147           Iterator<ParsedPersistenceXmlDescriptor> it = units.iterator();
+1148           builder.append(it.next().getName());
+1149           while (it.hasNext())
+1150           {
+1151             builder.append(", ");
+1152             builder.append(it.next().getName());
+1153           }
+1154           builder.append('.');
+1155           throw new MojoFailureException(builder.toString());
+1156       }
+1157     }
+1158 
+1159     for (ParsedPersistenceXmlDescriptor unit : units)
+1160     {
+1161       getLog().debug("Found persistence-unit " + unit.getName());
+1162       if (!unit.getName().equals(persistenceUnit))
+1163         continue;
+1164 
+1165       // See if we (Hibernate) are the persistence provider
+1166       if (!ProviderChecker.isProvider(unit, properties))
+1167       {
+1168         getLog().debug("Wrong provider: " + unit.getProviderClassName());
+1169         continue;
+1170       }
+1171 
+1172       getLog().info("Using persistence-unit " + unit.getName());
+1173       return unit;
+1174     }
+1175 
+1176     throw new MojoFailureException("Could not find persistence-unit " + persistenceUnit);
+1177   }
+1178 }
+
+
+ + +