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