1 package org.apache.ojb.broker.core; 2 3 17 18 import java.lang.reflect.Array ; 19 import java.util.ArrayList ; 20 import java.util.Collection ; 21 import java.util.HashMap ; 22 import java.util.Iterator ; 23 import java.util.List ; 24 import java.util.Map ; 25 26 import org.apache.ojb.broker.Identity; 27 import org.apache.ojb.broker.ManageableCollection; 28 import org.apache.ojb.broker.PBLifeCycleEvent; 29 import org.apache.ojb.broker.PersistenceBrokerException; 30 import org.apache.ojb.broker.accesslayer.OJBIterator; 31 import org.apache.ojb.broker.accesslayer.PagingIterator; 32 import org.apache.ojb.broker.accesslayer.PlainPrefetcher; 33 import org.apache.ojb.broker.accesslayer.RelationshipPrefetcher; 34 import org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl; 35 import org.apache.ojb.broker.core.proxy.CollectionProxyListener; 36 import org.apache.ojb.broker.core.proxy.IndirectionHandler; 37 import org.apache.ojb.broker.core.proxy.MaterializationListener; 38 import org.apache.ojb.broker.core.proxy.ProxyHelper; 39 import org.apache.ojb.broker.metadata.ClassDescriptor; 40 import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException; 41 import org.apache.ojb.broker.metadata.CollectionDescriptor; 42 import org.apache.ojb.broker.metadata.FieldDescriptor; 43 import org.apache.ojb.broker.metadata.FieldHelper; 44 import org.apache.ojb.broker.metadata.MetadataException; 45 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor; 46 import org.apache.ojb.broker.metadata.fieldaccess.PersistentField; 47 import org.apache.ojb.broker.query.Criteria; 48 import org.apache.ojb.broker.query.Query; 49 import org.apache.ojb.broker.query.QueryByCriteria; 50 import org.apache.ojb.broker.query.QueryFactory; 51 import org.apache.ojb.broker.util.BrokerHelper; 52 import org.apache.ojb.broker.util.collections.ManageableArrayList; 53 import org.apache.ojb.broker.util.collections.ManageableHashSet; 54 import org.apache.ojb.broker.util.collections.RemovalAwareCollection; 55 import org.apache.ojb.broker.util.collections.RemovalAwareList; 56 import org.apache.ojb.broker.util.collections.RemovalAwareSet; 57 import org.apache.ojb.broker.util.logging.Logger; 58 import org.apache.ojb.broker.util.logging.LoggerFactory; 59 60 69 public class QueryReferenceBroker 70 { 71 private Logger log = LoggerFactory.getLogger(QueryReferenceBroker.class); 72 73 private PersistenceBrokerImpl pb; 74 private HashMap m_retrievalTasks; 75 private ArrayList prefetchingListeners; 76 private final boolean batchRetrieval = true; 77 private final boolean prefetchProxies = true; 78 private Class classToPrefetch; 79 private PBLifeCycleEvent afterLookupEvent; 80 81 public QueryReferenceBroker(final PersistenceBrokerImpl pb) 82 { 83 this.pb = pb; 84 afterLookupEvent = new PBLifeCycleEvent(pb, PBLifeCycleEvent.Type.AFTER_LOOKUP); 85 } 86 87 93 private ManageableCollection getCollectionByQuery(Class collectionClass, Class itemClass, Query query) 94 throws ClassNotPersistenceCapableException, PersistenceBrokerException 95 { 96 if (log.isDebugEnabled()) log.debug("getCollectionByQuery (" + collectionClass + ", " + itemClass + ", " + query + ")"); 97 98 ClassDescriptor cld = pb.getClassDescriptor(itemClass); 99 ManageableCollection result = null; 100 OJBIterator iter = null; 101 int fullSize = -1; 102 int size = 0; 103 104 final boolean isRetrievalTasksCreated = batchRetrieval && m_retrievalTasks == null; 105 if (isRetrievalTasksCreated) 106 { 107 m_retrievalTasks = new HashMap (); 109 } 110 111 pb.getInternalCache().enableMaterializationCache(); 113 try 114 { 115 result = (ManageableCollection) collectionClass.newInstance(); 116 117 iter = pb.getIteratorFromQuery(query, cld); 120 iter.disableLifeCycleEvents(); 121 122 if (iter instanceof PagingIterator) 125 { 126 fullSize = iter.fullSize(); 127 } 128 129 while (iter.hasNext()) 130 { 131 Object candidate = iter.next(); 132 133 139 if (candidate != null) 140 { 141 IndirectionHandler handler = ProxyHelper.getIndirectionHandler(candidate); 142 143 if ((handler != null) || itemClass.isAssignableFrom(candidate.getClass())) 144 { 145 result.ojbAdd(candidate); 146 147 size++; 150 } 151 else 152 { 153 log.warn("Candidate object ["+candidate 155 +"] class ["+candidate.getClass().getName() 156 +"] is not a subtype of ["+itemClass.getName() 157 +"] or any type of proxy. NOT INCLUDED in result collection"); 158 } 159 if (prefetchProxies && (handler != null) 160 && (cld.getProxyPrefetchingLimit() > 0) 161 && addRetrievalTask(candidate, this)) 162 { 163 new PBMaterializationListener(candidate, m_retrievalTasks, 164 this, cld.getProxyPrefetchingLimit()); 165 } 166 } 167 } 168 169 if (isRetrievalTasksCreated) 170 { 171 final Class saveClassToPrefetch = classToPrefetch; 173 classToPrefetch = null; 174 try 175 { 176 performRetrievalTasks(); 177 } 178 finally 179 { 180 classToPrefetch = saveClassToPrefetch; 181 } 182 } 183 184 Iterator resultIter = result.ojbIterator(); 187 while (resultIter.hasNext()) 188 { 189 Object obj = resultIter.next(); 190 afterLookupEvent.setTarget(obj); 191 pb.fireBrokerEvent(afterLookupEvent); 192 afterLookupEvent.setTarget(null); 193 } 194 195 pb.getInternalCache().disableMaterializationCache(); 197 } 198 catch(RuntimeException e) 199 { 200 pb.getInternalCache().doLocalClear(); 202 throw e; 203 } 204 catch (Exception ex) 205 { 206 pb.getInternalCache().doLocalClear(); 208 log.error(ex); 209 throw new PersistenceBrokerException(ex); 210 } 211 finally 212 { 213 if (iter != null) 214 { 215 iter.releaseDbResources(); 216 } 217 if (isRetrievalTasksCreated) 218 { 219 m_retrievalTasks = null; 220 } 221 } 222 223 if (fullSize < 0) 226 { 227 fullSize = size; } 229 query.fullSize(fullSize); 230 231 return result; 232 } 233 234 244 public ManageableCollection getCollectionByQuery(Class collectionClass, Query query, boolean lazy) throws PersistenceBrokerException 245 { 246 ManageableCollection result; 247 248 try 249 { 250 if (query == null) 252 { 253 result = (ManageableCollection)collectionClass.newInstance(); 254 } 255 else 256 { 257 if (lazy) 258 { 259 result = pb.getProxyFactory().createCollectionProxy(pb.getPBKey(), query, collectionClass); 260 } 261 else 262 { 263 result = getCollectionByQuery(collectionClass, query.getSearchClass(), query); 264 } 265 } 266 return result; 267 } 268 catch (Exception e) 269 { 270 if(e instanceof PersistenceBrokerException) 271 { 272 throw (PersistenceBrokerException) e; 273 } 274 else 275 { 276 throw new PersistenceBrokerException(e); 277 } 278 } 279 } 280 281 284 public Collection getCollectionByQuery(Query query, boolean lazy) throws PersistenceBrokerException 285 { 286 return (Collection ) getCollectionByQuery(RemovalAwareCollection.class, query, lazy); 290 } 291 292 293 private Class getCollectionTypeClass(CollectionDescriptor cds) throws PersistenceBrokerException{ 294 297 Class fieldType = cds.getPersistentField().getType(); 298 Class collType; 299 300 if (fieldType.isArray() || fieldType.isAssignableFrom(RemovalAwareCollection.class)) 301 { 302 collType = cds.isMtoNRelation() ? ManageableArrayList.class : RemovalAwareCollection.class; 303 } 304 else if (fieldType.isAssignableFrom(RemovalAwareList.class)) 305 { 306 collType = cds.isMtoNRelation() ? ManageableArrayList.class : RemovalAwareList.class; 307 } 308 else if (fieldType.isAssignableFrom(RemovalAwareSet.class)) 309 { 310 collType = cds.isMtoNRelation() ? ManageableHashSet.class : RemovalAwareSet.class; 311 } 312 else if (ManageableCollection.class.isAssignableFrom(fieldType)) 313 { 314 collType = fieldType; 315 } 316 else 317 { 318 throw new MetadataException("Cannot determine a default collection type for collection "+cds.getAttributeName()+" in type "+cds.getClassDescriptor().getClassNameOfObject()); 319 } 320 return collType; 321 } 322 323 324 327 private boolean addRetrievalTask(Object obj, Object key) 328 { 329 ArrayList owners = (ArrayList ) m_retrievalTasks.get(key); 330 boolean isFirst = false; 331 332 if (owners == null) 333 { 334 owners = new ArrayList (); 335 m_retrievalTasks.put(key, owners); 336 isFirst = true; 337 } 338 owners.add(obj); 339 return isFirst; 340 } 341 342 347 public void performRetrievalTasks() 348 { 349 if (m_retrievalTasks == null) 350 { 351 return; 352 } 353 354 while (m_retrievalTasks.size() > 0) 355 { 356 HashMap tmp = m_retrievalTasks; 357 m_retrievalTasks = new HashMap (); 358 360 for (Iterator it = tmp.entrySet().iterator(); it.hasNext(); ) 361 { 362 Map.Entry entry = (Map.Entry ) it.next(); 363 Object key = entry.getKey(); 364 365 if (!(key instanceof ObjectReferenceDescriptor)) 366 { 367 continue; 368 } 369 370 ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor) key; 371 RelationshipPrefetcher prefetcher; 372 ArrayList owners = (ArrayList ) entry.getValue(); 373 374 if (ord.isLazy() || (ord.getItemProxyClass() != null)) 376 { 377 continue; 378 } 379 380 prefetcher = pb.getRelationshipPrefetcherFactory().createRelationshipPrefetcher(ord); 381 prefetcher.prefetchRelationship(owners); 382 it.remove(); 383 } 384 } 385 } 386 387 397 public void retrieveReference(Object obj, ClassDescriptor cld, ObjectReferenceDescriptor rds, boolean forced) 398 { 399 PersistentField refField; 400 Object refObj = null; 401 402 if (forced || rds.getCascadeRetrieve()) 403 { 404 pb.getInternalCache().enableMaterializationCache(); 405 try 406 { 407 Identity id = getReferencedObjectIdentity(obj, rds, cld); 408 boolean isRefObjDefined = true; 409 410 if (id == null) 411 { 412 refObj = null; 413 } else if ( pb.serviceObjectCache().lookup(id) != null ) 415 { 416 refObj = pb.doGetObjectByIdentity(id); 417 if (rds.isSuperReferenceDescriptor()) 418 { 419 ClassDescriptor superCld = cld.getRepository().getDescriptorFor(rds.getItemClass()); 421 retrieveReferences(refObj, superCld, false); 422 retrieveCollections(refObj, superCld, false); 423 } 424 } 425 else if ((m_retrievalTasks != null) 426 && !rds.isLazy() 427 && (rds.getItemProxyClass() == null)) 428 { 429 addRetrievalTask(obj, rds); 430 isRefObjDefined = false; 431 } 432 else 433 { 434 refObj = getReferencedObject(id, rds); 435 } 436 437 if (isRefObjDefined) 438 { 439 refField = rds.getPersistentField(); 440 refField.set(obj, refObj); 441 442 if ((refObj != null) && prefetchProxies 443 && (m_retrievalTasks != null) 444 && (rds.getProxyPrefetchingLimit() > 0)) 445 { 446 IndirectionHandler handler = ProxyHelper.getIndirectionHandler(refObj); 447 448 if ((handler != null) 449 && addRetrievalTask(obj, rds)) 450 { 451 new PBMaterializationListener(obj, m_retrievalTasks, 452 rds, rds.getProxyPrefetchingLimit()); 453 } 454 } 455 } 456 457 pb.getInternalCache().disableMaterializationCache(); 458 } 459 catch(RuntimeException e) 460 { 461 pb.getInternalCache().doLocalClear(); 462 throw e; 463 } 464 } 465 } 466 467 477 public void retrieveProxyReference(Object obj, ClassDescriptor cld, ObjectReferenceDescriptor rds, boolean forced) 478 { 479 PersistentField refField; 480 Object refObj = null; 481 482 pb.getInternalCache().enableMaterializationCache(); 483 try 484 { 485 Identity id = getReferencedObjectIdentity(obj, rds, cld); 486 if (id != null){ 487 refObj = pb.createProxy(rds.getItemClass(), id); 488 } 489 refField = rds.getPersistentField(); 490 refField.set(obj, refObj); 491 492 if ((refObj != null) && prefetchProxies 493 && (m_retrievalTasks != null) 494 && (rds.getProxyPrefetchingLimit() > 0)) 495 { 496 IndirectionHandler handler = ProxyHelper.getIndirectionHandler(refObj); 497 498 if ((handler != null) 499 && addRetrievalTask(obj, rds)) 500 { 501 new PBMaterializationListener(obj, m_retrievalTasks, 502 rds, rds.getProxyPrefetchingLimit()); 503 } 504 } 505 506 507 pb.getInternalCache().disableMaterializationCache(); 508 } 509 catch(RuntimeException e) 510 { 511 pb.getInternalCache().doLocalClear(); 512 throw e; 513 } 514 515 } 516 517 524 public void retrieveReferences(Object newObj, ClassDescriptor cld, boolean forced) throws PersistenceBrokerException 525 { 526 Iterator i = cld.getObjectReferenceDescriptors().iterator(); 527 528 final Class saveClassToPrefetch = classToPrefetch; 530 classToPrefetch = null; 531 532 pb.getInternalCache().enableMaterializationCache(); 533 try 534 { 535 while (i.hasNext()) 536 { 537 ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) i.next(); 538 retrieveReference(newObj, cld, rds, forced); 539 } 540 541 pb.getInternalCache().disableMaterializationCache(); 542 } 543 catch(RuntimeException e) 544 { 545 pb.getInternalCache().doLocalClear(); 546 throw e; 547 } 548 finally 549 { 550 classToPrefetch = saveClassToPrefetch; 551 } 552 } 553 554 561 public void retrieveProxyReferences(Object newObj, ClassDescriptor cld, boolean forced) throws PersistenceBrokerException 562 { 563 Iterator i = cld.getObjectReferenceDescriptors().iterator(); 564 565 final Class saveClassToPrefetch = classToPrefetch; 567 classToPrefetch = null; 568 569 pb.getInternalCache().enableMaterializationCache(); 570 try 571 { 572 while (i.hasNext()) 573 { 574 ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) i.next(); 575 retrieveProxyReference(newObj, cld, rds, forced); 576 } 577 578 pb.getInternalCache().disableMaterializationCache(); 579 } 580 catch(RuntimeException e) 581 { 582 pb.getInternalCache().doLocalClear(); 583 throw e; 584 } 585 finally 586 { 587 classToPrefetch = saveClassToPrefetch; 588 } 589 } 590 591 596 private Identity getReferencedObjectIdentity(Object obj, ObjectReferenceDescriptor rds, ClassDescriptor cld) 597 { 598 Object [] fkValues = rds.getForeignKeyValues(obj, cld); 599 FieldDescriptor[] fkFieldDescriptors = rds.getForeignKeyFieldDescriptors(cld); 600 boolean hasNullifiedFKValue = hasNullifiedFK(fkFieldDescriptors, fkValues); 601 609 if (hasNullifiedFKValue) 610 { 611 if(BrokerHelper.hasAnonymousKeyReference(cld, rds)) 612 { 613 Object referencedObject = rds.getPersistentField().get(obj); 614 if(referencedObject != null) 615 { 616 return pb.serviceIdentity().buildIdentity(referencedObject); 617 } 618 } 619 } 620 else 621 { 622 return pb.serviceIdentity().buildIdentity(rds.getItemClass(), pb.getTopLevelClass(rds.getItemClass()), fkValues); 624 } 625 return null; 626 } 627 628 private boolean hasNullifiedFK(FieldDescriptor[] fkFieldDescriptors, Object [] fkValues) 632 { 633 boolean result = true; 634 for (int i = 0; i < fkValues.length; i++) 635 { 636 if (!pb.serviceBrokerHelper().representsNull(fkFieldDescriptors[i], fkValues[i])) 637 { 638 result = false; 639 break; 640 } 641 } 642 return result; 643 } 644 645 653 private Object getReferencedObject(Identity id, ObjectReferenceDescriptor rds) 654 { 655 Class baseClassForProxy; 656 657 if (rds.isLazy()) 658 { 659 665 668 673 baseClassForProxy = rds.getItemClass(); 674 } 675 else 676 { 677 681 baseClassForProxy = rds.getItemProxyClass(); 682 } 683 684 if (baseClassForProxy != null) 685 { 686 try 687 { 688 return pb.createProxy(baseClassForProxy, id); 689 } 690 catch (Exception e) 691 { 692 log.error("Error while instantiate object " + id + ", msg: "+ e.getMessage(), e); 693 if(e instanceof PersistenceBrokerException) 694 { 695 throw (PersistenceBrokerException) e; 696 } 697 else 698 { 699 throw new PersistenceBrokerException(e); 700 } 701 } 702 } 703 else 704 { 705 return pb.doGetObjectByIdentity(id); 706 } 707 } 708 709 720 public void retrieveCollection(Object obj, ClassDescriptor cld, CollectionDescriptor cds, boolean forced) 721 { 722 doRetrieveCollection(obj, cld, cds, forced, cds.isLazy()); 723 } 724 725 736 public void retrieveProxyCollection(Object obj, ClassDescriptor cld, CollectionDescriptor cds, boolean forced) 737 { 738 doRetrieveCollection(obj, cld, cds, forced, true); 739 } 740 741 private void doRetrieveCollection(Object obj, ClassDescriptor cld, CollectionDescriptor cds, boolean forced, boolean lazyLoad) 742 { 743 if (forced || cds.getCascadeRetrieve()) 744 { 745 if ((m_retrievalTasks != null) && !cds.isLazy() 746 && !cds.hasProxyItems() 747 && (cds.getQueryCustomizer() == null)) 748 { 749 addRetrievalTask(obj, cds); 750 } 751 else 752 { 753 Class collectionClass = cds.getCollectionClass(); 755 PersistentField collectionField = cds.getPersistentField(); 756 Query fkQuery = getFKQuery(obj, cld, cds); 757 Object value; 758 759 pb.getInternalCache().enableMaterializationCache(); 760 try 761 { 762 if (collectionClass == null) 763 { 764 Collection result = (Collection )getCollectionByQuery(getCollectionTypeClass(cds), fkQuery, lazyLoad); 765 766 if (collectionField.getType().isArray()) 769 { 770 int length = result.size(); 771 Class itemtype = collectionField.getType().getComponentType(); 772 Object resultArray = Array.newInstance(itemtype, length); 773 int j = 0; 774 for (Iterator iter = result.iterator(); iter.hasNext();j++) 775 { 776 Array.set(resultArray, j, iter.next()); 777 } 778 collectionField.set(obj, resultArray); 779 } 780 else 781 { 782 collectionField.set(obj, result); 783 } 784 value = result; 785 } 786 else 787 { 788 ManageableCollection result = getCollectionByQuery(collectionClass, fkQuery, lazyLoad); 789 collectionField.set(obj, result); 790 value = result; 791 } 792 793 if (prefetchProxies && (m_retrievalTasks != null) 794 && (cds.getProxyPrefetchingLimit() > 0) 795 && (cds.getQueryCustomizer() == null) 796 && (ProxyHelper.isCollectionProxy(value))) 797 { 798 if (addRetrievalTask(obj, cds)) 799 { 800 new PBCollectionProxyListener(obj, 801 m_retrievalTasks, cds, cds.getProxyPrefetchingLimit()); 802 } 803 } 804 805 pb.getInternalCache().disableMaterializationCache(); 806 } 807 catch(RuntimeException e) 808 { 809 pb.getInternalCache().doLocalClear(); 810 throw e; 811 } 812 } 813 } 814 } 815 816 820 private Query getFKQuery(Object obj, ClassDescriptor cld, CollectionDescriptor cds) 821 { 822 Query fkQuery; 823 QueryByCriteria fkQueryCrit; 824 825 if (cds.isMtoNRelation()) 826 { 827 fkQueryCrit = getFKQueryMtoN(obj, cld, cds); 828 } 829 else 830 { 831 fkQueryCrit = getFKQuery1toN(obj, cld, cds); 832 } 833 834 if (!cds.getOrderBy().isEmpty()) 836 { 837 Iterator iter = cds.getOrderBy().iterator(); 838 while (iter.hasNext()) 839 { 840 fkQueryCrit.addOrderBy((FieldHelper)iter.next()); 841 } 842 } 843 844 if (cds.getQueryCustomizer() != null) 846 { 847 fkQuery = cds.getQueryCustomizer().customizeQuery(obj, pb, cds, fkQueryCrit); 848 } 849 else 850 { 851 fkQuery = fkQueryCrit; 852 } 853 854 return fkQuery; 855 } 856 857 865 private QueryByCriteria getFKQueryMtoN(Object obj, ClassDescriptor cld, CollectionDescriptor cod) 866 { 867 ValueContainer[] values = pb.serviceBrokerHelper().getKeyValues(cld, obj); 868 Object [] thisClassFks = cod.getFksToThisClass(); 869 Object [] itemClassFks = cod.getFksToItemClass(); 870 ClassDescriptor refCld = pb.getClassDescriptor(cod.getItemClass()); 871 Criteria criteria = new Criteria(); 872 873 for (int i = 0; i < thisClassFks.length; i++) 874 { 875 criteria.addEqualTo(cod.getIndirectionTable() + "." + thisClassFks[i], values[i].getValue()); 876 } 877 for (int i = 0; i < itemClassFks.length; i++) 878 { 879 criteria.addEqualToField(cod.getIndirectionTable() + "." + itemClassFks[i], 880 refCld.getPkFields()[i].getAttributeName()); 881 } 882 883 return QueryFactory.newQuery(refCld.getClassOfObject(), cod.getIndirectionTable(), criteria); 884 } 885 886 893 private QueryByCriteria getFKQuery1toN(Object obj, ClassDescriptor cld, CollectionDescriptor cod) 894 { 895 ValueContainer[] container = pb.serviceBrokerHelper().getKeyValues(cld, obj); 896 ClassDescriptor refCld = pb.getClassDescriptor(cod.getItemClass()); 897 FieldDescriptor[] fields = cod.getForeignKeyFieldDescriptors(refCld); 898 Criteria criteria = new Criteria(); 899 900 for (int i = 0; i < fields.length; i++) 901 { 902 FieldDescriptor fld = fields[i]; 903 criteria.addEqualTo(fld.getAttributeName(), container[i].getValue()); 904 } 905 906 return QueryFactory.newQuery(refCld.getClassOfObject(), criteria); 907 } 908 909 915 public Query getPKQuery(Identity oid) 916 { 917 Object [] values = oid.getPrimaryKeyValues(); 918 ClassDescriptor cld = pb.getClassDescriptor(oid.getObjectsTopLevelClass()); 919 FieldDescriptor[] fields = cld.getPkFields(); 920 Criteria criteria = new Criteria(); 921 922 for (int i = 0; i < fields.length; i++) 923 { 924 FieldDescriptor fld = fields[i]; 925 criteria.addEqualTo(fld.getAttributeName(), values[i]); 926 } 927 return QueryFactory.newQuery(cld.getClassOfObject(), criteria); 928 } 929 930 938 public void retrieveCollections(Object newObj, ClassDescriptor cld, boolean forced) throws PersistenceBrokerException 939 { 940 doRetrieveCollections(newObj, cld, forced, false); 941 } 942 943 951 public void retrieveProxyCollections(Object newObj, ClassDescriptor cld, boolean forced) throws PersistenceBrokerException 952 { 953 doRetrieveCollections(newObj, cld, forced, true); 954 } 955 956 private void doRetrieveCollections(Object newObj, ClassDescriptor cld, boolean forced, boolean forceProxyCollection) throws PersistenceBrokerException 957 { 958 Iterator i = cld.getCollectionDescriptors().iterator(); 959 960 final Class saveClassToPrefetch = classToPrefetch; 962 classToPrefetch = null; 963 964 pb.getInternalCache().enableMaterializationCache(); 965 try 966 { 967 while (i.hasNext()) 968 { 969 CollectionDescriptor cds = (CollectionDescriptor) i.next(); 970 if (forceProxyCollection){ 971 retrieveProxyCollection(newObj, cld, cds, forced); 972 } else { 973 retrieveCollection(newObj, cld, cds, forced); 974 } 975 } 976 pb.getInternalCache().disableMaterializationCache(); 977 } 978 catch (RuntimeException e) 979 { 980 pb.getInternalCache().doLocalClear(); 981 throw e; 982 } 983 finally 984 { 985 classToPrefetch = saveClassToPrefetch; 986 } 987 } 988 989 990 993 public void removePrefetchingListeners() 994 { 995 if (prefetchingListeners != null) 996 { 997 for (Iterator it = prefetchingListeners.iterator(); it.hasNext(); ) 998 { 999 PBPrefetchingListener listener = (PBPrefetchingListener) it.next(); 1000 listener.removeThisListener(); 1001 } 1002 prefetchingListeners.clear(); 1003 } 1004 } 1005 1006 public Class getClassToPrefetch() 1007 { 1008 return classToPrefetch; 1009 } 1010 1011 1015 class PBMaterializationListener extends PBPrefetchingListener implements MaterializationListener 1016 { 1017 private IndirectionHandler _listenedHandler; 1018 1019 PBMaterializationListener(Object owner, 1020 HashMap retrievalTasks, Object key, int limit) 1021 { 1022 super(owner, retrievalTasks, key, limit); 1023 } 1024 1025 protected void addThisListenerTo(Object owner) 1026 { 1027 _listenedHandler = ProxyHelper.getIndirectionHandler(owner); 1028 1029 if (_listenedHandler != null) 1030 { 1031 _listenedHandler.addListener(this); 1032 } 1033 } 1034 1035 protected void removeThisListener() 1036 { 1037 if (_listenedHandler != null) 1038 { 1039 _listenedHandler.removeListener(this); 1040 _listenedHandler = null; 1041 } 1042 } 1043 1044 protected RelationshipPrefetcher getPrefetcher(Object listenedObject) 1045 { 1046 if (_key instanceof ObjectReferenceDescriptor) 1047 { 1048 return pb.getRelationshipPrefetcherFactory().createRelationshipPrefetcher((ObjectReferenceDescriptor) _key); 1049 } 1050 else { 1052 IndirectionHandler handler = (IndirectionHandler) listenedObject; 1055 return new PlainPrefetcher(pb, handler.getIdentity().getObjectsTopLevelClass()); 1056 } 1057 } 1058 1059 public void beforeMaterialization(IndirectionHandler handler, Identity oid) 1060 { 1061 prefetch(handler); 1062 } 1063 1064 public void afterMaterialization(IndirectionHandler handler, Object materializedObject) 1065 { 1066 } 1068 } 1069 1070 abstract class PBPrefetchingListener 1071 { 1072 private HashMap _retrievalTasks; 1073 private int _limit; 1074 protected Object _key; 1075 1076 PBPrefetchingListener(Object owner, HashMap retrievalTasks, 1077 Object key, int limit) 1078 { 1079 _retrievalTasks = retrievalTasks; 1080 _key = key; 1081 _limit = limit + 1; if (prefetchingListeners == null) 1083 { 1084 prefetchingListeners = new ArrayList (); 1085 } 1086 addThisListenerTo(owner); 1087 prefetchingListeners.add(this); 1088 } 1089 1090 abstract protected void addThisListenerTo(Object owner); 1091 1092 abstract protected void removeThisListener(); 1093 1094 abstract protected RelationshipPrefetcher getPrefetcher(Object listenedObject); 1095 1096 protected void prefetch(Object listenedObject) 1097 { 1098 ArrayList owners = (ArrayList ) _retrievalTasks.get(_key); 1099 List toPrefetch; 1100 RelationshipPrefetcher prefetcher; 1101 boolean prefetchingAll; 1102 1103 removeThisListener(); 1104 1105 if (owners == null) 1106 { 1107 return; 1108 } 1109 1110 prefetcher = getPrefetcher(listenedObject); 1111 1112 if (owners.size() <= _limit) 1113 { 1114 toPrefetch = owners; 1115 prefetchingAll = true; 1116 } 1117 else 1118 { 1119 toPrefetch = owners.subList(0, _limit); 1120 prefetchingAll = false; 1121 } 1122 1123 final Class saveClassToPrefetch = classToPrefetch; 1124 classToPrefetch = prefetcher.getItemClassDescriptor().getClassOfObject(); 1125 try 1126 { 1127 prefetcher.prefetchRelationship(toPrefetch); 1128 } 1129 finally 1130 { 1131 classToPrefetch = saveClassToPrefetch; 1132 } 1133 1134 if (prefetchingAll) 1135 { 1136 _retrievalTasks.remove(_key); 1137 } 1138 else 1139 { 1140 toPrefetch.clear(); 1144 addThisListenerTo(owners.get(0)); 1145 } 1146 } 1147 } 1148 1149 class PBCollectionProxyListener extends PBPrefetchingListener 1150 implements CollectionProxyListener 1151 { 1152 CollectionProxyDefaultImpl _listenedCollection; 1153 1154 PBCollectionProxyListener(Object owner, 1155 HashMap retrievalTasks, CollectionDescriptor key, int limit) 1156 { 1157 super(owner, retrievalTasks, key, limit); 1158 } 1159 1160 protected void addThisListenerTo(Object owner) 1161 { 1162 PersistentField collectionField = 1163 ((CollectionDescriptor) _key).getPersistentField(); 1164 _listenedCollection = (CollectionProxyDefaultImpl) collectionField.get(owner); 1165 _listenedCollection.addListener(this); 1166 } 1167 1168 protected void removeThisListener() 1169 { 1170 if (_listenedCollection != null) 1171 { 1172 _listenedCollection.removeListener(this); 1173 _listenedCollection = null; 1174 } 1175 } 1176 1177 protected RelationshipPrefetcher getPrefetcher(Object listenedObject) 1178 { 1179 return pb.getRelationshipPrefetcherFactory().createRelationshipPrefetcher((CollectionDescriptor)_key); 1180 } 1181 1182 public void beforeLoading(CollectionProxyDefaultImpl col) 1183 { 1184 prefetch(col); 1185 } 1186 1187 public void afterLoading(CollectionProxyDefaultImpl col) 1188 { 1189 } 1191 } 1192} 1193 | Popular Tags |