Overwriting of a property with the same value is not reported as overwriting
[hibernate4-maven-plugin] / src / main / java / de / juplo / plugins / hibernate / AbstractSchemaMojo.java
index f6e18ea..06024c2 100644 (file)
@@ -4,12 +4,16 @@ package de.juplo.plugins.hibernate;
 import com.pyx4j.log4j.MavenLogAppender;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.security.NoSuchAlgorithmException;
+import java.time.ZonedDateTime;
 import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
@@ -45,25 +49,34 @@ import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
 import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
 import org.hibernate.boot.registry.selector.spi.StrategySelector;
 import org.hibernate.boot.spi.MetadataImplementor;
+import org.hibernate.cfg.AvailableSettings;
 import static org.hibernate.cfg.AvailableSettings.DIALECT;
 import static org.hibernate.cfg.AvailableSettings.DRIVER;
 import static org.hibernate.cfg.AvailableSettings.FORMAT_SQL;
+import static org.hibernate.cfg.AvailableSettings.HBM2DDL_DELIMITER;
 import static org.hibernate.cfg.AvailableSettings.HBM2DLL_CREATE_NAMESPACES;
 import static org.hibernate.cfg.AvailableSettings.IMPLICIT_NAMING_STRATEGY;
+import static org.hibernate.cfg.AvailableSettings.JPA_JDBC_DRIVER;
+import static org.hibernate.cfg.AvailableSettings.JPA_JDBC_PASSWORD;
+import static org.hibernate.cfg.AvailableSettings.JPA_JDBC_URL;
+import static org.hibernate.cfg.AvailableSettings.JPA_JDBC_USER;
 import static org.hibernate.cfg.AvailableSettings.PASS;
 import static org.hibernate.cfg.AvailableSettings.PHYSICAL_NAMING_STRATEGY;
 import static org.hibernate.cfg.AvailableSettings.SHOW_SQL;
 import static org.hibernate.cfg.AvailableSettings.USER;
 import static org.hibernate.cfg.AvailableSettings.URL;
+import org.hibernate.engine.config.spi.ConfigurationService;
 import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
 import org.hibernate.internal.util.config.ConfigurationException;
-import static org.hibernate.jpa.AvailableSettings.JDBC_DRIVER;
-import static org.hibernate.jpa.AvailableSettings.JDBC_PASSWORD;
-import static org.hibernate.jpa.AvailableSettings.JDBC_URL;
-import static org.hibernate.jpa.AvailableSettings.JDBC_USER;
 import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
 import org.hibernate.jpa.boot.internal.PersistenceXmlParser;
-import org.hibernate.jpa.boot.spi.ProviderChecker;
+import org.hibernate.tool.schema.TargetType;
+import org.hibernate.tool.schema.internal.ExceptionHandlerCollectingImpl;
+import org.hibernate.tool.schema.internal.exec.ScriptTargetOutputToFile;
+import org.hibernate.tool.schema.spi.ExecutionOptions;
+import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator;
+import org.hibernate.tool.schema.spi.ScriptTargetOutput;
+import org.hibernate.tool.schema.spi.TargetDescriptor;
 import org.scannotation.AnnotationDB;
 
 
@@ -76,19 +89,20 @@ import org.scannotation.AnnotationDB;
  */
 public abstract class AbstractSchemaMojo extends AbstractMojo
 {
-  public final static String EXPORT = "hibernate.schema.export";
-  public final static String DELIMITER = "hibernate.schema.delimiter";
+  public final static String EXECUTE = "hibernate.schema.execute";
   public final static String OUTPUTDIRECTORY = "project.build.outputDirectory";
   public final static String SCAN_CLASSES = "hibernate.schema.scan.classes";
   public final static String SCAN_DEPENDENCIES = "hibernate.schema.scan.dependencies";
   public final static String SCAN_TESTCLASSES = "hibernate.schema.scan.test_classes";
   public final static String TEST_OUTPUTDIRECTORY = "project.build.testOutputDirectory";
   public final static String SKIPPED = "hibernate.schema.skipped";
+  public final static String SCRIPT = "hibernate.schema.script";
 
   private final static Pattern SPLIT = Pattern.compile("[^,\\s]+");
 
   private final Set<String> packages = new HashSet<String>();
 
+
   /**
    * The maven project.
    * <p>
@@ -109,13 +123,13 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
    * @required
    * @readonly
    */
-  String buildDirectory;
+  private String buildDirectory;
 
 
   /** Parameters to configure the genaration of the SQL *********************/
 
   /**
-   * Export the database-schma to the database.
+   * Excecute the generated SQL.
    * If set to <code>false</code>, only the SQL-script is created and the
    * database is not touched.
    * <p>
@@ -125,10 +139,10 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
    * it is not known by Hibernate nor JPA and, hence, not picked up from
    * their configuration!
    *
-   * @parameter property="hibernate.schema.export" default-value="true"
+   * @parameter property="hibernate.schema.execute" default-value="true"
    * @since 2.0
    */
-  Boolean export;
+  private Boolean execute;
 
   /**
    * Skip execution
@@ -136,7 +150,7 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
    * If set to <code>true</code>, the execution is skipped.
    * <p>
    * A skipped execution is signaled via the maven-property
-   * <code>${hibernate.export.skipped}</code>.
+   * <code>${hibernate.schema.skipped}</code>.
    * <p>
    * The execution is skipped automatically, if no modified or newly added
    * annotated classes are found and the dialect was not changed.
@@ -153,10 +167,11 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
   private boolean skip;
 
   /**
-   * Force execution
+   * Force generation/execution
    * <p>
-   * Force execution, even if no modified or newly added annotated classes
-   * where found and the dialect was not changed.
+   * Force the generation and (if configured) the execution of the SQL, even if
+   * no modified or newly added annotated classes where found and the
+   * configuration was not changed.
    * <p>
    * <code>skip</code> takes precedence over <code>force</code>.
    * <p>
@@ -188,10 +203,10 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
    * it is not known by Hibernate nor JPA and, hence, not picked up from
    * their configuration!
    *
-   * @parameter property="hibernate.schema.delimiter" default-value=";"
+   * @parameter property="hibernate.hbm2ddl.delimiter" default-value=";"
    * @since 1.0
    */
-  String delimiter;
+  private String delimiter;
 
   /**
    * Show the generated SQL in the command-line output.
@@ -199,7 +214,7 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
    * @parameter property="hibernate.show_sql"
    * @since 1.0
    */
-  Boolean show;
+  private Boolean show;
 
   /**
    * Format output-file.
@@ -207,7 +222,7 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
    * @parameter property="hibernate.format_sql"
    * @since 1.0
    */
-  Boolean format;
+  private Boolean format;
 
   /**
    * Specifies whether to automatically create also the database schema/catalog.
@@ -215,7 +230,7 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
    * @parameter property="hibernate.hbm2dll.create_namespaces" default-value="false"
    * @since 2.0
    */
-  Boolean createNamespaces;
+  private Boolean createNamespaces;
 
   /**
    * Implicit naming strategy
@@ -445,7 +460,7 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
       throw new MojoFailureException("Digest-Algorithm MD5 is missing!", e);
     }
 
-    SimpleConnectionProvider connectionProvider =
+    final SimpleConnectionProvider connectionProvider =
         new SimpleConnectionProvider(getLog());
 
     try
@@ -489,13 +504,18 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
       else
         getLog().debug("Configuration unchanged.");
 
+      /** Check, that the outputfile is writable */
+      final File output = getOutputFile(filename);
+      /** Check, if the outputfile is missing or was changed */
+      checkOutputFile(output, tracker);
+
       /** Configure Hibernate */
-      StandardServiceRegistry serviceRegistry =
+      final StandardServiceRegistry serviceRegistry =
           new StandardServiceRegistryBuilder(bootstrapServiceRegitry)
               .applySettings(properties)
               .addService(ConnectionProvider.class, connectionProvider)
               .build();
-      MetadataSources sources = new MetadataSources(serviceRegistry);
+      final MetadataSources sources = new MetadataSources(serviceRegistry);
 
       /** Add the remaining class-path-elements */
       completeClassPath(classLoader);
@@ -546,30 +566,60 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
          * Add mappings from the default mapping-file
          * <code>META-INF/orm.xml</code>, if present
          */
-        try
+        boolean error = false;
+        InputStream is;
+        is = classLoader.getResourceAsStream("META-INF/orm.xml");
+        if (is != null)
         {
-          InputStream is = classLoader.getResourceAsStream("META-INF/orm.xml");
-          if (is != null)
+          getLog().info("Adding default JPA-XML-mapping from META-INF/orm.xml");
+          try
           {
-            getLog().info("Adding default JPA-XML-mapping from META-INF/orm.xml");
             tracker.track("META-INF/orm.xml", is);
             sources.addResource("META-INF/orm.xml");
           }
-          /**
-           * Add mappings from files, that are explicitly configured in the
-           * persistence unit
-           */
-          for (String mapping : unit.getMappingFileNames())
+          catch (IOException e)
           {
-            getLog().info("Adding explicitly configured mapping from " + mapping);
-            tracker.track(mapping, classLoader.getResourceAsStream(mapping));
-            sources.addResource(mapping);
+            getLog().error("cannot read META-INF/orm.xml: " + e);
+            error = true;
           }
         }
-        catch (IOException e)
+        else
         {
-          throw new MojoFailureException("Error reading XML-mappings", e);
+          getLog().debug("no META-INF/orm.xml found");
         }
+        /**
+         * Add mappings from files, that are explicitly configured in the
+         * persistence unit
+         */
+        for (String mapping : unit.getMappingFileNames())
+        {
+          getLog().info("Adding explicitly configured mapping from " + mapping);
+          is = classLoader.getResourceAsStream(mapping);
+          if (is != null)
+          {
+            try
+            {
+              tracker.track(mapping, is);
+              sources.addResource(mapping);
+            }
+            catch (IOException e)
+            {
+              getLog().info("cannot read mapping-file " + mapping + ": " + e);
+              error = true;
+            }
+          }
+          else
+          {
+            getLog().error("cannot find mapping-file " + mapping);
+            error = true;
+          }
+        }
+        if (error)
+          throw new MojoFailureException(
+              "error, while reading mappings configured in persistence-unit \"" +
+              unit.getName() +
+              "\""
+              );
       }
 
       /** Add the configured/collected annotated classes */
@@ -582,11 +632,9 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
       /** Skip execution, if mapping and configuration is unchanged */
       if (!tracker.modified())
       {
-        getLog().info(
-            "Mapping and configuration unchanged."
-            );
+        getLog().info("Mapping and configuration unchanged.");
         if (force)
-          getLog().info("Schema generation is forced!");
+          getLog().info("Generation/execution is forced!");
         else
         {
           getLog().info("Skipping schema generation!");
@@ -596,6 +644,20 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
       }
 
 
+      /** Truncate output file */
+      try
+      {
+        new FileOutputStream(output).getChannel().truncate(0).close();
+      }
+      catch (IOException e)
+      {
+        String error =
+            "Error while truncating " + output.getAbsolutePath() + ": "
+            + e.getMessage();
+        getLog().warn(error);
+        throw new MojoExecutionException(error);
+      }
+
       /** Create a connection, if sufficient configuration infromation is available */
       connectionProvider.open(classLoaderService, properties);
 
@@ -624,6 +686,42 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
             );
       }
 
+      /** Prepare the generation of the SQL */
+      Map settings = new HashMap();
+      settings.putAll(
+          serviceRegistry
+              .getService(ConfigurationService.class)
+              .getSettings()
+              );
+      ExceptionHandlerCollectingImpl handler =
+          new ExceptionHandlerCollectingImpl();
+      ExecutionOptions options =
+          SchemaManagementToolCoordinator
+              .buildExecutionOptions(settings, handler);
+      final EnumSet<TargetType> targetTypes = EnumSet.of(TargetType.SCRIPT);
+      if (execute)
+        targetTypes.add(TargetType.DATABASE);
+      TargetDescriptor target = new TargetDescriptor()
+      {
+        @Override
+        public EnumSet<TargetType> getTargetTypes()
+        {
+          return targetTypes;
+        }
+
+        @Override
+        public ScriptTargetOutput getScriptTargetOutput()
+        {
+          String charset =
+              (String)
+              serviceRegistry
+                  .getService(ConfigurationService.class)
+                  .getSettings()
+                  .get(AvailableSettings.HBM2DDL_CHARSET_NAME);
+          return new ScriptTargetOutputToFile(output, charset);
+        }
+      };
+
       /**
        * Change class-loader of current thread.
        * This is necessary, because still not all parts of Hibernate 5 use
@@ -634,11 +732,15 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
       try
       {
         thread.setContextClassLoader(classLoader);
-        build((MetadataImplementor)metadataBuilder.build());
+        build((MetadataImplementor)metadataBuilder.build(), options, target);
       }
       finally
       {
         thread.setContextClassLoader(contextClassLoader);
+        for (Exception e : handler.getExceptions())
+          getLog().error(e.getMessage());
+        /** Track, the content of the generated script */
+        checkOutputFile(output, tracker);
       }
     }
     catch (MojoExecutionException e)
@@ -670,7 +772,11 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
   }
 
 
-  abstract void build(MetadataImplementor metadata)
+  abstract void build(
+      MetadataImplementor metadata,
+      ExecutionOptions options,
+      TargetDescriptor target
+      )
     throws
       MojoFailureException,
       MojoExecutionException;
@@ -815,10 +921,10 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
       throws MojoFailureException
   {
     /**
-     * Special treatment for the configuration-value "export": if it is
+     * Special treatment for the configuration-value "execute": if it is
      * switched to "true", the genearation fo the schema should be forced!
      */
-    if (tracker.check(EXPORT, export.toString()) && export)
+    if (tracker.check(EXECUTE, execute.toString()) && execute)
       tracker.touch();
 
     /**
@@ -826,12 +932,12 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
      * Overwrite values from properties-file if the configuration parameter is
      * known to Hibernate.
      */
-    dialect = configure(properties, dialect, DIALECT);
-    tracker.track(DELIMITER, delimiter); // << not reflected in hibernate configuration!
-    format = configure(properties, format, FORMAT_SQL);
-    createNamespaces = configure(properties, createNamespaces, HBM2DLL_CREATE_NAMESPACES);
-    implicitNamingStrategy = configure(properties, implicitNamingStrategy, IMPLICIT_NAMING_STRATEGY);
-    physicalNamingStrategy = configure(properties, physicalNamingStrategy, PHYSICAL_NAMING_STRATEGY);
+    configure(properties, dialect, DIALECT);
+    configure(properties, delimiter, HBM2DDL_DELIMITER);
+    configure(properties, format, FORMAT_SQL);
+    configure(properties, createNamespaces, HBM2DLL_CREATE_NAMESPACES);
+    configure(properties, implicitNamingStrategy, IMPLICIT_NAMING_STRATEGY);
+    configure(properties, physicalNamingStrategy, PHYSICAL_NAMING_STRATEGY);
     tracker.track(OUTPUTDIRECTORY, outputDirectory); // << not reflected in hibernate configuration!
     tracker.track(SCAN_DEPENDENCIES, scanDependencies); // << not reflected in hibernate configuration!
     tracker.track(SCAN_TESTCLASSES, scanTestClasses.toString()); // << not reflected in hibernate configuration!
@@ -851,10 +957,10 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
      * Configure the connection parameters.
      * Overwrite values from properties-file.
      */
-    driver = configure(properties, driver, DRIVER, JDBC_DRIVER);
-    url = configure(properties, url, URL, JDBC_URL);
-    username = configure(properties, username, USER, JDBC_USER);
-    password = configure(properties, password, PASS, JDBC_PASSWORD);
+    configure(properties, driver, DRIVER, JPA_JDBC_DRIVER);
+    configure(properties, url, URL, JPA_JDBC_URL);
+    configure(properties, username, USER, JPA_JDBC_USER);
+    configure(properties, password, PASS, JPA_JDBC_PASSWORD);
 
     if (properties.isEmpty())
     {
@@ -867,59 +973,143 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
       getLog().info("  " + entry.getKey() + " = " + entry.getValue());
   }
 
-  private String configure(
+  private void configure(
       Properties properties,
       String value,
       String key,
       String alternativeKey
       )
   {
-    value = configure(properties, value, key);
-    if (value == null)
-      return properties.getProperty(alternativeKey);
+    configure(properties, value, key);
 
     if (properties.containsKey(alternativeKey))
     {
-      getLog().warn(
-          "Ignoring property " + alternativeKey + "=" +
-          properties.getProperty(alternativeKey) + " in favour for property " +
-          key + "=" + properties.getProperty(key)
-          );
-      properties.remove(alternativeKey);
+      if (properties.containsKey(key))
+      {
+        getLog().warn(
+            "Ignoring property " + alternativeKey + "=\"" +
+            properties.getProperty(alternativeKey) +
+            "\" in favour for property " + key + "=\"" +
+            properties.getProperty(key) + "\""
+            );
+        properties.remove(alternativeKey);
+      }
+      else
+      {
+        value = properties.getProperty(alternativeKey);
+        properties.remove(alternativeKey);
+        getLog().info(
+            "Using value \"" + value + "\" from property " + alternativeKey +
+            " for property " + key
+            );
+        properties.setProperty(key, value);
+      }
     }
-    return properties.getProperty(alternativeKey);
   }
 
-  private String configure(Properties properties, String value, String key)
+  private void configure(Properties properties, String value, String key)
   {
     if (value != null)
     {
       if (properties.containsKey(key))
-        getLog().debug(
-            "Overwriting property " + key + "=" + properties.getProperty(key) +
-            " with the value " + value
-            );
+      {
+        if (!properties.getProperty(key).equals(value))
+        {
+          getLog().info(
+              "Overwriting property " + key + "=\"" +
+              properties.getProperty(key) +
+              "\" with value \"" + value + "\""
+              );
+          properties.setProperty(key, value);
+        }
+      }
       else
-        getLog().debug("Using the value " + value + " for property " + key);
-      properties.setProperty(key, value);
+      {
+        getLog().debug("Using value \"" + value + "\" for property " + key);
+        properties.setProperty(key, value);
+      }
     }
-    return properties.getProperty(key);
   }
 
-  private boolean configure(Properties properties, Boolean value, String key)
+  private void configure(Properties properties, Boolean value, String key)
   {
-    if (value != null)
+    configure(properties, value == null ? null : value.toString(), key);
+  }
+
+  private File getOutputFile(String filename)
+      throws
+        MojoExecutionException
+  {
+    File output = new File(filename);
+
+    if (!output.isAbsolute())
     {
-      if (properties.containsKey(key))
-        getLog().debug(
-            "Overwriting property " + key + "=" + properties.getProperty(key) +
-            " with the value " + value
+      // Interpret relative file path relative to build directory
+      output = new File(buildDirectory, filename);
+    }
+    getLog().debug("Output file: " + output.getPath());
+
+    // Ensure that directory path for specified file exists
+    File outFileParentDir = output.getParentFile();
+    if (null != outFileParentDir && !outFileParentDir.exists())
+    {
+      try
+      {
+        getLog().info(
+            "Creating directory path for output file:" +
+            outFileParentDir.getPath()
             );
+        outFileParentDir.mkdirs();
+      }
+      catch (Exception e)
+      {
+        String error =
+            "Error creating directory path for output file: " + e.getMessage();
+        getLog().error(error);
+        throw new MojoExecutionException(error);
+      }
+    }
+
+    try
+    {
+      output.createNewFile();
+    }
+    catch (IOException e)
+    {
+      String error = "Error creating output file: " + e.getMessage();
+      getLog().error(error);
+      throw new MojoExecutionException(error);
+    }
+
+    if (!output.canWrite())
+    {
+      String error =
+          "Output file " + output.getAbsolutePath() + " is not writable!";
+      getLog().error(error);
+      throw new MojoExecutionException(error);
+    }
+
+    return output;
+  }
+
+  private void checkOutputFile(File output, ModificationTracker tracker)
+      throws
+        MojoExecutionException
+  {
+    try
+    {
+      if (output.exists())
+        tracker.track(SCRIPT, new FileInputStream(output));
       else
-        getLog().debug("Using the value " + value + " for property " + key);
-      properties.setProperty(key, value.toString());
+        tracker.track(SCRIPT, ZonedDateTime.now().toString());
+    }
+    catch (IOException e)
+    {
+      String error =
+          "Error while checking the generated script: " + e.getMessage();
+      getLog().error(error);
+      throw new MojoExecutionException(error);
     }
-    return Boolean.valueOf(properties.getProperty(key));
   }
 
   private void addMappings(MetadataSources sources, ModificationTracker tracker)
@@ -1057,8 +1247,9 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
     try
     {
       getLog().info("Adding annotated resource: " + name);
-      String packageName;
+      String packageName = null;
 
+      boolean error = false;
       try
       {
         Class<?> annotatedClass = classLoaderService.classForName(name);
@@ -1069,17 +1260,29 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
                 resourceName.length()
                 ) + ".class";
         InputStream is = annotatedClass.getResourceAsStream(resourceName);
-        if (tracker.track(name, is))
-          getLog().debug("New or modified class: " + name);
+        if (is != null)
+        {
+          if (tracker.track(name, is))
+            getLog().debug("New or modified class: " + name);
+          else
+            getLog().debug("Unchanged class: " + name);
+          sources.addAnnotatedClass(annotatedClass);
+          packageName = annotatedClass.getPackage().getName();
+        }
         else
-          getLog().debug("Unchanged class: " + name);
-        sources.addAnnotatedClass(annotatedClass);
-        packageName = annotatedClass.getPackage().getName();
+        {
+          getLog().error("cannot find ressource " + resourceName + " for class " + name);
+          error = true;
+        }
       }
       catch(ClassLoadingException e)
       {
         packageName = name;
       }
+      if (error)
+      {
+        throw new MojoExecutionException("error while inspecting annotated class " + name);
+      }
 
       while (packageName != null)
       {
@@ -1129,48 +1332,41 @@ public abstract class AbstractSchemaMojo extends AbstractMojo
             PersistenceUnitTransactionType.RESOURCE_LOCAL
              );
 
-    List<ParsedPersistenceXmlDescriptor> units = parser.doResolve(properties);
+    Map<String, ParsedPersistenceXmlDescriptor> units =
+        parser.doResolve(properties);
 
     if (persistenceUnit == null)
     {
-      switch (units.size())
+      Iterator<String> names = units.keySet().iterator();
+      if (!names.hasNext())
       {
-        case 0:
-          getLog().info("Found no META-INF/persistence.xml.");
-          return null;
-        case 1:
-          getLog().info("Using persistence-unit " + units.get(0).getName());
-          return units.get(0);
-        default:
-          StringBuilder builder = new StringBuilder();
-          builder.append("No name provided and multiple persistence units found: ");
-          Iterator<ParsedPersistenceXmlDescriptor> it = units.iterator();
-          builder.append(it.next().getName());
-          while (it.hasNext())
-          {
-            builder.append(", ");
-            builder.append(it.next().getName());
-          }
-          builder.append('.');
-          throw new MojoFailureException(builder.toString());
+        getLog().info("Found no META-INF/persistence.xml.");
+        return null;
       }
-    }
 
-    for (ParsedPersistenceXmlDescriptor unit : units)
-    {
-      getLog().debug("Found persistence-unit " + unit.getName());
-      if (!unit.getName().equals(persistenceUnit))
-        continue;
+      String name = names.next();
+      if (!names.hasNext())
+      {
+          getLog().info("Using persistence-unit " + name);
+          return units.get(name);
+      }
 
-      // See if we (Hibernate) are the persistence provider
-      if (!ProviderChecker.isProvider(unit, properties))
+      StringBuilder builder = new StringBuilder();
+      builder.append("No name provided and multiple persistence units found: ");
+      builder.append(name);
+      while(names.hasNext())
       {
-        getLog().debug("Wrong provider: " + unit.getProviderClassName());
-        continue;
+        builder.append(", ");
+        builder.append(names.next());
       }
+      builder.append('.');
+      throw new MojoFailureException(builder.toString());
+    }
 
-      getLog().info("Using persistence-unit " + unit.getName());
-      return unit;
+    if (units.containsKey(persistenceUnit))
+    {
+      getLog().info("Using configured persistence-unit " + persistenceUnit);
+      return units.get(persistenceUnit);
     }
 
     throw new MojoFailureException("Could not find persistence-unit " + persistenceUnit);