X-Git-Url: https://juplo.de/gitweb/?p=website;a=blobdiff_plain;f=dist%2Fhibernate4-maven-plugin-1.1.0%2Fxref%2Fde%2Fjuplo%2Fplugins%2Fhibernate4%2FHbm2DdlMojo.html;fp=dist%2Fhibernate4-maven-plugin-1.1.0%2Fxref%2Fde%2Fjuplo%2Fplugins%2Fhibernate4%2FHbm2DdlMojo.html;h=7f39b0f0b3e4e2aa9fcd28cbb8812cc6565d6a4f;hp=0000000000000000000000000000000000000000;hb=a53595184bd6e57bdc45292cc92c393c4e2dfe6e;hpb=c48c9ee0e9faa89a4c0a5323b367b9f5a6abe602 diff --git a/dist/hibernate4-maven-plugin-1.1.0/xref/de/juplo/plugins/hibernate4/Hbm2DdlMojo.html b/dist/hibernate4-maven-plugin-1.1.0/xref/de/juplo/plugins/hibernate4/Hbm2DdlMojo.html new file mode 100644 index 00000000..7f39b0f0 --- /dev/null +++ b/dist/hibernate4-maven-plugin-1.1.0/xref/de/juplo/plugins/hibernate4/Hbm2DdlMojo.html @@ -0,0 +1,1320 @@ + + + +Hbm2DdlMojo xref + + + +
View Javadoc
+1   package de.juplo.plugins.hibernate4;
+2   
+3   /*
+4    * Copyright 2001-2005 The Apache Software Foundation.
+5    *
+6    * Licensed under the Apache License, Version 2.0 (the "License");
+7    * you may not use this file except in compliance with the License.
+8    * You may obtain a copy of the License at
+9    *
+10   *      http://www.apache.org/licenses/LICENSE-2.0
+11   *
+12   * Unless required by applicable law or agreed to in writing, software
+13   * distributed under the License is distributed on an "AS IS" BASIS,
+14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+15   * See the License for the specific language governing permissions and
+16   * limitations under the License.
+17   */
+18  
+19  import com.pyx4j.log4j.MavenLogAppender;
+20  import java.io.File;
+21  import java.io.FileInputStream;
+22  import java.io.FileNotFoundException;
+23  import java.io.FileOutputStream;
+24  import java.io.IOException;
+25  import java.io.InputStream;
+26  import java.io.ObjectInputStream;
+27  import java.io.ObjectOutputStream;
+28  import java.math.BigInteger;
+29  import java.net.URL;
+30  import java.net.URLClassLoader;
+31  import java.security.MessageDigest;
+32  import java.security.NoSuchAlgorithmException;
+33  import java.sql.Driver;
+34  import java.sql.DriverPropertyInfo;
+35  import java.sql.SQLException;
+36  import java.sql.SQLFeatureNotSupportedException;
+37  import java.util.Collections;
+38  import java.util.Comparator;
+39  import java.util.HashMap;
+40  import java.util.HashSet;
+41  import java.util.LinkedHashSet;
+42  import java.util.LinkedList;
+43  import java.util.List;
+44  import java.util.Map;
+45  import java.util.Map.Entry;
+46  import java.util.Properties;
+47  import java.util.Set;
+48  import java.util.TreeSet;
+49  import java.util.logging.Logger;
+50  import java.util.regex.Matcher;
+51  import java.util.regex.Pattern;
+52  import javax.persistence.Embeddable;
+53  import javax.persistence.Entity;
+54  import javax.persistence.MappedSuperclass;
+55  import javax.persistence.spi.PersistenceUnitTransactionType;
+56  import org.apache.maven.artifact.Artifact;
+57  import org.apache.maven.model.Resource;
+58  import org.apache.maven.plugin.AbstractMojo;
+59  import org.apache.maven.plugin.MojoExecutionException;
+60  import org.apache.maven.plugin.MojoFailureException;
+61  import org.apache.maven.project.MavenProject;
+62  import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
+63  import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
+64  import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
+65  import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
+66  import org.hibernate.cfg.Environment;
+67  import org.hibernate.cfg.NamingStrategy;
+68  import org.hibernate.envers.configuration.spi.AuditConfiguration;
+69  import org.hibernate.internal.util.config.ConfigurationHelper;
+70  import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
+71  import org.hibernate.jpa.boot.internal.PersistenceXmlParser;
+72  import org.hibernate.jpa.boot.spi.ProviderChecker;
+73  import org.hibernate.tool.hbm2ddl.SchemaExport;
+74  import org.hibernate.tool.hbm2ddl.SchemaExport.Type;
+75  import org.hibernate.tool.hbm2ddl.Target;
+76  import org.scannotation.AnnotationDB;
+77  
+78  
+79  /**
+80   * Goal which extracts the hibernate-mapping-configuration and
+81   * exports an according SQL-database-schema.
+82   *
+83   * @goal export
+84   * @phase process-classes
+85   * @threadSafe
+86   * @requiresDependencyResolution runtime
+87   */
+88  public class Hbm2DdlMojo extends AbstractMojo
+89  {
+90    public final static String EXPORT_SKIPPED_PROPERTY = "hibernate.export.skipped";
+91  
+92    public final static String DRIVER_CLASS = "hibernate.connection.driver_class";
+93    public final static String URL = "hibernate.connection.url";
+94    public final static String USERNAME = "hibernate.connection.username";
+95    public final static String PASSWORD = "hibernate.connection.password";
+96    public final static String DIALECT = "hibernate.dialect";
+97    public final static String NAMING_STRATEGY="hibernate.ejb.naming_strategy";
+98    public final static String ENVERS = "hibernate.export.envers";
+99  
+100   public final static String JPA_DRIVER = "javax.persistence.jdbc.driver";
+101   public final static String JPA_URL = "javax.persistence.jdbc.url";
+102   public final static String JPA_USERNAME = "javax.persistence.jdbc.user";
+103   public final static String JPA_PASSWORD = "javax.persistence.jdbc.password";
+104 
+105   public final static String MD5S = "hibernate4-generatedschema.md5s";
+106 
+107   private final static Pattern split = Pattern.compile("[^,\\s]+");
+108 
+109 
+110   /**
+111    * The maven project.
+112    * <p>
+113    * Only needed internally.
+114    *
+115    * @parameter property="project"
+116    * @required
+117    * @readonly
+118    */
+119   private MavenProject project;
+120 
+121   /**
+122    * Build-directory.
+123    * <p>
+124    * Only needed internally.
+125    *
+126    * @parameter property="project.build.directory"
+127    * @required
+128    * @readonly
+129    */
+130   private String buildDirectory;
+131 
+132   /**
+133    * Classes-Directory to scan.
+134    * <p>
+135    * This parameter defaults to the maven build-output-directory for classes.
+136    * Additionally, all dependencies are scanned for annotated classes.
+137    *
+138    * @parameter property="project.build.outputDirectory"
+139    * @since 1.0
+140    */
+141   private String outputDirectory;
+142 
+143   /**
+144    * Whether to scan test-classes too, or not.
+145    * <p>
+146    * If this parameter is set to <code>true</code> the test-classes of the
+147    * artifact will be scanned for hibernate-annotated classes additionally.
+148    *
+149    * @parameter property="hibernate.export.scan_testclasses" default-value="false"
+150    * @since 1.0.1
+151    */
+152   private boolean scanTestClasses;
+153 
+154   /**
+155    * Dependency-Scopes, that should be scanned for annotated classes.
+156    * <p>
+157    * By default, only dependencies in the scope <code>compile</code> are
+158    * scanned for annotated classes. Multiple scopes can be seperated by
+159    * white space or commas.
+160    * <p>
+161    * If you do not want any dependencies to be scanned for annotated
+162    * classes, set this parameter to <code>none</code>.
+163    * <p>
+164    * The plugin does not scan for annotated classes in transitive
+165    * dependencies. If some of your annotated classes are hidden in a
+166    * transitive dependency, you can simply add that dependency explicitly.
+167    *
+168    * @parameter property="hibernate.export.scan_dependencies" default-value="compile"
+169    * @since 1.0.3
+170    */
+171   private String scanDependencies;
+172 
+173   /**
+174    * Test-Classes-Directory to scan.
+175    * <p>
+176    * This parameter defaults to the maven build-output-directory for
+177    * test-classes.
+178    * <p>
+179    * This parameter is only used, when <code>scanTestClasses</code> is set
+180    * to <code>true</code>!
+181    *
+182    * @parameter property="project.build.testOutputDirectory"
+183    * @since 1.0.2
+184    */
+185   private String testOutputDirectory;
+186 
+187   /**
+188    * Skip execution
+189    * <p>
+190    * If set to <code>true</code>, the execution is skipped.
+191    * <p>
+192    * A skipped execution is signaled via the maven-property
+193    * <code>${hibernate.export.skipped}</code>.
+194    * <p>
+195    * The execution is skipped automatically, if no modified or newly added
+196    * annotated classes are found and the dialect was not changed.
+197    *
+198    * @parameter property="hibernate.skip" default-value="${maven.test.skip}"
+199    * @since 1.0
+200    */
+201   private boolean skip;
+202 
+203   /**
+204    * Force execution
+205    * <p>
+206    * Force execution, even if no modified or newly added annotated classes
+207    * where found and the dialect was not changed.
+208    * <p>
+209    * <code>skip</code> takes precedence over <code>force</code>.
+210    *
+211    * @parameter property="hibernate.export.force" default-value="false"
+212    * @since 1.0
+213    */
+214   private boolean force;
+215 
+216   /**
+217    * SQL-Driver name.
+218    *
+219    * @parameter property="hibernate.connection.driver_class"
+220    * @since 1.0
+221    */
+222   private String driverClassName;
+223 
+224   /**
+225    * Database URL.
+226    *
+227    * @parameter property="hibernate.connection.url"
+228    * @since 1.0
+229    */
+230   private String url;
+231 
+232   /**
+233    * Database username
+234    *
+235    * @parameter property="hibernate.connection.username"
+236    * @since 1.0
+237    */
+238   private String username;
+239 
+240   /**
+241    * Database password
+242    *
+243    * @parameter property="hibernate.connection.password"
+244    * @since 1.0
+245    */
+246   private String password;
+247 
+248   /**
+249    * Hibernate dialect.
+250    *
+251    * @parameter property="hibernate.dialect"
+252    * @since 1.0
+253    */
+254   private String hibernateDialect;
+255 
+256   /**
+257    * Hibernate Naming Strategy
+258    *
+259    * @parameter property="hibernate.ejb.naming_strategy"
+260    * @since 1.0.2
+261    */
+262   private String hibernateNamingStrategy;
+263 
+264   /**
+265    * Path to Hibernate properties file.
+266    * If this parameter is not set the plugin will try to load the configuration
+267    * from a file <code>hibernate.properties</code> on the classpath. The
+268    * test-classpath takes precedence.
+269    *
+270    * @parameter
+271    * @since 1.0
+272    */
+273   private String hibernateProperties;
+274 
+275   /**
+276    * Path to Hibernate configuration file (.cfg.xml).
+277    * Settings in this file will overwrite settings in the properties file.
+278    * If this parameter is not set the plugin will try to load the configuration
+279    * from a file <code>hibernate.cfg.xml</code> on the classpath. The
+280    * test-classpath takes precedence.
+281    *
+282    * @parameter
+283    * @since 1.1.0
+284    */
+285   private String hibernateConfig;
+286 
+287   /**
+288    * Name of the persistence-unit.
+289    * If there is only one persistence-unit available, that unit will be used
+290    * automatically.
+291    * Settings in this file will overwrite settings in the properties or the
+292    * configuration file.
+293    *
+294    * @parameter
+295    * @since 1.1.0
+296    */
+297   private String persistenceUnit;
+298 
+299   /**
+300    * List of Hibernate-Mapping-Files (XML).
+301    * Multiple files can be separated with white-spaces and/or commas.
+302    *
+303    * @parameter property="hibernate.mapping"
+304    * @since 1.0.2
+305    */
+306   private String hibernateMapping;
+307 
+308   /**
+309    * Target of execution:
+310    * <ul>
+311    *   <li><strong>NONE</strong> only export schema to SQL-script (forces execution, signals skip)</li>
+312    *   <li><strong>EXPORT</strong> create database (<strong>DEFAULT!</strong>). forces execution, signals skip)</li>
+313    *   <li><strong>SCRIPT</strong> export schema to SQL-script and print it to STDOUT</li>
+314    *   <li><strong>BOTH</strong></li>
+315    * </ul>
+316    *
+317    * A database connection is only needed for EXPORT and BOTH, but a
+318    * Hibernate-Dialect must always be chosen.
+319    *
+320    * @parameter property="hibernate.export.target" default-value="EXPORT"
+321    * @since 1.0
+322    */
+323   private String target;
+324 
+325   /**
+326    * Type of execution.
+327    * <ul>
+328    *   <li><strong>NONE</strong> do nothing - just validate the configuration</li>
+329    *   <li><strong>CREATE</strong> create database-schema</li>
+330    *   <li><strong>DROP</strong> drop database-schema</li>
+331    *   <li><strong>BOTH</strong> (<strong>DEFAULT!</strong>)</li>
+332    * </ul>
+333    *
+334    * If NONE is choosen, no databaseconnection is needed.
+335    *
+336    * @parameter property="hibernate.export.type" default-value="BOTH"
+337    * @since 1.0
+338    */
+339   private String type;
+340 
+341   /**
+342    * Output file.
+343    *
+344    * @parameter property="hibernate.export.schema.filename" default-value="${project.build.directory}/schema.sql"
+345    * @since 1.0
+346    */
+347   private String outputFile;
+348 
+349   /**
+350    * Delimiter in output-file.
+351    *
+352    * @parameter property="hibernate.export.schema.delimiter" default-value=";"
+353    * @since 1.0
+354    */
+355   private String delimiter;
+356 
+357   /**
+358    * Format output-file.
+359    *
+360    * @parameter property="hibernate.export.schema.format" default-value="true"
+361    * @since 1.0
+362    */
+363   private boolean format;
+364 
+365   /**
+366    * Generate envers schema for auditing tables.
+367    *
+368    * @parameter property="hibernate.export.envers" default-value="true"
+369    * @since 1.0.3
+370    */
+371   private boolean envers;
+372 
+373 
+374   @Override
+375   public void execute()
+376     throws
+377       MojoFailureException,
+378       MojoExecutionException
+379   {
+380     if (skip)
+381     {
+382       getLog().info("Execution of hibernate4-maven-plugin:export was skipped!");
+383       project.getProperties().setProperty(EXPORT_SKIPPED_PROPERTY, "true");
+384       return;
+385     }
+386 
+387     Map<String,String> md5s;
+388     boolean modified = false;
+389     File saved = new File(buildDirectory + File.separator + MD5S);
+390 
+391     if (saved.isFile() && saved.length() > 0)
+392     {
+393       try
+394       {
+395         FileInputStream fis = new FileInputStream(saved);
+396         ObjectInputStream ois = new ObjectInputStream(fis);
+397         md5s = (HashMap<String,String>)ois.readObject();
+398         ois.close();
+399       }
+400       catch (Exception e)
+401       {
+402         md5s = new HashMap<String,String>();
+403         getLog().warn("Cannot read timestamps from saved: " + e);
+404       }
+405     }
+406     else
+407     {
+408       md5s = new HashMap<String,String>();
+409       try
+410       {
+411         saved.createNewFile();
+412       }
+413       catch (IOException e)
+414       {
+415         getLog().debug("Cannot create file \"" + saved.getPath() + "\" for timestamps: " + e);
+416       }
+417     }
+418 
+419     URLClassLoader classLoader = null;
+420     try
+421     {
+422       getLog().debug("Creating ClassLoader for project-dependencies...");
+423       List<String> classpathFiles = project.getCompileClasspathElements();
+424       if (scanTestClasses)
+425         classpathFiles.addAll(project.getTestClasspathElements());
+426       List<URL> urls = new LinkedList<URL>();
+427       File file;
+428       file = new File(testOutputDirectory);
+429       if (!file.exists())
+430       {
+431         getLog().info("creating test-output-directory: " + testOutputDirectory);
+432         file.mkdirs();
+433       }
+434       urls.add(file.toURI().toURL());
+435       file = new File(outputDirectory);
+436       if (!file.exists())
+437       {
+438         getLog().info("creating output-directory: " + outputDirectory);
+439         file.mkdirs();
+440       }
+441       urls.add(file.toURI().toURL());
+442       for (String pathElement : classpathFiles)
+443       {
+444         getLog().debug("Dependency: " + pathElement);
+445         urls.add(new File(pathElement).toURI().toURL());
+446       }
+447       classLoader =
+448           new URLClassLoader(
+449               urls.toArray(new URL[urls.size()]),
+450               getClass().getClassLoader()
+451               );
+452     }
+453     catch (Exception e)
+454     {
+455       getLog().error("Error while creating ClassLoader!", e);
+456       throw new MojoExecutionException(e.getMessage());
+457     }
+458 
+459     Set<Class<?>> classes =
+460         new TreeSet<Class<?>>(
+461             new Comparator<Class<?>>() {
+462               @Override
+463               public int compare(Class<?> a, Class<?> b)
+464               {
+465                 return a.getName().compareTo(b.getName());
+466               }
+467             }
+468           );
+469 
+470     try
+471     {
+472       AnnotationDB db = new AnnotationDB();
+473       File dir = new File(outputDirectory);
+474       if (dir.exists())
+475       {
+476         getLog().info("Scanning directory " + outputDirectory + " for annotated classes...");
+477         URL dirUrl = dir.toURI().toURL();
+478         db.scanArchives(dirUrl);
+479       }
+480       if (scanTestClasses)
+481       {
+482         dir = new File(testOutputDirectory);
+483         if (dir.exists())
+484         {
+485           getLog().info("Scanning directory " + testOutputDirectory + " for annotated classes...");
+486           URL dirUrl = dir.toURI().toURL();
+487           db.scanArchives(dirUrl);
+488         }
+489       }
+490       if (scanDependencies != null)
+491       {
+492         Matcher matcher = split.matcher(scanDependencies);
+493         while (matcher.find())
+494         {
+495           getLog().info("Scanning dependencies for scope " + matcher.group());
+496           for (Artifact artifact : project.getDependencyArtifacts())
+497           {
+498             if (!artifact.getScope().equalsIgnoreCase(matcher.group()))
+499               continue;
+500             if (artifact.getFile() == null)
+501             {
+502               getLog().warn(
+503                   "Cannot scan dependency " +
+504                   artifact.getId() +
+505                   ": no JAR-file available!"
+506                   );
+507               continue;
+508             }
+509             getLog().info(
+510                 "Scanning dependency " +
+511                 artifact.getId() +
+512                 " for annotated classes..."
+513                 );
+514             db.scanArchives(artifact.getFile().toURI().toURL());
+515           }
+516         }
+517       }
+518 
+519       Set<String> classNames = new HashSet<String>();
+520       if (db.getAnnotationIndex().containsKey(Entity.class.getName()))
+521         classNames.addAll(db.getAnnotationIndex().get(Entity.class.getName()));
+522       if (db.getAnnotationIndex().containsKey(MappedSuperclass.class.getName()))
+523         classNames.addAll(db.getAnnotationIndex().get(MappedSuperclass.class.getName()));
+524       if (db.getAnnotationIndex().containsKey(Embeddable.class.getName()))
+525         classNames.addAll(db.getAnnotationIndex().get(Embeddable.class.getName()));
+526 
+527       MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
+528       for (String name : classNames)
+529       {
+530         Class<?> annotatedClass = classLoader.loadClass(name);
+531         classes.add(annotatedClass);
+532         String resourceName = annotatedClass.getName();
+533         resourceName = resourceName.substring(resourceName.lastIndexOf(".") + 1, resourceName.length()) + ".class";
+534         InputStream is =
+535             annotatedClass
+536                 .getResourceAsStream(resourceName);
+537         byte[] buffer = new byte[1024*4]; // copy data in 4MB-chunks
+538         int i;
+539         while((i = is.read(buffer)) > -1)
+540           digest.update(buffer, 0, i);
+541         is.close();
+542         byte[] bytes = digest.digest();
+543         BigInteger bi = new BigInteger(1, bytes);
+544         String newMd5 = String.format("%0" + (bytes.length << 1) + "x", bi);
+545         String oldMd5 = !md5s.containsKey(name) ? "" : md5s.get(name);
+546         if (!newMd5.equals(oldMd5))
+547         {
+548           getLog().debug("Found new or modified annotated class: " + name);
+549           modified = true;
+550           md5s.put(name, newMd5);
+551         }
+552         else
+553         {
+554           getLog().debug(oldMd5 + " -> class unchanged: " + name);
+555         }
+556       }
+557     }
+558     catch (ClassNotFoundException e)
+559     {
+560       getLog().error("Error while adding annotated classes!", e);
+561       throw new MojoExecutionException(e.getMessage());
+562     }
+563     catch (Exception e)
+564     {
+565       getLog().error("Error while scanning!", e);
+566       throw new MojoFailureException(e.getMessage());
+567     }
+568 
+569 
+570     ValidationConfiguration config = new ValidationConfiguration();
+571     // Clear unused system-properties
+572     config.setProperties(new Properties());
+573 
+574 
+575     ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+576     StandardServiceRegistryImpl registry = null;
+577     MavenLogAppender.startPluginLog(this);
+578 
+579     try
+580     {
+581       /**
+582        * Change class-loader of current thread, so that hibernate can
+583        * see all dependencies!
+584        */
+585       Thread.currentThread().setContextClassLoader(classLoader);
+586 
+587 
+588       /** Try to read configuration from properties-file */
+589       try
+590       {
+591         if (hibernateProperties == null)
+592         {
+593           URL url = classLoader.findResource("hibernate.properties");
+594           if (url == null)
+595           {
+596             getLog().info("No hibernate.properties on the classpath!");
+597           }
+598           else
+599           {
+600             getLog().info("Reading settings from hibernate.properties on the classpath.");
+601             Properties properties = new Properties();
+602             properties.load(url.openStream());
+603             config.setProperties(properties);
+604           }
+605         }
+606         else
+607         {
+608           File file = new File(hibernateProperties);
+609           if (file.exists())
+610           {
+611             getLog().info("Reading settings from file " + hibernateProperties + "...");
+612             Properties properties = new Properties();
+613             properties.load(new FileInputStream(file));
+614             config.setProperties(properties);
+615           }
+616           else
+617             getLog().info("No hibernate-properties-file found! (Checked path: " + hibernateProperties + ")");
+618         }
+619       }
+620       catch (IOException e)
+621       {
+622         getLog().error("Error while reading properties!", e);
+623         throw new MojoExecutionException(e.getMessage());
+624       }
+625 
+626       /** Try to read configuration from configuration-file */
+627       try
+628       {
+629         if (hibernateConfig == null)
+630         {
+631           URL url = classLoader.findResource("hibernate.cfg.xml");
+632           if (url == null)
+633           {
+634             getLog().info("No hibernate.cfg.xml on the classpath!");
+635           }
+636           else
+637           {
+638             getLog().info("Reading settings from hibernate.cfg.xml on the classpath.");
+639             config.configure(url);
+640           }
+641         }
+642         else
+643         {
+644           File file = new File(hibernateConfig);
+645           if (file.exists())
+646           {
+647             getLog().info("Reading configuration from file " + hibernateConfig + "...");
+648             config.configure(file);
+649           }
+650           else
+651             getLog().info("No hibernate-configuration-file found! (Checked path: " + hibernateConfig + ")");
+652         }
+653       }
+654       catch (Exception e)
+655       {
+656         getLog().error("Error while reading configuration!", e);
+657         throw new MojoExecutionException(e.getMessage());
+658       }
+659 
+660       ParsedPersistenceXmlDescriptor persistenceUnitDescriptor =
+661           getPersistenceUnitDescriptor(
+662               persistenceUnit,
+663               config.getProperties(),
+664               new MavenProjectClassLoaderService(classLoader)
+665               );
+666       if (persistenceUnitDescriptor != null)
+667         config.setProperties(persistenceUnitDescriptor.getProperties());
+668 
+669 
+670       /** Overwrite values from properties-file or set, if given */
+671 
+672       if (driverClassName != null)
+673       {
+674         if (config.getProperties().containsKey(DRIVER_CLASS))
+675           getLog().debug(
+676               "Overwriting property " +
+677               DRIVER_CLASS + "=" + config.getProperty(DRIVER_CLASS) +
+678               " with the value " + driverClassName
+679             );
+680         else
+681           getLog().debug("Using the value " + driverClassName);
+682         config.setProperty(DRIVER_CLASS, driverClassName);
+683       }
+684       if (config.getProperty(DRIVER_CLASS) == null)
+685       {
+686         String driver = config.getProperty(JPA_DRIVER);
+687         if (driver != null)
+688         {
+689           getLog().info(
+690               DRIVER_CLASS +
+691               " is not set. Borrow setting from " +
+692               JPA_DRIVER +
+693               ": " +
+694               driver);
+695           config.setProperty(DRIVER_CLASS, driver);
+696         }
+697       }
+698 
+699       if (url != null)
+700       {
+701         if (config.getProperties().containsKey(URL))
+702           getLog().debug(
+703               "Overwriting property " +
+704               URL + "=" + config.getProperty(URL) +
+705               " with the value " + url
+706             );
+707         else
+708           getLog().debug("Using the value " + url);
+709         config.setProperty(URL, url);
+710       }
+711       if (config.getProperty(URL) == null)
+712       {
+713         String url = config.getProperty(JPA_URL);
+714         if (url != null)
+715         {
+716           getLog().info(
+717               URL +
+718               " is not set. Borrow setting from " +
+719               JPA_URL +
+720               ": " +
+721               url);
+722           config.setProperty(URL, url);
+723         }
+724       }
+725 
+726       if (username != null)
+727       {
+728         if (config.getProperties().containsKey(USERNAME))
+729           getLog().debug(
+730               "Overwriting property " +
+731               USERNAME + "=" + config.getProperty(USERNAME) +
+732               " with the value " + username
+733             );
+734         else
+735           getLog().debug("Using the value " + username);
+736         config.setProperty(USERNAME, username);
+737       }
+738       if (config.getProperty(USERNAME) == null)
+739       {
+740         String username = config.getProperty(JPA_USERNAME);
+741         if (username != null)
+742         {
+743           getLog().info(
+744               USERNAME +
+745               " is not set. Borrow setting from " +
+746               JPA_USERNAME +
+747               ": " +
+748               username);
+749           config.setProperty(USERNAME, username);
+750         }
+751       }
+752 
+753       if (password != null)
+754       {
+755         if (config.getProperties().containsKey(PASSWORD))
+756           getLog().debug(
+757               "Overwriting property " +
+758               PASSWORD + "=" + config.getProperty(PASSWORD) +
+759               " with value " + password
+760             );
+761         else
+762           getLog().debug("Using value " + password + " for property " + PASSWORD);
+763         config.setProperty(PASSWORD, password);
+764       }
+765       if (config.getProperty(PASSWORD) == null)
+766       {
+767         String password = config.getProperty(JPA_PASSWORD);
+768         if (password != null)
+769         {
+770           getLog().info(
+771               PASSWORD +
+772               " is not set. Borrow setting from " +
+773               JPA_PASSWORD +
+774               ": " +
+775               password);
+776           config.setProperty(PASSWORD, password);
+777         }
+778       }
+779 
+780       if (hibernateDialect != null)
+781       {
+782         if (config.getProperties().containsKey(DIALECT))
+783           getLog().debug(
+784               "Overwriting property " +
+785               DIALECT + "=" + config.getProperty(DIALECT) +
+786               " with value " + hibernateDialect
+787             );
+788         else
+789           getLog().debug(
+790               "Using value " + hibernateDialect + " for property " + DIALECT
+791               );
+792         config.setProperty(DIALECT, hibernateDialect);
+793       }
+794 
+795       if ( hibernateNamingStrategy != null )
+796       {
+797         if ( config.getProperties().contains(NAMING_STRATEGY))
+798           getLog().debug(
+799               "Overwriting property " +
+800               NAMING_STRATEGY + "=" + config.getProperty(NAMING_STRATEGY) +
+801               " with value " + hibernateNamingStrategy
+802              );
+803         else
+804           getLog().debug(
+805               "Using value " + hibernateNamingStrategy + " for property " +
+806               NAMING_STRATEGY
+807               );
+808         config.setProperty(NAMING_STRATEGY, hibernateNamingStrategy);
+809       }
+810 
+811       /** The generated SQL varies with the dialect! */
+812       if (md5s.containsKey(DIALECT))
+813       {
+814         String dialect = config.getProperty(DIALECT);
+815         if (md5s.get(DIALECT).equals(dialect))
+816           getLog().debug("SQL-dialect unchanged.");
+817         else
+818         {
+819           modified = true;
+820           if (dialect == null)
+821           {
+822             getLog().debug("SQL-dialect was unset.");
+823             md5s.remove(DIALECT);
+824           }
+825           else
+826           {
+827             getLog().debug("SQL-dialect changed: " + dialect);
+828             md5s.put(DIALECT, dialect);
+829           }
+830         }
+831       }
+832       else
+833       {
+834         String dialect = config.getProperty(DIALECT);
+835         if (dialect != null)
+836         {
+837           modified = true;
+838           md5s.put(DIALECT, config.getProperty(DIALECT));
+839         }
+840       }
+841 
+842       /** The generated SQL varies with the envers-configuration */
+843       if (md5s.get(ENVERS) != null)
+844       {
+845         if (md5s.get(ENVERS).equals(Boolean.toString(envers)))
+846           getLog().debug("Envers-Configuration unchanged. Enabled: " + envers);
+847         else
+848         {
+849           getLog().debug("Envers-Configuration changed. Enabled: " + envers);
+850           modified = true;
+851           md5s.put(ENVERS, Boolean.toString(envers));
+852         }
+853       }
+854       else
+855       {
+856         modified = true;
+857         md5s.put(ENVERS, Boolean.toString(envers));
+858       }
+859 
+860       if (config.getProperties().isEmpty())
+861       {
+862         getLog().error("No properties set!");
+863         throw new MojoFailureException("Hibernate configuration is missing!");
+864       }
+865 
+866       getLog().info("Gathered hibernate-configuration (turn on debugging for details):");
+867       for (Entry<Object,Object> entry : config.getProperties().entrySet())
+868         getLog().info("  " + entry.getKey() + " = " + entry.getValue());
+869 
+870 
+871       getLog().debug("Adding explicitly configured mappings...");
+872       if (hibernateMapping != null)
+873       {
+874         try
+875         {
+876           MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
+877           for (String filename : hibernateMapping.split("[\\s,]+"))
+878           {
+879             // First try the filename as absolute/relative path
+880             File file = new File(filename);
+881             if (!file.exists())
+882             {
+883               // If the file was not found, search for it in the resource-directories
+884               for (Resource resource : project.getResources())
+885               {
+886                 file = new File(resource.getDirectory() + File.separator + filename);
+887                 if (file.exists())
+888                   break;
+889               }
+890             }
+891             if (file != null && file.exists())
+892             {
+893               InputStream is = new FileInputStream(file);
+894               byte[] buffer = new byte[1024*4]; // copy data in 4MB-chunks
+895               int i;
+896               while((i = is.read(buffer)) > -1)
+897                 digest.update(buffer, 0, i);
+898               is.close();
+899               byte[] bytes = digest.digest();
+900               BigInteger bi = new BigInteger(1, bytes);
+901               String newMd5 = String.format("%0" + (bytes.length << 1) + "x", bi);
+902               String oldMd5 = !md5s.containsKey(filename) ? "" : md5s.get(filename);
+903               if (!newMd5.equals(oldMd5))
+904               {
+905                 getLog().debug("Found new or modified mapping-file: " + filename);
+906                 modified = true;
+907                 md5s.put(filename, newMd5);
+908               }
+909               else
+910               {
+911                 getLog().debug(oldMd5 + " -> mapping-file unchanged: " + filename);
+912               }
+913               getLog().debug("Adding mappings from XML-configurationfile: " + file);
+914               config.addFile(file);
+915             }
+916             else
+917               throw new MojoFailureException("File " + filename + " could not be found in any of the configured resource-directories!");
+918           }
+919         }
+920         catch (NoSuchAlgorithmException e)
+921         {
+922           throw new MojoFailureException("Cannot calculate MD5 sums!", e);
+923         }
+924         catch (FileNotFoundException e)
+925         {
+926           throw new MojoFailureException("Cannot calculate MD5 sums!", e);
+927         }
+928         catch (IOException e)
+929         {
+930           throw new MojoFailureException("Cannot calculate MD5 sums!", e);
+931         }
+932       }
+933 
+934       getLog().debug("Adding annotated classes to hibernate-mapping-configuration...");
+935       // build annotated packages
+936       Set<String> packages = new HashSet<String>();
+937       for (Class<?> annotatedClass : classes)
+938       {
+939         String packageName = annotatedClass.getPackage().getName();
+940         if (!packages.contains(packageName))
+941         {
+942           getLog().debug("Add package " + packageName);
+943           packages.add(packageName);
+944           config.addPackage(packageName);
+945           getLog().debug("type definintions" + config.getTypeDefs());
+946         }
+947         getLog().debug("Class " + annotatedClass);
+948         config.addAnnotatedClass(annotatedClass);
+949       }
+950 
+951       Target target = null;
+952       try
+953       {
+954         target = Target.valueOf(this.target.toUpperCase());
+955       }
+956       catch (IllegalArgumentException e)
+957       {
+958         getLog().error("Invalid value for configuration-option \"target\": " + this.target);
+959         getLog().error("Valid values are: NONE, SCRIPT, EXPORT, BOTH");
+960         throw new MojoExecutionException("Invalid value for configuration-option \"target\"");
+961       }
+962       Type type = null;
+963       try
+964       {
+965         type = Type.valueOf(this.type.toUpperCase());
+966       }
+967       catch (IllegalArgumentException e)
+968       {
+969         getLog().error("Invalid value for configuration-option \"type\": " + this.type);
+970         getLog().error("Valid values are: NONE, CREATE, DROP, BOTH");
+971         throw new MojoExecutionException("Invalid value for configuration-option \"type\"");
+972       }
+973 
+974 
+975       if (config.getProperty(DIALECT) == null)
+976         throw new MojoFailureException("hibernate-dialect must be set!");
+977 
+978 
+979       if (target.equals(Target.SCRIPT) || target.equals(Target.NONE))
+980       {
+981         project.getProperties().setProperty(EXPORT_SKIPPED_PROPERTY, "true");
+982       }
+983       if (
+984           !modified
+985           && !target.equals(Target.SCRIPT)
+986           && !target.equals(Target.NONE)
+987           && !force
+988         )
+989       {
+990         getLog().info("No modified annotated classes or mapping-files found and dialect unchanged.");
+991         getLog().info("Skipping schema generation!");
+992         project.getProperties().setProperty(EXPORT_SKIPPED_PROPERTY, "true");
+993         return;
+994       }
+995 
+996 
+997       if ( config.getProperties().containsKey(NAMING_STRATEGY))
+998       {
+999         String namingStrategy = config.getProperty(NAMING_STRATEGY);
+1000         getLog().debug("Explicitly set NamingStrategy: " + namingStrategy);
+1001         try
+1002         {
+1003           @SuppressWarnings("unchecked")
+1004           Class<NamingStrategy> namingStrategyClass = (Class<NamingStrategy>) Class.forName(namingStrategy);
+1005           config.setNamingStrategy(namingStrategyClass.newInstance());
+1006         }
+1007         catch (Exception e)
+1008         {
+1009           getLog().error("Error setting NamingStrategy", e);
+1010           throw new MojoExecutionException(e.getMessage());
+1011         }
+1012       }
+1013 
+1014 
+1015       Environment.verifyProperties(config.getProperties());
+1016       ConfigurationHelper.resolvePlaceHolders(config.getProperties());
+1017       registry =
+1018           (StandardServiceRegistryImpl)
+1019           new StandardServiceRegistryBuilder()
+1020               .applySettings(config.getProperties())
+1021               .build();
+1022 
+1023       config.buildMappings();
+1024 
+1025       if (envers)
+1026       {
+1027         getLog().info("Automatic auditing via hibernate-envers enabled!");
+1028         AuditConfiguration.getFor(config);
+1029       }
+1030 
+1031       SchemaExport export = new SchemaExport(registry, config);
+1032       export.setDelimiter(delimiter);
+1033       export.setFormat(format);
+1034 
+1035       File outF = new File(outputFile);
+1036 
+1037       if (!outF.isAbsolute())
+1038       {
+1039         // Interpret relative file path relative to build directory
+1040         outF = new File(buildDirectory, outputFile);
+1041         getLog().info("Adjusted relative path, resulting path is " + outF.getPath());
+1042       }
+1043 
+1044       // Ensure that directory path for specified file exists
+1045       File outFileParentDir = outF.getParentFile();
+1046       if (null != outFileParentDir && !outFileParentDir.exists())
+1047       {
+1048         try
+1049         {
+1050           getLog().info("Creating directory path for output file:" + outFileParentDir.getPath());
+1051           outFileParentDir.mkdirs();
+1052         }
+1053         catch (Exception e)
+1054         {
+1055           getLog().error("Error creating directory path for output file: " + e.getLocalizedMessage());
+1056         }
+1057       }
+1058 
+1059       export.setOutputFile(outF.getPath());
+1060       export.execute(target, type);
+1061 
+1062       for (Object exception : export.getExceptions())
+1063         getLog().debug(exception.toString());
+1064     }
+1065     finally
+1066     {
+1067       /** Stop Log-Capturing */
+1068       MavenLogAppender.endPluginLog(this);
+1069 
+1070       /** Restore the old class-loader (TODO: is this really necessary?) */
+1071       Thread.currentThread().setContextClassLoader(contextClassLoader);
+1072 
+1073       if (registry != null)
+1074         registry.destroy();
+1075     }
+1076 
+1077     /** Write md5-sums for annotated classes to file */
+1078     try
+1079     {
+1080       FileOutputStream fos = new FileOutputStream(saved);
+1081       ObjectOutputStream oos = new ObjectOutputStream(fos);
+1082       oos.writeObject(md5s);
+1083       oos.close();
+1084       fos.close();
+1085     }
+1086     catch (Exception e)
+1087     {
+1088       getLog().error("Cannot write md5-sums to file: " + e);
+1089     }
+1090   }
+1091 
+1092   private ParsedPersistenceXmlDescriptor getPersistenceUnitDescriptor(
+1093       String name,
+1094       Properties properties,
+1095       ClassLoaderService loader
+1096       )
+1097       throws
+1098         MojoFailureException
+1099   {
+1100     PersistenceXmlParser parser =
+1101         new PersistenceXmlParser(
+1102             loader,
+1103             PersistenceUnitTransactionType.RESOURCE_LOCAL
+1104              );
+1105 
+1106     List<ParsedPersistenceXmlDescriptor> units = parser.doResolve(properties);
+1107 
+1108     if (name == null)
+1109     {
+1110       switch (units.size())
+1111       {
+1112         case 0:
+1113           getLog().info("Found no META-INF/persistence.xml.");
+1114           return null;
+1115         case 1:
+1116           getLog().info("Using persistence-unit " + units.get(0).getName());
+1117           return units.get(0);
+1118         default:
+1119           getLog().warn("No name provided and multiple persistence units found:");
+1120           for (ParsedPersistenceXmlDescriptor unit : units)
+1121             getLog().warn(" - " + unit.getName());
+1122           return null;
+1123       }
+1124 
+1125     }
+1126 
+1127     for (ParsedPersistenceXmlDescriptor unit : units)
+1128     {
+1129       getLog().debug("Found persistence-unit " + unit.getName());
+1130       if (!unit.getName().equals(name))
+1131         continue;
+1132 
+1133       // See if we (Hibernate) are the persistence provider
+1134       if (!ProviderChecker.isProvider(unit, properties))
+1135       {
+1136         getLog().debug("Wrong provider: " + unit.getProviderClassName());
+1137         continue;
+1138       }
+1139 
+1140       getLog().info("Using persistence-unit " + unit.getName());
+1141       return unit;
+1142     }
+1143 
+1144     throw new MojoFailureException("Could not find persistence-unit " + name);
+1145   }
+1146 
+1147 
+1148   static final class MavenProjectClassLoaderService implements ClassLoaderService
+1149   {
+1150     final private ClassLoader loader;
+1151 
+1152 
+1153     public MavenProjectClassLoaderService(ClassLoader loader)
+1154     {
+1155       this.loader = loader;
+1156     }
+1157 
+1158 
+1159     @Override
+1160     public <T> Class<T> classForName(String name)
+1161     {
+1162       try
+1163       {
+1164         return (Class<T>)loader.loadClass(name);
+1165       }
+1166       catch (ClassNotFoundException e)
+1167       {
+1168         throw new ClassLoadingException( "Unable to load class [" + name + "]", e );
+1169       }
+1170     }
+1171 
+1172     @Override
+1173     public URL locateResource(String name)
+1174     {
+1175       return loader.getResource(name);
+1176     }
+1177 
+1178     @Override
+1179     public InputStream locateResourceStream(String name)
+1180     {
+1181       return loader.getResourceAsStream(name);
+1182     }
+1183 
+1184     @Override
+1185     public List<URL> locateResources(String name)
+1186     {
+1187       try
+1188       {
+1189         return Collections.list(loader.getResources(name));
+1190       }
+1191       catch (IOException e)
+1192       {
+1193         return Collections.EMPTY_LIST;
+1194       }
+1195     }
+1196 
+1197     @Override
+1198     public <S> LinkedHashSet<S> loadJavaServices(Class<S> serviceContract)
+1199     {
+1200       throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+1201     }
+1202 
+1203     @Override
+1204     public void stop() { }
+1205 
+1206   }
+1207 
+1208 
+1209   /**
+1210    * Needed, because DriverManager won't pick up drivers, that were not
+1211    * loaded by the system-classloader!
+1212    * See:
+1213    * http://stackoverflow.com/questions/288828/how-to-use-a-jdbc-driver-fromodifiedm-an-arbitrary-location
+1214    */
+1215   static final class DriverProxy implements Driver
+1216   {
+1217     private final Driver target;
+1218 
+1219     DriverProxy(Driver target)
+1220     {
+1221       if (target == null)
+1222         throw new NullPointerException();
+1223       this.target = target;
+1224     }
+1225 
+1226     public java.sql.Driver getTarget()
+1227     {
+1228       return target;
+1229     }
+1230 
+1231     @Override
+1232     public boolean acceptsURL(String url) throws SQLException
+1233     {
+1234       return target.acceptsURL(url);
+1235     }
+1236 
+1237     @Override
+1238     public java.sql.Connection connect(
+1239         String url,
+1240         java.util.Properties info
+1241       )
+1242       throws
+1243         SQLException
+1244     {
+1245       return target.connect(url, info);
+1246     }
+1247 
+1248     @Override
+1249     public int getMajorVersion()
+1250     {
+1251       return target.getMajorVersion();
+1252     }
+1253 
+1254     @Override
+1255     public int getMinorVersion()
+1256     {
+1257       return target.getMinorVersion();
+1258     }
+1259 
+1260     @Override
+1261     public DriverPropertyInfo[] getPropertyInfo(
+1262         String url,
+1263         Properties info
+1264       )
+1265       throws
+1266         SQLException
+1267     {
+1268       return target.getPropertyInfo(url, info);
+1269     }
+1270 
+1271     @Override
+1272     public boolean jdbcCompliant()
+1273     {
+1274       return target.jdbcCompliant();
+1275     }
+1276 
+1277     /**
+1278      * This Method cannot be annotated with @Override, becaus the plugin
+1279      * will not compile then under Java 1.6!
+1280      */
+1281     public Logger getParentLogger() throws SQLFeatureNotSupportedException
+1282     {
+1283       throw new SQLFeatureNotSupportedException("Not supported, for backward-compatibility with Java 1.6");
+1284     }
+1285 
+1286     @Override
+1287     public String toString()
+1288     {
+1289       return "Proxy: " + target;
+1290     }
+1291 
+1292     @Override
+1293     public int hashCode()
+1294     {
+1295       return target.hashCode();
+1296     }
+1297 
+1298     @Override
+1299     public boolean equals(Object obj)
+1300     {
+1301       if (!(obj instanceof DriverProxy))
+1302         return false;
+1303       DriverProxy other = (DriverProxy) obj;
+1304       return this.target.equals(other.target);
+1305     }
+1306   }
+1307 }
+
+
+ + +