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 @@ + + +
++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 } ++