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 List runtimeClasspathElements = project.getRuntimeClasspathElements();
1004 URL[] runtimeUrls = new URL[runtimeClasspathElements.size()];
1005 for (int i = 0; i < runtimeClasspathElements.size(); i++)
1006 {
1007 String element = (String) runtimeClasspathElements.get(i);
1008 runtimeUrls[i] = new File(element).toURI().toURL();
1009 }
1010 URLClassLoader newLoader = new URLClassLoader(
1011 runtimeUrls,
1012 Thread.currentThread().getContextClassLoader()
1013 );
1014 @SuppressWarnings("unchecked")
1015 Class<NamingStrategy> namingStrategyClass =
1016 (Class<NamingStrategy>) newLoader.loadClass(namingStrategy);
1017 config.setNamingStrategy(namingStrategyClass.newInstance());
1018 }
1019 catch (Exception e)
1020 {
1021 getLog().error("Error setting NamingStrategy", e);
1022 throw new MojoExecutionException(e.getMessage());
1023 }
1024 }
1025
1026
1027 Environment.verifyProperties(config.getProperties());
1028 ConfigurationHelper.resolvePlaceHolders(config.getProperties());
1029 registry =
1030 (StandardServiceRegistryImpl)
1031 new StandardServiceRegistryBuilder()
1032 .applySettings(config.getProperties())
1033 .build();
1034
1035 config.buildMappings();
1036
1037 if (envers)
1038 {
1039 getLog().info("Automatic auditing via hibernate-envers enabled!");
1040 AuditConfiguration.getFor(config);
1041 }
1042
1043 SchemaExport export = new SchemaExport(registry, config);
1044 export.setDelimiter(delimiter);
1045 export.setFormat(format);
1046
1047 File outF = new File(outputFile);
1048
1049 if (!outF.isAbsolute())
1050 {
1051
1052 outF = new File(buildDirectory, outputFile);
1053 getLog().info("Adjusted relative path, resulting path is " + outF.getPath());
1054 }
1055
1056
1057 File outFileParentDir = outF.getParentFile();
1058 if (null != outFileParentDir && !outFileParentDir.exists())
1059 {
1060 try
1061 {
1062 getLog().info("Creating directory path for output file:" + outFileParentDir.getPath());
1063 outFileParentDir.mkdirs();
1064 }
1065 catch (Exception e)
1066 {
1067 getLog().error("Error creating directory path for output file: " + e.getLocalizedMessage());
1068 }
1069 }
1070
1071 export.setOutputFile(outF.getPath());
1072 export.execute(target, type);
1073
1074 for (Object exception : export.getExceptions())
1075 getLog().debug(exception.toString());
1076 }
1077 finally
1078 {
1079
1080 MavenLogAppender.endPluginLog(this);
1081
1082
1083 Thread.currentThread().setContextClassLoader(contextClassLoader);
1084
1085 if (registry != null)
1086 registry.destroy();
1087 }
1088
1089
1090 try
1091 {
1092 FileOutputStream fos = new FileOutputStream(saved);
1093 ObjectOutputStream oos = new ObjectOutputStream(fos);
1094 oos.writeObject(md5s);
1095 oos.close();
1096 fos.close();
1097 }
1098 catch (Exception e)
1099 {
1100 getLog().error("Cannot write md5-sums to file: " + e);
1101 }
1102 }
1103
1104 private ParsedPersistenceXmlDescriptor getPersistenceUnitDescriptor(
1105 String name,
1106 Properties properties,
1107 ClassLoaderService loader
1108 )
1109 throws
1110 MojoFailureException
1111 {
1112 PersistenceXmlParser parser =
1113 new PersistenceXmlParser(
1114 loader,
1115 PersistenceUnitTransactionType.RESOURCE_LOCAL
1116 );
1117
1118 List<ParsedPersistenceXmlDescriptor> units = parser.doResolve(properties);
1119
1120 if (name == null)
1121 {
1122 switch (units.size())
1123 {
1124 case 0:
1125 getLog().info("Found no META-INF/persistence.xml.");
1126 return null;
1127 case 1:
1128 getLog().info("Using persistence-unit " + units.get(0).getName());
1129 return units.get(0);
1130 default:
1131 getLog().warn("No name provided and multiple persistence units found:");
1132 for (ParsedPersistenceXmlDescriptor unit : units)
1133 getLog().warn(" - " + unit.getName());
1134 return null;
1135 }
1136
1137 }
1138
1139 for (ParsedPersistenceXmlDescriptor unit : units)
1140 {
1141 getLog().debug("Found persistence-unit " + unit.getName());
1142 if (!unit.getName().equals(name))
1143 continue;
1144
1145
1146 if (!ProviderChecker.isProvider(unit, properties))
1147 {
1148 getLog().debug("Wrong provider: " + unit.getProviderClassName());
1149 continue;
1150 }
1151
1152 getLog().info("Using persistence-unit " + unit.getName());
1153 return unit;
1154 }
1155
1156 throw new MojoFailureException("Could not find persistence-unit " + name);
1157 }
1158
1159
1160 static final class MavenProjectClassLoaderService implements ClassLoaderService
1161 {
1162 final private ClassLoader loader;
1163
1164
1165 public MavenProjectClassLoaderService(ClassLoader loader)
1166 {
1167 this.loader = loader;
1168 }
1169
1170
1171 @Override
1172 public <T> Class<T> classForName(String name)
1173 {
1174 try
1175 {
1176 return (Class<T>)loader.loadClass(name);
1177 }
1178 catch (ClassNotFoundException e)
1179 {
1180 throw new ClassLoadingException( "Unable to load class [" + name + "]", e );
1181 }
1182 }
1183
1184 @Override
1185 public URL locateResource(String name)
1186 {
1187 return loader.getResource(name);
1188 }
1189
1190 @Override
1191 public InputStream locateResourceStream(String name)
1192 {
1193 return loader.getResourceAsStream(name);
1194 }
1195
1196 @Override
1197 public List<URL> locateResources(String name)
1198 {
1199 try
1200 {
1201 return Collections.list(loader.getResources(name));
1202 }
1203 catch (IOException e)
1204 {
1205 return Collections.EMPTY_LIST;
1206 }
1207 }
1208
1209 @Override
1210 public <S> LinkedHashSet<S> loadJavaServices(Class<S> serviceContract)
1211 {
1212 throw new UnsupportedOperationException("Not supported yet.");
1213 }
1214
1215 @Override
1216 public void stop() { }
1217
1218 }
1219
1220
1221
1222
1223
1224
1225
1226
1227 static final class DriverProxy implements Driver
1228 {
1229 private final Driver target;
1230
1231 DriverProxy(Driver target)
1232 {
1233 if (target == null)
1234 throw new NullPointerException();
1235 this.target = target;
1236 }
1237
1238 public java.sql.Driver getTarget()
1239 {
1240 return target;
1241 }
1242
1243 @Override
1244 public boolean acceptsURL(String url) throws SQLException
1245 {
1246 return target.acceptsURL(url);
1247 }
1248
1249 @Override
1250 public java.sql.Connection connect(
1251 String url,
1252 java.util.Properties info
1253 )
1254 throws
1255 SQLException
1256 {
1257 return target.connect(url, info);
1258 }
1259
1260 @Override
1261 public int getMajorVersion()
1262 {
1263 return target.getMajorVersion();
1264 }
1265
1266 @Override
1267 public int getMinorVersion()
1268 {
1269 return target.getMinorVersion();
1270 }
1271
1272 @Override
1273 public DriverPropertyInfo[] getPropertyInfo(
1274 String url,
1275 Properties info
1276 )
1277 throws
1278 SQLException
1279 {
1280 return target.getPropertyInfo(url, info);
1281 }
1282
1283 @Override
1284 public boolean jdbcCompliant()
1285 {
1286 return target.jdbcCompliant();
1287 }
1288
1289
1290
1291
1292
1293 public Logger getParentLogger() throws SQLFeatureNotSupportedException
1294 {
1295 throw new SQLFeatureNotSupportedException("Not supported, for backward-compatibility with Java 1.6");
1296 }
1297
1298 @Override
1299 public String toString()
1300 {
1301 return "Proxy: " + target;
1302 }
1303
1304 @Override
1305 public int hashCode()
1306 {
1307 return target.hashCode();
1308 }
1309
1310 @Override
1311 public boolean equals(Object obj)
1312 {
1313 if (!(obj instanceof DriverProxy))
1314 return false;
1315 DriverProxy other = (DriverProxy) obj;
1316 return this.target.equals(other.target);
1317 }
1318 }
1319 }