1 package de.juplo.plugins.hibernate4;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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.Driver;
34 import java.sql.DriverPropertyInfo;
35 import java.sql.SQLException;
36 import java.sql.SQLFeatureNotSupportedException;
37 import java.util.Collections;
38 import java.util.Comparator;
39 import java.util.HashMap;
40 import java.util.HashSet;
41 import java.util.LinkedHashSet;
42 import java.util.LinkedList;
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 javax.persistence.spi.PersistenceUnitTransactionType;
56 import org.apache.maven.artifact.Artifact;
57 import org.apache.maven.model.Resource;
58 import org.apache.maven.plugin.AbstractMojo;
59 import org.apache.maven.plugin.MojoExecutionException;
60 import org.apache.maven.plugin.MojoFailureException;
61 import org.apache.maven.project.MavenProject;
62 import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
63 import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
64 import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
65 import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
66 import org.hibernate.cfg.Environment;
67 import org.hibernate.cfg.NamingStrategy;
68 import org.hibernate.envers.configuration.spi.AuditConfiguration;
69 import org.hibernate.internal.util.config.ConfigurationHelper;
70 import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
71 import org.hibernate.jpa.boot.internal.PersistenceXmlParser;
72 import org.hibernate.jpa.boot.spi.ProviderChecker;
73 import org.hibernate.tool.hbm2ddl.SchemaExport;
74 import org.hibernate.tool.hbm2ddl.SchemaExport.Type;
75 import org.hibernate.tool.hbm2ddl.Target;
76 import org.scannotation.AnnotationDB;
77
78
79
80
81
82
83
84
85
86
87
88 public class Hbm2DdlMojo extends AbstractMojo
89 {
90 public final static String EXPORT_SKIPPED_PROPERTY = "hibernate.export.skipped";
91
92 public final static String DRIVER_CLASS = "hibernate.connection.driver_class";
93 public final static String URL = "hibernate.connection.url";
94 public final static String USERNAME = "hibernate.connection.username";
95 public final static String PASSWORD = "hibernate.connection.password";
96 public final static String DIALECT = "hibernate.dialect";
97 public final static String NAMING_STRATEGY="hibernate.ejb.naming_strategy";
98 public final static String ENVERS = "hibernate.export.envers";
99
100 public final static String JPA_DRIVER = "javax.persistence.jdbc.driver";
101 public final static String JPA_URL = "javax.persistence.jdbc.url";
102 public final static String JPA_USERNAME = "javax.persistence.jdbc.user";
103 public final static String JPA_PASSWORD = "javax.persistence.jdbc.password";
104
105 public final static String MD5S = "hibernate4-generatedschema.md5s";
106
107 private final static Pattern split = Pattern.compile("[^,\\s]+");
108
109
110
111
112
113
114
115
116
117
118
119 private MavenProject project;
120
121
122
123
124
125
126
127
128
129
130 private String buildDirectory;
131
132
133
134
135
136
137
138
139
140
141 private String outputDirectory;
142
143
144
145
146
147
148
149
150
151
152 private boolean scanTestClasses;
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171 private String scanDependencies;
172
173
174
175
176
177
178
179
180
181
182
183
184
185 private String testOutputDirectory;
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201 private boolean skip;
202
203
204
205
206
207
208
209
210
211
212
213
214 private boolean force;
215
216
217
218
219
220
221
222 private String driverClassName;
223
224
225
226
227
228
229
230 private String url;
231
232
233
234
235
236
237
238 private String username;
239
240
241
242
243
244
245
246 private String password;
247
248
249
250
251
252
253
254 private String hibernateDialect;
255
256
257
258
259
260
261
262 private String hibernateNamingStrategy;
263
264
265
266
267
268
269
270
271
272
273 private String hibernateProperties;
274
275
276
277
278
279
280
281
282
283
284
285 private String hibernateConfig;
286
287
288
289
290
291
292
293
294
295
296
297 private String persistenceUnit;
298
299
300
301
302
303
304
305
306 private String hibernateMapping;
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323 private String target;
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339 private String type;
340
341
342
343
344
345
346
347 private String outputFile;
348
349
350
351
352
353
354
355 private String delimiter;
356
357
358
359
360
361
362
363 private boolean format;
364
365
366
367
368
369
370
371 private boolean envers;
372
373
374 @Override
375 public void execute()
376 throws
377 MojoFailureException,
378 MojoExecutionException
379 {
380 if (skip)
381 {
382 getLog().info("Execution of hibernate4-maven-plugin:export was skipped!");
383 project.getProperties().setProperty(EXPORT_SKIPPED_PROPERTY, "true");
384 return;
385 }
386
387 Map<String,String> md5s;
388 boolean modified = false;
389 File saved = new File(buildDirectory + File.separator + MD5S);
390
391 if (saved.isFile() && saved.length() > 0)
392 {
393 try
394 {
395 FileInputStream fis = new FileInputStream(saved);
396 ObjectInputStream ois = new ObjectInputStream(fis);
397 md5s = (HashMap<String,String>)ois.readObject();
398 ois.close();
399 }
400 catch (Exception e)
401 {
402 md5s = new HashMap<String,String>();
403 getLog().warn("Cannot read timestamps from saved: " + e);
404 }
405 }
406 else
407 {
408 md5s = new HashMap<String,String>();
409 try
410 {
411 saved.createNewFile();
412 }
413 catch (IOException e)
414 {
415 getLog().debug("Cannot create file \"" + saved.getPath() + "\" for timestamps: " + e);
416 }
417 }
418
419 URLClassLoader classLoader = null;
420 try
421 {
422 getLog().debug("Creating ClassLoader for project-dependencies...");
423 List<String> classpathFiles = project.getCompileClasspathElements();
424 if (scanTestClasses)
425 classpathFiles.addAll(project.getTestClasspathElements());
426 List<URL> urls = new LinkedList<URL>();
427 File file;
428 file = new File(testOutputDirectory);
429 if (!file.exists())
430 {
431 getLog().info("creating test-output-directory: " + testOutputDirectory);
432 file.mkdirs();
433 }
434 urls.add(file.toURI().toURL());
435 file = new File(outputDirectory);
436 if (!file.exists())
437 {
438 getLog().info("creating output-directory: " + outputDirectory);
439 file.mkdirs();
440 }
441 urls.add(file.toURI().toURL());
442 for (String pathElement : classpathFiles)
443 {
444 getLog().debug("Dependency: " + pathElement);
445 urls.add(new File(pathElement).toURI().toURL());
446 }
447 classLoader =
448 new URLClassLoader(
449 urls.toArray(new URL[urls.size()]),
450 getClass().getClassLoader()
451 );
452 }
453 catch (Exception e)
454 {
455 getLog().error("Error while creating ClassLoader!", e);
456 throw new MojoExecutionException(e.getMessage());
457 }
458
459 Set<Class<?>> classes =
460 new TreeSet<Class<?>>(
461 new Comparator<Class<?>>() {
462 @Override
463 public int compare(Class<?> a, Class<?> b)
464 {
465 return a.getName().compareTo(b.getName());
466 }
467 }
468 );
469
470 try
471 {
472 AnnotationDB db = new AnnotationDB();
473 File dir = new File(outputDirectory);
474 if (dir.exists())
475 {
476 getLog().info("Scanning directory " + outputDirectory + " for annotated classes...");
477 URL dirUrl = dir.toURI().toURL();
478 db.scanArchives(dirUrl);
479 }
480 if (scanTestClasses)
481 {
482 dir = new File(testOutputDirectory);
483 if (dir.exists())
484 {
485 getLog().info("Scanning directory " + testOutputDirectory + " for annotated classes...");
486 URL dirUrl = dir.toURI().toURL();
487 db.scanArchives(dirUrl);
488 }
489 }
490 if (scanDependencies != null)
491 {
492 Matcher matcher = split.matcher(scanDependencies);
493 while (matcher.find())
494 {
495 getLog().info("Scanning dependencies for scope " + matcher.group());
496 for (Artifact artifact : project.getDependencyArtifacts())
497 {
498 if (!artifact.getScope().equalsIgnoreCase(matcher.group()))
499 continue;
500 if (artifact.getFile() == null)
501 {
502 getLog().warn(
503 "Cannot scan dependency " +
504 artifact.getId() +
505 ": no JAR-file available!"
506 );
507 continue;
508 }
509 getLog().info(
510 "Scanning dependency " +
511 artifact.getId() +
512 " for annotated classes..."
513 );
514 db.scanArchives(artifact.getFile().toURI().toURL());
515 }
516 }
517 }
518
519 Set<String> classNames = new HashSet<String>();
520 if (db.getAnnotationIndex().containsKey(Entity.class.getName()))
521 classNames.addAll(db.getAnnotationIndex().get(Entity.class.getName()));
522 if (db.getAnnotationIndex().containsKey(MappedSuperclass.class.getName()))
523 classNames.addAll(db.getAnnotationIndex().get(MappedSuperclass.class.getName()));
524 if (db.getAnnotationIndex().containsKey(Embeddable.class.getName()))
525 classNames.addAll(db.getAnnotationIndex().get(Embeddable.class.getName()));
526
527 MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
528 for (String name : classNames)
529 {
530 Class<?> annotatedClass = classLoader.loadClass(name);
531 classes.add(annotatedClass);
532 String resourceName = annotatedClass.getName();
533 resourceName = resourceName.substring(resourceName.lastIndexOf(".") + 1, resourceName.length()) + ".class";
534 InputStream is =
535 annotatedClass
536 .getResourceAsStream(resourceName);
537 byte[] buffer = new byte[1024*4];
538 int i;
539 while((i = is.read(buffer)) > -1)
540 digest.update(buffer, 0, i);
541 is.close();
542 byte[] bytes = digest.digest();
543 BigInteger bi = new BigInteger(1, bytes);
544 String newMd5 = String.format("%0" + (bytes.length << 1) + "x", bi);
545 String oldMd5 = !md5s.containsKey(name) ? "" : md5s.get(name);
546 if (!newMd5.equals(oldMd5))
547 {
548 getLog().debug("Found new or modified annotated class: " + name);
549 modified = true;
550 md5s.put(name, newMd5);
551 }
552 else
553 {
554 getLog().debug(oldMd5 + " -> class unchanged: " + name);
555 }
556 }
557 }
558 catch (ClassNotFoundException e)
559 {
560 getLog().error("Error while adding annotated classes!", e);
561 throw new MojoExecutionException(e.getMessage());
562 }
563 catch (Exception e)
564 {
565 getLog().error("Error while scanning!", e);
566 throw new MojoFailureException(e.getMessage());
567 }
568
569
570 ValidationConfiguration config = new ValidationConfiguration();
571
572 config.setProperties(new Properties());
573
574
575 ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
576 StandardServiceRegistryImpl registry = null;
577 MavenLogAppender.startPluginLog(this);
578
579 try
580 {
581
582
583
584
585 Thread.currentThread().setContextClassLoader(classLoader);
586
587
588
589 try
590 {
591 if (hibernateProperties == null)
592 {
593 URL url = classLoader.findResource("hibernate.properties");
594 if (url == null)
595 {
596 getLog().info("No hibernate.properties on the classpath!");
597 }
598 else
599 {
600 getLog().info("Reading settings from hibernate.properties on the classpath.");
601 Properties properties = new Properties();
602 properties.load(url.openStream());
603 config.setProperties(properties);
604 }
605 }
606 else
607 {
608 File file = new File(hibernateProperties);
609 if (file.exists())
610 {
611 getLog().info("Reading settings from file " + hibernateProperties + "...");
612 Properties properties = new Properties();
613 properties.load(new FileInputStream(file));
614 config.setProperties(properties);
615 }
616 else
617 getLog().info("No hibernate-properties-file found! (Checked path: " + hibernateProperties + ")");
618 }
619 }
620 catch (IOException e)
621 {
622 getLog().error("Error while reading properties!", e);
623 throw new MojoExecutionException(e.getMessage());
624 }
625
626
627 try
628 {
629 if (hibernateConfig == null)
630 {
631 URL url = classLoader.findResource("hibernate.cfg.xml");
632 if (url == null)
633 {
634 getLog().info("No hibernate.cfg.xml on the classpath!");
635 }
636 else
637 {
638 getLog().info("Reading settings from hibernate.cfg.xml on the classpath.");
639 config.configure(url);
640 }
641 }
642 else
643 {
644 File file = new File(hibernateConfig);
645 if (file.exists())
646 {
647 getLog().info("Reading configuration from file " + hibernateConfig + "...");
648 config.configure(file);
649 }
650 else
651 getLog().info("No hibernate-configuration-file found! (Checked path: " + hibernateConfig + ")");
652 }
653 }
654 catch (Exception e)
655 {
656 getLog().error("Error while reading configuration!", e);
657 throw new MojoExecutionException(e.getMessage());
658 }
659
660 ParsedPersistenceXmlDescriptor persistenceUnitDescriptor =
661 getPersistenceUnitDescriptor(
662 persistenceUnit,
663 config.getProperties(),
664 new MavenProjectClassLoaderService(classLoader)
665 );
666 if (persistenceUnitDescriptor != null)
667 config.setProperties(persistenceUnitDescriptor.getProperties());
668
669
670
671
672 if (driverClassName != null)
673 {
674 if (config.getProperties().containsKey(DRIVER_CLASS))
675 getLog().debug(
676 "Overwriting property " +
677 DRIVER_CLASS + "=" + config.getProperty(DRIVER_CLASS) +
678 " with the value " + driverClassName
679 );
680 else
681 getLog().debug("Using the value " + driverClassName);
682 config.setProperty(DRIVER_CLASS, driverClassName);
683 }
684 if (config.getProperty(DRIVER_CLASS) == null)
685 {
686 String driver = config.getProperty(JPA_DRIVER);
687 if (driver != null)
688 {
689 getLog().info(
690 DRIVER_CLASS +
691 " is not set. Borrow setting from " +
692 JPA_DRIVER +
693 ": " +
694 driver);
695 config.setProperty(DRIVER_CLASS, driver);
696 }
697 }
698
699 if (url != null)
700 {
701 if (config.getProperties().containsKey(URL))
702 getLog().debug(
703 "Overwriting property " +
704 URL + "=" + config.getProperty(URL) +
705 " with the value " + url
706 );
707 else
708 getLog().debug("Using the value " + url);
709 config.setProperty(URL, url);
710 }
711 if (config.getProperty(URL) == null)
712 {
713 String url = config.getProperty(JPA_URL);
714 if (url != null)
715 {
716 getLog().info(
717 URL +
718 " is not set. Borrow setting from " +
719 JPA_URL +
720 ": " +
721 url);
722 config.setProperty(URL, url);
723 }
724 }
725
726 if (username != null)
727 {
728 if (config.getProperties().containsKey(USERNAME))
729 getLog().debug(
730 "Overwriting property " +
731 USERNAME + "=" + config.getProperty(USERNAME) +
732 " with the value " + username
733 );
734 else
735 getLog().debug("Using the value " + username);
736 config.setProperty(USERNAME, username);
737 }
738 if (config.getProperty(USERNAME) == null)
739 {
740 String username = config.getProperty(JPA_USERNAME);
741 if (username != null)
742 {
743 getLog().info(
744 USERNAME +
745 " is not set. Borrow setting from " +
746 JPA_USERNAME +
747 ": " +
748 username);
749 config.setProperty(USERNAME, username);
750 }
751 }
752
753 if (password != null)
754 {
755 if (config.getProperties().containsKey(PASSWORD))
756 getLog().debug(
757 "Overwriting property " +
758 PASSWORD + "=" + config.getProperty(PASSWORD) +
759 " with value " + password
760 );
761 else
762 getLog().debug("Using value " + password + " for property " + PASSWORD);
763 config.setProperty(PASSWORD, password);
764 }
765 if (config.getProperty(PASSWORD) == null)
766 {
767 String password = config.getProperty(JPA_PASSWORD);
768 if (password != null)
769 {
770 getLog().info(
771 PASSWORD +
772 " is not set. Borrow setting from " +
773 JPA_PASSWORD +
774 ": " +
775 password);
776 config.setProperty(PASSWORD, password);
777 }
778 }
779
780 if (hibernateDialect != null)
781 {
782 if (config.getProperties().containsKey(DIALECT))
783 getLog().debug(
784 "Overwriting property " +
785 DIALECT + "=" + config.getProperty(DIALECT) +
786 " with value " + hibernateDialect
787 );
788 else
789 getLog().debug(
790 "Using value " + hibernateDialect + " for property " + DIALECT
791 );
792 config.setProperty(DIALECT, hibernateDialect);
793 }
794
795 if ( hibernateNamingStrategy != null )
796 {
797 if ( config.getProperties().contains(NAMING_STRATEGY))
798 getLog().debug(
799 "Overwriting property " +
800 NAMING_STRATEGY + "=" + config.getProperty(NAMING_STRATEGY) +
801 " with value " + hibernateNamingStrategy
802 );
803 else
804 getLog().debug(
805 "Using value " + hibernateNamingStrategy + " for property " +
806 NAMING_STRATEGY
807 );
808 config.setProperty(NAMING_STRATEGY, hibernateNamingStrategy);
809 }
810
811
812 if (md5s.containsKey(DIALECT))
813 {
814 String dialect = config.getProperty(DIALECT);
815 if (md5s.get(DIALECT).equals(dialect))
816 getLog().debug("SQL-dialect unchanged.");
817 else
818 {
819 modified = true;
820 if (dialect == null)
821 {
822 getLog().debug("SQL-dialect was unset.");
823 md5s.remove(DIALECT);
824 }
825 else
826 {
827 getLog().debug("SQL-dialect changed: " + dialect);
828 md5s.put(DIALECT, dialect);
829 }
830 }
831 }
832 else
833 {
834 String dialect = config.getProperty(DIALECT);
835 if (dialect != null)
836 {
837 modified = true;
838 md5s.put(DIALECT, config.getProperty(DIALECT));
839 }
840 }
841
842
843 if (md5s.get(ENVERS) != null)
844 {
845 if (md5s.get(ENVERS).equals(Boolean.toString(envers)))
846 getLog().debug("Envers-Configuration unchanged. Enabled: " + envers);
847 else
848 {
849 getLog().debug("Envers-Configuration changed. Enabled: " + envers);
850 modified = true;
851 md5s.put(ENVERS, Boolean.toString(envers));
852 }
853 }
854 else
855 {
856 modified = true;
857 md5s.put(ENVERS, Boolean.toString(envers));
858 }
859
860 if (config.getProperties().isEmpty())
861 {
862 getLog().error("No properties set!");
863 throw new MojoFailureException("Hibernate configuration is missing!");
864 }
865
866 getLog().info("Gathered hibernate-configuration (turn on debugging for details):");
867 for (Entry<Object,Object> entry : config.getProperties().entrySet())
868 getLog().info(" " + entry.getKey() + " = " + entry.getValue());
869
870
871 getLog().debug("Adding explicitly configured mappings...");
872 if (hibernateMapping != null)
873 {
874 try
875 {
876 MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
877 for (String filename : hibernateMapping.split("[\\s,]+"))
878 {
879
880 File file = new File(filename);
881 if (!file.exists())
882 {
883
884 for (Resource resource : project.getResources())
885 {
886 file = new File(resource.getDirectory() + File.separator + filename);
887 if (file.exists())
888 break;
889 }
890 }
891 if (file != null && file.exists())
892 {
893 InputStream is = new FileInputStream(file);
894 byte[] buffer = new byte[1024*4];
895 int i;
896 while((i = is.read(buffer)) > -1)
897 digest.update(buffer, 0, i);
898 is.close();
899 byte[] bytes = digest.digest();
900 BigInteger bi = new BigInteger(1, bytes);
901 String newMd5 = String.format("%0" + (bytes.length << 1) + "x", bi);
902 String oldMd5 = !md5s.containsKey(filename) ? "" : md5s.get(filename);
903 if (!newMd5.equals(oldMd5))
904 {
905 getLog().debug("Found new or modified mapping-file: " + filename);
906 modified = true;
907 md5s.put(filename, newMd5);
908 }
909 else
910 {
911 getLog().debug(oldMd5 + " -> mapping-file unchanged: " + filename);
912 }
913 getLog().debug("Adding mappings from XML-configurationfile: " + file);
914 config.addFile(file);
915 }
916 else
917 throw new MojoFailureException("File " + filename + " could not be found in any of the configured resource-directories!");
918 }
919 }
920 catch (NoSuchAlgorithmException e)
921 {
922 throw new MojoFailureException("Cannot calculate MD5 sums!", e);
923 }
924 catch (FileNotFoundException e)
925 {
926 throw new MojoFailureException("Cannot calculate MD5 sums!", e);
927 }
928 catch (IOException e)
929 {
930 throw new MojoFailureException("Cannot calculate MD5 sums!", e);
931 }
932 }
933
934 getLog().debug("Adding annotated classes to hibernate-mapping-configuration...");
935
936 Set<String> packages = new HashSet<String>();
937 for (Class<?> annotatedClass : classes)
938 {
939 String packageName = annotatedClass.getPackage().getName();
940 if (!packages.contains(packageName))
941 {
942 getLog().debug("Add package " + packageName);
943 packages.add(packageName);
944 config.addPackage(packageName);
945 getLog().debug("type definintions" + config.getTypeDefs());
946 }
947 getLog().debug("Class " + annotatedClass);
948 config.addAnnotatedClass(annotatedClass);
949 }
950
951 Target target = null;
952 try
953 {
954 target = Target.valueOf(this.target.toUpperCase());
955 }
956 catch (IllegalArgumentException e)
957 {
958 getLog().error("Invalid value for configuration-option \"target\": " + this.target);
959 getLog().error("Valid values are: NONE, SCRIPT, EXPORT, BOTH");
960 throw new MojoExecutionException("Invalid value for configuration-option \"target\"");
961 }
962 Type type = null;
963 try
964 {
965 type = Type.valueOf(this.type.toUpperCase());
966 }
967 catch (IllegalArgumentException e)
968 {
969 getLog().error("Invalid value for configuration-option \"type\": " + this.type);
970 getLog().error("Valid values are: NONE, CREATE, DROP, BOTH");
971 throw new MojoExecutionException("Invalid value for configuration-option \"type\"");
972 }
973
974
975 if (config.getProperty(DIALECT) == null)
976 throw new MojoFailureException("hibernate-dialect must be set!");
977
978
979 if (target.equals(Target.SCRIPT) || target.equals(Target.NONE))
980 {
981 project.getProperties().setProperty(EXPORT_SKIPPED_PROPERTY, "true");
982 }
983 if (
984 !modified
985 && !target.equals(Target.SCRIPT)
986 && !target.equals(Target.NONE)
987 && !force
988 )
989 {
990 getLog().info("No modified annotated classes or mapping-files found and dialect unchanged.");
991 getLog().info("Skipping schema generation!");
992 project.getProperties().setProperty(EXPORT_SKIPPED_PROPERTY, "true");
993 return;
994 }
995
996
997 if ( config.getProperties().containsKey(NAMING_STRATEGY))
998 {
999 String namingStrategy = config.getProperty(NAMING_STRATEGY);
1000 getLog().debug("Explicitly set NamingStrategy: " + namingStrategy);
1001 try
1002 {
1003 @SuppressWarnings("unchecked")
1004 Class<NamingStrategy> namingStrategyClass = (Class<NamingStrategy>) Class.forName(namingStrategy);
1005 config.setNamingStrategy(namingStrategyClass.newInstance());
1006 }
1007 catch (Exception e)
1008 {
1009 getLog().error("Error setting NamingStrategy", e);
1010 throw new MojoExecutionException(e.getMessage());
1011 }
1012 }
1013
1014
1015 Environment.verifyProperties(config.getProperties());
1016 ConfigurationHelper.resolvePlaceHolders(config.getProperties());
1017 registry =
1018 (StandardServiceRegistryImpl)
1019 new StandardServiceRegistryBuilder()
1020 .applySettings(config.getProperties())
1021 .build();
1022
1023 config.buildMappings();
1024
1025 if (envers)
1026 {
1027 getLog().info("Automatic auditing via hibernate-envers enabled!");
1028 AuditConfiguration.getFor(config);
1029 }
1030
1031 SchemaExport export = new SchemaExport(registry, config);
1032 export.setDelimiter(delimiter);
1033 export.setFormat(format);
1034
1035 File outF = new File(outputFile);
1036
1037 if (!outF.isAbsolute())
1038 {
1039
1040 outF = new File(buildDirectory, outputFile);
1041 getLog().info("Adjusted relative path, resulting path is " + outF.getPath());
1042 }
1043
1044
1045 File outFileParentDir = outF.getParentFile();
1046 if (null != outFileParentDir && !outFileParentDir.exists())
1047 {
1048 try
1049 {
1050 getLog().info("Creating directory path for output file:" + outFileParentDir.getPath());
1051 outFileParentDir.mkdirs();
1052 }
1053 catch (Exception e)
1054 {
1055 getLog().error("Error creating directory path for output file: " + e.getLocalizedMessage());
1056 }
1057 }
1058
1059 export.setOutputFile(outF.getPath());
1060 export.execute(target, type);
1061
1062 for (Object exception : export.getExceptions())
1063 getLog().debug(exception.toString());
1064 }
1065 finally
1066 {
1067
1068 MavenLogAppender.endPluginLog(this);
1069
1070
1071 Thread.currentThread().setContextClassLoader(contextClassLoader);
1072
1073 if (registry != null)
1074 registry.destroy();
1075 }
1076
1077
1078 try
1079 {
1080 FileOutputStream fos = new FileOutputStream(saved);
1081 ObjectOutputStream oos = new ObjectOutputStream(fos);
1082 oos.writeObject(md5s);
1083 oos.close();
1084 fos.close();
1085 }
1086 catch (Exception e)
1087 {
1088 getLog().error("Cannot write md5-sums to file: " + e);
1089 }
1090 }
1091
1092 private ParsedPersistenceXmlDescriptor getPersistenceUnitDescriptor(
1093 String name,
1094 Properties properties,
1095 ClassLoaderService loader
1096 )
1097 throws
1098 MojoFailureException
1099 {
1100 PersistenceXmlParser parser =
1101 new PersistenceXmlParser(
1102 loader,
1103 PersistenceUnitTransactionType.RESOURCE_LOCAL
1104 );
1105
1106 List<ParsedPersistenceXmlDescriptor> units = parser.doResolve(properties);
1107
1108 if (name == null)
1109 {
1110 switch (units.size())
1111 {
1112 case 0:
1113 getLog().info("Found no META-INF/persistence.xml.");
1114 return null;
1115 case 1:
1116 getLog().info("Using persistence-unit " + units.get(0).getName());
1117 return units.get(0);
1118 default:
1119 getLog().warn("No name provided and multiple persistence units found:");
1120 for (ParsedPersistenceXmlDescriptor unit : units)
1121 getLog().warn(" - " + unit.getName());
1122 return null;
1123 }
1124
1125 }
1126
1127 for (ParsedPersistenceXmlDescriptor unit : units)
1128 {
1129 getLog().debug("Found persistence-unit " + unit.getName());
1130 if (!unit.getName().equals(name))
1131 continue;
1132
1133
1134 if (!ProviderChecker.isProvider(unit, properties))
1135 {
1136 getLog().debug("Wrong provider: " + unit.getProviderClassName());
1137 continue;
1138 }
1139
1140 getLog().info("Using persistence-unit " + unit.getName());
1141 return unit;
1142 }
1143
1144 throw new MojoFailureException("Could not find persistence-unit " + name);
1145 }
1146
1147
1148 static final class MavenProjectClassLoaderService implements ClassLoaderService
1149 {
1150 final private ClassLoader loader;
1151
1152
1153 public MavenProjectClassLoaderService(ClassLoader loader)
1154 {
1155 this.loader = loader;
1156 }
1157
1158
1159 @Override
1160 public <T> Class<T> classForName(String name)
1161 {
1162 try
1163 {
1164 return (Class<T>)loader.loadClass(name);
1165 }
1166 catch (ClassNotFoundException e)
1167 {
1168 throw new ClassLoadingException( "Unable to load class [" + name + "]", e );
1169 }
1170 }
1171
1172 @Override
1173 public URL locateResource(String name)
1174 {
1175 return loader.getResource(name);
1176 }
1177
1178 @Override
1179 public InputStream locateResourceStream(String name)
1180 {
1181 return loader.getResourceAsStream(name);
1182 }
1183
1184 @Override
1185 public List<URL> locateResources(String name)
1186 {
1187 try
1188 {
1189 return Collections.list(loader.getResources(name));
1190 }
1191 catch (IOException e)
1192 {
1193 return Collections.EMPTY_LIST;
1194 }
1195 }
1196
1197 @Override
1198 public <S> LinkedHashSet<S> loadJavaServices(Class<S> serviceContract)
1199 {
1200 throw new UnsupportedOperationException("Not supported yet.");
1201 }
1202
1203 @Override
1204 public void stop() { }
1205
1206 }
1207
1208
1209
1210
1211
1212
1213
1214
1215 static final class DriverProxy implements Driver
1216 {
1217 private final Driver target;
1218
1219 DriverProxy(Driver target)
1220 {
1221 if (target == null)
1222 throw new NullPointerException();
1223 this.target = target;
1224 }
1225
1226 public java.sql.Driver getTarget()
1227 {
1228 return target;
1229 }
1230
1231 @Override
1232 public boolean acceptsURL(String url) throws SQLException
1233 {
1234 return target.acceptsURL(url);
1235 }
1236
1237 @Override
1238 public java.sql.Connection connect(
1239 String url,
1240 java.util.Properties info
1241 )
1242 throws
1243 SQLException
1244 {
1245 return target.connect(url, info);
1246 }
1247
1248 @Override
1249 public int getMajorVersion()
1250 {
1251 return target.getMajorVersion();
1252 }
1253
1254 @Override
1255 public int getMinorVersion()
1256 {
1257 return target.getMinorVersion();
1258 }
1259
1260 @Override
1261 public DriverPropertyInfo[] getPropertyInfo(
1262 String url,
1263 Properties info
1264 )
1265 throws
1266 SQLException
1267 {
1268 return target.getPropertyInfo(url, info);
1269 }
1270
1271 @Override
1272 public boolean jdbcCompliant()
1273 {
1274 return target.jdbcCompliant();
1275 }
1276
1277
1278
1279
1280
1281 public Logger getParentLogger() throws SQLFeatureNotSupportedException
1282 {
1283 throw new SQLFeatureNotSupportedException("Not supported, for backward-compatibility with Java 1.6");
1284 }
1285
1286 @Override
1287 public String toString()
1288 {
1289 return "Proxy: " + target;
1290 }
1291
1292 @Override
1293 public int hashCode()
1294 {
1295 return target.hashCode();
1296 }
1297
1298 @Override
1299 public boolean equals(Object obj)
1300 {
1301 if (!(obj instanceof DriverProxy))
1302 return false;
1303 DriverProxy other = (DriverProxy) obj;
1304 return this.target.equals(other.target);
1305 }
1306 }
1307 }