X-Git-Url: https://juplo.de/gitweb/?a=blobdiff_plain;f=dist%2Fhibernate4-maven-plugin-1.0.2%2Fxref%2Fde%2Fjuplo%2Fplugins%2Fhibernate4%2FHbm2DdlMojo.html;fp=dist%2Fhibernate4-maven-plugin-1.0.2%2Fxref%2Fde%2Fjuplo%2Fplugins%2Fhibernate4%2FHbm2DdlMojo.html;h=fa2488ce59054583c460a10861ff8593d6943c65;hb=a53595184bd6e57bdc45292cc92c393c4e2dfe6e;hp=0000000000000000000000000000000000000000;hpb=c48c9ee0e9faa89a4c0a5323b367b9f5a6abe602;p=website diff --git a/dist/hibernate4-maven-plugin-1.0.2/xref/de/juplo/plugins/hibernate4/Hbm2DdlMojo.html b/dist/hibernate4-maven-plugin-1.0.2/xref/de/juplo/plugins/hibernate4/Hbm2DdlMojo.html new file mode 100644 index 00000000..fa2488ce --- /dev/null +++ b/dist/hibernate4-maven-plugin-1.0.2/xref/de/juplo/plugins/hibernate4/Hbm2DdlMojo.html @@ -0,0 +1,908 @@ + + +
+ ++ +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.Connection; +34 import java.sql.Driver; +35 import java.sql.DriverManager; +36 import java.sql.DriverPropertyInfo; +37 import java.sql.SQLException; +38 import java.sql.SQLFeatureNotSupportedException; +39 import java.util.Comparator; +40 import java.util.Enumeration; +41 import java.util.HashMap; +42 import java.util.HashSet; +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 javax.persistence.Embeddable; +51 import javax.persistence.Entity; +52 import javax.persistence.MappedSuperclass; +53 import org.apache.maven.model.Resource; +54 import org.apache.maven.plugin.AbstractMojo; +55 import org.apache.maven.plugin.MojoExecutionException; +56 import org.apache.maven.plugin.MojoFailureException; +57 import org.apache.maven.project.MavenProject; +58 import org.hibernate.cfg.Configuration; +59 import org.hibernate.cfg.NamingStrategy; +60 import org.hibernate.tool.hbm2ddl.SchemaExport; +61 import org.hibernate.tool.hbm2ddl.SchemaExport.Type; +62 import org.hibernate.tool.hbm2ddl.Target; +63 import org.scannotation.AnnotationDB; +64 +65 +66 /** +67 * Goal which extracts the hibernate-mapping-configuration and +68 * exports an according SQL-database-schema. +69 * +70 * @goal export +71 * @phase process-classes +72 * @threadSafe +73 * @requiresDependencyResolution runtime +74 */ +75 public class Hbm2DdlMojo extends AbstractMojo +76 { +77 public final static String EXPORT_SKIPPED_PROPERTY = "hibernate.export.skipped"; +78 +79 public final static String DRIVER_CLASS = "hibernate.connection.driver_class"; +80 public final static String URL = "hibernate.connection.url"; +81 public final static String USERNAME = "hibernate.connection.username"; +82 public final static String PASSWORD = "hibernate.connection.password"; +83 public final static String DIALECT = "hibernate.dialect"; +84 public final static String NAMING_STRATEGY="hibernate.ejb.naming_strategy"; +85 +86 private final static String MD5S = "schema.md5s"; +87 +88 /** +89 * The maven project. +90 * <p> +91 * Only needed internally. +92 * +93 * @parameter property="project" +94 * @required +95 * @readonly +96 */ +97 private MavenProject project; +98 +99 /** +100 * Build-directory. +101 * <p> +102 * Only needed internally. +103 * +104 * @parameter property="project.build.directory" +105 * @required +106 * @readonly +107 */ +108 private String buildDirectory; +109 +110 /** +111 * Classes-Directory to scan. +112 * <p> +113 * This parameter defaults to the maven build-output-directory for classes. +114 * Additonally, all dependencies are scanned for annotated classes. +115 * +116 * @parameter property="project.build.outputDirectory" +117 */ +118 private String outputDirectory; +119 +120 /** +121 * Wether to scan test-classes too, or not. +122 * <p> +123 * If this parameter is set to <code>true</code> the test-classes of the +124 * artifact will be scanned for hibernate-annotated classes additionally. +125 * +126 * @parameter property="hibernate.export.scan_testclasses" default-value="false" +127 */ +128 private boolean scanTestClasses; +129 +130 /** +131 * Test-Classes-Directory to scan. +132 * <p> +133 * This parameter defaults to the maven build-output-directory for +134 * test-classes. +135 * <p> +136 * This parameter is only used, when <code>scanTestClasses</code> is set +137 * to <code>true</code>! +138 * +139 * @parameter property="project.build.testOutputDirectory" +140 */ +141 private String testOutputDirectory; +142 +143 /** +144 * Skip execution +145 * <p> +146 * If set to <code>true</code>, the execution is skipped. +147 * <p> +148 * A skipped excecution is signaled via the maven-property +149 * <code>${hibernate.export.skipped}</code>. +150 * <p> +151 * The excecution is skipped automatically, if no modified or newly added +152 * annotated classes are found and the dialect was not changed. +153 * +154 * @parameter property="maven.test.skip" default-value="false" +155 */ +156 private boolean skip; +157 +158 /** +159 * Force execution +160 * <p> +161 * Force execution, even if no modified or newly added annotated classes +162 * where found and the dialect was not changed. +163 * <p> +164 * <code>skip</code> takes precedence over <code>force</code>. +165 * +166 * @parameter property="hibernate.export.force" default-value="false" +167 */ +168 private boolean force; +169 +170 /** +171 * SQL-Driver name. +172 * +173 * @parameter property="hibernate.connection.driver_class" +174 */ +175 private String driverClassName; +176 +177 /** +178 * Database URL. +179 * +180 * @parameter property="hibernate.connection.url" +181 */ +182 private String url; +183 +184 /** +185 * Database username +186 * +187 * @parameter property="hibernate.connection.username" +188 */ +189 private String username; +190 +191 /** +192 * Database password +193 * +194 * @parameter property="hibernate.connection.password" +195 */ +196 private String password; +197 +198 /** +199 * Hibernate dialect. +200 * +201 * @parameter property="hibernate.dialect" +202 */ +203 private String hibernateDialect; +204 +205 /** +206 * Hibernate Naming Strategy +207 * @parameter property="hibernate.ejb.naming_strategy" +208 */ +209 private String hibernateNamingStrategy; +210 +211 /** +212 * Path to Hibernate configuration file. +213 * +214 * @parameter default-value="${project.build.outputDirectory}/hibernate.properties" +215 */ +216 private String hibernateProperties; +217 +218 /** +219 * List of Hibernate-Mapping-Files (XML). +220 * Multiple files can be separated with white-spaces and/or commas. +221 * +222 * @parameter property="hibernate.mapping" +223 */ +224 private String hibernateMapping; +225 +226 /** +227 * Target of execution: +228 * <ul> +229 * <li><strong>NONE</strong> only export schema to SQL-script (forces excecution, signals skip)</li> +230 * <li><strong>EXPORT</strong> create database (<strong>DEFAULT!</strong>). forces excecution, signals skip)</li> +231 * <li><strong>SCRIPT</strong> export schema to SQL-script and print it to STDOUT</li> +232 * <li><strong>BOTH</strong></li> +233 * </ul> +234 * +235 * A databaseconnection is only needed for EXPORT and BOTH, but a +236 * Hibernate-Dialect must always be choosen. +237 * +238 * @parameter property="hibernate.export.target" default-value="EXPORT" +239 */ +240 private String target; +241 +242 /** +243 * Type of execution. +244 * <ul> +245 * <li><strong>NONE</strong> do nothing - just validate the configuration</li> +246 * <li><strong>CREATE</strong> create database-schema</li> +247 * <li><strong>DROP</strong> drop database-schema</li> +248 * <li><strong>BOTH</strong> (<strong>DEFAULT!</strong>)</li> +249 * </ul> +250 * +251 * If NONE is choosen, no databaseconnection is needed. +252 * +253 * @parameter property="hibernate.export.type" default-value="BOTH" +254 */ +255 private String type; +256 +257 /** +258 * Output file. +259 * +260 * @parameter property="hibernate.export.schema.filename" default-value="${project.build.directory}/schema.sql" +261 */ +262 private String outputFile; +263 +264 /** +265 * Delimiter in output-file. +266 * +267 * @parameter property="hibernate.export.schema.delimiter" default-value=";" +268 */ +269 private String delimiter; +270 +271 /** +272 * Format output-file. +273 * +274 * @parameter property="hibernate.export.schema.format" default-value="true" +275 */ +276 private boolean format; +277 +278 +279 @Override +280 public void execute() +281 throws +282 MojoFailureException, +283 MojoExecutionException +284 { +285 if (skip) +286 { +287 getLog().info("Exectuion of hibernate4-maven-plugin:export was skipped!"); +288 project.getProperties().setProperty(EXPORT_SKIPPED_PROPERTY, "true"); +289 return; +290 } +291 +292 File dir = new File(outputDirectory); +293 if (!dir.exists()) +294 throw new MojoExecutionException("Cannot scan for annotated classes in " + outputDirectory + ": directory does not exist!"); +295 +296 Map<String,String> md5s; +297 boolean modified = false; +298 File saved = new File(buildDirectory + File.separator + MD5S); +299 +300 if (saved.exists()) +301 { +302 try +303 { +304 FileInputStream fis = new FileInputStream(saved); +305 ObjectInputStream ois = new ObjectInputStream(fis); +306 md5s = (HashMap<String,String>)ois.readObject(); +307 ois.close(); +308 } +309 catch (Exception e) +310 { +311 md5s = new HashMap<String,String>(); +312 getLog().warn("Cannot read timestamps from saved: " + e); +313 } +314 } +315 else +316 { +317 md5s = new HashMap<String,String>(); +318 try +319 { +320 saved.createNewFile(); +321 } +322 catch (IOException e) +323 { +324 getLog().warn("Cannot create saved for timestamps: " + e); +325 } +326 } +327 +328 ClassLoader classLoader = null; +329 try +330 { +331 getLog().debug("Creating ClassLoader for project-dependencies..."); +332 List<String> classpathFiles = project.getCompileClasspathElements(); +333 if (scanTestClasses) +334 classpathFiles.addAll(project.getTestClasspathElements()); +335 URL[] urls = new URL[classpathFiles.size()]; +336 for (int i = 0; i < classpathFiles.size(); ++i) +337 { +338 getLog().debug("Dependency: " + classpathFiles.get(i)); +339 urls[i] = new File(classpathFiles.get(i)).toURI().toURL(); +340 } +341 classLoader = new URLClassLoader(urls, getClass().getClassLoader()); +342 } +343 catch (Exception e) +344 { +345 getLog().error("Error while creating ClassLoader!", e); +346 throw new MojoExecutionException(e.getMessage()); +347 } +348 +349 Set<Class<?>> classes = +350 new TreeSet<Class<?>>( +351 new Comparator<Class<?>>() { +352 @Override +353 public int compare(Class<?> a, Class<?> b) +354 { +355 return a.getName().compareTo(b.getName()); +356 } +357 } +358 ); +359 +360 try +361 { +362 AnnotationDB db = new AnnotationDB(); +363 getLog().info("Scanning directory " + outputDirectory + " for annotated classes..."); +364 URL dirUrl = dir.toURI().toURL(); +365 db.scanArchives(dirUrl); +366 if (scanTestClasses) +367 { +368 dir = new File(testOutputDirectory); +369 if (!dir.exists()) +370 throw new MojoExecutionException("Cannot scan for annotated test-classes in " + testOutputDirectory + ": directory does not exist!"); +371 getLog().info("Scanning directory " + testOutputDirectory + " for annotated classes..."); +372 dirUrl = dir.toURI().toURL(); +373 db.scanArchives(dirUrl); +374 } +375 +376 Set<String> classNames = new HashSet<String>(); +377 if (db.getAnnotationIndex().containsKey(Entity.class.getName())) +378 classNames.addAll(db.getAnnotationIndex().get(Entity.class.getName())); +379 if (db.getAnnotationIndex().containsKey(MappedSuperclass.class.getName())) +380 classNames.addAll(db.getAnnotationIndex().get(MappedSuperclass.class.getName())); +381 if (db.getAnnotationIndex().containsKey(Embeddable.class.getName())) +382 classNames.addAll(db.getAnnotationIndex().get(Embeddable.class.getName())); +383 +384 MessageDigest digest = java.security.MessageDigest.getInstance("MD5"); +385 for (String name : classNames) +386 { +387 Class<?> annotatedClass = classLoader.loadClass(name); +388 classes.add(annotatedClass); +389 InputStream is = +390 annotatedClass +391 .getResourceAsStream(annotatedClass.getSimpleName() + ".class"); +392 byte[] buffer = new byte[1024*4]; // copy data in 4MB-chunks +393 int i; +394 while((i = is.read(buffer)) > -1) +395 digest.update(buffer, 0, i); +396 is.close(); +397 byte[] bytes = digest.digest(); +398 BigInteger bi = new BigInteger(1, bytes); +399 String newMd5 = String.format("%0" + (bytes.length << 1) + "x", bi); +400 String oldMd5 = !md5s.containsKey(name) ? "" : md5s.get(name); +401 if (!newMd5.equals(oldMd5)) +402 { +403 getLog().debug("Found new or modified annotated class: " + name); +404 modified = true; +405 md5s.put(name, newMd5); +406 } +407 else +408 { +409 getLog().debug(oldMd5 + " -> class unchanged: " + name); +410 } +411 } +412 } +413 catch (ClassNotFoundException e) +414 { +415 getLog().error("Error while adding annotated classes!", e); +416 throw new MojoExecutionException(e.getMessage()); +417 } +418 catch (Exception e) +419 { +420 getLog().error("Error while scanning!", e); +421 throw new MojoFailureException(e.getMessage()); +422 } +423 +424 if (classes.isEmpty()) +425 { +426 if (hibernateMapping == null || hibernateMapping.isEmpty()) +427 throw new MojoFailureException("No annotated classes found in directory " + outputDirectory); +428 } +429 else +430 { +431 getLog().debug("Detected classes with mapping-annotations:"); +432 for (Class<?> annotatedClass : classes) +433 getLog().debug(" " + annotatedClass.getName()); +434 } +435 +436 +437 Properties properties = new Properties(); +438 +439 /** Try to read configuration from properties-file */ +440 try +441 { +442 File file = new File(hibernateProperties); +443 if (file.exists()) +444 { +445 getLog().info("Reading properties from file " + hibernateProperties + "..."); +446 properties.load(new FileInputStream(file)); +447 } +448 else +449 getLog().info("No hibernate-properties-file found! (Checked path: " + hibernateProperties + ")"); +450 } +451 catch (IOException e) +452 { +453 getLog().error("Error while reading properties!", e); +454 throw new MojoExecutionException(e.getMessage()); +455 } +456 +457 /** Overwrite values from propertie-file or set, if given */ +458 if (driverClassName != null) +459 { +460 if (properties.containsKey(DRIVER_CLASS)) +461 getLog().debug( +462 "Overwriting property " + +463 DRIVER_CLASS + "=" + properties.getProperty(DRIVER_CLASS) + +464 " with the value " + driverClassName +465 ); +466 else +467 getLog().debug("Using the value " + driverClassName); +468 properties.setProperty(DRIVER_CLASS, driverClassName); +469 } +470 if (url != null) +471 { +472 if (properties.containsKey(URL)) +473 getLog().debug( +474 "Overwriting property " + +475 URL + "=" + properties.getProperty(URL) + +476 " with the value " + url +477 ); +478 else +479 getLog().debug("Using the value " + url); +480 properties.setProperty(URL, url); +481 } +482 if (username != null) +483 { +484 if (properties.containsKey(USERNAME)) +485 getLog().debug( +486 "Overwriting property " + +487 USERNAME + "=" + properties.getProperty(USERNAME) + +488 " with the value " + username +489 ); +490 else +491 getLog().debug("Using the value " + username); +492 properties.setProperty(USERNAME, username); +493 } +494 if (password != null) +495 { +496 if (properties.containsKey(PASSWORD)) +497 getLog().debug( +498 "Overwriting property " + +499 PASSWORD + "=" + properties.getProperty(PASSWORD) + +500 " with the value " + password +501 ); +502 else +503 getLog().debug("Using the value " + password); +504 properties.setProperty(PASSWORD, password); +505 } +506 if (hibernateDialect != null) +507 { +508 if (properties.containsKey(DIALECT)) +509 getLog().debug( +510 "Overwriting property " + +511 DIALECT + "=" + properties.getProperty(DIALECT) + +512 " with the value " + hibernateDialect +513 ); +514 else +515 getLog().debug("Using the value " + hibernateDialect); +516 properties.setProperty(DIALECT, hibernateDialect); +517 } +518 if ( hibernateNamingStrategy != null ) +519 { +520 if ( properties.contains(NAMING_STRATEGY)) +521 getLog().debug( +522 "Overwriting property " + +523 NAMING_STRATEGY + "=" + properties.getProperty(NAMING_STRATEGY) + +524 " with the value " + hibernateNamingStrategy +525 ); +526 else +527 getLog().debug("Using the value " + hibernateNamingStrategy); +528 properties.setProperty(NAMING_STRATEGY, hibernateNamingStrategy); +529 } +530 +531 /** The generated SQL varies with the dialect! */ +532 if (md5s.containsKey(DIALECT)) +533 { +534 String dialect = properties.getProperty(DIALECT); +535 if (md5s.get(DIALECT).equals(dialect)) +536 getLog().debug("SQL-dialect unchanged."); +537 else +538 { +539 getLog().debug("SQL-dialect changed: " + dialect); +540 modified = true; +541 md5s.put(DIALECT, dialect); +542 } +543 } +544 else +545 { +546 modified = true; +547 md5s.put(DIALECT, properties.getProperty(DIALECT)); +548 } +549 +550 if (properties.isEmpty()) +551 { +552 getLog().error("No properties set!"); +553 throw new MojoFailureException("Hibernate-Configuration is missing!"); +554 } +555 +556 Configuration config = new Configuration(); +557 config.setProperties(properties); +558 +559 if ( properties.containsKey(NAMING_STRATEGY)) +560 { +561 String namingStrategy = properties.getProperty(NAMING_STRATEGY); +562 getLog().debug("Explicitly set NamingStrategy: " + namingStrategy); +563 try +564 { +565 @SuppressWarnings("unchecked") +566 Class<NamingStrategy> namingStrategyClass = (Class<NamingStrategy>) Class.forName(namingStrategy); +567 config.setNamingStrategy(namingStrategyClass.newInstance()); +568 } +569 catch (Exception e) +570 { +571 getLog().error("Error setting NamingStrategy", e); +572 throw new MojoExecutionException(e.getMessage()); +573 } +574 } +575 +576 getLog().debug("Adding annotated classes to hibernate-mapping-configuration..."); +577 for (Class<?> annotatedClass : classes) +578 { +579 getLog().debug("Class " + annotatedClass); +580 config.addAnnotatedClass(annotatedClass); +581 } +582 +583 if (hibernateMapping != null) +584 { +585 try +586 { +587 MessageDigest digest = java.security.MessageDigest.getInstance("MD5"); +588 for (String filename : hibernateMapping.split("[\\s,]+")) +589 { +590 // First try the filename as absolute/relative path +591 File file = new File(filename); +592 if (!file.exists()) +593 { +594 // If the file was not found, search for it in the resource-directories +595 for (Resource resource : project.getResources()) +596 { +597 file = new File(resource.getDirectory() + File.separator + filename); +598 if (file.exists()) +599 break; +600 } +601 } +602 if (file != null && file.exists()) +603 { +604 InputStream is = new FileInputStream(file); +605 byte[] buffer = new byte[1024*4]; // copy data in 4MB-chunks +606 int i; +607 while((i = is.read(buffer)) > -1) +608 digest.update(buffer, 0, i); +609 is.close(); +610 byte[] bytes = digest.digest(); +611 BigInteger bi = new BigInteger(1, bytes); +612 String newMd5 = String.format("%0" + (bytes.length << 1) + "x", bi); +613 String oldMd5 = !md5s.containsKey(filename) ? "" : md5s.get(filename); +614 if (!newMd5.equals(oldMd5)) +615 { +616 getLog().debug("Found new or modified mapping-file: " + filename); +617 modified = true; +618 md5s.put(filename, newMd5); +619 } +620 else +621 { +622 getLog().debug(oldMd5 + " -> mapping-file unchanged: " + filename); +623 } +624 getLog().debug("Adding mappings from XML-configurationfile: " + file); +625 config.addFile(file); +626 } +627 else +628 throw new MojoFailureException("File " + filename + " could not be found in any of the configured resource-directories!"); +629 } +630 } +631 catch (NoSuchAlgorithmException e) +632 { +633 throw new MojoFailureException("Cannot calculate MD5-summs!", e); +634 } +635 catch (FileNotFoundException e) +636 { +637 throw new MojoFailureException("Cannot calculate MD5-summs!", e); +638 } +639 catch (IOException e) +640 { +641 throw new MojoFailureException("Cannot calculate MD5-summs!", e); +642 } +643 } +644 +645 Target target = null; +646 try +647 { +648 target = Target.valueOf(this.target.toUpperCase()); +649 } +650 catch (IllegalArgumentException e) +651 { +652 getLog().error("Invalid value for configuration-option \"target\": " + this.target); +653 getLog().error("Valid values are: NONE, SCRIPT, EXPORT, BOTH"); +654 throw new MojoExecutionException("Invalid value for configuration-option \"target\""); +655 } +656 Type type = null; +657 try +658 { +659 type = Type.valueOf(this.type.toUpperCase()); +660 } +661 catch (IllegalArgumentException e) +662 { +663 getLog().error("Invalid value for configuration-option \"type\": " + this.type); +664 getLog().error("Valid values are: NONE, CREATE, DROP, BOTH"); +665 throw new MojoExecutionException("Invalid value for configuration-option \"type\""); +666 } +667 +668 if (target.equals(Target.SCRIPT) || target.equals(Target.NONE)) +669 { +670 project.getProperties().setProperty(EXPORT_SKIPPED_PROPERTY, "true"); +671 } +672 if ( +673 !modified +674 && !target.equals(Target.SCRIPT) +675 && !target.equals(Target.NONE) +676 && !force +677 ) +678 { +679 getLog().info("No modified annotated classes or mapping-files found and dialect unchanged."); +680 getLog().info("Skipping schema generation!"); +681 project.getProperties().setProperty(EXPORT_SKIPPED_PROPERTY, "true"); +682 return; +683 } +684 +685 getLog().info("Gathered hibernate-configuration (turn on debugging for details):"); +686 for (Entry<Object,Object> entry : properties.entrySet()) +687 getLog().info(" " + entry.getKey() + " = " + entry.getValue()); +688 +689 Connection connection = null; +690 try +691 { +692 /** +693 * The connection must be established outside of hibernate, because +694 * hibernate does not use the context-classloader of the current +695 * thread and, hence, would not be able to resolve the driver-class! +696 */ +697 getLog().debug("Target: " + target + ", Type: " + type); +698 switch (target) +699 { +700 case EXPORT: +701 case BOTH: +702 switch (type) +703 { +704 case CREATE: +705 case DROP: +706 case BOTH: +707 Class driverClass = classLoader.loadClass(properties.getProperty(DRIVER_CLASS)); +708 getLog().debug("Registering JDBC-driver " + driverClass.getName()); +709 DriverManager.registerDriver(new DriverProxy((Driver)driverClass.newInstance())); +710 getLog().debug( +711 "Opening JDBC-connection to " +712 + properties.getProperty(URL) +713 + " as " +714 + properties.getProperty(USERNAME) +715 + " with password " +716 + properties.getProperty(PASSWORD) +717 ); +718 connection = DriverManager.getConnection( +719 properties.getProperty(URL), +720 properties.getProperty(USERNAME), +721 properties.getProperty(PASSWORD) +722 ); +723 } +724 } +725 } +726 catch (ClassNotFoundException e) +727 { +728 getLog().error("Dependency for driver-class " + properties.getProperty(DRIVER_CLASS) + " is missing!"); +729 throw new MojoExecutionException(e.getMessage()); +730 } +731 catch (Exception e) +732 { +733 getLog().error("Cannot establish connection to database!"); +734 Enumeration<Driver> drivers = DriverManager.getDrivers(); +735 if (!drivers.hasMoreElements()) +736 getLog().error("No drivers registered!"); +737 while (drivers.hasMoreElements()) +738 getLog().debug("Driver: " + drivers.nextElement()); +739 throw new MojoExecutionException(e.getMessage()); +740 } +741 +742 ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); +743 MavenLogAppender.startPluginLog(this); +744 try +745 { +746 /** +747 * Change class-loader of current thread, so that hibernate can +748 * see all dependencies! +749 */ +750 Thread.currentThread().setContextClassLoader(classLoader); +751 +752 SchemaExport export = new SchemaExport(config, connection); +753 export.setOutputFile(outputFile); +754 export.setDelimiter(delimiter); +755 export.setFormat(format); +756 export.execute(target, type); +757 +758 for (Object exception : export.getExceptions()) +759 getLog().debug(exception.toString()); +760 } +761 finally +762 { +763 /** Stop Log-Capturing */ +764 MavenLogAppender.endPluginLog(this); +765 +766 /** Restore the old class-loader (TODO: is this really necessary?) */ +767 Thread.currentThread().setContextClassLoader(contextClassLoader); +768 +769 /** Close the connection */ +770 try +771 { +772 if (connection != null) +773 connection.close(); +774 } +775 catch (SQLException e) +776 { +777 getLog().error("Error while closing connection: " + e.getMessage()); +778 } +779 } +780 +781 /** Write md5-sums for annotated classes to file */ +782 try +783 { +784 FileOutputStream fos = new FileOutputStream(saved); +785 ObjectOutputStream oos = new ObjectOutputStream(fos); +786 oos.writeObject(md5s); +787 oos.close(); +788 fos.close(); +789 } +790 catch (Exception e) +791 { +792 getLog().error("Cannot write md5-sums to file: " + e); +793 } +794 } +795 +796 /** +797 * Needed, because DriverManager won't pick up drivers, that were not +798 * loaded by the system-classloader! +799 * See: +800 * http://stackoverflow.com/questions/288828/how-to-use-a-jdbc-driver-fromodifiedm-an-arbitrary-location +801 */ +802 static final class DriverProxy implements Driver +803 { +804 private final Driver target; +805 +806 DriverProxy(Driver target) +807 { +808 if (target == null) +809 throw new NullPointerException(); +810 this.target = target; +811 } +812 +813 public java.sql.Driver getTarget() +814 { +815 return target; +816 } +817 +818 @Override +819 public boolean acceptsURL(String url) throws SQLException +820 { +821 return target.acceptsURL(url); +822 } +823 +824 @Override +825 public java.sql.Connection connect( +826 String url, +827 java.util.Properties info +828 ) +829 throws +830 SQLException +831 { +832 return target.connect(url, info); +833 } +834 +835 @Override +836 public int getMajorVersion() +837 { +838 return target.getMajorVersion(); +839 } +840 +841 @Override +842 public int getMinorVersion() +843 { +844 return target.getMinorVersion(); +845 } +846 +847 @Override +848 public DriverPropertyInfo[] getPropertyInfo( +849 String url, +850 Properties info +851 ) +852 throws +853 SQLException +854 { +855 return target.getPropertyInfo(url, info); +856 } +857 +858 @Override +859 public boolean jdbcCompliant() +860 { +861 return target.jdbcCompliant(); +862 } +863 +864 /** +865 * This Method cannot be annotated with @Override, becaus the plugin +866 * will not compile then under Java 1.6! +867 */ +868 public Logger getParentLogger() throws SQLFeatureNotSupportedException +869 { +870 throw new SQLFeatureNotSupportedException("Not supported, for backward-compatibility with Java 1.6"); +871 } +872 +873 @Override +874 public String toString() +875 { +876 return "Proxy: " + target; +877 } +878 +879 @Override +880 public int hashCode() +881 { +882 return target.hashCode(); +883 } +884 +885 @Override +886 public boolean equals(Object obj) +887 { +888 if (!(obj instanceof DriverProxy)) +889 return false; +890 DriverProxy other = (DriverProxy) obj; +891 return this.target.equals(other.target); +892 } +893 } +894 } ++