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