1 package org.apache.ojb.broker.metadata; 2 3 17 18 import java.io.Serializable ; 19 import java.util.*; 20 21 import org.apache.commons.lang.SystemUtils; 22 import org.apache.commons.lang.builder.ToStringBuilder; 23 import org.apache.commons.lang.builder.ToStringStyle; 24 import org.apache.ojb.broker.OJBRuntimeException; 25 import org.apache.ojb.broker.PersistenceBrokerException; 26 import org.apache.ojb.broker.locking.IsolationLevels; 27 import org.apache.ojb.broker.util.ClassHelper; 28 import org.apache.ojb.broker.util.logging.LoggerFactory; 29 import org.apache.ojb.broker.util.logging.Logger; 30 31 42 public final class DescriptorRepository extends DescriptorBase 43 implements Serializable , XmlCapable, IsolationLevels 44 { 45 static final long serialVersionUID = -1556339982311359524L; 46 private Logger log = LoggerFactory.getLogger(DescriptorRepository.class); 47 48 52 private static final String VERSION = "1.0"; 53 56 private int defaultIsolationLevel = IsolationLevels.IL_DEFAULT; 57 61 private final HashMap descriptorTable; 62 67 private Map extentTable; 68 69 private Map superClassMultipleJoinedTablesMap; 70 71 private transient Map m_multiMappedTableMap; 72 private transient Map m_topLevelClassTable; 73 private transient Map m_firstConcreteClassMap; 74 private transient Map m_allConcreteSubClass; 75 76 79 public DescriptorRepository() throws PersistenceBrokerException 80 { 81 descriptorTable = new HashMap(); 82 extentTable = new HashMap(); 83 superClassMultipleJoinedTablesMap = new HashMap(); 84 } 85 86 public static String getVersion() 87 { 88 return VERSION; 89 } 90 91 97 void addExtent(String classname, ClassDescriptor cld) 98 { 99 synchronized (extentTable) 100 { 101 extentTable.put(classname, cld); 102 } 103 } 104 105 109 void removeExtent(String classname) 110 { 111 synchronized (extentTable) 112 { 113 ClassDescriptor cld = (ClassDescriptor) extentTable.remove(classname); 115 if(cld != null && m_topLevelClassTable != null) 116 { 117 Class extClass = null; 118 try 119 { 120 extClass = ClassHelper.getClass(classname); 121 } 122 catch (ClassNotFoundException e) 123 { 124 throw new MetadataException("Can't instantiate class object for needed extent remove", e); 126 } 127 cld.removeExtentClass(classname); 129 m_topLevelClassTable.remove(extClass); 130 m_firstConcreteClassMap = null; 133 } 134 } 135 } 136 137 146 public Class getTopLevelClass(Class clazz) throws ClassNotPersistenceCapableException 147 { 148 if(m_topLevelClassTable == null) 149 { 150 m_topLevelClassTable = new HashMap(); 151 } 152 Class retval = (Class ) m_topLevelClassTable.get(clazz); 154 if (retval == null) 155 { 156 synchronized (extentTable) 157 { 158 ClassDescriptor cld = (ClassDescriptor) extentTable.get(clazz.getName()); 159 if (cld == null) 160 { 161 cld = getDescriptorFor(clazz).getSuperClassDescriptor(); 163 } 164 165 if (cld != null) 166 { 167 retval = getTopLevelClass(cld.getClassOfObject()); 170 if (retval == null) 172 { 173 retval = clazz; 174 } 175 } 176 else 177 { 178 ClassDescriptor temp = getDescriptorFor(clazz); 183 retval = temp.getClassOfObject(); 184 } 185 m_topLevelClassTable.put(clazz, retval); 186 } 187 } 188 return retval; 189 } 190 191 196 public synchronized FieldDescriptor[] getFieldDescriptorsForMultiMappedTable(ClassDescriptor targetCld) 197 { 198 if (m_multiMappedTableMap == null) 199 { 200 m_multiMappedTableMap = new HashMap(); 201 } 202 203 FieldDescriptor[] retval = (FieldDescriptor[]) m_multiMappedTableMap.get(targetCld.getClassNameOfObject()); 204 if (retval == null) 205 { 206 retval = getAllMappedColumns(getClassesMappedToSameTable(targetCld)); 207 m_multiMappedTableMap.put(targetCld.getClassNameOfObject(), retval); 208 } 209 return retval; 210 } 211 212 private FieldDescriptor[] getAllMappedColumns(List classDescriptors) 213 { 214 220 List allFieldDescriptors = new Vector(); 221 222 Set visitedColumns = new HashSet(); 223 Iterator it = classDescriptors.iterator(); 224 ClassDescriptor temp = null; 225 FieldDescriptor[] fields; 226 while (it.hasNext()) 227 { 228 temp = (ClassDescriptor) it.next(); 229 fields = temp.getFieldDescriptions(); 230 if (fields != null) 231 { 232 for (int i = 0; i < fields.length; i++) 233 { 234 245 final String columnName = fields[i].getColumnName(); 246 if (!visitedColumns.contains(columnName)) 247 { 248 visitedColumns.add(columnName); 249 allFieldDescriptors.add(fields[i]); 250 } 251 } 252 } 253 } 254 FieldDescriptor[] retval = new FieldDescriptor[allFieldDescriptors.size()]; 255 allFieldDescriptors.toArray(retval); 256 return retval; 257 } 258 259 private List getClassesMappedToSameTable(ClassDescriptor targetCld) 260 { 261 266 Iterator iter = ((HashMap)descriptorTable.clone()).values().iterator(); 267 List retval = new ArrayList(); 268 retval.add(targetCld); 270 while (iter.hasNext()) 271 { 272 ClassDescriptor cld = (ClassDescriptor) iter.next(); 273 if (cld.getFullTableName() != null) 274 { 275 if (cld.getFullTableName().equals(targetCld.getFullTableName()) 276 && !targetCld.getClassOfObject().equals(cld.getClassOfObject())) 277 { 278 retval.add(cld); 279 } 280 } 281 } 282 return retval; 283 } 284 285 public Map getDescriptorTable() 286 { 287 return descriptorTable; 288 } 289 290 297 public ClassDescriptor findFirstConcreteClass(ClassDescriptor cld) 298 { 299 if(m_firstConcreteClassMap == null) 300 { 301 m_firstConcreteClassMap = new HashMap(); 302 } 303 ClassDescriptor result = (ClassDescriptor) m_firstConcreteClassMap.get(cld.getClassNameOfObject()); 304 if (result == null) 305 { 306 if(cld.isInterface() || cld.isAbstract()) 307 { 308 if(cld.isExtent()) 309 { 310 List extents = cld.getExtentClasses(); 311 for (int i = 0; i < extents.size(); i++) 312 { 313 Class ext = (Class ) extents.get(i); 314 result = findFirstConcreteClass(getDescriptorFor(ext)); 315 if(result != null) break; 316 } 317 } 318 else 319 { 320 LoggerFactory.getDefaultLogger().error("["+this.getClass().getName()+"] Found interface/abstract class" + 321 " in metadata declarations without concrete class: "+cld.getClassNameOfObject()); 322 } 323 m_firstConcreteClassMap.put(cld.getClassNameOfObject(), result); 324 } 325 else 326 { 327 result = cld; 328 } 329 } 330 return result; 331 } 332 333 340 public Collection getAllConcreteSubclassDescriptors(ClassDescriptor aCld) 341 { 342 if(m_allConcreteSubClass == null) 343 { 344 m_allConcreteSubClass = new HashMap(); 345 } 346 Collection concreteSubclassClds = (Collection) m_allConcreteSubClass.get(aCld.getClassOfObject()); 347 348 if (concreteSubclassClds == null) 349 { 350 concreteSubclassClds = new ArrayList(); 354 Iterator iter = aCld.getExtentClasses().iterator(); 355 356 while (iter.hasNext()) 357 { 358 Class extentClass = (Class ) iter.next(); 359 ClassDescriptor extCld = getDescriptorFor(extentClass); 360 if (aCld.equals(extCld)) 361 { 362 continue; 364 } 365 if (!extCld.isInterface() && !extCld.isAbstract()) 366 { 367 if (!concreteSubclassClds.contains(extCld)) 368 { 369 concreteSubclassClds.add(extCld); 370 } 371 } 372 373 Iterator subIter = getAllConcreteSubclassDescriptors(extCld).iterator(); 375 while (subIter.hasNext()) 376 { 377 ClassDescriptor subCld = (ClassDescriptor)subIter.next(); 378 if (!concreteSubclassClds.contains(subCld)) 379 { 380 concreteSubclassClds.add(subCld); 381 } 382 } 383 } 384 m_allConcreteSubClass.put(aCld.getClassOfObject(), concreteSubclassClds); 385 } 386 387 return concreteSubclassClds; 388 } 389 390 391 394 public boolean hasDescriptorFor(Class c) 395 { 396 return descriptorTable.containsKey(c.getName()); 397 } 398 399 403 public ClassDescriptor getDescriptorFor(String strClassName) throws ClassNotPersistenceCapableException 404 { 405 ClassDescriptor result = discoverDescriptor(strClassName); 406 if (result == null) 407 { 408 throw new ClassNotPersistenceCapableException(strClassName + " not found in OJB Repository"); 409 } 410 else 411 { 412 return result; 413 } 414 } 415 416 419 public ClassDescriptor getDescriptorFor(Class c) throws ClassNotPersistenceCapableException 420 { 421 return this.getDescriptorFor(c.getName()); 422 } 423 424 427 public void setClassDescriptor(ClassDescriptor cld) 428 { 429 this.put(cld.getClassNameOfObject(), cld); 430 } 431 432 436 public void put(Class c, ClassDescriptor cld) 437 { 438 this.put(c.getName(), cld); 439 } 440 441 445 public void put(String classname, ClassDescriptor cld) 446 { 447 cld.setRepository(this); synchronized (descriptorTable) 449 { 450 descriptorTable.put(classname, cld); 451 List extentClasses = cld.getExtentClasses(); 452 for (int i = 0; i < extentClasses.size(); ++i) 453 { 454 addExtent(((Class ) extentClasses.get(i)).getName(), cld); 455 } 456 changeDescriptorEvent(); 457 } 458 } 459 460 public void remove(String className) 461 { 462 synchronized (descriptorTable) 463 { 464 ClassDescriptor cld = (ClassDescriptor) descriptorTable.remove(className); 465 if(cld != null) 466 { 467 Iterator it = descriptorTable.values().iterator(); 469 while (it.hasNext()) 470 { 471 ((ClassDescriptor) it.next()).removeExtentClass(className); 472 } 473 removeExtent(className); 474 List extentClasses = cld.getExtentClasses(); 475 for (int i = 0; i < extentClasses.size(); ++i) 476 { 477 removeExtent(((Class ) extentClasses.get(i)).getName()); 478 } 479 changeDescriptorEvent(); 480 deregisterSuperClassMultipleJoinedTables(cld); 483 } 484 } 485 } 486 487 public void remove(Class clazz) 488 { 489 remove(clazz.getName()); 490 } 491 492 private synchronized void changeDescriptorEvent() 493 { 494 m_multiMappedTableMap = null; 495 m_topLevelClassTable = null; 496 m_firstConcreteClassMap = null; 497 m_allConcreteSubClass = null; 498 } 499 500 503 public Iterator iterator() 504 { 505 508 return ((HashMap)descriptorTable.clone()).values().iterator(); 509 } 510 511 515 public int getDefaultIsolationLevel() 516 { 517 return defaultIsolationLevel; 518 } 519 520 524 public void setDefaultIsolationLevel(int defaultIsolationLevel) 525 { 526 this.defaultIsolationLevel = defaultIsolationLevel; 527 } 528 529 532 public String toString() 533 { 534 Iterator it = descriptorTable.entrySet().iterator(); 535 ToStringBuilder buf = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); 536 String className = "class name: "; 537 String tableName = "> table name: "; 538 while (it.hasNext()) 539 { 540 Map.Entry me = (Map.Entry) it.next(); 541 ClassDescriptor descriptor = (ClassDescriptor) me.getValue(); 542 buf.append(className + me.getKey() + " =", tableName + descriptor.getFullTableName()); 543 } 544 return buf.toString(); 545 } 546 547 550 public String toXML() 551 { 552 String eol = SystemUtils.LINE_SEPARATOR; 553 StringBuffer buf = new StringBuffer (); 554 555 Iterator i = this.iterator(); 557 while (i.hasNext()) 558 { 559 buf.append(((XmlCapable) i.next()).toXML() + eol); 560 } 561 return buf.toString(); 562 } 563 564 569 protected String getIsolationLevelAsString() 570 { 571 if (defaultIsolationLevel == IL_READ_UNCOMMITTED) 572 { 573 return LITERAL_IL_READ_UNCOMMITTED; 574 } 575 else if (defaultIsolationLevel == IL_READ_COMMITTED) 576 { 577 return LITERAL_IL_READ_COMMITTED; 578 } 579 else if (defaultIsolationLevel == IL_REPEATABLE_READ) 580 { 581 return LITERAL_IL_REPEATABLE_READ; 582 } 583 else if (defaultIsolationLevel == IL_SERIALIZABLE) 584 { 585 return LITERAL_IL_SERIALIZABLE; 586 } 587 else if (defaultIsolationLevel == IL_OPTIMISTIC) 588 { 589 return LITERAL_IL_OPTIMISTIC; 590 } 591 return LITERAL_IL_READ_UNCOMMITTED; 592 } 593 594 612 protected ClassDescriptor discoverDescriptor(String className) 613 { 614 ClassDescriptor result = (ClassDescriptor) descriptorTable.get(className); 615 if (result == null) 616 { 617 Class clazz; 618 try 619 { 620 clazz = ClassHelper.getClass(className, true); 621 } 622 catch (ClassNotFoundException e) 623 { 624 throw new OJBRuntimeException("Class, " + className + ", could not be found.", e); 625 } 626 result = discoverDescriptor(clazz); 627 } 628 return result; 629 } 630 631 639 private ClassDescriptor discoverDescriptor(Class clazz) 640 { 641 ClassDescriptor result = (ClassDescriptor) descriptorTable.get(clazz.getName()); 642 643 if (result == null) 644 { 645 Class superClass = clazz.getSuperclass(); 646 if (superClass != null) 648 { 649 result = discoverDescriptor(superClass); 650 } 651 if (result == null) 652 { 653 Class [] interfaces = clazz.getInterfaces(); 657 658 if ((interfaces != null) && (interfaces.length > 0)) 659 { 660 for (int idx = 0; (idx < interfaces.length) && (result == null); idx++) 661 { 662 result = discoverDescriptor(interfaces[idx]); 663 } 664 } 665 } 666 667 if (result != null) 668 { 669 descriptorTable.put(clazz.getName(), result); 670 } 671 } 672 return result; 673 } 674 675 682 protected void registerSuperClassMultipleJoinedTables(ClassDescriptor cld) 683 { 684 689 if(cld.getBaseClass() != null) 690 { 691 try 692 { 693 Class superClass = ClassHelper.getClass(cld.getBaseClass()); 694 Class currentClass = cld.getClassOfObject(); 695 synchronized(descriptorTable) 696 { 697 List subClasses = (List) superClassMultipleJoinedTablesMap.get(superClass); 698 if(subClasses == null) 699 { 700 subClasses = new ArrayList(); 701 superClassMultipleJoinedTablesMap.put(superClass, subClasses); 702 } 703 if(!subClasses.contains(currentClass)) 704 { 705 if(log.isDebugEnabled()) 706 { 707 log.debug("(MultipleJoinedTables): Register sub-class '" + currentClass 708 + "' for class '" + superClass); 709 } 710 subClasses.add(currentClass); 711 } 712 } 713 } 714 catch(Exception e) 715 { 716 throw new MetadataException("Can't register super class '" + cld.getBaseClass() 717 + "' for class-descriptor: " + cld, e); 718 } 719 } 720 } 721 722 728 protected void deregisterSuperClassMultipleJoinedTables(ClassDescriptor cld) 729 { 730 try 731 { 732 Class currentClass = cld.getClassOfObject(); 733 synchronized(descriptorTable) 734 { 735 List subClasses = (List) superClassMultipleJoinedTablesMap.remove(currentClass); 737 if(subClasses != null && log.isDebugEnabled()) 738 { 739 log.debug("(MultipleJoinedTables): Deregister class " + currentClass 740 + " with sub classes " + subClasses); 741 } 742 if(cld.getBaseClass() != null) 743 { 744 Class superClass = ClassHelper.getClass(cld.getBaseClass()); 746 subClasses = (List) superClassMultipleJoinedTablesMap.get(superClass); 747 if(subClasses != null) 748 { 749 boolean removed = subClasses.remove(currentClass); 750 if(removed && log.isDebugEnabled()) 751 { 752 log.debug("(MultipleJoinedTables): Remove sub-class entry '" + currentClass 753 + "' in mapping for class '" + superClass + "'"); 754 } 755 } 756 } 757 } 758 } 759 catch(Exception e) 760 { 761 throw new MetadataException("Can't deregister super class '" + cld.getBaseClass() 762 + "' for class-descriptor: " + cld, e); 763 } 764 } 765 766 775 public Class [] getSubClassesMultipleJoinedTables(ClassDescriptor cld, boolean wholeTree) 776 { 777 ArrayList result = new ArrayList(); 778 createResultSubClassesMultipleJoinedTables(result, cld, wholeTree); 779 return (Class []) result.toArray(new Class [result.size()]); 780 } 781 782 790 private void createResultSubClassesMultipleJoinedTables(List result, ClassDescriptor cld, boolean wholeTree) 791 { 792 List tmp = (List) superClassMultipleJoinedTablesMap.get(cld.getClassOfObject()); 793 if(tmp != null) 794 { 795 result.addAll(tmp); 796 if(wholeTree) 797 { 798 for(int i = 0; i < tmp.size(); i++) 799 { 800 Class subClass = (Class ) tmp.get(i); 801 ClassDescriptor subCld = getDescriptorFor(subClass); 802 createResultSubClassesMultipleJoinedTables(result, subCld, wholeTree); 803 } 804 } 805 } 806 } 807 808 protected void finalize() throws Throwable 809 { 810 log.info("# finalize DescriptorRepository instance #"); 811 super.finalize(); 812 } 813 } 814 | Popular Tags |