1 package org.hibernate.cfg; 3 4 import java.io.File ; 5 import java.io.FileInputStream ; 6 import java.io.FileNotFoundException ; 7 import java.io.FileOutputStream ; 8 import java.io.IOException ; 9 import java.io.InputStream ; 10 import java.io.ObjectInputStream ; 11 import java.io.Serializable ; 12 import java.io.StringReader ; 13 import java.net.URL ; 14 import java.util.ArrayList ; 15 import java.util.Enumeration ; 16 import java.util.HashMap ; 17 import java.util.HashSet ; 18 import java.util.Iterator ; 19 import java.util.List ; 20 import java.util.Map ; 21 import java.util.Properties ; 22 import java.util.Set ; 23 import java.util.TreeMap ; 24 import java.util.Map.Entry; 25 import java.util.jar.JarFile ; 26 import java.util.zip.ZipEntry ; 27 28 import org.apache.commons.logging.Log; 29 import org.apache.commons.logging.LogFactory; 30 import org.dom4j.Attribute; 31 import org.dom4j.DocumentException; 32 import org.dom4j.Element; 33 import org.hibernate.EmptyInterceptor; 34 import org.hibernate.HibernateException; 35 import org.hibernate.Interceptor; 36 import org.hibernate.MappingException; 37 import org.hibernate.SessionFactory; 38 import org.hibernate.dialect.Dialect; 39 import org.hibernate.dialect.MySQLDialect; 40 import org.hibernate.engine.FilterDefinition; 41 import org.hibernate.engine.Mapping; 42 import org.hibernate.event.AutoFlushEventListener; 43 import org.hibernate.event.PersistEventListener; 44 import org.hibernate.event.DeleteEventListener; 45 import org.hibernate.event.DirtyCheckEventListener; 46 import org.hibernate.event.EvictEventListener; 47 import org.hibernate.event.FlushEntityEventListener; 48 import org.hibernate.event.FlushEventListener; 49 import org.hibernate.event.InitializeCollectionEventListener; 50 import org.hibernate.event.LoadEventListener; 51 import org.hibernate.event.LockEventListener; 52 import org.hibernate.event.MergeEventListener; 53 import org.hibernate.event.PostDeleteEventListener; 54 import org.hibernate.event.PostInsertEventListener; 55 import org.hibernate.event.PostLoadEventListener; 56 import org.hibernate.event.PostUpdateEventListener; 57 import org.hibernate.event.PreDeleteEventListener; 58 import org.hibernate.event.PreInsertEventListener; 59 import org.hibernate.event.PreLoadEventListener; 60 import org.hibernate.event.PreUpdateEventListener; 61 import org.hibernate.event.RefreshEventListener; 62 import org.hibernate.event.ReplicateEventListener; 63 import org.hibernate.event.SaveOrUpdateEventListener; 64 import org.hibernate.event.SessionEventListenerConfig; 65 import org.hibernate.id.IdentifierGenerator; 66 import org.hibernate.id.PersistentIdentifierGenerator; 67 import org.hibernate.impl.SessionFactoryImpl; 68 import org.hibernate.mapping.Collection; 69 import org.hibernate.mapping.ForeignKey; 70 import org.hibernate.mapping.IdentifierCollection; 71 import org.hibernate.mapping.Index; 72 import org.hibernate.mapping.PersistentClass; 73 import org.hibernate.mapping.Property; 74 import org.hibernate.mapping.RootClass; 75 import org.hibernate.mapping.SimpleValue; 76 import org.hibernate.mapping.Table; 77 import org.hibernate.mapping.UniqueKey; 78 import org.hibernate.secure.JACCConfiguration; 79 import org.hibernate.tool.hbm2ddl.DatabaseMetadata; 80 import org.hibernate.tool.hbm2ddl.TableMetadata; 81 import org.hibernate.type.SerializationException; 82 import org.hibernate.type.Type; 83 import org.hibernate.util.ArrayHelper; 84 import org.hibernate.util.CollectionHelper; 85 import org.hibernate.util.SerializationHelper; 86 import org.hibernate.util.XMLHelper; 87 import org.hibernate.util.ReflectHelper; 88 import org.w3c.dom.Document ; 89 import org.xml.sax.EntityResolver ; 90 import org.xml.sax.InputSource ; 91 92 109 public class Configuration implements Serializable { 110 111 private static Log log = LogFactory.getLog( Configuration.class ); 112 113 protected Map classes; 114 protected Map imports; 115 protected Map collections; 116 protected Map tables; 117 protected Map namedQueries; 118 protected Map namedSqlQueries; 119 120 protected Map sqlResultSetMappings; 121 protected Map filterDefinitions; 122 protected List secondPasses; 123 protected List propertyReferences; 124 protected Map extendsQueue; private Interceptor interceptor; 126 private Properties properties; 127 private EntityResolver entityResolver; 128 129 private transient XMLHelper xmlHelper; 130 protected transient Map typeDefs; 131 132 protected NamingStrategy namingStrategy = DefaultNamingStrategy.INSTANCE; 133 134 private SessionEventListenerConfig sessionEventListenerConfig; 135 136 protected final SettingsFactory settingsFactory; 137 138 protected void reset() { 139 classes = new HashMap (); 140 imports = new HashMap (); 141 collections = new HashMap (); 142 tables = new TreeMap (); 143 namedQueries = new HashMap (); 144 namedSqlQueries = new HashMap (); 145 sqlResultSetMappings = new HashMap (); 146 xmlHelper = new XMLHelper(); 147 typeDefs = new HashMap (); 148 propertyReferences = new ArrayList (); 149 secondPasses = new ArrayList (); 150 interceptor = EmptyInterceptor.INSTANCE; 151 properties = Environment.getProperties(); 152 entityResolver = XMLHelper.DEFAULT_DTD_RESOLVER; 153 sessionEventListenerConfig = new SessionEventListenerConfig(); 154 filterDefinitions = new HashMap (); 155 extendsQueue = new HashMap (); 156 } 157 158 private transient Mapping mapping = buildMapping(); 159 160 protected Configuration(SettingsFactory settingsFactory) { 161 this.settingsFactory = settingsFactory; 162 reset(); 163 } 164 165 public Configuration() { 166 this( new SettingsFactory() ); 167 } 168 169 172 public Iterator getClassMappings() { 173 return classes.values().iterator(); 174 } 175 176 179 public Iterator getCollectionMappings() { 180 return collections.values().iterator(); 181 } 182 183 186 public Iterator getTableMappings() { 187 return tables.values().iterator(); 188 } 189 190 193 public PersistentClass getClassMapping(String persistentClass) { 194 return ( PersistentClass ) classes.get( persistentClass ); 195 } 196 197 203 public Collection getCollectionMapping(String role) { 204 return ( Collection ) collections.get( role ); 205 } 206 207 214 public void setEntityResolver(EntityResolver entityResolver) { 215 this.entityResolver = entityResolver; 216 } 217 218 223 public Configuration addFile(String xmlFile) throws MappingException { 224 log.info( "Reading mappings from file: " + xmlFile ); 225 try { 226 List errors = new ArrayList (); 227 org.dom4j.Document doc = xmlHelper.createSAXReader( xmlFile, errors, entityResolver ) 228 .read( new File ( xmlFile ) ); 229 if ( errors.size() != 0 ) { 230 throw new MappingException( "invalid mapping", ( Throwable ) errors.get( 0 ) ); 231 } 232 add( doc ); 233 return this; 234 } 235 catch ( Exception e ) { 236 throw new MappingException( 237 "Could not read mapping document from file: " + xmlFile, 238 e 239 ); 240 } 241 } 242 243 248 public Configuration addFile(File xmlFile) throws MappingException { 249 log.info( "Reading mappings from file: " + xmlFile.getPath() ); 250 try { 251 addInputStream( new FileInputStream ( xmlFile ) ); 252 } 253 catch ( Exception e ) { 254 throw new MappingException( 255 "Could not read mapping document from file: " + xmlFile.getPath(), 256 e 257 ); 258 } 259 return this; 260 } 261 262 267 public Configuration addCacheableFile(File xmlFile) throws MappingException { 268 try { 269 File lazyfile = new File ( xmlFile.getAbsolutePath() + ".bin" ); 270 org.dom4j.Document doc = null; 271 List errors = new ArrayList (); 272 273 final boolean useCachedFile = xmlFile.exists() && 274 lazyfile.exists() && 275 xmlFile.lastModified() < lazyfile.lastModified(); 276 277 if ( useCachedFile ) { 278 try { 279 log.info( "Reading mappings from cache file: " + lazyfile ); 280 doc = ( org.dom4j.Document ) SerializationHelper.deserialize( new FileInputStream ( lazyfile ) ); 281 } 282 catch ( SerializationException e ) { 283 log.warn( "Could not deserialize cache file: " + lazyfile.getPath(), e ); 284 } 285 } 286 287 if ( doc == null ) { 289 log.info( "Reading mappings from file: " + xmlFile ); 290 doc = xmlHelper.createSAXReader( xmlFile.getAbsolutePath(), errors, entityResolver ) 291 .read( xmlFile ); 292 try { 293 log.debug( "Writing cache file for: " + xmlFile + " to: " + lazyfile ); 294 SerializationHelper.serialize( ( Serializable ) doc, new FileOutputStream ( lazyfile ) ); 295 } 296 catch ( SerializationException e ) { 297 log.warn( "Could not write cached file: " + lazyfile, e ); 298 } 299 } 300 301 if ( errors.size() != 0 ) { 302 throw new MappingException( "invalid mapping", ( Throwable ) errors.get( 0 ) ); 303 } 304 add( doc ); 305 return this; 306 } 307 catch ( Exception e ) { 308 throw new MappingException( 309 "Could not read mapping document from file: " + xmlFile, 310 e 311 ); 312 } 313 } 314 315 public Configuration addCacheableFile(String xmlFile) throws MappingException { 316 return addCacheableFile( new File ( xmlFile ) ); 317 } 318 319 320 325 public Configuration addXML(String xml) throws MappingException { 326 if ( log.isDebugEnabled() ) log.debug( "Mapping XML:\n" + xml ); 327 try { 328 List errors = new ArrayList (); 329 org.dom4j.Document doc = xmlHelper.createSAXReader( "XML String", errors, entityResolver ) 330 .read( new StringReader ( xml ) ); 331 if ( errors.size() != 0 ) { 332 throw new MappingException( "invalid mapping", ( Throwable ) errors.get( 0 ) ); 333 } 334 add( doc ); 335 } 336 catch ( DocumentException e ) { 337 throw new MappingException( "Could not parse mapping document in XML string", e ); 338 } 339 return this; 340 } 341 342 347 public Configuration addURL(URL url) throws MappingException { 348 if ( log.isDebugEnabled() ) log.debug( "Reading mapping document from URL:" + url ); 349 try { 350 addInputStream( url.openStream() ); 351 } 352 catch ( Exception e ) { 353 throw new MappingException( "Could not read mapping document from URL: " + url, e ); 354 } 355 return this; 356 } 357 358 363 public Configuration addDocument(Document doc) throws MappingException { 364 if ( log.isDebugEnabled() ) log.debug( "Mapping document:\n" + doc ); 365 add( xmlHelper.createDOMReader().read( doc ) ); 366 return this; 367 } 368 369 protected void add(org.dom4j.Document doc) throws MappingException { 370 HbmBinder.bindRoot( doc, createMappings(), CollectionHelper.EMPTY_MAP ); 371 } 373 374 378 public Mappings createMappings() { 379 return new Mappings( 380 classes, 381 collections, 382 tables, 383 namedQueries, 384 namedSqlQueries, 385 sqlResultSetMappings, 386 imports, 387 secondPasses, 388 propertyReferences, 389 namingStrategy, 390 typeDefs, 391 filterDefinitions, 392 extendsQueue 393 ); 394 } 395 396 401 public Configuration addInputStream(InputStream xmlInputStream) throws MappingException { 402 try { 403 List errors = new ArrayList (); 404 org.dom4j.Document doc = xmlHelper.createSAXReader( "XML InputStream", errors, entityResolver ) 405 .read( new InputSource ( xmlInputStream ) ); 406 if ( errors.size() != 0 ) { 407 throw new MappingException( "invalid mapping", ( Throwable ) errors.get( 0 ) ); 408 } 409 add( doc ); 410 return this; 411 } 412 catch ( DocumentException e ) { 413 throw new MappingException( "Could not parse mapping document in input stream", e ); 414 } 415 finally { 416 try { 417 xmlInputStream.close(); 418 } 419 catch ( IOException ioe ) { 420 log.warn( "Could not close input stream", ioe ); 421 } 422 } 423 } 424 425 431 public Configuration addResource(String path, ClassLoader classLoader) throws MappingException { 432 log.info( "Reading mappings from resource: " + path ); 433 InputStream rsrc = classLoader.getResourceAsStream( path ); 434 if ( rsrc == null ) { 435 throw new MappingException( "Resource: " + path + " not found" ); 436 } 437 try { 438 return addInputStream( rsrc ); 439 } 440 catch ( MappingException me ) { 441 throw new MappingException( "Could not read mappings from resource: " + path, me ); 442 } 443 } 444 445 450 public Configuration addResource(String path) throws MappingException { 451 log.info( "Reading mappings from resource: " + path ); 452 InputStream rsrc = Thread.currentThread().getContextClassLoader().getResourceAsStream( path ); 453 if ( rsrc == null ) { 454 rsrc = Environment.class.getClassLoader().getResourceAsStream( path ); 455 } 456 if ( rsrc == null ) { 457 throw new MappingException( "Resource: " + path + " not found" ); 458 } 459 try { 460 return addInputStream( rsrc ); 461 } 462 catch ( MappingException me ) { 463 throw new MappingException( "Could not read mappings from resource: " + path, me ); 464 } 465 } 466 467 473 public Configuration addClass(Class persistentClass) throws MappingException { 474 String fileName = persistentClass.getName().replace( '.', '/' ) + ".hbm.xml"; 475 log.info( "Reading mappings from resource: " + fileName ); 476 InputStream rsrc = persistentClass.getClassLoader().getResourceAsStream( fileName ); 477 if ( rsrc == null ) { 478 throw new MappingException( "Resource: " + fileName + " not found" ); 479 } 480 try { 481 return addInputStream( rsrc ); 482 } 483 catch ( MappingException me ) { 484 throw new MappingException( 485 "Could not read mappings from resource: " + fileName, 486 me 487 ); 488 } 489 } 490 491 496 public Configuration addJar(File jar) throws MappingException { 497 498 log.info( "Searching for mapping documents in jar: " + jar.getName() ); 499 500 final JarFile jarFile; 501 try { 502 jarFile = new JarFile ( jar ); 503 } 504 catch ( IOException ioe ) { 505 throw new MappingException( 506 "Could not read mapping documents from jar: " + jar.getName(), 507 ioe 508 ); 509 } 510 511 Enumeration jarEntries = jarFile.entries(); 512 while ( jarEntries.hasMoreElements() ) { 513 514 ZipEntry ze = ( ZipEntry ) jarEntries.nextElement(); 515 516 if ( ze.getName().endsWith( ".hbm.xml" ) ) { 517 log.info( "Found mapping document in jar: " + ze.getName() ); 518 try { 519 addInputStream( jarFile.getInputStream( ze ) ); 520 } 521 catch ( Exception e ) { 522 throw new MappingException( 523 "Could not read mapping documents from jar: " + jar.getName(), 524 e 525 ); 526 } 527 } 528 } 529 530 return this; 531 532 } 533 534 540 public Configuration addDirectory(File dir) throws MappingException { 541 File [] files = dir.listFiles(); 542 for ( int i = 0; i < files.length; i++ ) { 543 if ( files[i].isDirectory() ) { 544 addDirectory( files[i] ); 545 } 546 else if ( files[i].getName().endsWith( ".hbm.xml" ) ) { 547 addFile( files[i] ); 548 } 549 } 550 return this; 551 } 552 553 private Iterator iterateGenerators(Dialect dialect) throws MappingException { 554 555 TreeMap generators = new TreeMap (); 556 String defaultCatalog = properties.getProperty(Environment.DEFAULT_CATALOG); 557 String defaultSchema = properties.getProperty(Environment.DEFAULT_SCHEMA); 558 559 Iterator iter = classes.values().iterator(); 560 while ( iter.hasNext() ) { 561 PersistentClass pc = ( PersistentClass ) iter.next(); 562 563 if ( !pc.isInherited() ) { 564 565 IdentifierGenerator ig = pc.getIdentifier() 566 .createIdentifierGenerator( 567 dialect, 568 defaultCatalog, 569 defaultSchema, 570 (RootClass) pc 571 ); 572 573 if ( ig instanceof PersistentIdentifierGenerator ) { 574 generators.put( ( ( PersistentIdentifierGenerator ) ig ).generatorKey(), ig ); 575 } 576 577 } 578 } 579 580 iter = collections.values().iterator(); 581 while ( iter.hasNext() ) { 582 Collection collection = ( Collection ) iter.next(); 583 584 if ( collection.isIdentified() ) { 585 586 IdentifierGenerator ig = ( ( IdentifierCollection ) collection ).getIdentifier() 587 .createIdentifierGenerator( 588 dialect, 589 defaultCatalog, 590 defaultSchema, 591 null 592 ); 593 594 if ( ig instanceof PersistentIdentifierGenerator ) { 595 generators.put( ( ( PersistentIdentifierGenerator ) ig ).generatorKey(), ig ); 596 } 597 598 } 599 } 600 601 return generators.values().iterator(); 602 } 603 604 609 public String [] generateDropSchemaScript(Dialect dialect) throws HibernateException { 610 611 secondPassCompile(); 612 613 String defaultCatalog = properties.getProperty(Environment.DEFAULT_CATALOG); 614 String defaultSchema = properties.getProperty(Environment.DEFAULT_SCHEMA); 615 616 ArrayList script = new ArrayList ( 50 ); 617 618 if ( dialect.dropConstraints() ) { 619 Iterator iter = getTableMappings(); 620 while ( iter.hasNext() ) { 621 Table table = ( Table ) iter.next(); 622 if ( table.isPhysicalTable() ) { 623 Iterator subIter = table.getForeignKeyIterator(); 624 while ( subIter.hasNext() ) { 625 ForeignKey fk = ( ForeignKey ) subIter.next(); 626 if ( fk.isPhysicalConstraint() ) { 627 script.add( fk.sqlDropString( 628 dialect, 629 defaultCatalog, 630 defaultSchema ) ); 631 } 632 } 633 } 634 } 635 } 636 637 638 Iterator iter = getTableMappings(); 639 while ( iter.hasNext() ) { 640 641 Table table = ( Table ) iter.next(); 642 if ( table.isPhysicalTable() ) { 643 644 651 652 script.add( table.sqlDropString( 653 dialect, 654 defaultCatalog, 655 defaultSchema ) ); 656 657 } 658 659 } 660 661 iter = iterateGenerators( dialect ); 662 while ( iter.hasNext() ) { 663 String [] lines = ( ( PersistentIdentifierGenerator ) iter.next() ).sqlDropStrings( dialect ); 664 for ( int i = 0; i < lines.length; i++ ) script.add( lines[i] ); 665 } 666 667 return ArrayHelper.toStringArray( script ); 668 } 669 670 675 public String [] generateSchemaCreationScript(Dialect dialect) throws HibernateException { 676 secondPassCompile(); 677 678 ArrayList script = new ArrayList ( 50 ); 679 String defaultCatalog = properties.getProperty(Environment.DEFAULT_CATALOG); 680 String defaultSchema = properties.getProperty(Environment.DEFAULT_SCHEMA); 681 682 Iterator iter = getTableMappings(); 683 while ( iter.hasNext() ) { 684 Table table = ( Table ) iter.next(); 685 if ( table.isPhysicalTable() ) { 686 script.add( table.sqlCreateString( 687 dialect, 688 mapping, 689 defaultCatalog, 690 defaultSchema ) ); 691 Iterator comments = table.sqlCommentStrings(dialect, defaultCatalog, defaultSchema); 692 while ( comments.hasNext() ) { 693 script.add( comments.next() ); 694 } 695 } 696 } 697 698 iter = getTableMappings(); 699 while ( iter.hasNext() ) { 700 Table table = ( Table ) iter.next(); 701 if ( table.isPhysicalTable() ) { 702 703 if( !dialect.supportsUniqueConstraintInCreateAlterTable() ) { 704 Iterator subIter = table.getUniqueKeyIterator(); 705 while ( subIter.hasNext() ) { 706 UniqueKey uk = (UniqueKey) subIter.next(); 707 script.add( uk.sqlCreateString(dialect, mapping, defaultCatalog, defaultSchema ) ); 708 } 709 } 710 711 712 Iterator subIter = table.getIndexIterator(); 713 while ( subIter.hasNext() ) { 714 Index index = ( Index ) subIter.next(); 715 script.add( index.sqlCreateString( dialect, 716 mapping, 717 defaultCatalog, 718 defaultSchema ) ); 719 } 720 721 if ( dialect.hasAlterTable() ) { 722 subIter = table.getForeignKeyIterator(); 723 while ( subIter.hasNext() ) { 724 ForeignKey fk = ( ForeignKey ) subIter.next(); 725 if ( fk.isPhysicalConstraint() ) { 726 script.add( fk.sqlCreateString( dialect, mapping, 727 defaultCatalog, 728 defaultSchema ) ); 729 } 730 } 731 } 732 733 } 734 } 735 736 iter = iterateGenerators( dialect ); 737 while ( iter.hasNext() ) { 738 String [] lines = ( ( PersistentIdentifierGenerator ) iter.next() ).sqlCreateStrings( dialect ); 739 for ( int i = 0; i < lines.length; i++ ) script.add( lines[i] ); 740 } 741 742 return ArrayHelper.toStringArray( script ); 743 } 744 745 750 public String [] generateSchemaUpdateScript(Dialect dialect, DatabaseMetadata databaseMetadata) 751 throws HibernateException { 752 secondPassCompile(); 753 754 String defaultCatalog = properties.getProperty(Environment.DEFAULT_CATALOG); 755 String defaultSchema = properties.getProperty(Environment.DEFAULT_SCHEMA); 756 757 ArrayList script = new ArrayList ( 50 ); 758 759 Iterator iter = getTableMappings(); 760 while ( iter.hasNext() ) { 761 Table table = ( Table ) iter.next(); 762 if ( table.isPhysicalTable() ) { 763 764 TableMetadata tableInfo = databaseMetadata.getTableMetadata( 765 table.getName(), 766 table.getSchema(), 767 table.getCatalog() 768 ); 769 if ( tableInfo == null ) { 770 script.add( table.sqlCreateString( 771 dialect, 772 mapping, 773 defaultCatalog, 774 defaultSchema ) ); 775 } 776 else { 777 Iterator subiter = table.sqlAlterStrings( 778 dialect, 779 mapping, 780 tableInfo, 781 defaultCatalog, 782 defaultSchema 783 ); 784 while ( subiter.hasNext() ) script.add( subiter.next() ); 785 } 786 787 Iterator comments = table.sqlCommentStrings(dialect, defaultCatalog, defaultSchema); 788 while ( comments.hasNext() ) { 789 script.add( comments.next() ); 790 } 791 792 } 793 } 794 795 iter = getTableMappings(); 796 while ( iter.hasNext() ) { 797 Table table = ( Table ) iter.next(); 798 if ( table.isPhysicalTable() ) { 799 800 TableMetadata tableInfo = databaseMetadata.getTableMetadata( table.getName(), 801 table.getSchema(), 802 table.getCatalog() ); 803 804 if ( dialect.hasAlterTable() ) { 805 Iterator subIter = table.getForeignKeyIterator(); 806 while ( subIter.hasNext() ) { 807 ForeignKey fk = ( ForeignKey ) subIter.next(); 808 if ( fk.isPhysicalConstraint() ) { 809 boolean create = tableInfo == null || ( 810 tableInfo.getForeignKeyMetadata( fk.getName() ) == null && ( 811 !( dialect instanceof MySQLDialect ) || 813 tableInfo.getIndexMetadata( fk.getName() ) == null 814 ) 815 ); 816 if ( create ) script.add( fk.sqlCreateString( 817 dialect, 818 mapping, 819 defaultCatalog, 820 defaultSchema ) ); 821 } 822 } 823 } 824 825 } 826 827 845 } 846 847 iter = iterateGenerators( dialect ); 848 while ( iter.hasNext() ) { 849 PersistentIdentifierGenerator generator = ( PersistentIdentifierGenerator ) iter.next(); 850 Object key = generator.generatorKey(); 851 if ( !databaseMetadata.isSequence( key ) && !databaseMetadata.isTable( key ) ) { 852 String [] lines = generator.sqlCreateStrings( dialect ); 853 for ( int i = 0; i < lines.length; i++ ) script.add( lines[i] ); 854 } 855 } 856 857 return ArrayHelper.toStringArray( script ); 858 } 859 860 private void validate() throws MappingException { 861 Iterator iter = classes.values().iterator(); 862 while ( iter.hasNext() ) { 863 ( ( PersistentClass ) iter.next() ).validate( mapping ); 864 } 865 iter = collections.values().iterator(); 866 while ( iter.hasNext() ) { 867 ( ( Collection ) iter.next() ).validate( mapping ); 868 } 869 } 870 871 875 public void buildMappings() { 876 secondPassCompile(); 877 } 878 879 882 protected org.dom4j.Document findPossibleExtends() { 883 Iterator iter = extendsQueue.entrySet().iterator(); 884 while ( iter.hasNext() ) { 885 Map.Entry entry = ( Entry ) iter.next(); 886 String superclass = ( String ) entry.getKey(); 887 if ( getClassMapping( superclass ) != null ) { 888 List queue = (List ) entry.getValue(); 889 if ( queue.isEmpty() ) { 890 iter.remove(); 891 } 892 else { 893 return ( org.dom4j.Document ) queue.remove(0); 894 } 895 } 896 } 897 return null; 898 } 899 900 protected void secondPassCompile() throws MappingException { 902 log.info( "processing extends queue" ); 903 904 processExtendsQueue(); 905 906 log.info( "processing collection mappings" ); 907 908 Iterator iter = secondPasses.iterator(); 909 while ( iter.hasNext() ) { 910 HbmBinder.SecondPass sp = ( HbmBinder.SecondPass ) iter.next(); 911 sp.doSecondPass( classes, CollectionHelper.EMPTY_MAP ); iter.remove(); 913 } 914 915 log.info( "processing association property references" ); 916 917 iter = propertyReferences.iterator(); 918 while ( iter.hasNext() ) { 919 Mappings.PropertyReference upr = ( Mappings.PropertyReference ) iter.next(); 920 921 PersistentClass clazz = getClassMapping( upr.referencedClass ); 922 if ( clazz == null ) { 923 throw new MappingException( 924 "property-ref to unmapped class: " + 925 upr.referencedClass 926 ); 927 } 928 929 Property prop = clazz.getReferencedProperty(upr.propertyName); 930 if ( upr.unique ) { 931 ( ( SimpleValue ) prop.getValue() ).setAlternateUniqueKey( true ); 932 } 933 } 934 935 937 log.info( "processing foreign key constraints" ); 938 939 iter = getTableMappings(); 940 Set done = new HashSet (); 941 while ( iter.hasNext() ) { 942 secondPassCompileForeignKeys( ( Table ) iter.next(), done ); 943 } 944 945 } 946 947 950 private void processExtendsQueue() { 951 org.dom4j.Document document = findPossibleExtends(); 952 while ( document != null ) { 953 add( document ); 954 document = findPossibleExtends(); 955 } 956 957 if ( extendsQueue.size() > 0 ) { 958 Iterator iterator = extendsQueue.keySet().iterator(); 959 StringBuffer buf = new StringBuffer ( "Following superclasses referenced in extends not found: " ); 960 while ( iterator.hasNext() ) { 961 String element = ( String ) iterator.next(); 962 buf.append( element ); 963 if ( iterator.hasNext() ) buf.append( "," ); 964 } 965 throw new MappingException( buf.toString() ); 966 } 967 } 968 969 protected void secondPassCompileForeignKeys(Table table, Set done) throws MappingException { 970 971 table.createForeignKeys(); 972 973 Iterator iter = table.getForeignKeyIterator(); 974 while ( iter.hasNext() ) { 975 976 ForeignKey fk = ( ForeignKey ) iter.next(); 977 if ( !done.contains( fk ) ) { 978 done.add( fk ); 979 final String referencedEntityName = fk.getReferencedEntityName(); 980 if (referencedEntityName==null) { 981 throw new MappingException( 982 "An association from the table "+ 983 fk.getTable().getName() + 984 " does not specify the referenced entity" 985 ); 986 } 987 if ( log.isDebugEnabled() ) { 988 log.debug( "resolving reference to class: " + referencedEntityName ); 989 } 990 PersistentClass referencedClass = ( PersistentClass ) classes.get( referencedEntityName ); 991 if ( referencedClass == null ) { 992 throw new MappingException( 993 "An association from the table " + 994 fk.getTable().getName() + 995 " refers to an unmapped class: " + 996 referencedEntityName 997 ); 998 } 999 if ( referencedClass.isJoinedSubclass() ) { 1000 secondPassCompileForeignKeys( referencedClass.getSuperclass().getTable(), done ); 1001 } 1002 fk.setReferencedTable( referencedClass.getTable() ); 1003 fk.alignColumns(); 1004 } 1005 } 1006 } 1007 1008 1011 public Map getNamedQueries() { 1012 return namedQueries; 1013 } 1014 1015 1024 public SessionFactory buildSessionFactory() throws HibernateException { 1025 log.debug( "Preparing to build session factory with filters : " + filterDefinitions ); 1026 secondPassCompile(); 1027 validate(); 1028 Environment.verifyProperties( properties ); 1029 Properties copy = new Properties (); 1030 copy.putAll( properties ); 1031 Settings settings = buildSettings(); 1032 1033 return new SessionFactoryImpl( 1034 this, 1035 mapping, 1036 settings, 1037 sessionEventListenerConfig.shallowCopy() 1038 ); 1039 } 1040 1041 1044 public Interceptor getInterceptor() { 1045 return interceptor; 1046 } 1047 1048 1051 public Properties getProperties() { 1052 return properties; 1053 } 1054 1055 1058 public Configuration setInterceptor(Interceptor interceptor) { 1059 this.interceptor = interceptor; 1060 return this; 1061 } 1062 1063 1066 public Configuration setProperties(Properties properties) { 1067 this.properties = properties; 1068 return this; 1069 } 1070 1071 1074 public Configuration addProperties(Properties extraProperties) { 1075 this.properties.putAll( extraProperties ); 1076 return this; 1077 } 1078 1079 1082 public Configuration setProperty(String propertyName, String value) { 1083 properties.setProperty( propertyName, value ); 1084 return this; 1085 } 1086 1087 1090 public String getProperty(String propertyName) { 1091 return properties.getProperty( propertyName ); 1092 } 1093 1094 private void addProperties(Element parent) { 1095 Iterator iter = parent.elementIterator( "property" ); 1096 while ( iter.hasNext() ) { 1097 Element node = ( Element ) iter.next(); 1098 String name = node.attributeValue( "name" ); 1099 String value = node.getText().trim(); 1100 log.debug( name + "=" + value ); 1101 properties.setProperty( name, value ); 1102 if ( !name.startsWith( "hibernate" ) ) { 1103 properties.setProperty( "hibernate." + name, value ); 1104 } 1105 } 1106 Environment.verifyProperties( properties ); 1107 } 1108 1109 1114 protected InputStream getConfigurationInputStream(String resource) throws HibernateException { 1115 1116 log.info( "Configuration resource: " + resource ); 1117 1118 InputStream stream = Environment.class.getResourceAsStream( resource ); 1119 if ( stream == null ) { 1120 stream = Thread.currentThread().getContextClassLoader() 1121 .getResourceAsStream( resource ); 1122 } 1123 if ( stream == null ) { 1124 log.warn( resource + " not found" ); 1125 throw new HibernateException( resource + " not found" ); 1126 } 1127 return stream; 1128 1129 } 1130 1131 1135 public Configuration configure() throws HibernateException { 1136 configure( "/hibernate.cfg.xml" ); 1137 return this; 1138 } 1139 1140 1147 public Configuration configure(String resource) throws HibernateException { 1148 log.info( "configuring from resource: " + resource ); 1149 InputStream stream = getConfigurationInputStream( resource ); 1150 return doConfigure( stream, resource ); 1151 } 1152 1153 1162 public Configuration configure(URL url) throws HibernateException { 1163 log.info( "configuring from url: " + url.toString() ); 1164 try { 1165 return doConfigure( url.openStream(), url.toString() ); 1166 } 1167 catch ( IOException ioe ) { 1168 throw new HibernateException( "could not configure from URL: " + url, ioe ); 1169 } 1170 } 1171 1172 1181 public Configuration configure(File configFile) throws HibernateException { 1182 log.info( "configuring from file: " + configFile.getName() ); 1183 try { 1184 return doConfigure( new FileInputStream ( configFile ), configFile.toString() ); 1185 } 1186 catch ( FileNotFoundException fnfe ) { 1187 throw new HibernateException( "could not find file: " + configFile, fnfe ); 1188 } 1189 } 1190 1191 1201 protected Configuration doConfigure(InputStream stream, String resourceName) throws HibernateException { 1202 1203 org.dom4j.Document doc; 1204 try { 1205 List errors = new ArrayList (); 1206 doc = xmlHelper.createSAXReader( resourceName, errors, entityResolver ) 1207 .read( new InputSource ( stream ) ); 1208 if ( errors.size() != 0 ) { 1209 throw new MappingException( 1210 "invalid configuration", 1211 ( Throwable ) errors.get( 0 ) 1212 ); 1213 } 1214 } 1215 catch ( DocumentException e ) { 1216 throw new HibernateException( 1217 "Could not parse configuration: " + resourceName, 1218 e 1219 ); 1220 } 1221 finally { 1222 try { 1223 stream.close(); 1224 } 1225 catch ( IOException ioe ) { 1226 log.warn( "could not close input stream for: " + resourceName, ioe ); 1227 } 1228 } 1229 1230 return doConfigure( doc ); 1231 1232 } 1233 1234 1243 public Configuration configure(Document document) throws HibernateException { 1244 log.info( "configuring from XML document" ); 1245 return doConfigure( xmlHelper.createDOMReader().read( document ) ); 1246 } 1247 1248 protected Configuration doConfigure(org.dom4j.Document doc) throws HibernateException { 1249 1250 Element sfNode = doc.getRootElement().element( "session-factory" ); 1251 String name = sfNode.attributeValue( "name" ); 1252 if ( name != null ) properties.setProperty( Environment.SESSION_FACTORY_NAME, name ); 1253 addProperties( sfNode ); 1254 parseSessionFactory( sfNode, name ); 1255 1256 Element secNode = doc.getRootElement().element( "security" ); 1257 if ( secNode != null ) parseSecurity( secNode ); 1258 1259 log.info( "Configured SessionFactory: " + name ); 1260 log.debug( "properties: " + properties ); 1261 1262 return this; 1263 1264 } 1265 1266 private void parseSessionFactory(Element sfNode, String name) { 1267 Iterator elements = sfNode.elementIterator(); 1268 while ( elements.hasNext() ) { 1269 Element subelement = ( Element ) elements.next(); 1270 String subelementName = subelement.getName(); 1271 if ( "mapping".equals( subelementName ) ) { 1272 parseMappingElement(subelement, name); 1273 } 1274 else if ( "class-cache".equals( subelementName ) ) { 1275 String className = subelement.attributeValue( "class" ); 1276 Attribute regionNode = subelement.attribute( "region" ); 1277 final String region = ( regionNode == null ) ? className : regionNode.getValue(); 1278 setCacheConcurrencyStrategy( className, subelement.attributeValue( "usage" ), region ); 1279 } 1280 else if ( "collection-cache".equals( subelementName ) ) { 1281 String role = subelement.attributeValue( "collection" ); 1282 Attribute regionNode = subelement.attribute( "region" ); 1283 final String region = ( regionNode == null ) ? role : regionNode.getValue(); 1284 setCollectionCacheConcurrencyStrategy( role, subelement.attributeValue( "usage" ), region ); 1285 } 1286 else if ( "listener".equals( subelementName ) ) { 1287 parseListener( subelement ); 1288 } 1289 } 1290 } 1291 1292 protected void parseMappingElement(Element subelement, String name) { 1293 Attribute rsrc = subelement.attribute( "resource" ); 1294 Attribute file = subelement.attribute( "file" ); 1295 Attribute jar = subelement.attribute( "jar" ); 1296 Attribute pkg = subelement.attribute( "package" ); 1297 Attribute clazz = subelement.attribute( "class" ); 1298 if ( rsrc != null ) { 1299 log.debug( name + "<-" + rsrc ); 1300 addResource( rsrc.getValue() ); 1301 } 1302 else if ( jar != null ) { 1303 log.debug( name + "<-" + jar ); 1304 addJar( new File ( jar.getValue() ) ); 1305 } 1306 else if ( pkg != null ) { 1307 throw new MappingException("An AnnotationConfiguration instance is required to use <mapping package=\"" + pkg.getValue() + "\"/>"); 1308 } 1309 else if ( clazz != null ) { 1310 throw new MappingException("An AnnotationConfiguration instance is required to use <mapping clazz=\"" + clazz.getValue() + "\"/>"); 1311 } 1312 else { 1313 if ( file == null ) throw new MappingException( "<mapping> element in configuration specifies no attributes" ); 1314 log.debug( name + "<-" + file ); 1315 addFile( file.getValue() ); 1316 } 1317 } 1318 1319 private void parseSecurity(Element secNode) { 1320 String contextId = secNode.attributeValue( "context" ); 1321 log.info( "JACC contextID: " + contextId ); 1322 JACCConfiguration jcfg = new JACCConfiguration( contextId ); 1323 Iterator grantElements = secNode.elementIterator(); 1324 while ( grantElements.hasNext() ) { 1325 Element grantElement = ( Element ) grantElements.next(); 1326 String elementName = grantElement.getName(); 1327 if ( "grant".equals( elementName ) ) { 1328 jcfg.addPermission( 1329 grantElement.attributeValue( "role" ), 1330 grantElement.attributeValue( "entity-name" ), 1331 grantElement.attributeValue( "actions" ) 1332 ); 1333 } 1334 } 1335 } 1336 1337 private void parseListener(Element element) { 1338 String type = element.attributeValue( "type" ); 1339 String impl = element.attributeValue( "class" ); 1340 log.debug( "Encountered configured listener : " + type + "=" + impl ); 1341 setListener( type, impl ); 1342 } 1343 1344 public void setListener(String type, String listenerClass) { 1345 try { 1346 Object listener = ReflectHelper.classForName( listenerClass ).newInstance(); 1347 setListener( type, listener ); 1348 } 1349 catch ( Throwable t ) { 1350 log.warn( "Unable to instantiate specified listener class [" + listenerClass + "]", t ); 1351 } 1352 } 1353 1354 public void setListener(String type, Object listener) { 1355 if ( "auto-flush".equals( type ) ) { 1356 sessionEventListenerConfig.setAutoFlushEventListener( ( AutoFlushEventListener ) listener ); 1357 } 1358 else if ( "merge".equals( type ) ) { 1359 sessionEventListenerConfig.setMergeEventListener( ( MergeEventListener ) listener ); 1360 } 1361 else if ( "create".equals( type ) ) { 1362 sessionEventListenerConfig.setCreateEventListener( ( PersistEventListener ) listener ); 1363 } 1364 else if ( "delete".equals( type ) ) { 1365 sessionEventListenerConfig.setDeleteEventListener( ( DeleteEventListener ) listener ); 1366 } 1367 else if ( "dirty-check".equals( type ) ) { 1368 sessionEventListenerConfig.setDirtyCheckEventListener( ( DirtyCheckEventListener ) listener ); 1369 } 1370 else if ( "evict".equals( type ) ) { 1371 sessionEventListenerConfig.setEvictEventListener( ( EvictEventListener ) listener ); 1372 } 1373 else if ( "flush".equals( type ) ) { 1374 sessionEventListenerConfig.setFlushEventListener( ( FlushEventListener ) listener ); 1375 } 1376 else if ( "flush-entity".equals( type ) ) { 1377 sessionEventListenerConfig.setFlushEntityEventListener( ( FlushEntityEventListener ) listener ); 1378 } 1379 else if ( "load".equals( type ) ) { 1380 sessionEventListenerConfig.setLoadEventListener( ( LoadEventListener ) listener ); 1381 } 1382 else if ( "load-collection".equals( type ) ) { 1383 sessionEventListenerConfig.setInitializeCollectionEventListener( ( InitializeCollectionEventListener ) listener ); 1384 } 1385 else if ( "lock".equals( type ) ) { 1386 sessionEventListenerConfig.setLockEventListener( ( LockEventListener ) listener ); 1387 } 1388 else if ( "refresh".equals( type ) ) { 1389 sessionEventListenerConfig.setRefreshEventListener( ( RefreshEventListener ) listener ); 1390 } 1391 else if ( "replicate".equals( type ) ) { 1392 sessionEventListenerConfig.setReplicateEventListener( ( ReplicateEventListener ) listener ); 1393 } 1394 else if ( "save-update".equals( type ) ) { 1395 sessionEventListenerConfig.setSaveOrUpdateEventListener( ( SaveOrUpdateEventListener ) listener ); 1396 } 1397 else if ( "save".equals( type ) ) { 1398 sessionEventListenerConfig.setSaveEventListener( ( SaveOrUpdateEventListener ) listener ); 1399 } 1400 else if ( "update".equals( type ) ) { 1401 sessionEventListenerConfig.setUpdateEventListener( ( SaveOrUpdateEventListener ) listener ); 1402 } 1403 else if ( "pre-load".equals( type ) ) { 1404 sessionEventListenerConfig.setPreLoadEventListener( ( PreLoadEventListener ) listener ); 1405 } 1406 else if ( "pre-update".equals( type ) ) { 1407 sessionEventListenerConfig.setPreUpdateEventListener( ( PreUpdateEventListener ) listener ); 1408 } 1409 else if ( "pre-delete".equals( type ) ) { 1410 sessionEventListenerConfig.setPreDeleteEventListener( ( PreDeleteEventListener ) listener ); 1411 } 1412 else if ( "pre-insert".equals( type ) ) { 1413 sessionEventListenerConfig.setPreInsertEventListener( ( PreInsertEventListener ) listener ); 1414 } 1415 else if ( "post-load".equals( type ) ) { 1416 sessionEventListenerConfig.setPostLoadEventListener( ( PostLoadEventListener ) listener ); 1417 } 1418 else if ( "post-update".equals( type ) ) { 1419 sessionEventListenerConfig.setPostUpdateEventListener( ( PostUpdateEventListener ) listener ); 1420 } 1421 else if ( "post-delete".equals( type ) ) { 1422 sessionEventListenerConfig.setPostDeleteEventListener( ( PostDeleteEventListener ) listener ); 1423 } 1424 else if ( "post-insert".equals( type ) ) { 1425 sessionEventListenerConfig.setPostInsertEventListener( ( PostInsertEventListener ) listener ); 1426 } 1427 else { 1428 log.warn( "Unrecognized listener type [" + type + "]" ); 1429 } 1430 } 1431 1432 public SessionEventListenerConfig getSessionEventListenerConfig() { 1433 return sessionEventListenerConfig; 1434 } 1435 1436 RootClass getRootClassMapping(String clazz) throws MappingException { 1437 try { 1438 return ( RootClass ) getClassMapping( clazz ); 1439 } 1440 catch ( ClassCastException cce ) { 1441 throw new MappingException( "You may only specify a cache for root <class> mappings" ); 1442 } 1443 } 1444 1445 1453 public Configuration setCacheConcurrencyStrategy(String clazz, String concurrencyStrategy) 1454 throws MappingException { 1455 setCacheConcurrencyStrategy( clazz, concurrencyStrategy, clazz ); 1456 return this; 1457 } 1458 1459 void setCacheConcurrencyStrategy(String clazz, String concurrencyStrategy, String region) 1460 throws MappingException { 1461 RootClass rootClass = getRootClassMapping( clazz ); 1462 if (rootClass == null) throw new MappingException("Cannot cache an unknown entity: " + clazz); 1463 rootClass.setCacheConcurrencyStrategy( concurrencyStrategy ); 1464 rootClass.setCacheRegionName( region ); 1465 } 1466 1467 1475 public Configuration setCollectionCacheConcurrencyStrategy(String collectionRole, String concurrencyStrategy) 1476 throws MappingException { 1477 setCollectionCacheConcurrencyStrategy( collectionRole, concurrencyStrategy, collectionRole ); 1478 return this; 1479 } 1480 1481 void setCollectionCacheConcurrencyStrategy(String collectionRole, String concurrencyStrategy, String region) 1482 throws MappingException { 1483 Collection collection = getCollectionMapping( collectionRole ); 1484 if (collection == null) throw new MappingException("Cannot cache an unknown collection: " + collectionRole); 1485 collection.setCacheConcurrencyStrategy( concurrencyStrategy ); 1486 collection.setCacheRegionName( region ); 1487 } 1488 1489 1494 public Map getImports() { 1495 return imports; 1496 } 1497 1498 1501 public Settings buildSettings() throws HibernateException { 1502 return settingsFactory.buildSettings( properties ); 1503 } 1504 1505 public Map getNamedSQLQueries() { 1506 return namedSqlQueries; 1507 } 1508 1509 public Map getSqlResultSetMappings() { 1510 return sqlResultSetMappings; 1511 } 1512 1513 1516 public NamingStrategy getNamingStrategy() { 1517 return namingStrategy; 1518 } 1519 1520 1525 public Configuration setNamingStrategy(NamingStrategy namingStrategy) { 1526 this.namingStrategy = namingStrategy; 1527 return this; 1528 } 1529 1530 private Mapping buildMapping() { 1531 return new Mapping() { 1532 1535 public Type getIdentifierType(String persistentClass) throws MappingException { 1536 PersistentClass pc = ( ( PersistentClass ) classes.get( persistentClass ) ); 1537 if (pc==null) throw new MappingException("persistent class not known: " + persistentClass); 1538 return pc.getIdentifier().getType(); 1539 } 1540 1541 public String getIdentifierPropertyName(String persistentClass) throws MappingException { 1542 final PersistentClass pc = ( PersistentClass ) classes.get( persistentClass ); 1543 if (pc==null) throw new MappingException("persistent class not known: " + persistentClass); 1544 if ( !pc.hasIdentifierProperty() ) return null; 1545 return pc.getIdentifierProperty().getName(); 1546 } 1547 1548 public Type getReferencedPropertyType(String persistentClass, String propertyName) throws MappingException { 1549 final PersistentClass pc = ( PersistentClass ) classes.get( persistentClass ); 1550 if (pc==null) throw new MappingException("persistent class not known: " + persistentClass); 1551 Property prop = pc.getReferencedProperty(propertyName); 1552 if (prop==null) throw new MappingException("property not known: " + persistentClass + '.' + propertyName); 1553 return prop.getType(); 1554 } 1555 }; 1556 } 1557 1558 private void readObject(ObjectInputStream ois) throws IOException , ClassNotFoundException { 1559 ois.defaultReadObject(); 1560 this.mapping = buildMapping(); 1561 xmlHelper = new XMLHelper(); 1562 } 1563 1564 public Map getFilterDefinitions() { 1565 return filterDefinitions; 1566 } 1567 1568 public void addFilterDefinition(FilterDefinition definition) { 1569 filterDefinitions.put( definition.getFilterName(), definition ); 1570 } 1571} 1572 1573 1574 1575 1576 1577 1578 | Popular Tags |