1 23 24 29 30 package com.sun.jdo.spi.persistence.support.sqlstore; 31 32 import com.sun.jdo.api.persistence.support.*; 33 import com.sun.jdo.spi.persistence.support.sqlstore.ejb.EJBHelper; 34 import com.sun.jdo.spi.persistence.support.sqlstore.model.*; 35 import com.sun.jdo.spi.persistence.support.sqlstore.query.jqlc.QueryValueFetcher; 36 import com.sun.jdo.spi.persistence.support.sqlstore.sco.SqlTimestamp; 37 import com.sun.jdo.spi.persistence.support.sqlstore.sql.UpdateObjectDescImpl; 38 import com.sun.jdo.spi.persistence.support.sqlstore.state.LifeCycleState; 39 import com.sun.jdo.spi.persistence.support.sqlstore.state.PersistentNonTransactional; 40 import com.sun.jdo.spi.persistence.support.sqlstore.state.PersistentClean; 41 import com.sun.jdo.spi.persistence.support.sqlstore.state.Hollow; 42 import com.sun.jdo.spi.persistence.utility.I18NHelper; 43 import com.sun.jdo.spi.persistence.utility.NullSemaphore; 44 import com.sun.jdo.spi.persistence.utility.Semaphore; 45 import com.sun.jdo.spi.persistence.utility.SemaphoreImpl; 46 import com.sun.jdo.spi.persistence.utility.logging.Logger; 47 48 import java.lang.reflect.Field ; 49 import java.lang.reflect.InvocationTargetException ; 50 import java.lang.reflect.Method ; 51 import java.sql.Timestamp ; 52 import java.util.*; 53 54 55 58 public class SQLStateManager implements Cloneable , StateManager, TestStateManager { 59 60 private static final int PRESENCE_MASK = 0; 61 62 private static final int SET_MASK = 1; 63 64 private static final int MAX_MASKS = 2; 65 66 private BitSet fieldMasks; 67 68 69 public ArrayList hiddenValues; 70 71 private ClassDesc persistenceConfig; 72 73 private PersistenceManager persistenceManager; 74 75 private PersistenceStore store; 76 77 private SQLStateManager beforeImage; 78 79 private Object persistentObject; 80 81 private Object objectId; 82 83 private LifeCycleState state; 84 85 86 private static final short ST_UPDATE_DISABLED = 0x1; 87 88 private static final short ST_REGISTERED = 0x2; 89 90 private static final short ST_VISITED = 0x4; 91 92 private static final short ST_PREPARED_PHASE_II = 0x8; 93 94 private static final short ST_FIELD_TRACKING_INPROGRESS = 0x10; 95 96 private static final short ST_DELETE_INPROGRESS = 0x20; 97 98 private static final short ST_VALIDATION_FAILED = 0x40; 99 100 private short stateFlags; 101 102 private boolean isReplacementInstance = false; 105 106 private boolean needsRegisterAtRollback = false; 109 110 private boolean needsVerifyAtDeregister = false; 113 114 private boolean valid = false; 117 118 119 private UpdateObjectDescImpl updateDesc; 120 121 122 private HashSet updatedForeignReferences; 123 124 125 private int referenceCount; 126 127 128 private final Semaphore lock; 129 130 131 private static Logger logger = LogHelperStateManager.getLogger(); 132 133 134 private final static ResourceBundle messages = I18NHelper.loadBundle( 135 SQLStateManager.class); 136 137 138 public static final String USE_BATCH_PROPERTY = 139 "com.sun.jdo.spi.persistence.support.sqlstore.USE_BATCH"; 141 145 private static final boolean USE_BATCH = Boolean.valueOf( 146 System.getProperty(USE_BATCH_PROPERTY, "true")).booleanValue(); 148 152 public SQLStateManager(PersistenceStore store, ClassDesc persistenceConfig) { 153 this.store = store; 154 this.persistenceConfig = persistenceConfig; 155 156 if (EJBHelper.isManaged()) { 157 this.lock = new NullSemaphore("SQLStateManager"); } else { 159 this.lock = new SemaphoreImpl("SQLStateManager"); } 161 } 162 163 public synchronized void initialize(boolean persistentInDB) { 164 boolean xactActive = persistenceManager.isActiveTransaction(); 165 boolean optimistic = persistenceManager.isOptimisticTransaction(); 166 boolean nontransactionalRead = persistenceManager.isNontransactionalRead(); 167 LifeCycleState oldstate = state; 168 169 if (state == null) { 170 if (persistentInDB == false) { 171 state = LifeCycleState.getLifeCycleState(LifeCycleState.HOLLOW); 174 persistenceManager.setFlags(persistentObject, LOAD_REQUIRED); 175 } else { 176 if (xactActive && !optimistic) { 177 state = LifeCycleState.getLifeCycleState(LifeCycleState.P_CLEAN); 178 persistenceManager.setFlags(persistentObject, READ_OK); 179 } else { 180 state = LifeCycleState.getLifeCycleState(LifeCycleState.P_NON_TX); 181 persistenceManager.setFlags(persistentObject, LOAD_REQUIRED); 182 } 183 valid = true; 184 } 185 } else if (state.needMerge()) { 186 state = state.transitionReadField(optimistic, nontransactionalRead, xactActive); 187 188 if (state.needsReload(optimistic, nontransactionalRead, xactActive)) { 191 persistenceManager.setFlags(persistentObject, LOAD_REQUIRED); 192 } else { 193 if (persistenceManager.getFlags(persistentObject) == LOAD_REQUIRED) { 194 persistenceManager.setFlags(persistentObject, READ_OK); 195 } 196 } 197 } 198 199 registerInstance(false, null, oldstate); 200 } 201 202 private void registerInstance(boolean throwDuplicateException, 203 ArrayList newlyRegisteredSMs, LifeCycleState oldstate) { 204 205 if ((stateFlags & ST_REGISTERED) == 0 || (oldstate != state && (oldstate == null || oldstate.isDirty() != state.isDirty() || 208 oldstate.isTransactional() != state.isTransactional()))) { 209 210 persistenceManager.registerInstance(this, getObjectId(), throwDuplicateException, false); 211 stateFlags |= ST_REGISTERED; 212 if (newlyRegisteredSMs != null) { 213 if (!newlyRegisteredSMs.contains(this)) 214 newlyRegisteredSMs.add(this); 215 } 216 } 217 } 218 219 public void setPersistenceManager(com.sun.jdo.api.persistence.support.PersistenceManager pm) { 220 this.persistenceManager = (PersistenceManager) pm; 221 } 222 223 public void setPersistent(Object pc) { 224 this.persistentObject = pc; 225 } 226 227 public PersistenceStore getStore() { 228 return store; 229 } 230 231 public Object getPersistent() { 232 return persistentObject; 233 } 234 235 public PersistenceConfig getPersistenceConfig() { 236 return persistenceConfig; 237 } 238 239 private UpdateObjectDescImpl getUpdateDesc() { 240 if (updateDesc == null) { 241 updateDesc = (UpdateObjectDescImpl) store.getUpdateObjectDesc( 242 persistenceConfig.getPersistenceCapableClass()); 243 } 244 245 if (updateDesc.getConcurrency() == null) { 246 boolean optimistic = persistenceManager.isOptimisticTransaction(); 247 updateDesc.setConcurrency(persistenceConfig.getConcurrency(optimistic)); 248 } 249 250 return updateDesc; 251 } 252 253 private void unsetMaskBit(int index, int mask) { 254 if (fieldMasks == null) { 255 newFieldMasks(); 256 } else { 257 if (index >= 0) { 258 fieldMasks.clear(index + mask * persistenceConfig.maxFields); 259 } else { 260 fieldMasks.clear(-(index + 1) + persistenceConfig.maxVisibleFields + 261 mask * persistenceConfig.maxFields); 262 } 263 } 264 } 265 266 private void clearMask(int mask) { 267 if (fieldMasks != null) { 268 fieldMasks.clear(mask * persistenceConfig.maxFields, 269 (mask+1) * persistenceConfig.maxFields); 270 } 271 } 272 273 private void setVisibleMaskBits(int mask) { 274 if (fieldMasks == null) { 275 newFieldMasks(); 276 } 277 278 int offset = mask * persistenceConfig.maxFields; 279 fieldMasks.set(offset, offset + persistenceConfig.maxVisibleFields); 280 } 281 282 private BitSet getVisibleMaskBits(int mask) { 283 if (fieldMasks == null) { 284 newFieldMasks(); 285 } 286 287 int offset = mask * persistenceConfig.maxFields; 288 return fieldMasks.get(offset, offset + persistenceConfig.maxVisibleFields); 289 } 290 291 private void newFieldMasks() { 292 this.fieldMasks = new BitSet(MAX_MASKS * persistenceConfig.maxFields); 293 } 294 295 public void setPresenceMaskBit(int index) { 296 if (fieldMasks == null) { 297 newFieldMasks(); 298 } 299 300 if (index >= 0) { 301 fieldMasks.set(index + PRESENCE_MASK * persistenceConfig.maxFields); 302 } else { 303 fieldMasks.set(-(index + 1) + persistenceConfig.maxVisibleFields + 304 PRESENCE_MASK * persistenceConfig.maxFields); 305 } 306 } 307 308 private void setSetMaskBit(int index) { 309 if (fieldMasks == null) { 310 newFieldMasks(); 311 } 312 313 if (index >= 0) { 314 fieldMasks.set(index + SET_MASK * persistenceConfig.maxFields); 315 } else { 316 fieldMasks.set(-(index + 1) + persistenceConfig.maxVisibleFields + 317 SET_MASK * persistenceConfig.maxFields); 318 } 319 } 320 321 public boolean getPresenceMaskBit(int index) { 322 if (fieldMasks == null) { 323 newFieldMasks(); 324 } 325 326 if (index >= 0) { 327 return fieldMasks.get(index + PRESENCE_MASK * persistenceConfig.maxFields); 328 } else { 329 return fieldMasks.get(-(index + 1) + persistenceConfig.maxVisibleFields + 330 PRESENCE_MASK * persistenceConfig.maxFields); 331 } 332 } 333 334 public boolean getSetMaskBit(int index) { 335 if (fieldMasks == null) { 336 newFieldMasks(); 337 } 338 339 if (index >= 0) { 340 return fieldMasks.get(index + SET_MASK * persistenceConfig.maxFields); 341 } else { 342 return fieldMasks.get(-(index + 1) + persistenceConfig.maxVisibleFields + 343 SET_MASK * persistenceConfig.maxFields); 344 } 345 } 346 347 public Object getHiddenValue(int index) { 348 if (index >= 0) { 350 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 351 "core.statemanager.poshiddenindex", "" + index)); } 353 354 int realIndex = -(index + 1); 355 356 if ((hiddenValues != null) && (realIndex < hiddenValues.size())) { 357 return hiddenValues.get(realIndex); 358 } 359 360 return null; 361 } 362 363 public void setHiddenValue(int index, Object value) { 364 if (index >= 0) { 366 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 367 "core.statemanager.poshiddenindex", "" + index)); } 369 370 int realIndex = -(index + 1); 371 372 if (hiddenValues == null) { 373 hiddenValues = new ArrayList(); 374 } 375 376 for (int i = hiddenValues.size(); i <= realIndex; i++) { 377 hiddenValues.add(null); 378 } 379 380 hiddenValues.set(realIndex, value); 381 } 382 383 public synchronized void replaceObjectField(String fieldName, Object o) { 384 boolean debug = logger.isLoggable(); 385 386 if (debug) { 387 Object [] items = new Object [] {fieldName, o.getClass().getName()}; 388 logger.fine("sqlstore.sqlstatemanager.replaceobjectfield", items); } 390 391 FieldDesc fieldDesc = persistenceConfig.getField(fieldName); 392 Object oldo = prepareSetField(fieldDesc, o); 393 394 if ((oldo instanceof SCO) && oldo != o) { 395 if (debug) 396 logger.fine("sqlstore.sqlstatemanager.replaceobjectfield.unsetsco"); ((SCO) oldo).unsetOwner(); 398 } 399 } 400 401 public synchronized void makeDirty(String fieldName) { 402 boolean debug = logger.isLoggable(); 403 404 if (debug) { 405 logger.fine("sqlstore.sqlstatemanager.makedirty", fieldName); } 407 408 FieldDesc fieldDesc = persistenceConfig.getField(fieldName); 409 410 Object oldo = fieldDesc.getValue(this); 413 414 prepareUpdateField(fieldDesc, null); 415 416 Object newo = fieldDesc.getValue(this); 418 419 if ((newo instanceof SCO) && oldo != newo) { 420 if (oldo instanceof SCOCollection) { 421 if (debug) { 422 logger.fine("sqlstore.sqlstatemanager.makedirty.fixscocollection"); } 424 425 ((SCOCollection) oldo).clearInternal(); 426 ((SCOCollection) oldo).addAllInternal((Collection) newo); 427 } 428 429 else if (oldo instanceof SCODate) { 430 if (debug) { 431 logger.fine("sqlstore.sqlstatemanager.makedirty.fixscodate"); } 433 434 long l = ((java.util.Date ) newo).getTime(); 435 int n = 0; 437 438 if (newo instanceof Timestamp) { 439 n = ((Timestamp) newo).getNanos(); 440 } else { 441 n = (int) ((l % 1000) * 1000000); 442 } 443 444 if (oldo instanceof SqlTimestamp) { 445 ((SCODate) oldo).setTimeInternal(l); 446 ((SqlTimestamp) oldo).setNanosInternal(n); 447 448 } else if (newo instanceof Timestamp) { 449 ((SCODate) oldo).setTimeInternal(l + (n / 1000000)); 450 } else { 451 ((SCODate) oldo).setTimeInternal(l); 452 } 453 } 454 455 updateTrackedFields(fieldDesc, oldo, null); 456 fieldDesc.setValue(this, oldo); 457 458 if (newo instanceof SCO) 460 ((SCO) newo).unsetOwner(); 461 } 462 } 463 464 467 public void applyUpdates(String fieldName, SCOCollection c) { 468 boolean debug = logger.isLoggable(); 469 470 if (debug) { 471 logger.fine("sqlstore.sqlstatemanager.applyupdates", fieldName); } 473 474 FieldDesc fieldDesc = persistenceConfig.getField(fieldName); 475 if (fieldDesc instanceof ForeignFieldDesc) { 476 ArrayList removed = new ArrayList(c.getRemoved()); 477 ArrayList added = new ArrayList(c.getAdded()); 478 479 c.reset(); 482 processCollectionUpdates((ForeignFieldDesc) fieldDesc, removed, added, null, true, false); 483 } 484 486 if (debug) { 487 logger.fine("sqlstore.sqlstatemanager.applyupdates.exit"); } 489 } 490 491 public void makePresent(String fieldName, Object value) { 492 boolean debug = logger.isLoggable(); 493 494 if (debug) { 495 logger.fine("sqlstore.sqlstatemanager.makepresent", fieldName); } 497 498 FieldDesc fieldDesc = persistenceConfig.getField(fieldName); 499 fieldDesc.setValue(this, value); 500 setPresenceMaskBit(fieldDesc.absoluteID); 501 } 502 503 public void setObjectId(Object objectId) { 504 this.objectId = objectId; 506 } 507 508 public Object getObjectId() { 509 if (objectId == null) { 511 Class oidClass = persistenceConfig.getOidClass(); 512 Object oid = null; 513 514 try { 515 oid = oidClass.newInstance(); 516 } catch (Exception e) { 517 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 518 "core.statemanager.cantnewoid", oidClass.getName()), e); } 520 521 Field keyFields[] = persistenceConfig.getKeyFields(); 522 String keyFieldNames[] = persistenceConfig.getKeyFieldNames(); 523 for (int i = 0; i < keyFields.length; i++) { 524 Field keyField = keyFields[i]; 525 try { 526 FieldDesc fd = persistenceConfig.getField(keyFieldNames[i]); 527 528 if (fd != null) { 529 keyField.set(oid, fd.getValue(this)); 530 } 531 532 } catch (IllegalAccessException e) { 533 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 534 "core.statemanager.cantsetkeyfield", keyField.getName()), e); } 536 } 537 objectId = oid; 538 } 539 540 return objectId; 541 } 542 543 private void makeAutoPersistent(Object pc) { 544 persistenceManager.makePersistent(pc); 545 SQLStateManager sm = (SQLStateManager) persistenceManager.getStateManager(pc); 546 547 sm.state = LifeCycleState.getLifeCycleState(LifeCycleState.AP_NEW); 548 } 549 550 555 public void makePersistent(PersistenceManager pm, Object pc) { 556 557 boolean debug = logger.isLoggable(); 558 559 if (debug) { 560 logger.fine("sqlstore.sqlstatemanager.makepersistence", persistenceConfig.getPersistenceCapableClass().getName()); 562 } 563 564 if (state != null) { 566 if (state.isAutoPersistent()) { 567 state = state.transitionMakePersistent(); 568 } 569 return; 570 } 571 572 this.persistenceManager = pm; 573 this.persistentObject = pc; 574 575 setVisibleMaskBits(PRESENCE_MASK); 578 getBeforeImage(); 579 580 state = LifeCycleState.getLifeCycleState(LifeCycleState.P_NEW); 581 582 try { 583 registerInstance(true, null, null); 584 } catch (JDOException e) { 585 this.release(); 586 587 throw e; 588 } 589 590 pm.setStateManager(pc, this); 594 valid = true; 595 596 try { 600 getLock(); 601 602 Object obj = null; 604 ArrayList fields = persistenceConfig.fields; 605 for (int i = 0; i < fields.size(); i++) { 606 FieldDesc f = (FieldDesc) fields.get(i); 607 608 if ((f.sqlProperties & FieldDesc.PROP_SECONDARY_TRACKED_FIELD) > 0) { 614 continue; 615 } 616 617 obj = f.getValue(this); 618 619 if (f instanceof ForeignFieldDesc) { 620 ForeignFieldDesc ff = (ForeignFieldDesc) f; 621 ArrayList trackedFields = null; 622 623 if (debug) { 624 logger.fine("sqlstore.sqlstatemanager.processforeign", ff.getName()); } 626 627 if ((ff.sqlProperties & FieldDesc.PROP_PRIMARY_TRACKED_FIELD) > 0) { 628 trackedFields = ff.getTrackedFields(); 629 Object theValue = obj; 630 631 for (int j = 0; j < trackedFields.size(); j++) { 632 FieldDesc tf = (FieldDesc) trackedFields.get(j); 633 Object value = tf.getValue(this); 634 635 if ((theValue != null) && (value != null) && (theValue != value)) { 636 if (needsVerifyAtDeregister) { 637 persistenceManager.deregisterInstance(getObjectId(), this); 638 needsVerifyAtDeregister = false; 639 } else { 640 persistenceManager.deregisterInstance(getObjectId()); 641 } 642 this.release(); 643 throw new JDOUserException(I18NHelper.getMessage(messages, 644 "core.statemanager.conflictingvalues", ff.getName(), tf.getName())); } else if ((theValue == null) && (value != null)) { 646 theValue = value; 647 } 648 } 649 650 if (theValue != obj) { 651 obj = theValue; 652 ff.setValue(this, obj); 653 } 654 } 655 656 if (obj != null) { 657 if (obj instanceof Collection) { 658 if (((Collection) obj).size() > 0) { 659 ArrayList removed = null; 660 ArrayList added = new ArrayList((Collection) obj); 661 processCollectionUpdates(ff, removed, added, null, true, false); 662 } 663 } else { 664 ff.setValue(this, null); 666 667 updateObjectField(ff, obj, true, false); 668 669 ff.setValue(this, obj); 671 } 672 } else { 673 if ((ff.getInverseRelationshipField() != null) && (ff.cardinalityUPB > 1)) { 676 replaceCollection(ff, null); 677 } 678 } 679 680 updateTrackedFields(ff, ff.getValue(this), null); 681 } else { 682 if ((f.sqlProperties & FieldDesc.PROP_TRACK_RELATIONSHIP_FIELD) > 0) { 684 ArrayList trackedFields = f.getTrackedFields(); 685 boolean found = false; 686 687 for (int j = trackedFields.size() - 1; j >= 0; j--) { 688 FieldDesc tf = (FieldDesc) trackedFields.get(j); 689 690 if (tf instanceof ForeignFieldDesc) { 691 if (tf.getValue(this) != null) { 692 found = true; 693 break; 694 } 695 } else { 696 break; 697 } 698 } 699 700 if (!found) { 701 updateTrackedFields(f, obj, null); 703 } 705 } else { 706 updateTrackedFields(f, obj, null); 707 } 708 709 if ((f.sqlProperties & FieldDesc.PROP_RECORD_ON_UPDATE) > 0) { 710 getUpdateDesc().recordUpdatedField((LocalFieldDesc) f); 711 } 712 } 713 714 if (debug) { 715 logger.fine("sqlstore.sqlstatemanager.makedirtyfield", f.getName()); } 717 718 setSetMaskBit(f.absoluteID); 719 } 720 } finally { 721 releaseLock(); 722 } 723 } 724 725 731 public void deletePersistent() { 732 if (logger.isLoggable()) { 733 logger.fine("sqlstore.sqlstatemanager.deletepersistence", persistenceConfig.getPersistenceCapableClass().getName()); 735 736 } 737 738 747 persistenceManager.acquireFieldUpdateLock(); 748 try { 749 try { 750 getLock(); 751 752 if (state.isDeleted()) { 753 return; 754 } 755 756 deleteRelationships(); 757 758 LifeCycleState oldstate = state; 759 state = state.transitionDeletePersistent(); 760 persistenceManager.setFlags(persistentObject, LOAD_REQUIRED); 761 registerInstance(false, null, oldstate); 762 } finally { 763 releaseLock(); 764 } 765 } finally { 766 persistenceManager.releaseFieldUpdateLock(); 767 } 768 } 769 770 775 private void deleteRelationships() { 776 ArrayList foreignFields = persistenceConfig.foreignFields; 777 int size = foreignFields.size(); 778 stateFlags |= ST_DELETE_INPROGRESS; 779 780 for (int i = 0; i < size; i++) { 781 ForeignFieldDesc ff = (ForeignFieldDesc) foreignFields.get(i); 782 ForeignFieldDesc irf = ff.getInverseRelationshipField(); 783 784 if ((ff.sqlProperties & FieldDesc.PROP_SECONDARY_TRACKED_FIELD) > 0) { 786 continue; 787 } 788 789 if ((ff.deleteAction != ForeignFieldDesc.ACT_CASCADE) && (irf == null)) { 791 continue; 792 } 793 794 prepareUpdateField(ff, null); 795 796 if (ff.cardinalityUPB > 1) { 797 Collection c = (Collection) ff.getValue(this); 798 799 if (c != null) { 800 ArrayList removed = new ArrayList(c); 801 802 processCollectionUpdates(ff, removed, null, null, true, false); 807 808 if (c instanceof SCOCollection) { 809 ((SCOCollection) c).clearInternal(); 810 } else { 811 c.clear(); 812 } 813 814 if (ff.deleteAction == ForeignFieldDesc.ACT_CASCADE) { 815 Iterator iter = removed.iterator(); 816 817 while (iter.hasNext()) { 818 Object obj = iter.next(); 819 820 if (obj != null) { 821 SQLStateManager sm = (SQLStateManager) 822 persistenceManager.getStateManager(obj); 823 824 if ((sm != null) && !sm.isDeleted() && 828 ((sm.stateFlags & ST_DELETE_INPROGRESS) == 0)) { 829 try { 830 persistenceManager.deletePersistent(obj); 831 } catch (Throwable e) { 832 } 833 } 834 } 835 } 836 } 837 } 838 } else { 839 Object obj = ff.getValue(this); 840 841 if (obj != null) { 842 updateObjectField(ff, null, true, false); 843 ff.setValue(this, null); 844 845 if (ff.deleteAction == ForeignFieldDesc.ACT_CASCADE) { 846 SQLStateManager sm = (SQLStateManager) 847 persistenceManager.getStateManager(obj); 848 849 if ((sm != null) && !sm.isDeleted() && 853 ((sm.stateFlags & ST_DELETE_INPROGRESS) == 0)) { 854 try { 855 persistenceManager.deletePersistent(obj); 856 } catch (Throwable e) { 857 } 858 } 859 } 860 } 861 } 862 } 863 864 stateFlags &= ~ST_DELETE_INPROGRESS; 865 } 866 867 876 public void updatePersistent(StateManager next) { 877 boolean debug = logger.isLoggable(); 878 879 if ((stateFlags & ST_UPDATE_DISABLED) > 0) { 880 if (debug) { 881 Object [] items = new Object [] {persistenceConfig.getPersistenceCapableClass().getName(), 882 persistentObject}; 883 logger.fine("sqlstore.sqlstatemanager.updatepersistent.skipped", items); } 885 return; 886 } 887 888 try { 889 if (debug) { 890 logger.fine("sqlstore.sqlstatemanager.updatepersistent", persistenceConfig.getPersistenceCapableClass().getName()); 892 } 893 894 ArrayList actions = new ArrayList(); 895 896 getUpdateActions(actions); 898 899 if (actions.size() == 1 && useBatch()) { 900 UpdateObjectDesc updateDesc = (UpdateObjectDesc)actions.get(0); 902 boolean immediateFlush = requiresImmediateFlush((SQLStateManager)next); 903 904 if (debug && immediateFlush) { 905 Object [] items = new Object [] {getPersistent(), (next != null) ? next.getPersistent() : null}; 906 logger.fine("sqlstore.sqlstatemanager.updatepersistent.immediateflush", items); } 908 909 store.executeBatch(persistenceManager, updateDesc, immediateFlush); 910 } else if (actions.size() > 0) { 911 store.execute(persistenceManager, actions); 912 } 913 914 incrementVersion(actions); 915 916 if (debug) { 917 logger.fine("sqlstore.sqlstatemanager.updatepersistent.exit"); } 919 } catch (JDOException e) { 920 e.addFailedObject(persistentObject); 921 throw e; 922 } catch (Exception e) { 923 logger.throwing("sqlstore.SQLStateManager", "updatePersistent", e); throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 925 "core.generic.unknownexception"), e); } 927 } 928 929 935 static private void incrementVersion(List actions) { 936 937 for (Iterator iter = actions.iterator(); iter.hasNext(); ) { 938 ((UpdateObjectDescImpl) iter.next()).incrementVersion(); 939 } 940 } 941 942 946 public void incrementVersion() { 947 LocalFieldDesc [] versionFields = persistenceConfig.getVersionFields(); 948 949 for (int i = 0; i < versionFields.length; i++) { 950 versionFields[i].incrementValue(this); 951 } 952 } 953 954 957 public boolean hasVersionConsistency() { 958 return persistenceConfig.hasVersionConsistency(); 959 } 960 961 964 public boolean verifyPersistent() { 965 assert persistenceConfig.hasVersionConsistency(); 966 boolean verified = true; 967 968 if (state instanceof PersistentClean) { 969 RetrieveDesc verificationRD = persistenceConfig.getRetrieveDescForVerificationQuery(store); 970 LocalFieldDesc[] keyFields = persistenceConfig.getKeyFieldDescs(); 971 LocalFieldDesc[] versionFields = persistenceConfig.getVersionFields(); 972 973 Object [] parameters = new Object [keyFields.length + versionFields.length]; 976 copyValues(parameters, keyFields, 0); 977 copyValues(parameters, versionFields, keyFields.length); 978 979 Boolean result = (Boolean ) store. 981 retrieve(persistenceManager, verificationRD, new QueryValueFetcher(parameters)); 982 verified = result.booleanValue(); 983 } 984 return verified; 985 } 986 987 995 private boolean useBatch() { 996 boolean result = false; 997 998 if (USE_BATCH) { 999 switch(state.getUpdateAction()) { 1000 1001 case ActionDesc.LOG_CREATE: 1002 result = !getUpdateDesc().hasChangedRelationships() && 1003 !getUpdateDesc().hasModifiedLobField(); 1004 break; 1005 case ActionDesc.LOG_DESTROY: 1006 case ActionDesc.LOG_UPDATE: 1007 result = !persistenceManager.isOptimisticTransaction() && 1012 !persistenceConfig.hasModifiedCheckAtCommitConsistency() && 1013 !getUpdateDesc().hasChangedRelationships() && 1014 !getUpdateDesc().hasModifiedLobField() && 1015 !hasVersionConsistency(); 1016 break; 1017 default: 1018 result = false; 1019 break; 1020 } 1021 } 1022 1023 return result; 1024 } 1025 1026 1029 public void setVerificationFailed() { 1030 if (hasVersionConsistency()) { 1031 stateFlags |= ST_VALIDATION_FAILED; 1032 } 1033 } 1034 1035 1038 public boolean isVerificationFailed() { 1039 return (stateFlags & ST_VALIDATION_FAILED) > 0; 1040 } 1041 1042 1050 private boolean requiresImmediateFlush(SQLStateManager next) { 1051 if (next == null) 1054 return true; 1055 1056 if (persistenceConfig != next.persistenceConfig) 1059 return true; 1060 1061 if (state.getUpdateAction() != next.state.getUpdateAction()) 1064 return true; 1065 1066 if ((next.stateFlags & ST_UPDATE_DISABLED) > 0) 1068 return true; 1069 1070 if (!next.useBatch()) 1072 return true; 1073 1074 if (getUpdateDesc().getUpdateAction() == ActionDesc.LOG_UPDATE && 1077 persistenceConfig.hasLocalNonDFGFields()) { 1078 1079 if (!compareUpdatedFields(next)) 1080 return true; 1081 } 1082 1083 return false; 1085 } 1086 1087 private boolean compareUpdatedFields(SQLStateManager next) { 1088 BitSet updFields = getVisibleMaskBits(SET_MASK); 1089 BitSet nextUpdFields = (next != null) ? next.getVisibleMaskBits(SET_MASK) : null; 1090 1091 return updFields.equals(nextUpdFields); 1092 } 1093 1094 public void refreshPersistent() { 1095 boolean debug = logger.isLoggable(); 1096 1097 if (debug) { 1098 logger.fine("sqlstore.sqlstatemanager.refreshpersistent", persistenceConfig.getPersistenceCapableClass().getName()); 1100 } 1101 1102 if (state.isRefreshable()) { 1104 LifeCycleState oldstate = state; 1105 state = state.transitionRefreshPersistent(); 1106 reload(null); 1107 registerInstance(false, null, oldstate); 1108 } 1109 1110 if (debug) { 1111 logger.fine("sqlstore.sqlstatemanager.refreshpersistent.exit"); } 1113 } 1114 1115 1123 public void reload() { 1124 boolean debug = logger.isLoggable(Logger.FINER); 1125 1126 if (debug) { 1127 logger.finer("sqlstore.sqlstatemanager.unconditionalreload", persistenceConfig.getPersistenceCapableClass().getName()); 1129 } 1130 1131 persistenceManager.acquireShareLock(); 1132 1133 try { 1134 getLock(); 1135 1136 reload(null); 1137 1138 } finally { 1139 persistenceManager.releaseShareLock(); 1140 releaseLock(); 1141 1142 if (debug) { 1143 logger.finer("sqlstore.sqlstatemanager.unconditionalreload.exit"); } 1145 } 1146 } 1147 1148 1153 private void reload(FieldDesc additionalField) { 1154 boolean debug = logger.isLoggable(); 1155 1156 if (debug) { 1157 String fieldName = 1158 (additionalField != null) ? additionalField.getName() : null; 1159 logger.fine("sqlstore.sqlstatemanager.reload", persistenceConfig.getPersistenceCapableClass().getName(), fieldName); 1161 } 1162 1163 clearMask(PRESENCE_MASK); 1166 1167 markKeyFieldsPresent(); 1169 1170 clearMask(SET_MASK); 1171 1172 LifeCycleState oldState = state; 1173 state = state.transitionReload(persistenceManager.isActiveTransaction()); 1174 1175 if (!retrieveFromVersionConsistencyCache(additionalField)) { 1176 1179 try { 1180 retrieve(additionalField); 1181 } catch (JDOException e) { 1182 state = oldState; 1184 throw e; 1185 } 1186 } 1187 registerInstance(false, null, oldState); 1188 1189 if (persistenceManager.getFlags(persistentObject) == LOAD_REQUIRED) { 1190 persistenceManager.setFlags(persistentObject, READ_OK); 1191 } 1192 1193 if (debug) { 1194 logger.fine("sqlstore.sqlstatemanager.reload.exit"); } 1196 } 1197 1198 1204 private boolean retrieveFromVersionConsistencyCache(FieldDesc additionalField) { 1205 boolean rc = 1206 persistenceManager.initializeFromVersionConsistencyCache(this); 1207 1208 if (rc) { 1209 1210 if (additionalField != null 1212 && !getPresenceMaskBit(additionalField.absoluteID)) { 1213 1214 realizeField(additionalField); 1215 } 1216 } 1217 return rc; 1218 } 1219 1220 1227 public void prepareToUpdatePhaseI() { 1228 boolean debug = logger.isLoggable(); 1229 1230 if (debug) { 1231 logger.fine("sqlstore.sqlstatemanager.preparetoupdateph1", persistenceConfig.getPersistenceCapableClass().getName()); 1233 } 1234 1235 int action = state.getUpdateAction(); 1236 1237 if (action == ActionDesc.LOG_NOOP || action == ActionDesc.LOG_DESTROY) { 1238 return; 1240 } 1241 1242 getUpdateDesc(); 1244 1245 ArrayList newlyRegisteredSMs = new ArrayList(); 1246 ArrayList foreignFields = persistenceConfig.foreignFields; 1247 int size = foreignFields.size(); 1248 1249 for (int i = 0; i < size; i++) { 1250 ForeignFieldDesc ff = (ForeignFieldDesc) foreignFields.get(i); 1251 1252 if ((ff.sqlProperties & FieldDesc.PROP_SECONDARY_TRACKED_FIELD) > 0) { 1253 continue; 1254 } 1255 1256 if ((ff.cardinalityUPB > 1) && (getSetMaskBit(ff.absoluteID) == true)) { 1257 Collection v = (Collection) ff.getValue(this); 1258 1259 if ((v != null) && (!(v instanceof SCO) || (((SCO) v).getOwner() == null)) && 1260 (v.size() > 0)) { 1261 ArrayList removed = null; 1262 ArrayList added = new ArrayList(v); 1263 1264 processCollectionUpdates(ff, removed, added, newlyRegisteredSMs, true, false); 1265 } 1266 } 1267 } 1268 1269 for (int i = 0; i < newlyRegisteredSMs.size(); i++) { 1272 SQLStateManager sm = (SQLStateManager) newlyRegisteredSMs.get(i); 1273 1274 sm.prepareToUpdatePhaseI(); 1275 } 1276 1277 if (debug) { 1278 logger.fine("sqlstore.sqlstatemanager.preparetoupdateph1.exit"); } 1280 } 1281 1282 1289 public void prepareToUpdatePhaseII(HashSet phase3sms) { 1290 boolean debug = logger.isLoggable(); 1291 1292 if (debug) { 1293 logger.fine("sqlstore.sqlstatemanager.preparetoupdateph2", persistenceConfig.getPersistenceCapableClass().getName()); 1295 } 1296 1297 if (state.isAutoPersistent()) { 1301 state = state.transitionMakePending(); 1302 phase3sms.add(this); 1303 return; 1304 } 1305 1306 if ((stateFlags & ST_PREPARED_PHASE_II) > 0) { 1307 return; 1308 } 1309 1310 stateFlags |= ST_PREPARED_PHASE_II; 1311 1312 if ((!state.isNew() && !state.isDirty()) || state.isDeleted()) { 1313 return; 1314 } 1315 1316 ArrayList foreignFields = persistenceConfig.foreignFields; 1317 int size = foreignFields.size(); 1318 1319 for (int i = 0; i < size; i++) { 1322 ForeignFieldDesc ff = (ForeignFieldDesc) foreignFields.get(i); 1323 1324 if (ff.cardinalityUPB <= 1) { 1325 if (getPresenceMaskBit(ff.absoluteID)) { 1326 Object v = ff.getValue(this); 1327 1328 if (v != null) { 1329 transitionPersistent(v, phase3sms); 1330 } 1331 } 1332 } else { 1333 Collection c = getCollectionValue(ff); 1334 1335 if (c != null) { 1336 Iterator iter = c.iterator(); 1337 1338 while (iter.hasNext()) { 1339 Object v = iter.next(); 1340 1341 transitionPersistent(v, phase3sms); 1342 } 1343 } 1344 } 1345 } 1346 1347 if (debug) { 1348 logger.fine("sqlstore.sqlstatemanager.preparetoupdateph2.exit"); } 1350 } 1351 1352 1356 public void prepareToUpdatePhaseIII() { 1357 boolean debug = logger.isLoggable(); 1358 1359 if (debug) { 1360 logger.fine("sqlstore.sqlstatemanager.preparetoupdateph3", persistenceConfig.getPersistenceCapableClass().getName()); 1362 } 1363 1364 if (!state.isPersistentInDataStore()) { 1365 if (updateDesc != null) { 1369 updateDesc.clearUpdatedJoinTableRelationships(); 1370 } 1371 1372 return; 1374 } 1375 1376 ArrayList foreignFields = persistenceConfig.foreignFields; 1377 int size = foreignFields.size(); 1378 1379 for (int i = 0; i < size; i++) { 1382 ForeignFieldDesc ff = (ForeignFieldDesc) foreignFields.get(i); 1383 1384 if (ff.cardinalityUPB <= 1) { 1385 if (getPresenceMaskBit(ff.absoluteID)) { 1386 Object v = ff.getValue(this); 1387 1388 if (v != null) { 1389 updateObjectField(ff, null, false, false); 1390 } 1391 } 1392 } else { 1393 Collection c = getCollectionValue(ff); 1394 1395 if (c != null) { 1396 if (c.size() > 0) { 1397 ArrayList removed = new ArrayList(c); 1398 ArrayList added = null; 1399 1400 processCollectionUpdates(ff, removed, added, null, false, false); 1401 } 1402 } 1403 } 1404 } 1405 1406 if (debug) { 1407 logger.fine("sqlstore.sqlstatemanager.preparetoupdateph3.exit"); } 1409 } 1410 1411 1423 private void transitionPersistent(Object pc, HashSet phase3sms) { 1424 SQLStateManager sm = (SQLStateManager) persistenceManager.getStateManager(pc); 1425 1426 if (sm != null && sm.state.isAutoPersistent()) { 1432 sm.state = sm.state.transitionMakePersistent(); 1433 phase3sms.remove(sm); 1434 sm.prepareToUpdatePhaseII(phase3sms); 1435 } 1436 } 1437 1438 1449 private Collection getCollectionValue(ForeignFieldDesc ff) { 1450 Collection c = null; 1451 if (ff.cardinalityUPB > 1) { 1452 c = (Collection) ff.getValue(this); 1453 if (c != null && c instanceof SCOCollection) { 1454 SCOCollection sco = (SCOCollection) c; 1455 if (sco.isDeferred()) { 1456 c = sco.getAdded(); 1457 } 1458 } 1459 } 1460 return c; 1461 } 1462 1463 private void getUpdateActions(ArrayList actions) { 1464 if ((stateFlags & ST_VISITED) > 0) { 1465 return; 1466 } 1467 1468 int action = state.getUpdateAction(); 1469 1470 if ((action == ActionDesc.LOG_NOOP) && (updateDesc == null)) { 1471 return; 1472 } 1473 1474 getUpdateDesc(); 1476 1477 updateDesc.setObjectInfo(getBeforeImage(), this, action); 1478 1479 if ((action == ActionDesc.LOG_DESTROY) || (action == ActionDesc.LOG_CREATE) || 1480 updateDesc.hasUpdatedFields() || updateDesc.hasUpdatedJoinTableRelationships()) { 1481 actions.add(updateDesc); 1482 } 1483 1484 stateFlags |= ST_VISITED; 1485 1486 if (updatedForeignReferences != null) { 1487 Iterator iter = updatedForeignReferences.iterator(); 1488 1489 while (iter.hasNext()) { 1490 SQLStateManager sm = ((UpdatedForeignReference) iter.next()).getStateManager(); 1491 1492 if (sm.referenceCount == 1) { 1493 sm.getUpdateActions(actions); 1494 } 1495 1496 sm.referenceCount--; 1497 } 1498 } 1499 } 1500 1501 public void release() { 1502 if (null != persistenceManager) { 1503 1504 persistenceManager.setStateManager(persistentObject, null); 1507 } 1508 1509 persistentObject = null; 1510 objectId = null; 1511 persistenceManager = null; 1512 beforeImage = null; 1513 hiddenValues = null; 1514 updatedForeignReferences = null; 1515 updateDesc = null; 1516 persistenceConfig = null; 1517 store = null; 1518 valid = false; 1519 } 1520 1521 private void reset(boolean retainValues, boolean wasNew, boolean keepState) { 1522 boolean debug = logger.isLoggable(); 1523 1524 if (debug) { 1525 Object [] items = new Object [] {Boolean.valueOf(retainValues), 1526 Boolean.valueOf(wasNew), Boolean.valueOf(keepState)}; 1527 logger.fine("sqlstore.sqlstatemanager.reset", items); 1529 } 1530 1531 if (state == null) { 1532 1534 if (!keepState) { 1535 persistenceManager.clearFields(persistentObject); 1536 } 1537 1538 persistenceManager.setFlags(persistentObject, READ_WRITE_OK); 1540 1541 if (needsVerifyAtDeregister) { 1542 persistenceManager.deregisterInstance(getObjectId(), this); 1543 } else { 1544 persistenceManager.deregisterInstance(getObjectId()); 1545 } 1546 this.release(); 1547 } else { 1548 stateFlags = 0; 1550 beforeImage = null; 1551 updatedForeignReferences = null; 1552 referenceCount = 0; 1553 1554 if (updateDesc != null) { 1555 updateDesc.reset(); 1556 } 1557 1558 if (retainValues || (state instanceof PersistentNonTransactional)) { 1561 FieldDesc f = null; 1562 ArrayList fields = persistenceConfig.fields; 1563 for (int i = 0; i < fields.size(); i++) { 1564 f = (FieldDesc) fields.get(i); 1565 Object v = f.getValue(this); 1566 1567 if (wasNew && (f instanceof ForeignFieldDesc) && 1571 (v == null) && (((ForeignFieldDesc) f).getInverseRelationshipField() == null)) { 1572 if (debug) 1573 logger.fine("sqlstore.sqlstatemanager.unsetmask", f.getName()); unsetMaskBit(f.absoluteID, PRESENCE_MASK); 1575 } 1576 1577 if ((v instanceof Collection) && !(v instanceof SCOCollection) 1580 && !keepState) { 1581 if (debug) 1582 logger.fine("sqlstore.sqlstatemanager.resettingcollection"); 1584 replaceCollection((ForeignFieldDesc) f, (Collection) v); 1585 1586 if (debug) { 1587 logger.fine("sqlstore.sqlstatemanager.newtype", (f.getValue(this)).getClass()); } 1589 } else if (v instanceof SCOCollection) { 1590 ((SCOCollection) v).reset(); 1591 } 1592 1593 else if ((v instanceof java.util.Date ) && !(v instanceof SCODate) 1595 && !keepState) { 1596 if (debug) 1597 logger.fine("sqlstore.sqlstatemanager.resettingdate"); 1599 v = f.convertValue(v, this); 1600 f.setValue(this, v); 1601 if (debug) { 1602 logger.fine("sqlstore.sqlstatemanager.newtype", (f.getValue(this)).getClass()); } 1604 } 1605 } 1606 1607 persistenceManager.setFlags(persistentObject, LOAD_REQUIRED); 1613 } else { 1614 clearMask(PRESENCE_MASK); 1615 persistenceManager.clearFields(persistentObject); 1616 1617 markKeyFieldsPresent(); 1619 1620 persistenceManager.setFlags(persistentObject, LOAD_REQUIRED); 1621 } 1622 1623 clearMask(SET_MASK); 1624 isReplacementInstance = false; 1625 needsRegisterAtRollback = false; 1626 needsVerifyAtDeregister = false; 1627 } 1628 } 1629 1630 1633 public boolean isProcessed() { 1634 return (referenceCount == 0); 1635 } 1636 1637 public void flushed() { 1638 state = state.transitionFlushed(); 1640 1641 clearMask(SET_MASK); 1642 1643 stateFlags &= ~ST_VISITED; 1644 stateFlags &= ~ST_UPDATE_DISABLED; 1645 stateFlags &= ~ST_REGISTERED; 1646 1647 persistenceManager.setFlags(persistentObject, LOAD_REQUIRED); 1649 1650 if (updatedForeignReferences != null) { 1651 updatedForeignReferences.clear(); 1652 } 1653 1654 if (updateDesc != null) { 1655 updateDesc.reset(); 1656 } 1657 } 1658 1659 public void commit(boolean retainValues) { 1660 boolean wasNew = (state.isNew() && !state.isDeleted()); 1661 state = state.transitionCommit(retainValues); 1662 reset(retainValues, wasNew, false); 1663 } 1664 1665 public void rollback(boolean retainValues) { 1666 boolean wasNew = (state.isNew() && !state.isDeleted()); 1667 boolean needsRestore = state.needsRestoreOnRollback(retainValues); 1668 state = state.transitionRollback(retainValues); 1669 boolean keepState = needsRestore; 1670 1671 if ((beforeImage != null) && (needsRestore == true)) { 1673 copyFields(beforeImage, true, false); 1674 1675 keepState = true; 1677 } 1678 1679 if (needsRegisterAtRollback && !isReplacementInstance) { 1680 persistenceManager.registerInstance(this, getObjectId()); 1681 } 1682 reset(retainValues, wasNew, keepState); 1683 } 1684 1685 private void markKeyFieldsPresent() { 1686 ArrayList keyFields = persistenceConfig.getPrimaryTable().getKey().getFields(); 1687 1688 for (int i = 0; i < keyFields.size(); i++) { 1689 LocalFieldDesc fd = (LocalFieldDesc) keyFields.get(i); 1690 1691 if (fd != null) { 1692 setPresenceMaskBit(fd.absoluteID); 1693 } 1694 } 1695 } 1696 1697 public void prepareGetField(int fieldID) { 1698 FieldDesc fieldDesc = persistenceConfig.getField(fieldID); 1699 1700 prepareGetField(fieldDesc, false, true); 1701 } 1702 1703 private void prepareGetField(FieldDesc fieldDesc) { 1704 prepareGetField(fieldDesc, true, false); 1705 } 1706 1707 1716 private void prepareGetField(FieldDesc fieldDesc, boolean internal, boolean acquireShareLock) { 1717 boolean debug = logger.isLoggable(Logger.FINEST); 1718 1719 if (debug) { 1720 logger.finest("sqlstore.sqlstatemanager.preparegetfield", fieldDesc.getName()); } 1722 1723 if (acquireShareLock) { 1724 persistenceManager.acquireShareLock(); 1725 } 1726 1727 try { 1728 getLock(); 1729 1730 boolean xactActive = persistenceManager.isActiveTransaction(); 1731 boolean optimistic = persistenceManager.isOptimisticTransaction(); 1732 boolean nontransactionalRead = persistenceManager.isNontransactionalRead(); 1733 1734 if (state.needsReload(optimistic, nontransactionalRead, xactActive)) { 1735 reload(fieldDesc); 1736 } 1737 1738 LifeCycleState oldstate = state; 1739 state = state.transitionReadField(optimistic, nontransactionalRead, xactActive); 1740 1741 registerInstance(false, null, oldstate); 1742 1743 if (state.isNavigable() || !internal) { 1745 if (getPresenceMaskBit(fieldDesc.absoluteID) == false) { 1746 realizeField(fieldDesc); 1747 } 1748 } 1749 } catch (JDOException e) { 1750 throw e; 1751 } catch (Exception e) { 1752 logger.log(Logger.FINE,"sqlstore.exception.log", e); 1753 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 1754 "core.statemanager.getfieldfailed"), e); } finally { 1756 if (acquireShareLock) { 1757 persistenceManager.releaseShareLock(); 1758 } 1759 releaseLock(); 1760 1761 if (debug) { 1762 logger.finest("sqlstore.sqlstatemanager.preparegetfield.exit"); } 1764 } 1765 } 1766 1767 1776 private void realizeField(FieldDesc fieldDesc) { 1777 assert fieldDesc != null; 1778 1779 boolean debug = logger.isLoggable(); 1780 1781 if (debug) { 1782 logger.fine("sqlstore.sqlstatemanager.realizefield", fieldDesc.getName()); } 1784 1785 if (!persistenceConfig.isNavigable()) { 1786 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 1787 "core.statemanager.notnavigable", fieldDesc.getName(), persistentObject.getClass().getName())); 1789 } 1790 1791 boolean fieldRealized = false; 1792 1793 if (fieldDesc instanceof ForeignFieldDesc) { 1794 ForeignFieldDesc ff = (ForeignFieldDesc) fieldDesc; 1795 1796 if (ff.fetchGroup <= FieldDesc.GROUP_NONE 1803 && persistenceConfig.getFetchGroup(ff.fetchGroup).size() <= 1 1804 && !ff.useJoinTable()) { 1805 1806 fieldRealized = realizeForeignField(ff); 1807 } 1808 } 1809 1810 if (!fieldRealized) { 1811 retrieve(fieldDesc); 1812 } 1813 1814 if (debug) { 1815 logger.fine("sqlstore.sqlstatemanager.realizefield.exit"); } 1817 } 1818 1819 1836 private boolean realizeForeignField(ForeignFieldDesc foreignField) { 1837 assert foreignField != null; 1838 1839 boolean isPresent = false; 1840 boolean debug = logger.isLoggable(); 1841 1842 if (debug) { 1843 logger.fine("sqlstore.sqlstatemanager.realizeforeignfield", foreignField.getName()); 1845 } 1846 1847 for (int i = 0; i < foreignField.localFields.size(); i++) { 1849 LocalFieldDesc lf = (LocalFieldDesc) foreignField.localFields.get(i); 1850 isPresent = getPresenceMaskBit(lf.absoluteID); 1851 1852 if (!isPresent) { 1853 break; 1854 } 1855 } 1856 1857 if (isPresent) { 1858 populateForeignField(foreignField); 1862 } 1863 1864 if (debug) { 1865 logger.fine("sqlstore.sqlstatemanager.realizeforeignfield.exit", Boolean.valueOf(isPresent)); 1867 } 1868 1869 return isPresent; 1870 } 1871 1872 1884 private void populateForeignField(ForeignFieldDesc foreignField) { 1885 assert foreignField != null; 1886 1887 boolean foundInstance = false; 1888 1889 if (foreignField.hasForeignKey() && foreignField.isMappedToPk()) { 1890 Object pc = getObjectById(foreignField, null, null, true); 1892 1893 if (foundInstance = (pc != null)) { 1894 foreignField.setValue(this, pc); 1895 } 1896 } 1897 1898 if (!foundInstance) { 1899 Collection result = retrieveForeign(foreignField); 1901 attachQueryResult(foreignField, result); 1902 } 1903 1904 setPresenceMaskBit(foreignField.absoluteID); 1906 } 1907 1908 1916 private void attachQueryResult(ForeignFieldDesc foreignField, 1917 Collection queryResult) { 1918 assert foreignField != null; 1919 1920 if (foreignField.getComponentType() != null) { 1926 replaceCollection(foreignField, queryResult); 1929 } else if (queryResult == null || queryResult.size() == 0) { 1930 foreignField.setValue(this, null); 1931 } else { 1932 if (queryResult.size() > 1) { 1933 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 1934 "core.persistencestore.toomanyobjforcard1", persistenceConfig.getName(), 1936 foreignField.getName(), "" + queryResult.size())); } 1938 Object v = queryResult.iterator().next(); 1939 foreignField.setValue(this, v); 1940 } 1941 } 1942 1943 1965 private Collection retrieveForeign(ForeignFieldDesc foreignField) { 1966 assert foreignField != null; 1967 1968 Collection result = null; 1969 boolean debug = logger.isLoggable(); 1970 1971 if (debug) { 1972 logger.fine("sqlstore.sqlstatemanager.retrieveforeign", foreignField.getName()); 1974 } 1975 1976 Object [] values = new Object [foreignField.localFields.size()]; 1977 boolean isValidForeignKey = true; 1978 1979 for (int i = 0; i < foreignField.localFields.size(); i++) { 1980 FieldDesc flf = (FieldDesc) foreignField.localFields.get(i); 1981 1982 if (!getPresenceMaskBit(i)) { 1983 } 1985 1986 if (getSetMaskBit(flf.absoluteID)) { 1987 values[i] = flf.getValue(beforeImage); 1990 } else { 1991 values[i] = flf.getValue(this); 1992 } 1993 1994 if (values[i] == null) { 1996 isValidForeignKey = false; 1998 } 1999 } 2000 2001 if (isValidForeignKey) { 2002 RetrieveDesc fdesc = 2004 persistenceConfig.getRetrieveDescForFKQuery(foreignField, store); 2005 result = (Collection) store.retrieve( 2006 persistenceManager, fdesc, new QueryValueFetcher(values)); 2007 } 2008 2009 if (debug) { 2010 logger.fine("sqlstore.sqlstatemanager.retrieveforeign.exit"); } 2012 2013 return result; 2014 } 2015 2016 2028 private void retrieve(FieldDesc additionalField) { 2029 boolean debug = logger.isLoggable(); 2030 2031 if (debug) { 2032 String fieldName = (additionalField != null) ? additionalField.getName() : null; 2033 logger.fine("sqlstore.sqlstatemanager.retrieve", fieldName); } 2035 2036 LocalFieldDesc[] keyFields = persistenceConfig.getKeyFieldDescs(); 2037 Object [] values = new Object [keyFields.length]; 2038 copyValues(values, keyFields, 0); 2039 2040 RetrieveDesc rd = persistenceConfig.getRetrieveDescForPKQuery(additionalField, store); 2042 Collection result = (Collection) store. 2043 retrieve(persistenceManager, rd, new QueryValueFetcher(values)); 2044 2045 if (result.size() > 1) { 2046 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 2047 "core.statemanager.toomanyrows", persistenceConfig.getPersistenceCapableClass().getName())); 2049 } else if (result.size() < 1 || result.iterator().next() != persistentObject) { 2050 2051 throw new JDOObjectNotFoundException(I18NHelper.getMessage(messages, 2054 "core.statemanager.objectnotfound"), new Object []{persistentObject}); 2056 } 2057 2058 if (debug) { 2059 logger.fine("sqlstore.sqlstatemanager.retrieve.exit"); } 2061 } 2062 2063 2072 private void copyValues(Object [] values, LocalFieldDesc[] fields, int startIndex) { 2073 2074 assert values.length - startIndex >= fields.length; 2076 2077 for (int i = 0; i < fields.length; i++) { 2078 LocalFieldDesc field = fields[i]; 2079 values[i + startIndex] = field.getValue(this); 2080 2081 assert values[i + startIndex] != null; 2083 } 2084 } 2085 2086 public SQLStateManager getBeforeImage() { 2087 2088 if (beforeImage == null && isBeforeImageRequired()) { 2090 boolean debug = logger.isLoggable(); 2091 2092 if (debug) { 2093 logger.fine("sqlstore.sqlstatemanager.getbeforeimage", persistenceConfig.getPersistenceCapableClass().getName()); 2095 } 2096 2097 try { 2098 getLock(); 2099 2100 beforeImage = copyPersistent(); 2102 } finally { 2103 releaseLock(); 2104 } 2105 2106 if (debug) { 2107 logger.fine("sqlstore.sqlstatemanager.getbeforeimage.exit"); } 2109 } 2110 2111 return beforeImage; 2112 } 2113 2114 public boolean isBeforeImageRequired() { 2115 2116 com.sun.jdo.api.persistence.support.Transaction t = persistenceManager.currentTransaction(); 2117 boolean isBeforeImageRequired = 2122 persistenceManager.isOptimisticTransaction() || 2123 getUpdateDesc().hasChangedRelationships() || 2124 t.getRetainValues() || t.getRestoreValues() || 2125 persistenceConfig.hasModifiedCheckAtCommitConsistency(); 2126 if (logger.isLoggable(Logger.FINER)) { 2127 logger.finer("sqlstore.sqlstatemanager.isbeforeimagerequired", Boolean.valueOf(isBeforeImageRequired)); 2129 } 2130 return isBeforeImageRequired; 2131 } 2132 2133 private SQLStateManager copyPersistent() { 2134 PersistenceManager pm = (PersistenceManager) getPersistenceManagerInternal(); 2135 SQLStateManager newStateManager = (SQLStateManager) clone(); 2136 2137 pm.newInstance(newStateManager); 2139 2140 newStateManager.copyFields(this, true, true); 2141 2142 return newStateManager; 2143 } 2144 2145 2153 public void copyFields(StateManager source) { 2154 if (!(source instanceof SQLStateManager)) { 2155 String className = 2156 (source != null) ? source.getClass().getName() : null; 2157 throw new IllegalArgumentException (className); 2158 } 2159 2160 SQLStateManager sqlSource = (SQLStateManager) source; 2161 2162 if (persistenceConfig != sqlSource.getPersistenceConfig()) { 2163 Class thisPCClass = 2164 persistenceConfig.getPersistenceCapableClass(); 2165 Class sourcePCClass = 2166 sqlSource.getPersistenceConfig().getPersistenceCapableClass(); 2167 throw new IllegalArgumentException ( 2168 I18NHelper.getMessage( 2169 messages, 2170 "core.statemanager.copyFields.mismatch", thisPCClass.getName(), 2172 sourcePCClass.getName())); 2173 } 2174 2175 copyFields(sqlSource, false, true); 2176 } 2177 2178 2186 private void copyFields(SQLStateManager source, 2187 boolean copyRelationships, 2188 boolean clone) { 2189 ArrayList fields = null; 2190 2191 clearMask(PRESENCE_MASK); 2194 clearMask(SET_MASK); 2195 2196 for (int i = 0; i < 2; i++) { 2197 if (i == 0) { 2198 fields = persistenceConfig.fields; 2199 } else { 2200 fields = persistenceConfig.hiddenFields; 2201 } 2202 2203 for (int j = 0; (fields != null) && (j < fields.size()); j++) { 2204 FieldDesc f = (FieldDesc) fields.get(j); 2205 2206 if (!copyRelationships && f.isRelationshipField()) { 2207 continue; 2208 } 2209 2210 if (source.getPresenceMaskBit(f.absoluteID)) { 2211 Object value = f.getValue(source); 2212 f.setValue(this, (clone) ? cloneObjectMaybe(value) : value); 2213 setPresenceMaskBit(f.absoluteID); 2214 } 2215 } 2216 } 2217 } 2218 2219 private Object cloneObjectMaybe(Object source) { 2220 2222 if (source != null) { 2223 if ((source instanceof SCO)) { 2225 return ((SCO)source).cloneInternal(); 2226 2227 } else if (!(source instanceof Number ) && 2228 !(source instanceof String ) && 2229 !(source instanceof Character ) && 2230 !(source instanceof Boolean ) && 2231 !(source instanceof com.sun.jdo.api.persistence.support.PersistenceCapable) && 2233 !(source instanceof byte[])) { 2234 try { 2235 Class type = source.getClass(); 2236 2237 if (!type.isArray()) { 2238 Method m = type.getMethod("clone", (Class []) null); 2240 if (m != null) { 2241 return m.invoke(source, (Object []) null); 2242 } 2243 } else { 2244 Object srcArray[] = (Object []) source; 2245 Object dstArray[] = (Object []) 2246 java.lang.reflect.Array.newInstance(type.getComponentType(), srcArray.length); 2247 2248 for (int i = 0; i < srcArray.length; i++) { 2249 dstArray[i] = srcArray[i]; 2250 } 2251 return dstArray; 2252 } 2253 } catch (NoSuchMethodException e) { 2254 if (logger.isLoggable()) { 2255 Object [] items = new Object [] {e, source.getClass().getName()}; 2256 logger.fine("sqlstore.sqlstatemanager.nosuchmethodexcep.clone", items); } 2258 } catch (InvocationTargetException e) { 2259 } catch (IllegalAccessException e) { 2260 } 2261 } 2262 } 2263 2264 return source; 2265 } 2266 2267 2280 private void prepareUpdateField(FieldDesc fieldDesc, ArrayList newlyRegisteredSMs) { 2281 2282 if (fieldDesc.isKeyField()) { 2287 return; 2288 } 2289 2290 getUpdateDesc().markRelationshipChange(fieldDesc); 2291 2292 boolean debug = logger.isLoggable(); 2293 2294 if (debug) { 2295 Object [] items = new Object [] {fieldDesc.getName(),state}; 2296 logger.fine("sqlstore.sqlstatemanager.prepareupdatefield", items); } 2298 2299 boolean optimistic = persistenceManager.isOptimisticTransaction(); 2300 boolean xactActive = persistenceManager.isActiveTransaction(); 2301 boolean nontransactionalRead = persistenceManager.isNontransactionalRead(); 2302 2303 if (state.needsReload(optimistic, nontransactionalRead, xactActive)) { 2304 reload(fieldDesc); 2305 } 2306 2307 LifeCycleState oldstate = state; 2311 state = state.transitionWriteField(xactActive); 2312 registerInstance(false, newlyRegisteredSMs, oldstate); 2313 2314 if (state == oldstate && getSetMaskBit(fieldDesc.absoluteID) && 2315 getPresenceMaskBit(fieldDesc.absoluteID)) { 2316 return; 2319 } 2320 2321 if (state.isBeforeImageUpdatable()) { 2323 2324 if (!getPresenceMaskBit(fieldDesc.absoluteID)) { 2328 prepareGetField(fieldDesc); 2329 } 2330 2331 updateBeforeImage(fieldDesc, null); 2332 } 2333 2334 recordUpdatedField(fieldDesc); 2335 2336 if (debug) { 2337 logger.fine("sqlstore.sqlstatemanager.prepareupdatefield.exit"); } 2339 } 2340 2341 2351 private void updateBeforeImage(FieldDesc fieldDesc, Object value) { 2352 2353 getBeforeImage(); 2354 2355 if (beforeImage != null 2356 && !beforeImage.getPresenceMaskBit(fieldDesc.absoluteID) 2357 && (fieldDesc.sqlProperties & FieldDesc.PROP_LOG_ON_UPDATE) > 0) { 2358 2359 if (value == null) { 2360 value = fieldDesc.getValue(this); 2361 } 2362 2363 if (value != null) { 2364 if (logger.isLoggable(Logger.FINEST)) { 2365 Object [] items = new Object [] {fieldDesc, value}; 2366 logger.finest("sqlstore.sqlstatemanager.updatebeforeimage", items); } 2368 2369 fieldDesc.setValue(beforeImage, cloneObjectMaybe(value)); 2370 beforeImage.setPresenceMaskBit(fieldDesc.absoluteID); 2371 } 2372 } 2373 } 2374 2375 2381 private void recordUpdatedField(FieldDesc fieldDesc) { 2382 boolean debug = logger.isLoggable(Logger.FINEST); 2383 2384 if (!fieldDesc.isRelationshipField() && 2385 (fieldDesc.sqlProperties & FieldDesc.PROP_RECORD_ON_UPDATE) > 0) { 2386 if (debug) { 2387 logger.finest("sqlstore.sqlstatemanager.recordingfield", fieldDesc); } 2389 getUpdateDesc().recordUpdatedField((LocalFieldDesc) fieldDesc); 2390 } 2391 2392 if (debug) { 2393 logger.finest("sqlstore.sqlstatemanager.makedirtyfield", fieldDesc); } 2395 setSetMaskBit(fieldDesc.absoluteID); 2396 } 2397 2398 2405 public void addDependency(StateManager sm) { 2406 2407 if (logger.isLoggable()) { 2408 Object [] items = new Object [] {this, sm}; 2409 logger.fine("sqlstore.sqlstatemanager.adddependency", items); } 2411 2412 2418 SQLStateManager other = (SQLStateManager)sm; 2419 if (!state.isNew() || !state.isDeleted()) { 2420 2423 this.addUpdatedForeignReference(null, other); 2425 } else if ((other.stateFlags & ST_REGISTERED) == 0) { 2426 2427 persistenceManager.registerInstance(other, other.getObjectId(), false, true); 2430 other.stateFlags |= ST_REGISTERED; 2431 } 2432 } 2433 2434 2444 public void resolveDependencies() { 2445 if (logger.isLoggable()) { 2446 logger.fine("sqlstore.sqlstatemanager.resolvedependencies", this.getPersistent()); } 2448 2449 if (updatedForeignReferences != null) { 2450 Iterator iter = updatedForeignReferences.iterator(); 2451 2452 while (iter.hasNext()) { 2453 final UpdatedForeignReference ufr = (UpdatedForeignReference) iter.next(); 2454 final ForeignFieldDesc fieldDesc = ufr.getFieldDesc(); 2455 final SQLStateManager foreignSM = ufr.getStateManager(); 2456 2457 if (resolveDependency(fieldDesc, foreignSM)) { 2458 foreignSM.removeDependency(); 2459 iter.remove(); 2460 } 2461 } 2462 } 2463 } 2464 2465 2483 private boolean resolveDependency(ForeignFieldDesc fieldDesc, 2484 SQLStateManager foreignSM) { 2485 boolean removeDependency = false; 2486 Object pc = foreignSM.getPersistent(); 2487 2488 if (!state.isPersistentInDataStore()) { 2489 if (state.getUpdateAction() != ActionDesc.LOG_CREATE) { 2492 removeDependency = true; 2494 } else if (!checkRelationship(this, fieldDesc, pc)) { 2495 removeDependency = true; 2497 } 2498 } else { 2499 if (fieldDesc != null) { 2504 if (foreignSM.state.getUpdateAction() != ActionDesc.LOG_DESTROY) { 2508 removeDependency = true; 2510 } else if (fieldDesc.cardinalityUPB <= 1) { 2511 if (!checkRelationship(beforeImage, fieldDesc, pc)) { 2516 removeDependency = true; 2518 } 2519 } 2520 } 2521 } 2522 2523 if (removeDependency && logger.isLoggable()) { 2524 Object [] items = new Object [] {this.getPersistent(), fieldDesc.getName(), pc}; 2525 logger.fine("sqlstore.sqlstatemanager.resolvedependency", items); } 2527 return removeDependency; 2528 } 2529 2530 2534 private void removeDependency() { 2535 if (--referenceCount == 0) { 2536 stateFlags &= ~ST_UPDATE_DISABLED; 2537 } 2538 } 2539 2540 2553 static private boolean checkRelationship(SQLStateManager sm, 2554 ForeignFieldDesc fieldDesc, 2555 Object pc) { 2556 boolean related = false; 2557 2558 if (fieldDesc != null && sm != null 2559 && sm.getPresenceMaskBit(fieldDesc.absoluteID)) { 2560 2561 if (fieldDesc.cardinalityUPB > 1) { 2562 Collection c = sm.getCollectionValue(fieldDesc); 2564 2565 related = c.contains(pc); 2567 } else { 2568 related = fieldDesc.getValue(sm) == pc; 2569 } 2570 } 2571 return related; 2572 } 2573 2574 2591 private void registerRemoveDependency(ForeignFieldDesc fieldDesc, SQLStateManager removedSM) { 2592 if (this.state.isPersistentInDataStore() && 2593 removedSM.state.isPersistentInDataStore()) { 2594 2595 this.addUpdatedForeignReference(fieldDesc, removedSM); 2596 } 2597 } 2598 2599 2614 private void registerCreateDependency(ForeignFieldDesc inverseFieldDesc, SQLStateManager addedSM) { 2615 if (!addedSM.state.isPersistentInDataStore()) { 2616 addedSM.addUpdatedForeignReference(inverseFieldDesc, this); 2617 } 2618 } 2619 2620 2634 private void addUpdatedForeignReference(ForeignFieldDesc fieldDesc, SQLStateManager sm) { 2635 2636 if (sm == this) { 2638 return; 2639 } 2640 2641 if (updatedForeignReferences == null) { 2646 updatedForeignReferences = new HashSet(); 2647 2648 if ((stateFlags & ST_REGISTERED) == 0) { 2651 persistenceManager.registerInstance(this, getObjectId(), false, true); 2652 stateFlags |= ST_REGISTERED; 2653 } 2654 } 2655 2656 if (updatedForeignReferences.add(new UpdatedForeignReference(fieldDesc, sm))) { 2657 sm.stateFlags |= ST_UPDATE_DISABLED; 2658 sm.referenceCount++; 2659 2660 if (logger.isLoggable() ) { 2661 String fieldName = (fieldDesc != null) ? fieldDesc.getName() : null; 2662 Object [] items = new Object [] {this.persistentObject, fieldName, 2663 sm.persistentObject, new Integer (sm.referenceCount)}; 2664 logger.fine("sqlstore.sqlstatemanager.addupdate", items); } 2666 2667 if ((sm.stateFlags & ST_REGISTERED) == 0) { 2670 persistenceManager.registerInstance(sm, sm.getObjectId(), false, true); 2671 sm.stateFlags |= ST_REGISTERED; 2672 } 2673 } 2674 } 2675 2676 2686 private void removeUpdatedForeignReference(ForeignFieldDesc fieldDesc, SQLStateManager sm) { 2687 if ((updatedForeignReferences == null) || 2688 (updatedForeignReferences.size() == 0)) { 2689 return; 2690 } 2691 2692 if (updatedForeignReferences.remove(new UpdatedForeignReference(fieldDesc, sm))) { 2693 sm.referenceCount--; 2694 2695 if (logger.isLoggable()) { 2696 String fieldName = (fieldDesc != null) ? fieldDesc.getName() : null; 2697 Object [] items = new Object [] {this.persistentObject, fieldName, 2698 sm.persistentObject, new Integer (sm.referenceCount)}; 2699 logger.fine("sqlstore.sqlstatemanager.removeupdate", items); } 2701 2702 if (sm.referenceCount == 0) { 2703 sm.stateFlags &= ~ST_UPDATE_DISABLED; 2704 } 2705 } 2706 } 2707 2708 2727 private boolean updateObjectField(ForeignFieldDesc fieldDesc, 2728 Object addedObject, 2729 boolean updateInverseRelationshipField, 2730 boolean managedRelationshipInProgress) { 2731 2732 boolean debug = logger.isLoggable(); 2733 2734 if (debug) { 2735 Object [] items = new Object [] {fieldDesc.getName(),fieldDesc.getComponentType()}; 2736 logger.fine("sqlstore.sqlstatemanager.updateobjfield", items); } 2738 2739 Object removedObject = fieldDesc.getValue(this); 2740 2741 if (addedObject != removedObject) { 2743 2744 SQLStateManager addedSM = getAddedSM(addedObject, null); 2745 SQLStateManager removedSM = getRemovedSM(removedObject); 2746 SQLStateManager addedInverseFieldSM = null; 2747 2748 if (addedSM != null && addedSM.isDeleted()) { 2750 JDOUserException ex = new JDOUserException(I18NHelper.getMessage(messages, 2751 "jdo.lifecycle.deleted.accessField")); ex.addFailedObject(addedObject); 2753 throw ex; 2754 } 2755 2756 ForeignFieldDesc inverseFieldDesc = fieldDesc.getInverseRelationshipField(); 2757 2758 updateRelationshipInDataStore(fieldDesc, addedSM, removedSM, 2759 inverseFieldDesc, managedRelationshipInProgress); 2760 2761 if (updateInverseRelationshipField && inverseFieldDesc != null) { 2762 addedInverseFieldSM = manageRelationshipForObjectField(inverseFieldDesc, addedSM, removedSM, 2763 managedRelationshipInProgress); 2764 } 2765 2766 manageDependencyForObjectField(fieldDesc, addedSM, removedSM, addedInverseFieldSM); 2767 } 2768 2769 if (debug) { 2770 logger.fine("sqlstore.sqlstatemanager.updateobjfield.exit"); } 2772 2773 return true; 2774 } 2775 2776 2790 private void updateRelationshipInDataStore(ForeignFieldDesc fieldDesc, 2791 SQLStateManager addedSM, 2792 SQLStateManager removedSM, 2793 ForeignFieldDesc inverseFieldDesc, 2794 boolean managedRelationshipInProgress) { 2795 2796 if (!fieldDesc.useJoinTable()) { 2797 processForeignKeys(fieldDesc, addedSM, removedSM, inverseFieldDesc, 2798 managedRelationshipInProgress); 2799 } else { 2800 processJoinTableEntries(fieldDesc, addedSM, removedSM, inverseFieldDesc, 2801 managedRelationshipInProgress); 2802 } 2803 } 2804 2805 2821 private void processForeignKeys(ForeignFieldDesc fieldDesc, 2822 SQLStateManager addedSM, 2823 SQLStateManager removedSM, 2824 ForeignFieldDesc inverseFieldDesc, 2825 boolean managedRelationshipInProgress) { 2826 2827 boolean updateOtherSide = (fieldDesc.sqlProperties & FieldDesc.PROP_REF_INTEGRITY_UPDATES) == 0; 2830 2831 if (updateOtherSide) { 2832 if (removedSM != null) { 2834 removedSM.nullifyForeignKey(inverseFieldDesc, this, fieldDesc, false); 2835 } 2836 if (addedSM != null && !managedRelationshipInProgress) { 2839 addedSM.setForeignKey(inverseFieldDesc, this, fieldDesc); 2840 } 2841 } else { 2842 if (removedSM != null) { 2844 nullifyForeignKey(fieldDesc, removedSM, inverseFieldDesc, addedSM != null); 2847 } 2848 if (addedSM != null && !managedRelationshipInProgress) { 2851 setForeignKey(fieldDesc, addedSM, inverseFieldDesc); 2853 } 2854 } 2855 } 2856 2857 2871 private void processJoinTableEntries(ForeignFieldDesc fieldDesc, 2872 SQLStateManager addedSM, 2873 SQLStateManager removedSM, 2874 ForeignFieldDesc inverseFieldDesc, 2875 boolean managedRelationshipInProgress) { 2876 2877 boolean updateOtherSide = (fieldDesc.sqlProperties & FieldDesc.PROP_REF_INTEGRITY_UPDATES) == 0; 2880 2881 if (updateOtherSide) { 2882 if (removedSM != null) { 2884 removedSM.removeJoinTableEntry(inverseFieldDesc, this, fieldDesc); 2885 } 2886 2887 if (addedSM != null && !managedRelationshipInProgress) { 2890 addedSM.addJoinTableEntry(inverseFieldDesc, this, fieldDesc); 2891 } 2892 } else { 2893 if (removedSM != null) { 2895 removeJoinTableEntry(fieldDesc, removedSM, inverseFieldDesc); 2898 } 2899 2900 if (addedSM != null && !managedRelationshipInProgress) { 2903 addJoinTableEntry(fieldDesc, addedSM, inverseFieldDesc); 2904 } 2905 } 2906 } 2907 2908 2919 private SQLStateManager manageRelationshipForObjectField(ForeignFieldDesc inverseFieldDesc, 2920 SQLStateManager addedSM, 2921 SQLStateManager removedSM, 2922 boolean managedRelationshipInProgress) { 2923 2924 Object addedInverseFieldValue = null; 2925 SQLStateManager addedInverseFieldSM = null; 2926 2927 if (removedSM != null) { 2928 removedSM.removeRelationship(inverseFieldDesc, this); 2929 } 2930 2931 if (addedSM != null && !managedRelationshipInProgress) { 2932 addedInverseFieldValue = addedSM.addRelationship(inverseFieldDesc, this); 2933 2934 if (addedInverseFieldValue != null) { 2935 addedInverseFieldSM = (SQLStateManager) 2936 persistenceManager.getStateManager(addedInverseFieldValue); 2937 } 2938 } 2939 2940 return addedInverseFieldSM; 2941 } 2942 2943 2966 private void manageDependencyForObjectField(ForeignFieldDesc fieldDesc, 2967 SQLStateManager addedSM, 2968 SQLStateManager removedSM, 2969 SQLStateManager addedInverseFieldSM) { 2970 2971 boolean updateOtherSide = (fieldDesc.sqlProperties & FieldDesc.PROP_REF_INTEGRITY_UPDATES) == 0; 2974 2975 if (updateOtherSide && removedSM != null && addedSM != null) { 2978 2979 if (removedSM.state.isPersistentInDataStore() 2982 && this.state.isPersistentInDataStore()) { 2983 2984 removedSM.addUpdatedForeignReference(null, addedSM); 2987 } 2988 } 2989 2990 if (!updateOtherSide && addedInverseFieldSM != null) { 2993 2994 if (addedInverseFieldSM.state.isPersistentInDataStore() 2997 && addedSM.state.isPersistentInDataStore()) { 2998 2999 addedInverseFieldSM.addUpdatedForeignReference(null, this); 3002 } 3003 } 3004 } 3005 3006 3023 private SQLStateManager getAddedSM(Object addedObject, ArrayList newlyRegisteredSMs) { 3024 SQLStateManager addedSM = null; 3025 3026 if (addedObject != null) { 3027 if ((addedSM = (SQLStateManager) persistenceManager.getStateManager(addedObject)) == null) { 3029 makeAutoPersistent(addedObject); 3030 addedSM = (SQLStateManager) persistenceManager.getStateManager(addedObject); 3031 3032 if (newlyRegisteredSMs != null && !newlyRegisteredSMs.contains(addedSM)) { 3035 newlyRegisteredSMs.add(addedSM); 3036 } 3037 } 3038 } 3039 return addedSM; 3040 } 3041 3042 3050 private SQLStateManager getRemovedSM(Object removedObject) { 3051 SQLStateManager removedSM = null; 3052 3053 if (removedObject != null) { 3054 removedSM = (SQLStateManager) persistenceManager.getStateManager(removedObject); 3055 } 3056 return removedSM; 3057 } 3058 3059 3081 private void processCollectionUpdates(ForeignFieldDesc fieldDesc, 3082 ArrayList removedList, 3083 ArrayList addedList, 3084 ArrayList newlyRegisteredSMs, 3085 boolean updateInverseRelationshipField, 3086 boolean managedRelationshipInProgress) { 3087 3088 boolean debug = logger.isLoggable(); 3089 ForeignFieldDesc inverseFieldDesc = fieldDesc.getInverseRelationshipField(); 3090 3091 3095 if (debug) { 3096 Object [] items = new Object [] {removedList,addedList}; 3097 logger.fine("sqlstore.sqlstatemanager.processcollectionupdate", items); } 3099 3100 if (removedList != null) { 3102 removeCollectionRelationship(fieldDesc, removedList, inverseFieldDesc, 3103 updateInverseRelationshipField, managedRelationshipInProgress); 3104 } 3105 3106 if (addedList != null) { 3108 addCollectionRelationship(fieldDesc, addedList, inverseFieldDesc, 3109 newlyRegisteredSMs, 3110 updateInverseRelationshipField, managedRelationshipInProgress); 3111 } 3112 3113 if (debug) { 3114 logger.fine("sqlstore.sqlstatemanager.processcollectionupdate.exit"); } 3116 } 3117 3118 3131 private void removeCollectionRelationship(ForeignFieldDesc fieldDesc, 3132 ArrayList removedList, 3133 ForeignFieldDesc inverseFieldDesc, 3134 boolean updateInverseRelationshipField, 3135 boolean managedRelationshipInProgress) { 3136 3137 for (int i = 0; i < removedList.size(); i++) { 3138 SQLStateManager removedSM = getRemovedSM(removedList.get(i)); 3139 3140 if (removedSM != null) { 3143 3144 if (!managedRelationshipInProgress) { 3148 updateRelationshipInDataStore(fieldDesc, null, removedSM, inverseFieldDesc, false); 3149 3150 if (updateInverseRelationshipField && inverseFieldDesc != null) { 3152 removedSM.removeRelationship(inverseFieldDesc, this); 3153 } 3154 } 3155 } 3156 } 3157 } 3158 3159 3178 private void nullifyForeignKey(ForeignFieldDesc fieldDesc, 3179 SQLStateManager removedSM, 3180 ForeignFieldDesc inverseFieldDesc, 3181 boolean setDependencyOnly) { 3182 3183 if (!isDeleted() && !setDependencyOnly) { 3184 if (fieldDesc != null) { 3188 for (int i = 0; i < fieldDesc.localFields.size(); i++) { 3189 LocalFieldDesc la = (LocalFieldDesc) fieldDesc.localFields.get(i); 3190 3191 nullifyForeignKey(fieldDesc, la); 3192 } 3193 } else { 3194 for (int i = 0; i < inverseFieldDesc.foreignFields.size(); i++) { 3195 LocalFieldDesc la = (LocalFieldDesc) inverseFieldDesc.foreignFields.get(i); 3196 3197 nullifyForeignKey(fieldDesc, la); 3198 } 3199 } 3200 } 3201 3202 registerRemoveDependency(fieldDesc, removedSM); 3204 } 3205 3206 3216 private void nullifyForeignKey(ForeignFieldDesc fieldDesc, LocalFieldDesc la) { 3217 3218 if (!getSetMaskBit(la.absoluteID)) { 3219 prepareUpdateField(la, null); 3220 } 3221 3222 JDOUserException pkUpdateEx = null; 3223 3224 if (la.isKeyField()) { 3225 try { 3226 assertPKUpdate(la, null); 3227 } catch (JDOUserException e) { 3228 3237 if (((stateFlags & ST_DELETE_INPROGRESS) == 0)) { 3238 throw e; 3239 } 3240 3241 pkUpdateEx = e; 3242 } 3243 } 3244 3245 if (pkUpdateEx == null) { 3246 updateTrackedFields(la, null, fieldDesc); 3248 la.setValue(this, null); 3249 } 3250 } 3251 3252 3270 private void removeJoinTableEntry(ForeignFieldDesc fieldDesc, 3271 SQLStateManager removedSM, 3272 ForeignFieldDesc inverseFieldDesc) { 3273 3274 if (removedSM.state.isAutoPersistent() || this.state.isAutoPersistent()) { 3281 removedSM.removeUpdatedForeignReference(inverseFieldDesc, this); 3282 this.removeUpdatedForeignReference(fieldDesc, removedSM); 3283 } 3284 3285 if (fieldDesc != null && getUpdateDesc().removeUpdatedJoinTableRelationship( 3287 fieldDesc, removedSM, ActionDesc.LOG_CREATE) == false) { 3288 3289 if (inverseFieldDesc == null || removedSM.getUpdateDesc().removeUpdatedJoinTableRelationship( 3291 inverseFieldDesc, this, ActionDesc.LOG_CREATE) == false) { 3292 3293 getUpdateDesc().recordUpdatedJoinTableRelationship( 3296 fieldDesc, this, removedSM, ActionDesc.LOG_DESTROY); 3297 3298 registerRemoveDependency(fieldDesc, removedSM); 3300 } 3301 } else if (fieldDesc == null) { 3302 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 3303 "core.statemanager.cantschedulejointable", this.getPersistenceConfig().getPersistenceCapableClass().getName(), 3305 removedSM.getPersistenceConfig().getPersistenceCapableClass().getName())); 3306 } 3307 } 3308 3309 3316 private void removeRelationship(ForeignFieldDesc fieldDesc, SQLStateManager removedSM) { 3317 3318 boolean isCollection = (fieldDesc.cardinalityUPB > 1); 3319 3320 if (!isCollection) { 3321 prepareUpdateFieldSpecial(fieldDesc, removedSM.persistentObject, false); 3322 updateTrackedFields(fieldDesc, null, null); 3323 fieldDesc.setValue(this, null); 3324 } else { 3325 try { 3326 prepareUpdateFieldSpecial(fieldDesc, null, true); 3327 SCOCollection c = (SCOCollection) fieldDesc.getValue(this); 3328 c.removeInternal(removedSM.persistentObject); 3329 updateTrackedFields(fieldDesc, c, null); 3330 } catch (ClassCastException e) { 3331 } 3333 } 3334 } 3335 3336 3352 private void addCollectionRelationship(ForeignFieldDesc fieldDesc, 3353 ArrayList addedList, 3354 ForeignFieldDesc inverseFieldDesc, 3355 ArrayList newlyRegisteredSMs, 3356 boolean updateInverseRelationshipField, 3357 boolean managedRelationshipInProgress) { 3358 3359 JDOUserException ex = null; 3360 3361 for (int i = 0; i < addedList.size(); i++) { 3362 Object addedObject = addedList.get(i); 3363 SQLStateManager addedSM = getAddedSM(addedObject, newlyRegisteredSMs); 3364 3365 if (addedSM != null) { 3368 3369 if (addedSM.isDeleted()) { 3370 if (inverseFieldDesc != null) { 3374 if (ex == null) { 3375 ex = new JDOUserException(I18NHelper.getMessage(messages, 3376 "jdo.lifecycle.deleted.accessField")); } 3378 3379 ex.addFailedObject(addedObject); 3380 } 3381 continue; 3382 } 3383 3384 if (!managedRelationshipInProgress) { 3388 updateRelationshipInDataStore(fieldDesc, addedSM, null, inverseFieldDesc, false); 3389 3390 if (updateInverseRelationshipField && inverseFieldDesc != null) { 3392 addedSM.addRelationship(inverseFieldDesc, this); 3393 } 3394 } 3395 } 3396 } 3397 3398 if (ex != null) { 3399 throw ex; 3400 } 3401 } 3402 3403 3420 private void setForeignKey(ForeignFieldDesc fieldDesc, 3421 SQLStateManager addedSM, 3422 ForeignFieldDesc inverseFieldDesc) { 3423 3424 if (!isDeleted()) { 3425 if (fieldDesc != null) { 3429 for (int i = 0; i < fieldDesc.localFields.size(); i++) { 3430 LocalFieldDesc la = (LocalFieldDesc) fieldDesc.localFields.get(i); 3431 LocalFieldDesc fa = (LocalFieldDesc) fieldDesc.foreignFields.get(i); 3432 3433 setForeignKey(fieldDesc, la, fa.getValue(addedSM)); 3434 } 3435 } else { 3436 for (int i = 0; i < inverseFieldDesc.foreignFields.size(); i++) { 3437 LocalFieldDesc la = (LocalFieldDesc) inverseFieldDesc.foreignFields.get(i); 3438 LocalFieldDesc fa = (LocalFieldDesc) inverseFieldDesc.localFields.get(i); 3439 3440 setForeignKey(fieldDesc, la, fa.getValue(addedSM)); 3441 } 3442 } 3443 } 3444 3445 registerCreateDependency(inverseFieldDesc, addedSM); 3447 } 3448 3449 3463 private void setForeignKey(ForeignFieldDesc fieldDesc, 3464 LocalFieldDesc la, 3465 Object faValue) { 3466 3467 if (!getSetMaskBit(la.absoluteID)) { 3468 prepareUpdateField(la, null); 3469 } 3470 3471 if (la.isKeyField()) { 3472 assertPKUpdate(la, faValue); 3473 } 3474 3475 updateTrackedFields(la, faValue, fieldDesc); 3476 la.setValue(this, faValue); 3477 } 3478 3479 3495 private void addJoinTableEntry(ForeignFieldDesc fieldDesc, 3496 SQLStateManager addedSM, 3497 ForeignFieldDesc inverseFieldDesc) { 3498 3499 3504 if (fieldDesc != null && getUpdateDesc().removeUpdatedJoinTableRelationship( 3506 fieldDesc, addedSM, ActionDesc.LOG_DESTROY) == false) { 3507 3508 if (inverseFieldDesc == null || addedSM.getUpdateDesc().removeUpdatedJoinTableRelationship( 3510 inverseFieldDesc, this, ActionDesc.LOG_DESTROY) == false) { 3511 3512 getUpdateDesc().recordUpdatedJoinTableRelationship( 3515 fieldDesc, this, addedSM, ActionDesc.LOG_CREATE); 3516 3517 registerCreateDependency(inverseFieldDesc, addedSM); 3519 } 3520 } else if (fieldDesc == null) { 3521 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 3522 "core.statemanager.cantschedulejointable", this.getPersistenceConfig().getPersistenceCapableClass().getName(), 3524 addedSM.getPersistenceConfig().getPersistenceCapableClass().getName())); 3525 } 3526 } 3527 3528 3536 private Object addRelationship(ForeignFieldDesc fieldDesc, 3537 SQLStateManager addedSM) { 3538 3539 Object previousValue = null; 3540 boolean isCollection = (fieldDesc.cardinalityUPB > 1); 3541 3542 if (!isCollection) { 3543 previousValue = prepareSetField(fieldDesc, addedSM.persistentObject, true); 3544 } else { 3545 try { 3546 prepareUpdateFieldSpecial(fieldDesc, null, true); 3547 SCOCollection c = (SCOCollection) fieldDesc.getValue(this); 3548 3549 if (c == null) { 3553 replaceCollection(fieldDesc, null); 3554 c = (SCOCollection) fieldDesc.getValue(this); 3555 } 3556 3557 c.addInternal(addedSM.persistentObject); 3558 updateTrackedFields(fieldDesc, c, null); 3559 } catch (ClassCastException e) { 3560 } 3562 } 3563 3564 return previousValue; 3565 } 3566 3567 3591 private synchronized void prepareUpdateFieldSpecial(FieldDesc fieldDesc, 3592 Object beforeImageValue, 3593 boolean createDeferredCollection) { 3594 if (fieldDesc.isKeyField()) { 3595 throw new JDOUnsupportedOptionException(I18NHelper.getMessage(messages, 3596 "core.statemanager.nopkupdate")); } 3598 3599 getUpdateDesc().markRelationshipChange(fieldDesc); 3600 3601 boolean debug = logger.isLoggable(); 3602 3603 if (debug) { 3604 Object [] items = new Object [] {fieldDesc.getName(),state}; 3605 logger.fine("sqlstore.sqlstatemanager.prepareupdatefieldspl", items); } 3607 3608 boolean optimistic = persistenceManager.isOptimisticTransaction(); 3609 boolean xactActive = persistenceManager.isActiveTransaction(); 3610 boolean nontransactionalRead = persistenceManager.isNontransactionalRead(); 3611 3612 if (state.needsReload(optimistic, nontransactionalRead, xactActive)) { 3613 if (!optimistic) { 3614 persistenceManager.clearFields(this.persistentObject); 3615 } 3616 3617 reload(null); 3618 } 3619 3620 LifeCycleState oldstate = state; 3621 state = state.transitionWriteField(xactActive); 3622 registerInstance(false, null, oldstate); 3623 3624 if (getSetMaskBit(fieldDesc.absoluteID)) { 3625 return; 3627 } 3628 3629 if (!getPresenceMaskBit(fieldDesc.absoluteID)) { 3630 if (!createDeferredCollection) { 3631 if (!(beforeImageValue instanceof SCOCollection) || 3632 !((SCOCollection) beforeImageValue).isDeferred()) { 3633 3634 updateBeforeImage(fieldDesc, beforeImageValue); 3635 3636 setPresenceMaskBit(fieldDesc.absoluteID); 3638 } 3639 } else { 3640 if (!(fieldDesc instanceof ForeignFieldDesc) || 3642 (((ForeignFieldDesc) fieldDesc).cardinalityUPB <= 1)) { 3643 return; 3645 } 3646 3647 Object value = fieldDesc.getValue(this); 3648 3649 if (value == null) { 3650 SCOCollection c = (SCOCollection) persistenceManager.newCollectionInstanceInternal( 3653 fieldDesc.getType(), 3654 persistentObject, 3655 fieldDesc.getName(), 3656 fieldDesc.getComponentType(), 3657 false, 3658 10); 3659 c.markDeferred(); 3660 fieldDesc.setValue(this, c); 3661 } 3662 } 3665 } 3666 3667 recordUpdatedField(fieldDesc); 3668 3669 if (debug) { 3670 logger.fine("sqlstore.sqlstatemanager.prepareupdatefieldspl.exit"); } 3672 } 3673 3674 3696 private void updateTrackedFields(FieldDesc fieldDesc, 3697 Object value, 3698 ForeignFieldDesc fieldToIgnore) { 3699 3700 ArrayList trackedFields = fieldDesc.getTrackedFields(); 3701 3702 if (trackedFields == null) { 3703 return; 3704 } 3705 3706 boolean debug = logger.isLoggable(Logger.FINEST); 3707 3708 if (debug) { 3709 Object [] items = new Object [] {fieldDesc.getName(), value, 3710 ((fieldToIgnore != null) ? fieldToIgnore.getName() : null)}; 3711 logger.finest("sqlstore.sqlstatemanager.updatetrackedfields", items); } 3713 3714 Object currentValue = fieldDesc.getValue(this); 3715 int size = trackedFields.size(); 3716 3717 ArrayList fieldsToIgnore = ((fieldToIgnore != null) ? fieldToIgnore.getTrackedFields() : null); 3718 3719 if (fieldDesc instanceof ForeignFieldDesc) { 3720 for (int i = 0; i < size; i++) { 3722 ForeignFieldDesc tf = (ForeignFieldDesc) trackedFields.get(i); 3723 prepareUpdateFieldSpecial(tf, currentValue, false); 3724 tf.setValue(this, value); 3725 } 3726 } else { 3727 Object previousValues[] = new Object [size]; 3728 LocalFieldDesc primaryTrackedField = null; 3729 Object primaryTrackedFieldValue = null; 3730 3731 if ((fieldDesc.sqlProperties & FieldDesc.PROP_PRIMARY_TRACKED_FIELD) > 0) { 3732 primaryTrackedField = (LocalFieldDesc) fieldDesc; 3733 primaryTrackedFieldValue = value; 3734 } 3735 3736 for (int i = 0; i < size; i++) { 3737 FieldDesc tf = (FieldDesc) trackedFields.get(i); 3738 3739 if (tf instanceof LocalFieldDesc) { 3740 Object convertedValue = null; 3741 Object convertedCurrentValue = null; 3742 3743 try { 3746 convertedValue = tf.convertValue(value, this); 3747 convertedCurrentValue = tf.convertValue(currentValue, this); 3748 } catch (JDOUserException e) { 3749 for (int j = 0; j < i; j++) { 3754 tf = (FieldDesc) trackedFields.get(j); 3755 3756 tf.setValue(this, previousValues[j]); 3757 } 3758 3759 throw e; 3760 } 3761 3762 if ((tf.sqlProperties & FieldDesc.PROP_PRIMARY_TRACKED_FIELD) > 0) { 3763 primaryTrackedField = (LocalFieldDesc) tf; 3764 primaryTrackedFieldValue = convertedValue; 3765 } 3766 3767 prepareUpdateFieldSpecial(tf, convertedCurrentValue, false); 3768 3769 previousValues[i] = tf.getValue(this); 3771 3772 tf.setValue(this, convertedValue); 3773 } else { 3774 if (((stateFlags & ST_FIELD_TRACKING_INPROGRESS) > 0) 3776 || (tf == fieldToIgnore) 3777 || ((fieldsToIgnore != null) && fieldsToIgnore.contains(tf))) { 3778 continue; 3779 } 3780 3781 ForeignFieldDesc ftf = (ForeignFieldDesc) tf; 3782 3783 Object pc = null; 3784 3785 if (primaryTrackedFieldValue != null) { 3786 pc = getObjectById(ftf, primaryTrackedField, primaryTrackedFieldValue, false); 3787 } 3788 3789 stateFlags |= ST_FIELD_TRACKING_INPROGRESS; 3790 prepareSetField(ftf, pc); 3791 stateFlags &= ~ST_FIELD_TRACKING_INPROGRESS; 3792 } 3793 } 3794 } 3795 3796 if (debug) { 3797 logger.finest("sqlstore.sqlstatemanager.updatetrackedfields.exit"); } 3799 } 3800 3801 3818 private Object getObjectById(ForeignFieldDesc ff, 3819 LocalFieldDesc updatedField, 3820 Object value, 3821 boolean forNavigation) { 3822 assert ff.cardinalityUPB <=1; 3823 assert forNavigation ? updatedField == null && value == null : true; 3825 3826 Object rc = null; 3827 Object oid = ff.createObjectId(this, updatedField, value); 3828 3829 if (oid != null) { 3830 rc = persistenceManager.getObjectById(oid); 3831 LifeCycleState rcState = ((SQLStateManager) 3832 ((PersistenceCapable) rc).jdoGetStateManager()).state; 3833 3834 if (forNavigation && (rcState instanceof Hollow)) { 3835 rc = null; 3836 } 3837 } 3838 3839 return rc; 3840 } 3841 3842 3854 private Object doUpdateField(FieldDesc fieldDesc, 3855 Object value, 3856 boolean managedRelationshipInProgress) { 3857 3858 prepareUpdateField(fieldDesc, null); 3859 3860 if (fieldDesc instanceof ForeignFieldDesc) { 3861 ForeignFieldDesc ff = (ForeignFieldDesc) fieldDesc; 3862 if (ff.cardinalityUPB > 1) { 3863 updateCollectionField(ff, (Collection) value, 3864 managedRelationshipInProgress); 3865 } else { 3866 updateObjectField(ff, value, true, 3867 managedRelationshipInProgress); 3868 } 3869 } 3870 3871 updateTrackedFields(fieldDesc, value, null); 3872 3873 Object currentValue = fieldDesc.getValue(this); 3874 fieldDesc.setValue(this, value); 3875 return currentValue; 3876 } 3877 3878 private Object prepareSetField(int fieldID, Object value) { 3879 FieldDesc fieldDesc = persistenceConfig.getField(fieldID); 3880 3881 return prepareSetField(fieldDesc, value, false, true); 3882 } 3883 3884 private Object prepareSetField(FieldDesc fieldDesc, Object value) { 3885 return prepareSetField(fieldDesc, value, false, false); 3886 } 3887 3888 3904 private Object prepareSetField(FieldDesc fieldDesc, Object value, 3905 boolean managedRelationshipInProgress) { 3906 return prepareSetField(fieldDesc, value, managedRelationshipInProgress, false); 3907 } 3908 3909 3920 private Object prepareSetField(FieldDesc fieldDesc, Object value, 3921 boolean managedRelationshipInProgress, 3922 boolean acquireShareLock) { 3923 boolean debug = logger.isLoggable(Logger.FINEST); 3924 3925 if (debug) { 3926 logger.finest("sqlstore.sqlstatemanager.preparesetfield", fieldDesc.getName()); } 3928 3929 if (acquireShareLock) { 3930 persistenceManager.acquireShareLock(); 3931 } 3932 3933 try { 3934 getLock(); 3935 3936 if ((fieldDesc.sqlProperties & FieldDesc.PROP_READ_ONLY) > 0) { 3937 throw new JDOUserException(I18NHelper.getMessage(messages, 3938 "core.statemanager.readonly", fieldDesc.getName(), persistentObject.getClass().getName())); 3940 } 3941 3942 if ((fieldDesc.getTrackedFields() != null) || 3946 (fieldDesc instanceof ForeignFieldDesc)) { 3947 3948 persistenceManager.acquireFieldUpdateLock(); 3949 try { 3950 return doUpdateField(fieldDesc, value, managedRelationshipInProgress); 3951 } finally { 3952 persistenceManager.releaseFieldUpdateLock(); 3953 } 3954 3955 } else { 3956 return doUpdateField(fieldDesc, value, managedRelationshipInProgress); 3957 } 3958 } catch (JDOException e) { 3959 throw e; 3960 } catch (Exception e) { 3961 logger.log(Logger.FINE,"sqlstore.exception.log", e); 3962 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 3963 "core.statemanager.setfieldfailed"), e); } finally { 3965 if (acquireShareLock) { 3966 persistenceManager.releaseShareLock(); 3967 } 3968 releaseLock(); 3969 3970 if (debug) { 3971 logger.finest("sqlstore.sqlstatemanager.preparesetfield.exit"); } 3973 } 3974 } 3975 3976 3985 private void updateCollectionField(ForeignFieldDesc fieldDesc, 3986 Collection value, 3987 boolean managedRelationshipInProgress) { 3988 boolean debug = logger.isLoggable(Logger.FINEST); 3989 3990 if (debug) { 3991 Object [] items = new Object [] {value,((value == null)? "NO" : value.getClass().getName())}; logger.finest("sqlstore.sqlstatemanager.processforeignfield", items); } 3994 3995 Object currVal = fieldDesc.getValue(this); 3996 3997 if (currVal != value) { 3999 Object owner = null; 4000 ArrayList added = null; 4001 ArrayList removed = null; 4002 4003 if (value != null && value instanceof SCOCollection) { 4005 SCOCollection sco = (SCOCollection) value; 4006 owner = sco.getOwner(); 4007 4008 if (owner == null) { 4009 sco.setOwner(persistentObject, fieldDesc.getName(), 4010 fieldDesc.getComponentType()); 4011 4012 } else if (owner != persistentObject || 4013 !fieldDesc.getName().equals(sco.getFieldName())) { 4014 4015 throw new JDOUserException(I18NHelper.getMessage( 4016 messages, "core.statemanager.anotherowner"), new Object []{owner, sco.getFieldName()}); 4018 } 4019 added = new ArrayList(value); 4022 } 4023 4024 Object befrVal = fieldDesc.getValue(beforeImage); 4025 if (currVal != null) { 4026 if (debug) 4027 logger.finest("sqlstore.sqlstatemanager.processforeignfield.remove"); 4029 4032 if (((Collection) currVal).size() > 0) { 4033 removed = new ArrayList((Collection) currVal); 4034 } 4035 4036 if (currVal instanceof SCOCollection) { 4037 if (debug) 4038 logger.finest("sqlstore.sqlstatemanager.processforeignfield.reset"); ((SCO) currVal).unsetOwner(); 4041 } 4042 } else if (getSetMaskBit(fieldDesc.absoluteID) == false && befrVal != null) 4043 { 4045 if (debug) 4046 logger.finest("sqlstore.sqlstatemanager.processforeignfield.remove_from_bi"); 4049 if (((Collection) befrVal).size() > 0) { 4050 removed = new ArrayList((Collection) befrVal); 4051 } 4052 } 4053 4054 processCollectionUpdates(fieldDesc, removed, added, null, true, 4055 managedRelationshipInProgress); 4056 } 4057 } 4058 4059 public Object clone() { 4060 SQLStateManager clone = new SQLStateManager(store, persistenceConfig); 4061 clone.persistenceManager = persistenceManager; 4062 4063 return clone; 4064 } 4065 4066 private void assertNotPK(int fieldNumber) { 4067 if (persistenceConfig.isPKField(fieldNumber)) 4068 throw new JDOUnsupportedOptionException(I18NHelper.getMessage(messages, 4069 "core.statemanager.nopkupdate")); } 4071 4072 private void assertPKUpdate(FieldDesc f, Object value) { 4073 Object currentValue = f.getValue(this); 4074 boolean throwException = false; 4075 4076 if ((value != null) && (currentValue != null)) { 4079 if (value.toString().compareTo(currentValue.toString()) != 0) { 4080 throwException = true; 4081 } 4082 } else if (value != currentValue) { 4083 throwException = true; 4084 } 4085 4086 if (throwException) { 4087 throw new JDOUnsupportedOptionException(I18NHelper.getMessage(messages, 4088 "core.statemanager.nopkupdate")); } 4090 } 4091 4092 4095 public com.sun.jdo.api.persistence.support.PersistenceManager getPersistenceManagerInternal() { 4096 return persistenceManager; 4097 } 4098 4099 4102 public com.sun.jdo.api.persistence.support.PersistenceManager getPersistenceManager() { 4103 return (persistenceManager == null)? null : persistenceManager.getCurrentWrapper(); 4104 } 4105 4106 4107 4110 public byte setFlags(byte flags) { 4112 return flags; 4115 } 4116 4117 4121 public void loadForRead() { 4122 boolean debug = logger.isLoggable(Logger.FINER); 4123 4124 if (debug) { 4125 logger.finer("sqlstore.sqlstatemanager.loadforread"); } 4127 4128 persistenceManager.acquireShareLock(); 4129 4130 try { 4131 getLock(); 4132 4133 byte oldFlags = persistenceManager.getFlags(persistentObject); 4134 4135 if (oldFlags != LOAD_REQUIRED) { 4138 return; 4139 } 4140 4141 try { 4142 boolean xactActive = persistenceManager.isActiveTransaction(); 4143 boolean optimistic = persistenceManager.isOptimisticTransaction(); 4144 boolean nontransactionalRead = persistenceManager.isNontransactionalRead(); 4145 4146 if (state.needsReload(optimistic, nontransactionalRead, xactActive)) { 4147 reload(null); 4148 } 4149 4150 LifeCycleState oldstate = state; 4151 state = state.transitionReadField(optimistic, nontransactionalRead, xactActive); 4152 persistenceManager.setFlags(persistentObject, READ_OK); 4153 registerInstance(false, null, oldstate); 4154 } catch (JDOException e) { 4155 persistenceManager.setFlags(persistentObject, oldFlags); 4157 throw e; 4158 } 4159 } finally { 4160 persistenceManager.releaseShareLock(); 4161 releaseLock(); 4162 4163 if (debug) { 4164 logger.finer("sqlstore.sqlstatemanager.loadforread.exit"); } 4166 } 4167 } 4168 4169 4173 public void loadForUpdate() { 4174 boolean debug = logger.isLoggable(Logger.FINER); 4175 4176 if (debug) { 4177 logger.finer("sqlstore.sqlstatemanager.loadforupdate"); } 4179 4180 persistenceManager.acquireShareLock(); 4181 4182 try { 4183 getLock(); 4184 4185 byte oldFlags = persistenceManager.getFlags(persistentObject); 4186 4187 if (oldFlags == READ_WRITE_OK) { 4190 return; 4191 } 4192 4193 persistenceManager.setFlags(persistentObject, READ_WRITE_OK); 4194 4195 ArrayList fields = persistenceConfig.fields; 4196 4197 try { 4198 for (int i = 0; i < fields.size(); i++) { 4200 FieldDesc f = (FieldDesc) fields.get(i); 4201 4202 if (f.fetchGroup == FieldDesc.GROUP_DEFAULT) { 4203 prepareUpdateField(f, null); 4205 } 4206 } 4207 } catch (JDOException e) { 4208 persistenceManager.setFlags(persistentObject, oldFlags); 4210 throw e; 4211 } 4212 } finally { 4213 persistenceManager.releaseShareLock(); 4214 releaseLock(); 4215 4216 if (debug) { 4217 logger.finer("sqlstore.sqlstatemanager.loadforupdate.exit"); } 4219 } 4220 } 4221 4222 4230 public synchronized void replaceCollection(ForeignFieldDesc ff, Collection c) { 4231 Collection collection = (Collection) ff.getValue(this); 4232 4233 SCOCollection scoCollection = null; 4234 4235 if ((collection == null) || !(collection instanceof SCO)) { 4236 scoCollection = (SCOCollection) persistenceManager.newCollectionInstanceInternal( 4237 ff.getType(), persistentObject, ff.getName(), 4238 ff.getComponentType(), false, ((c != null) ? c.size() : 0)); 4239 4240 ff.setValue(this, scoCollection); 4241 scoCollection.addAllInternal(c); 4242 } else { 4243 scoCollection = (SCOCollection) collection; 4244 4245 if (scoCollection.isDeferred()) { 4246 scoCollection.applyDeferredUpdates(c); 4247 4248 ArrayList trackedFields = ff.getTrackedFields(); 4250 if (trackedFields != null) { 4251 for (int i = 0; i < trackedFields.size(); i++) { 4252 ForeignFieldDesc tf = (ForeignFieldDesc) trackedFields.get(i); 4253 4254 setPresenceMaskBit(tf.absoluteID); 4255 } 4256 } 4257 } else { 4258 scoCollection.clearInternal(); 4259 scoCollection.addAllInternal(c); 4260 } 4261 } 4262 4263 if (c != null && c instanceof SCO) { 4265 ((SCO) c).unsetOwner(); 4266 } 4267 } 4268 4269 4272 protected LifeCycleState getCurrentState() { 4273 return state; 4274 } 4275 4276 4285 4288 public boolean isDirty() { 4289 if (state != null) { 4290 return state.isDirty(); 4291 } 4292 4293 return false; 4294 } 4295 4296 4299 public boolean isTransactional() { 4300 if (state != null) { 4301 return state.isTransactional(); 4302 } 4303 4304 return false; 4305 } 4306 4307 4310 public boolean isNew() { 4311 if (state != null) { 4312 return state.isNew(); 4313 } 4314 4315 return false; 4316 } 4317 4318 4321 public boolean isDeleted() { 4322 if (state != null) { 4323 return state.isDeleted(); 4324 } 4325 4326 return false; 4327 } 4328 4329 4332 public boolean isPersistent() { 4333 if (state != null) { 4334 return state.isPersistent(); 4335 } 4336 4337 return false; 4338 } 4339 4340 4343 public boolean needsRegisterWithVersionConsistencyCache() { 4344 boolean rc = hasVersionConsistency(); 4345 if (rc && state != null) { 4346 rc = state.isPersistent() 4347 && state.isTransactional() 4348 && !state.isNew() 4349 && !state.isDirty() 4350 && !state.isDeleted(); 4351 } 4352 4353 return rc; 4354 } 4355 4356 4359 public boolean needsUpdateInVersionConsistencyCache() { 4360 boolean rc = hasVersionConsistency(); 4361 if (rc && state != null) { 4362 rc = (state.isDirty() 4363 || state.isNew() 4364 || persistenceConfig.hasLocalNonDFGFields()) 4365 && !state.isDeleted(); 4366 } 4367 4368 return rc; 4369 } 4370 4371 4377 public boolean setBooleanField(int fieldNumber, boolean value) { 4378 assertNotPK(fieldNumber); 4379 prepareSetField(fieldNumber, new Boolean (value)); 4380 return value; 4381 } 4382 4383 public boolean[] setBooleanArrayField(int fieldNumber, boolean[] value) { 4384 prepareSetField(fieldNumber, null); 4385 return value; 4386 } 4387 4388 public byte setByteField(int fieldNumber, byte value) { 4389 assertNotPK(fieldNumber); 4390 prepareSetField(fieldNumber, new Byte (value)); 4391 return value; 4392 } 4393 4394 public byte[] setByteArrayField(int fieldNumber, byte[] value) { 4395 prepareSetField(fieldNumber, null); 4396 return value; 4397 } 4398 4399 public short setShortField(int fieldNumber, short value) { 4400 assertNotPK(fieldNumber); 4401 prepareSetField(fieldNumber, new Short (value)); 4402 return value; 4403 } 4404 4405 public short[] setShortArrayField(int fieldNumber, short[] value) { 4406 prepareSetField(fieldNumber, null); 4407 return value; 4408 } 4409 4410 public int setIntField(int fieldNumber, int value) { 4411 assertNotPK(fieldNumber); 4412 prepareSetField(fieldNumber, new Integer (value)); 4413 return value; 4414 } 4415 4416 public int[] setIntArrayField(int fieldNumber, int[] value) { 4417 prepareSetField(fieldNumber, null); 4418 return value; 4419 } 4420 4421 public long setLongField(int fieldNumber, long value) { 4422 assertNotPK(fieldNumber); 4423 prepareSetField(fieldNumber, new Long (value)); 4424 return value; 4425 } 4426 4427 public long[] setLongArrayField(int fieldNumber, long[] value) { 4428 prepareSetField(fieldNumber, null); 4429 return value; 4430 } 4431 4432 public char setCharField(int fieldNumber, char value) { 4433 assertNotPK(fieldNumber); 4434 prepareSetField(fieldNumber, null); 4435 return value; 4436 } 4437 4438 public char setCharArrayField(int fieldNumber, char value) { 4439 prepareSetField(fieldNumber, null); 4440 return value; 4441 } 4442 4443 public float setFloatField(int fieldNumber, float value) { 4444 assertNotPK(fieldNumber); 4445 prepareSetField(fieldNumber, new Float (value)); 4446 return value; 4447 } 4448 4449 public float[] setFloatArrayField(int fieldNumber, float[] value) { 4450 prepareSetField(fieldNumber, null); 4451 return value; 4452 } 4453 4454 public double setDoubleField(int fieldNumber, double value) { 4455 assertNotPK(fieldNumber); 4456 prepareSetField(fieldNumber, new Double (value)); 4457 return value; 4458 } 4459 4460 public double[] setDoubleArrayField(int fieldNumber, double[] value) { 4461 prepareSetField(fieldNumber, null); 4462 return value; 4463 } 4464 4465 public String setStringField(int fieldNumber, String value) { 4466 assertNotPK(fieldNumber); 4467 prepareSetField(fieldNumber, value); 4468 return value; 4469 } 4470 4471 public String [] setStringArrayField(int fieldNumber, String [] value) { 4472 prepareSetField(fieldNumber, null); 4473 return value; 4474 } 4475 4476 4479 public Object setObjectField(int fieldNumber, Object value) { 4480 assertNotPK(fieldNumber); 4481 prepareSetField(fieldNumber, value); 4482 return value; 4483 } 4484 4485 public Object [] setObjectArrayField(int fieldNumber, Object [] value) { 4486 prepareSetField(fieldNumber, value); 4487 return value; 4488 } 4489 4490 4491 public boolean testIsLoaded(int fieldNumber) { 4492 return getPresenceMaskBit(fieldNumber); 4493 } 4494 4495 public boolean testIsLoaded(String fieldName) { 4496 FieldDesc f = persistenceConfig.getField(fieldName); 4497 4498 return testIsLoaded(f.absoluteID); 4499 } 4500 4501 public boolean testIsAutoPersistent() { 4502 return state.isAutoPersistent(); 4503 } 4504 4505 4511 public void markNotRegistered() { 4512 needsRegisterAtRollback = true; 4513 } 4514 4515 4519 public void markVerifyAtDeregister() { 4520 needsVerifyAtDeregister = true; 4521 } 4522 4523 4527 public void markReplacement() { 4528 isReplacementInstance = true; 4529 } 4530 4531 4534 public void getLock() { 4536 lock.acquire(); 4537 } 4538 4539 4542 public void releaseLock() { 4543 lock.release(); 4544 } 4545 4546 4547 4550 public boolean isValid() { 4551 return valid; 4552 } 4553 4554 4558 public void setValid() { 4559 try { 4560 getLock(); 4561 valid = true; 4562 } finally { 4563 releaseLock(); 4564 } 4565 } 4566 4567 4573 private class UpdatedForeignReference { 4574 ForeignFieldDesc fieldDesc; 4575 SQLStateManager sm; 4576 4577 private UpdatedForeignReference(ForeignFieldDesc fieldDesc, SQLStateManager sm) { 4578 this.fieldDesc = fieldDesc; 4579 this.sm = sm; 4580 } 4581 4582 private ForeignFieldDesc getFieldDesc() { 4583 return fieldDesc; 4584 } 4585 4586 private SQLStateManager getStateManager() { 4587 return sm; 4588 } 4589 4590 public boolean equals(Object obj) { 4591 if (obj != null && 4592 this.getClass().equals(obj.getClass())) { 4593 final UpdatedForeignReference other = (UpdatedForeignReference) obj; 4594 4595 return (this.fieldDesc == other.fieldDesc && this.sm == other.sm); 4596 } 4597 return (false); 4598 } 4599 4600 public int hashCode() { 4601 int hashCode = sm.hashCode(); 4602 if (fieldDesc != null) { 4603 hashCode += fieldDesc.hashCode(); 4604 } 4605 return hashCode; 4606 } 4607 } 4608} 4609 | Popular Tags |