1 10 11 package com.triactive.jdo.state; 12 13 import com.triactive.jdo.AbstractFieldManager; 14 import com.triactive.jdo.FieldManager; 15 import com.triactive.jdo.GenericFieldManager; 16 import com.triactive.jdo.PersistenceManager; 17 import com.triactive.jdo.SCO; 18 import com.triactive.jdo.model.ClassMetaData; 19 import com.triactive.jdo.model.FieldMetaData; 20 import com.triactive.jdo.sco.SCOProcessor; 21 import com.triactive.jdo.store.StoreManager; 22 import java.io.PrintWriter ; 23 import java.lang.reflect.Method ; 24 import java.util.Arrays ; 25 import java.util.Collection ; 26 import java.util.Map ; 27 import javax.jdo.InstanceCallbacks; 28 import javax.jdo.JDOFatalInternalException; 29 import javax.jdo.JDOFatalUserException; 30 import javax.jdo.JDOUnsupportedOptionException; 31 import javax.jdo.JDOUserException; 32 import javax.jdo.Transaction; 33 import javax.jdo.spi.JDOImplHelper; 34 import javax.jdo.spi.PersistenceCapable; 35 import javax.jdo.spi.StateManager; 36 import org.apache.log4j.Category; 37 38 39 45 46 public class StateManagerImpl implements com.triactive.jdo.StateManager 47 { 48 private static final Category LOG = Category.getInstance(StateManagerImpl.class); 49 private static final JDOImplHelper helper; 50 private static final StateFieldManager hollowFieldManager = new StateFieldManager(); 51 52 private PersistenceManager myPM; 53 private PersistenceCapable myPC; 54 private Transaction myTX; 55 private Object myID; 56 private LifeCycleState myLC; 57 private byte jdoFlags; 58 private PersistenceCapable savedImage = null; 59 private byte savedFlags; 60 private boolean[] savedLoadedFields = null; 61 62 private ClassMetaData cmd; 63 private StoreManager srm; 64 private int fieldCount; 65 66 private boolean inserting = false; 67 private boolean dirty = false; 68 private boolean deleting = false; 69 private boolean flushing = false; 70 private boolean changingState = false; 71 private boolean postLoadPending = false; 72 private boolean disconnecting = false; 73 private boolean[] dirtyFields; 74 private boolean[] loadedFields; 75 private boolean[] defaultFetchGroupFields; 76 private boolean[] secondClassMutableFields; 77 private int[] allFieldNumbers; 78 private int[] persistentFieldNumbers; 79 private int[] defaultFetchGroupFieldNumbers; 80 private int[] secondClassMutableFieldNumbers; 81 82 private FieldManager currFM = null; 83 84 static 85 { 86 try 87 { 88 helper = JDOImplHelper.getInstance(); 89 } 90 catch (SecurityException e) 91 { 92 throw new JDOFatalUserException("Insufficient access granted to com.triactive.jdo.*", e); 93 } 94 } 95 96 97 108 109 public StateManagerImpl(PersistenceManager pm, PersistenceCapable pc) 110 { 111 myPM = pm; 112 myTX = pm.currentTransaction(); 113 srm = myPM.getStoreManager(); 114 myPC = pc; 115 myID = null; 116 myLC = LifeCycleState.getLifeCycleState(LifeCycleState.T_CLEAN); 117 jdoFlags = PersistenceCapable.READ_OK; 118 cmd = ClassMetaData.forClass(pc.getClass()); 119 120 initialize(); 121 122 for (int i = 0; i < fieldCount; ++i) 123 loadedFields[i] = true; 124 125 myPC.jdoReplaceStateManager(this); 126 myPC.jdoReplaceFlags(); 127 128 replaceSCOFields(); 129 } 130 131 132 145 146 public StateManagerImpl(PersistenceManager pm, Class pcClass, Object id) 147 { 148 myPM = pm; 149 myTX = pm.currentTransaction(); 150 srm = myPM.getStoreManager(); 151 myID = id; 152 myLC = LifeCycleState.getLifeCycleState(LifeCycleState.HOLLOW); 153 jdoFlags = PersistenceCapable.LOAD_REQUIRED; 154 cmd = ClassMetaData.forClass(pcClass); 155 156 initialize(); 157 158 myPC = helper.newInstance(pcClass, this); 159 } 160 161 162 private void initialize() 163 { 164 fieldCount = cmd.getInheritedFieldCount() + cmd.getFieldCount(); 165 166 dirtyFields = new boolean[fieldCount]; 167 loadedFields = (boolean[])cmd.getTransactionalFieldFlags().clone(); 168 defaultFetchGroupFields = cmd.getDefaultFetchGroupFieldFlags(); 169 secondClassMutableFields = cmd.getSecondClassMutableFieldFlags(); 170 171 allFieldNumbers = cmd.getAllFieldNumbers(); 172 persistentFieldNumbers = cmd.getPersistentFieldNumbers(); 173 defaultFetchGroupFieldNumbers = cmd.getDefaultFetchGroupFieldNumbers(); 174 secondClassMutableFieldNumbers = cmd.getSecondClassMutableFieldNumbers(); 175 } 176 177 178 182 void replaceSCOFields() 183 { 184 StateFieldManager scoFieldValues = new StateFieldManager(); 185 186 provideFields(secondClassMutableFieldNumbers, scoFieldValues); 187 replaceFields(secondClassMutableFieldNumbers, scoFieldValues); 188 } 189 190 191 Object wrapSCOInstance(int field, Object value) 192 { 193 if (value == null || (value instanceof SCO && ((SCO)value).getOwner() == myPC)) 194 return value; 195 else 196 { 197 FieldMetaData fmd = cmd.getFieldAbsolute(field); 198 Class fieldType = fmd.getType(); 199 200 SCOProcessor scoProc = SCOProcessor.forFieldType(fieldType); 201 202 if (scoProc == null) 203 throw new JDOUserException("Class not supported as a second-class object: " + fieldType.getName()); 204 205 return scoProc.newSCOInstance(myPC, fmd.getName(), value); 206 } 207 } 208 209 210 213 private void disownSCOFields() 214 { 215 provideFields(secondClassMutableFieldNumbers, new AbstractFieldManager() 216 { 217 public void storeObjectField(int fieldNumber, Object value) 218 { 219 if (value instanceof SCO) 220 ((SCO)value).unsetOwner(); 221 } 222 }); 223 } 224 225 226 private boolean isDFGLoaded() 227 { 228 for (int i = 0; i < defaultFetchGroupFieldNumbers.length; ++i) 229 { 230 if (!loadedFields[defaultFetchGroupFieldNumbers[i]]) 231 return false; 232 } 233 234 return true; 235 } 236 237 238 void enlistInTransaction() 239 { 240 myPM.enlistInTransaction(this); 241 242 if (jdoFlags == PersistenceCapable.LOAD_REQUIRED && isDFGLoaded()) 243 { 244 248 jdoFlags = PersistenceCapable.READ_OK; 249 myPC.jdoReplaceFlags(); 250 } 251 } 252 253 254 void evictFromTransaction() 255 { 256 myPM.evictFromTransaction(this); 257 258 if (jdoFlags == PersistenceCapable.READ_OK && myLC.isPersistent()) 259 { 260 264 jdoFlags = PersistenceCapable.LOAD_REQUIRED; 265 myPC.jdoReplaceFlags(); 266 } 267 } 268 269 270 void saveFields() 271 { 272 savedFlags = jdoFlags; 273 savedLoadedFields = (boolean[])loadedFields.clone(); 274 savedImage = myPC.jdoNewInstance(this); 275 savedImage.jdoCopyFields(myPC, allFieldNumbers); 276 277 for (int i = 0; i < secondClassMutableFieldNumbers.length; ++i) 278 { 279 int field = secondClassMutableFieldNumbers[i]; 280 281 287 Object value = provideField(savedImage, field); 288 289 if (value != null) 290 { 291 if (value instanceof SCO) 292 value = ((SCO)value).clone(); 293 else 294 { 295 Class c = value.getClass(); 296 297 try 298 { 299 Method m = c.getMethod("clone", null); 300 301 if (m != null) 302 value = m.invoke(value, null); 303 } 304 catch (Exception e) 305 { 306 throw new JDOFatalInternalException("SCO class not cloneable: " + c.getName()); 307 } 308 } 309 310 replaceField(savedImage, field, value); 311 } 312 } 313 } 314 315 316 void restoreFields() 317 { 318 if (savedImage != null) 319 { 320 loadedFields = savedLoadedFields; 321 jdoFlags = savedFlags; 322 myPC.jdoReplaceFlags(); 323 myPC.jdoCopyFields(savedImage, allFieldNumbers); 324 325 clearDirtyFlags(); 326 discardSavedFields(); 327 } 328 } 329 330 331 void discardSavedFields() 332 { 333 savedFlags = 0; 334 savedLoadedFields = null; 335 savedImage = null; 336 } 337 338 339 void clearPersistentFields() 340 { 341 try 342 { 343 if (myPC instanceof InstanceCallbacks) 344 ((InstanceCallbacks)myPC).jdoPreClear(); 345 } 346 finally 347 { 348 replaceFieldsInternal(persistentFieldNumbers, hollowFieldManager); 349 clearLoadedFlags(); 350 clearDirtyFlags(); 351 } 352 } 353 354 355 private void clearLoadedFlags() 356 { 357 jdoFlags = PersistenceCapable.LOAD_REQUIRED; 358 myPC.jdoReplaceFlags(); 359 System.arraycopy(cmd.getTransactionalFieldFlags(), 0, loadedFields, 0, loadedFields.length); 360 } 361 362 363 private void clearDirtyFlags() 364 { 365 dirty = false; 366 clearFlags(dirtyFields); 367 } 368 369 370 374 375 private static int[] getFlagsSetTo(boolean[] flags, boolean state) 376 { 377 int[] temp = new int[flags.length]; 378 int j = 0; 379 380 for (int i = 0; i < flags.length; i++) 381 { 382 if (flags[i] == state) 383 temp[j++] = i; 384 } 385 386 if (j != 0) 387 { 388 int[] fieldNumbers = new int[j]; 389 System.arraycopy(temp, 0, fieldNumbers, 0, j); 390 391 return fieldNumbers; 392 } 393 else 394 return null; 395 } 396 397 398 403 404 private static int[] getFlagsSetTo(boolean[] flags, int[] indices, boolean state) 405 { 406 int[] temp = new int[indices.length]; 407 int j = 0; 408 409 for (int i = 0; i < indices.length; i++) 410 { 411 if (flags[indices[i]] == state) 412 temp[j++] = indices[i]; 413 } 414 415 if (j != 0) 416 { 417 int[] fieldNumbers = new int[j]; 418 System.arraycopy(temp, 0, fieldNumbers, 0, j); 419 420 return fieldNumbers; 421 } 422 else 423 return null; 424 } 425 426 427 private static void clearFlags(boolean[] flags) 428 { 429 for (int i = 0; i < flags.length; i++) 430 flags[i] = false; 431 } 432 433 434 private boolean disconnectClone(PersistenceCapable pc) 435 { 436 if (pc != myPC) 437 { 438 if (LOG.isDebugEnabled()) 439 LOG.debug("Disconnecting clone " + toJVMIDString(pc) + " from " + this); 440 441 445 byte myJdoFlags = jdoFlags; 446 jdoFlags = PersistenceCapable.READ_WRITE_OK; 447 448 try 449 { 450 pc.jdoReplaceFlags(); 451 } 452 finally 453 { 454 jdoFlags = myJdoFlags; 455 } 456 457 pc.jdoReplaceStateManager(null); 458 return true; 459 } 460 else 461 return false; 462 } 463 464 465 474 475 public byte replacingFlags(PersistenceCapable pc) 476 { 477 if (pc != myPC) 479 return PersistenceCapable.READ_WRITE_OK; 480 else 481 return jdoFlags; 482 } 483 484 485 493 494 public javax.jdo.PersistenceManager getPersistenceManager(PersistenceCapable pc) 495 { 496 if (disconnectClone(pc)) 497 return null; 498 else 499 { 500 this.myPM.hereIsStateManager(this, myPC); 501 return myPM; 502 } 503 } 504 505 506 private void postWriteField(int field) 507 { 508 514 if (myLC.isPersistent() && !inserting) 515 { 516 dirty = true; 517 dirtyFields[field] = true; 518 loadedFields[field] = true; 519 520 524 if (!flushing) 525 { 526 if (myTX.isActive()) 527 myPM.markDirty(this); 528 else 529 flush(); 530 } 531 } 532 } 533 534 535 538 539 public void makeDirty(int field) 540 { 541 transitionWriteField(); 542 postWriteField(field); 543 } 544 545 546 552 553 public void makeDirty(PersistenceCapable pc, String fieldName) 554 { 555 if (!disconnectClone(pc)) 556 { 557 int fieldNumber = cmd.getAbsoluteFieldNumber(fieldName); 558 559 if (fieldNumber == -1) 560 throw new JDOUserException("No such field '" + fieldName + "' in class " + cmd.getPCClass().getName()); 561 562 makeDirty(fieldNumber); 563 } 564 } 565 566 567 public Object getObjectId() 568 { 569 return myID; 570 } 571 572 573 public StoreManager getStoreManager() 574 { 575 return srm; 576 } 577 578 579 public PersistenceManager getPersistenceManager() 580 { 581 return myPM; 582 } 583 584 585 595 596 public Object getObjectId(PersistenceCapable pc) 597 { 598 if (disconnectClone(pc)) 599 return null; 600 else 601 return myID; 602 } 603 604 605 618 619 public StateManager replacingStateManager(PersistenceCapable pc, StateManager sm) 620 { 621 if (myLC == null) 622 throw new JDOFatalInternalException("Null LifeCycleState"); 623 624 if (pc == myPC) 625 { 626 if (sm != null) 627 throw new JDOFatalInternalException("Attempted to replace with a different state manager"); 628 if (!disconnecting) 629 throw new JDOFatalInternalException("Attempted to clear state manager from other than disconnect()"); 630 631 if (LOG.isDebugEnabled()) 632 LOG.debug("Clearing state manager for " + toJVMIDString(pc)); 633 634 return null; 635 } 636 else if (pc == savedImage) 637 return null; 638 else 639 return sm; 640 } 641 642 643 652 653 public Object getTransactionalObjectId(PersistenceCapable pc) 654 { 655 return getObjectId(pc); 656 } 657 658 659 673 674 public boolean isDirty(PersistenceCapable pc) 675 { 676 if (disconnectClone(pc)) 677 return false; 678 else 679 return myLC.isDirty(); 680 } 681 682 683 697 698 public boolean isTransactional(PersistenceCapable pc) 699 { 700 if (disconnectClone(pc)) 701 return false; 702 else 703 return myLC.isTransactional(); 704 } 705 706 707 718 719 public boolean isPersistent(PersistenceCapable pc) 720 { 721 if (disconnectClone(pc)) 722 return false; 723 else 724 return myLC.isPersistent(); 725 } 726 727 728 741 742 public boolean isNew(PersistenceCapable pc) 743 { 744 if (disconnectClone(pc)) 745 return false; 746 else 747 return myLC.isNew(); 748 } 749 750 751 763 764 public boolean isDeleted(PersistenceCapable pc) 765 { 766 if (disconnectClone(pc)) 767 return false; 768 else 769 return myLC.isDeleted(); 770 } 771 772 773 799 800 private void postLoad() 801 { 802 if (changingState) 803 postLoadPending = true; 804 else 805 { 806 815 if (jdoFlags == PersistenceCapable.LOAD_REQUIRED && myLC.isTransactional()) 816 { 817 jdoFlags = PersistenceCapable.READ_OK; 818 myPC.jdoReplaceFlags(); 819 } 820 821 if (myPC instanceof InstanceCallbacks) 822 ((InstanceCallbacks)myPC).jdoPostLoad(); 823 } 824 } 825 826 827 831 832 public void validate() 833 { 834 if (!myLC.isTransactional()) 835 { 836 842 if (myTX.isActive() && defaultFetchGroupFieldNumbers.length != 0) 843 retrieve(true); 844 else 845 srm.lookup(this); 846 } 847 } 848 849 850 857 858 public void offerPrefetchedFields(int[] fieldNumbers, FieldManager fieldManager) 859 { 860 if (!myLC.isTransactional()) 861 { 862 863 transitionReadField(); 864 865 boolean dfgWasAlreadyLoaded = isDFGLoaded(); 866 867 replaceFields(fieldNumbers, fieldManager); 868 869 if (!dfgWasAlreadyLoaded && isDFGLoaded()) 870 postLoad(); 871 } 872 } 873 874 875 880 881 void loadDFGFields() 882 { 883 int[] fieldNumbers = getFlagsSetTo(loadedFields, defaultFetchGroupFieldNumbers, false); 884 885 if (fieldNumbers != null) 886 { 887 srm.fetch(this, fieldNumbers); 888 postLoad(); 889 } 890 } 891 892 893 899 900 private void loadNonDFGField(int fieldNumber) 901 { 902 srm.fetch(this, new int[] { fieldNumber }); 903 } 904 905 906 910 911 void loadUnloadedFields() 912 { 913 int[] fieldNumbers = getFlagsSetTo(loadedFields, false); 914 915 if (fieldNumbers != null) 916 { 917 boolean dfgWasAlreadyLoaded = isDFGLoaded(); 918 919 srm.fetch(this, fieldNumbers); 920 921 922 if (!dfgWasAlreadyLoaded) 923 postLoad(); 924 } 925 } 926 927 928 932 933 void refreshLoadedFields() 934 { 935 int[] fieldNumbers = getFlagsSetTo(loadedFields, true); 936 937 if (fieldNumbers != null) 938 { 939 clearDirtyFlags(); 940 clearLoadedFlags(); 941 942 srm.fetch(this, fieldNumbers); 943 944 if (isDFGLoaded()) 945 postLoad(); 946 } 947 } 948 949 950 957 958 public void preSerialize(PersistenceCapable pc) 959 { 960 if (disconnectClone(pc)) 961 return; 962 963 retrieve(false); 964 } 965 966 967 978 979 public boolean isLoaded(PersistenceCapable pc, int field) 980 { 981 if (disconnectClone(pc)) 982 return true; 983 else 984 { 985 transitionReadField(); 986 987 if (!loadedFields[field]) 988 { 989 if (defaultFetchGroupFields[field]) 990 loadDFGFields(); 991 else 992 loadNonDFGField(field); 993 } 994 995 return true; 996 } 997 } 998 999 1000 1011 1012 public Object getField(int field) 1013 { 1014 isLoaded(myPC, field); 1015 return provideField(myPC, field); 1016 } 1017 1018 1019 1034 1035 public void setField(int field, Object currentValue, Object newValue) 1036 { 1037 if (!loadedFields[field] || currentValue != newValue) 1038 writeObjectField(field, currentValue, newValue); 1039 } 1040 1041 1042 1049 1050 public boolean getBooleanField(PersistenceCapable pc, int field, boolean currentValue) 1051 { 1052 throw new JDOUnsupportedOptionException("Method not supported"); 1053 } 1054 1055 1056 1063 1064 public byte getByteField(PersistenceCapable pc, int field, byte currentValue) 1065 { 1066 throw new JDOUnsupportedOptionException("Method not supported"); 1067 } 1068 1069 1070 1077 1078 public char getCharField(PersistenceCapable pc, int field, char currentValue) 1079 { 1080 throw new JDOUnsupportedOptionException("Method not supported"); 1081 } 1082 1083 1084 1091 1092 public double getDoubleField(PersistenceCapable pc, int field, double currentValue) 1093 { 1094 throw new JDOUnsupportedOptionException("Method not supported"); 1095 } 1096 1097 1098 1105 1106 public float getFloatField(PersistenceCapable pc, int field, float currentValue) 1107 { 1108 throw new JDOUnsupportedOptionException("Method not supported"); 1109 } 1110 1111 1112 1119 1120 public int getIntField(PersistenceCapable pc, int field, int currentValue) 1121 { 1122 throw new JDOUnsupportedOptionException("Method not supported"); 1123 } 1124 1125 1126 1133 1134 public long getLongField(PersistenceCapable pc, int field, long currentValue) 1135 { 1136 throw new JDOUnsupportedOptionException("Method not supported"); 1137 } 1138 1139 1140 1147 1148 public short getShortField(PersistenceCapable pc, int field, short currentValue) 1149 { 1150 throw new JDOUnsupportedOptionException("Method not supported"); 1151 } 1152 1153 1154 1161 1162 public String getStringField(PersistenceCapable pc, int field, String currentValue) 1163 { 1164 throw new JDOUnsupportedOptionException("Method not supported"); 1165 } 1166 1167 1168 1175 1176 public Object getObjectField(PersistenceCapable pc, int field, Object currentValue) 1177 { 1178 throw new JDOUnsupportedOptionException("Method not supported"); 1179 } 1180 1181 1182 1188 1189 private void writeField(int field, Object newValue) 1190 { 1191 transitionWriteField(); 1192 replaceField(myPC, field, newValue); 1193 postWriteField(field); 1194 } 1195 1196 1197 1204 1205 private void writeObjectField(int field, Object currentValue, Object newValue) 1206 { 1207 transitionWriteField(); 1208 1209 if (secondClassMutableFields[field]) 1210 { 1211 if (currentValue instanceof SCO) 1212 ((SCO)currentValue).unsetOwner(); 1213 1214 newValue = wrapSCOInstance(field, newValue); 1215 } 1216 1217 replaceField(myPC, field, newValue); 1218 postWriteField(field); 1219 } 1220 1221 1222 1231 1232 public void setBooleanField(PersistenceCapable pc, int field, boolean currentValue, boolean newValue) 1233 { 1234 if (pc != myPC) 1235 { 1236 replaceField(pc, field, newValue ? Boolean.TRUE : Boolean.FALSE); 1237 disconnectClone(pc); 1238 } 1239 else 1240 { 1241 if (!loadedFields[field] || currentValue != newValue) 1242 writeField(field, newValue ? Boolean.TRUE : Boolean.FALSE); 1243 } 1244 } 1245 1246 1247 1256 1257 public void setByteField(PersistenceCapable pc, int field, byte currentValue, byte newValue) 1258 { 1259 if (pc != myPC) 1260 { 1261 replaceField(pc, field, new Byte (newValue)); 1262 disconnectClone(pc); 1263 } 1264 else 1265 { 1266 if (!loadedFields[field] || currentValue != newValue) 1267 writeField(field, new Byte (newValue)); 1268 } 1269 } 1270 1271 1272 1281 1282 public void setCharField(PersistenceCapable pc, int field, char currentValue, char newValue) 1283 { 1284 if (pc != myPC) 1285 { 1286 replaceField(pc, field, new Character (newValue)); 1287 disconnectClone(pc); 1288 } 1289 else 1290 { 1291 if (!loadedFields[field] || currentValue != newValue) 1292 writeField(field, new Character (newValue)); 1293 } 1294 } 1295 1296 1297 1306 1307 public void setDoubleField(PersistenceCapable pc, int field, double currentValue, double newValue) 1308 { 1309 if (pc != myPC) 1310 { 1311 replaceField(pc, field, new Double (newValue)); 1312 disconnectClone(pc); 1313 } 1314 else 1315 { 1316 if (!loadedFields[field] || currentValue != newValue) 1317 writeField(field, new Double (newValue)); 1318 } 1319 } 1320 1321 1322 1331 1332 public void setFloatField(PersistenceCapable pc, int field, float currentValue, float newValue) 1333 { 1334 if (pc != myPC) 1335 { 1336 replaceField(pc, field, new Float (newValue)); 1337 disconnectClone(pc); 1338 } 1339 else 1340 { 1341 if (!loadedFields[field] || currentValue != newValue) 1342 writeField(field, new Float (newValue)); 1343 } 1344 } 1345 1346 1347 1356 1357 public void setIntField(PersistenceCapable pc, int field, int currentValue, int newValue) 1358 { 1359 if (pc != myPC) 1360 { 1361 replaceField(pc, field, new Integer (newValue)); 1362 disconnectClone(pc); 1363 } 1364 else 1365 { 1366 if (!loadedFields[field] || currentValue != newValue) 1367 writeField(field, new Integer (newValue)); 1368 } 1369 } 1370 1371 1372 1381 1382 public void setLongField(PersistenceCapable pc, int field, long currentValue, long newValue) 1383 { 1384 if (pc != myPC) 1385 { 1386 replaceField(pc, field, new Long (newValue)); 1387 disconnectClone(pc); 1388 } 1389 else 1390 { 1391 if (!loadedFields[field] || currentValue != newValue) 1392 writeField(field, new Long (newValue)); 1393 } 1394 } 1395 1396 1397 1406 1407 public void setShortField(PersistenceCapable pc, int field, short currentValue, short newValue) 1408 { 1409 if (pc != myPC) 1410 { 1411 replaceField(pc, field, new Short (newValue)); 1412 disconnectClone(pc); 1413 } 1414 else 1415 { 1416 if (!loadedFields[field] || currentValue != newValue) 1417 writeField(field, new Short (newValue)); 1418 } 1419 } 1420 1421 1422 1431 1432 public void setStringField(PersistenceCapable pc, int field, String currentValue, String newValue) 1433 { 1434 if (pc != myPC) 1435 { 1436 replaceField(pc, field, newValue); 1437 disconnectClone(pc); 1438 } 1439 else 1440 { 1441 if (!loadedFields[field] || !equals(currentValue, newValue)) 1442 writeField(field, newValue); 1443 } 1444 } 1445 1446 1447 1456 1457 public void setObjectField(PersistenceCapable pc, int field, Object currentValue, Object newValue) 1458 { 1459 if (pc != myPC) 1460 { 1461 replaceField(pc, field, newValue); 1462 disconnectClone(pc); 1463 } 1464 else 1465 { 1466 if (!loadedFields[field] || currentValue != newValue) 1467 writeObjectField(field, currentValue, newValue); 1468 } 1469 } 1470 1471 1472 1480 1481 private static boolean equals(Object o1, Object o2) 1482 { 1483 return o1 == null ? (o2 == null) : o1.equals(o2); 1484 } 1485 1486 1487 1496 1497 public void providedBooleanField(PersistenceCapable pc, int field, boolean currentValue) 1498 { 1499 currFM.storeBooleanField(field, currentValue); 1500 } 1501 1502 1503 1512 1513 public void providedByteField(PersistenceCapable pc, int field, byte currentValue) 1514 { 1515 currFM.storeByteField(field, currentValue); 1516 } 1517 1518 1519 1528 1529 public void providedCharField(PersistenceCapable pc, int field, char currentValue) 1530 { 1531 currFM.storeCharField(field, currentValue); 1532 } 1533 1534 1535 1544 1545 public void providedDoubleField(PersistenceCapable pc, int field, double currentValue) 1546 { 1547 currFM.storeDoubleField(field, currentValue); 1548 } 1549 1550 1551 1560 1561 public void providedFloatField(PersistenceCapable pc, int field, float currentValue) 1562 { 1563 currFM.storeFloatField(field, currentValue); 1564 } 1565 1566 1567 1576 1577 public void providedIntField(PersistenceCapable pc, int field, int currentValue) 1578 { 1579 currFM.storeIntField(field, currentValue); 1580 } 1581 1582 1583 1592 1593 public void providedLongField(PersistenceCapable pc, int field, long currentValue) 1594 { 1595 currFM.storeLongField(field, currentValue); 1596 } 1597 1598 1599 1608 1609 public void providedShortField(PersistenceCapable pc, int field, short currentValue) 1610 { 1611 currFM.storeShortField(field, currentValue); 1612 } 1613 1614 1615 1616 1625 1626 public void providedStringField(PersistenceCapable pc, int field, String currentValue) 1627 { 1628 currFM.storeStringField(field, currentValue); 1629 } 1630 1631 1632 1641 1642 public void providedObjectField(PersistenceCapable pc, int field, Object currentValue) 1643 { 1644 currFM.storeObjectField(field, currentValue); 1645 } 1646 1647 1648 1656 1657 public boolean replacingBooleanField(PersistenceCapable pc, int field) 1658 { 1659 boolean value = currFM.fetchBooleanField(field); 1660 loadedFields[field] = true; 1661 1662 return value; 1663 } 1664 1665 1666 1674 1675 public byte replacingByteField(PersistenceCapable obj, int field) 1676 { 1677 byte value = currFM.fetchByteField(field); 1678 loadedFields[field] = true; 1679 1680 return value; 1681 } 1682 1683 1684 1692 1693 public char replacingCharField(PersistenceCapable obj, int field) 1694 { 1695 char value = currFM.fetchCharField(field); 1696 loadedFields[field] = true; 1697 1698 return value; 1699 } 1700 1701 1702 1710 1711 public double replacingDoubleField(PersistenceCapable obj, int field) 1712 { 1713 double value = currFM.fetchDoubleField(field); 1714 loadedFields[field] = true; 1715 1716 return value; 1717 } 1718 1719 1720 1728 1729 public float replacingFloatField(PersistenceCapable obj, int field) 1730 { 1731 float value = currFM.fetchFloatField(field); 1732 loadedFields[field] = true; 1733 1734 return value; 1735 } 1736 1737 1738 1746 1747 public int replacingIntField(PersistenceCapable obj, int field) 1748 { 1749 int value = currFM.fetchIntField(field); 1750 loadedFields[field] = true; 1751 1752 return value; 1753 } 1754 1755 1756 1764 1765 public long replacingLongField(PersistenceCapable obj, int field) 1766 { 1767 long value = currFM.fetchLongField(field); 1768 loadedFields[field] = true; 1769 1770 return value; 1771 } 1772 1773 1774 1782 1783 public short replacingShortField(PersistenceCapable obj, int field) 1784 { 1785 short value = currFM.fetchShortField(field); 1786 loadedFields[field] = true; 1787 1788 return value; 1789 } 1790 1791 1792 1800 1801 public String replacingStringField(PersistenceCapable obj, int field) 1802 { 1803 String value = currFM.fetchStringField(field); 1804 loadedFields[field] = true; 1805 1806 return value; 1807 } 1808 1809 1810 1818 1819 public Object replacingObjectField(PersistenceCapable obj, int field) 1820 { 1821 Object value = currFM.fetchObjectField(field); 1822 loadedFields[field] = true; 1823 1824 return value; 1825 } 1826 1827 1828 public PersistenceCapable getObject() 1829 { 1830 return myPC; 1831 } 1832 1833 1834 private synchronized Object provideField(PersistenceCapable pc, int fieldNumber) 1835 { 1836 Object obj; 1837 1838 FieldManager prevFM = currFM; 1839 currFM = new StateFieldManager(); 1840 1841 try 1842 { 1843 pc.jdoProvideField(fieldNumber); 1844 return currFM.fetchObjectField(fieldNumber); 1845 } 1846 finally 1847 { 1848 currFM = prevFM; 1849 } 1850 } 1851 1852 1853 private synchronized void replaceField(PersistenceCapable pc, int fieldNumber, final Object value) 1854 { 1855 FieldManager prevFM = currFM; 1856 currFM = new GenericFieldManager() 1857 { 1858 public Object fetchObjectField(int field) 1859 { 1860 return value; 1861 } 1862 1863 public void storeObjectField(int field, Object value) {} }; 1865 1866 try 1867 { 1868 pc.jdoReplaceField(fieldNumber); 1869 } 1870 finally 1871 { 1872 currFM = prevFM; 1873 } 1874 } 1875 1876 1877 1887 1888 public synchronized void provideFields(int fieldNumbers[], FieldManager fm) 1889 { 1890 FieldManager prevFM = currFM; 1891 currFM = fm; 1892 1893 try 1894 { 1895 myPC.jdoProvideFields(fieldNumbers); 1896 } 1897 finally 1898 { 1899 currFM = prevFM; 1900 } 1901 } 1902 1903 1904 1917 1918 public synchronized void replaceFields(int fieldNumbers[], FieldManager fm) 1919 { 1920 replaceFieldsInternal(fieldNumbers, new SCOWrapper(fm, this, secondClassMutableFields)); 1921 } 1922 1923 1924 private synchronized void replaceFieldsInternal(int fieldNumbers[], FieldManager fm) 1925 { 1926 FieldManager prevFM = currFM; 1927 currFM = fm; 1928 1929 try 1930 { 1931 myPC.jdoReplaceFields(fieldNumbers); 1932 } 1933 finally 1934 { 1935 currFM = prevFM; 1936 } 1937 } 1938 1939 1940 private void preStateChange() 1941 { 1942 changingState = true; 1943 } 1944 1945 1946 private void postStateChange() 1947 { 1948 changingState = false; 1949 1950 if (postLoadPending) 1951 { 1952 postLoadPending = false; 1953 postLoad(); 1954 } 1955 } 1956 1957 1958 1970 1971 public boolean makePersistent() 1972 { 1973 if (myLC.isPersistent()) 1974 return false; 1975 1976 LifeCycleState oldLC = myLC; 1977 preStateChange(); 1978 try { myLC = myLC.transitionMakePersistent(this, myTX); } 1979 finally { postStateChange(); } 1980 1981 boolean succeeded = false; 1982 1983 try 1984 { 1985 myID = srm.newObjectID(myPC.getClass()); 1986 1987 if (inserting) 1988 throw new JDOFatalInternalException("makePersistent() called recursively"); 1989 1990 inserting = true; 1991 1992 try 1993 { 1994 if (myPC instanceof InstanceCallbacks) 1995 ((InstanceCallbacks)myPC).jdoPreStore(); 1996 1997 srm.insert(this); 1998 } 1999 finally 2000 { 2001 inserting = false; 2002 } 2003 2004 succeeded = true; 2005 } 2006 finally 2007 { 2008 if (!succeeded) 2009 { 2010 preStateChange(); 2011 try { myLC = myLC.transitionRollbackState(this, oldLC); } 2012 finally { postStateChange(); } 2013 2014 myID = null; 2015 } 2016 } 2017 2018 myPM.dataStoreModified(); 2019 2020 return true; 2021 } 2022 2023 2024 private void transitionReadField() 2025 { 2026 preStateChange(); 2027 try { myLC = myLC.transitionReadField(this, myTX); } 2028 finally { postStateChange(); } 2029 } 2030 2031 2032 private void transitionWriteField() 2033 { 2034 preStateChange(); 2035 try { myLC = myLC.transitionWriteField(this, myTX); } 2036 finally { postStateChange(); } 2037 } 2038 2039 2040 public void makeTransactional() 2041 { 2042 preStateChange(); 2043 try { myLC = myLC.transitionMakeTransactional(this, myTX); } 2044 finally { postStateChange(); } 2045 } 2046 2047 2048 public void makeNontransactional() 2049 { 2050 preStateChange(); 2051 try { myLC = myLC.transitionMakeNontransactional(this); } 2052 finally { postStateChange(); } 2053 } 2054 2055 2056 public void makeTransient() 2057 { 2058 preStateChange(); 2059 try { myLC = myLC.transitionMakeTransient(this); } 2060 finally { postStateChange(); } 2061 } 2062 2063 2064 public void evict() 2065 { 2066 preStateChange(); 2067 try { myLC = myLC.transitionEvict(this); } 2068 finally { postStateChange(); } 2069 } 2070 2071 2072 public void refresh() 2073 { 2074 preStateChange(); 2075 try { myLC = myLC.transitionRefresh(this, myTX); } 2076 finally { postStateChange(); } 2077 } 2078 2079 2080 public void retrieve(boolean DFGOnly) 2081 { 2082 preStateChange(); 2083 try { myLC = myLC.transitionRetrieve(this, myTX, DFGOnly); } 2084 finally { postStateChange(); } 2085 } 2086 2087 2088 2092 2093 public void postCommit() 2094 { 2095 preStateChange(); 2096 try { myLC = myLC.transitionCommit(this, myTX); } 2097 finally { postStateChange(); } 2098 } 2099 2100 2101 2105 2106 public void preRollback() 2107 { 2108 preStateChange(); 2109 try { myLC = myLC.transitionRollback(this, myTX); } 2110 finally { postStateChange(); } 2111 } 2112 2113 2114 void preDelete() 2115 { 2116 if (myPC instanceof InstanceCallbacks) 2117 ((InstanceCallbacks)myPC).jdoPreDelete(); 2118 } 2119 2120 2121 2128 2129 public void deletePersistent() 2130 { 2131 if (myLC.isDeleted()) 2132 return; 2133 2134 if (deleting) 2135 throw new JDOFatalInternalException("deletePersistent() called recursively"); 2136 2137 deleting = true; 2138 2139 try 2140 { 2141 LifeCycleState oldLC = myLC; 2142 preStateChange(); 2143 try { myLC = myLC.transitionDeletePersistent(this, myTX); } 2144 finally { postStateChange(); } 2145 2146 boolean succeeded = false; 2147 2148 try 2149 { 2150 srm.delete(this); 2151 clearLoadedFlags(); 2152 2153 succeeded = true; 2154 } 2155 finally 2156 { 2157 if (!succeeded) 2158 { 2159 preStateChange(); 2160 try { myLC = myLC.transitionRollbackState(this, oldLC); } 2161 finally { postStateChange(); } 2162 } 2163 } 2164 } 2165 finally 2166 { 2167 deleting = false; 2168 } 2169 2170 myPM.dataStoreModified(); 2171 } 2172 2173 2174 2185 2186 public void flush() 2187 { 2188 if (dirty) 2189 { 2190 if (flushing) 2191 throw new JDOFatalInternalException("flush() re-entered"); 2192 2193 flushing = true; 2194 2195 try 2196 { 2197 if (myPC instanceof InstanceCallbacks && !deleting) 2198 ((InstanceCallbacks)myPC).jdoPreStore(); 2199 2200 int[] dirtyFieldNumbers = getFlagsSetTo(dirtyFields, true); 2201 2202 if (dirtyFieldNumbers == null) 2203 throw new JDOFatalInternalException("dirty == true but no fields are marked dirty"); 2204 2205 srm.update(this, dirtyFieldNumbers); 2206 2207 clearDirtyFlags(); 2208 } 2209 finally 2210 { 2211 flushing = false; 2212 } 2213 2214 myPM.dataStoreModified(); 2215 } 2216 } 2217 2218 2219 void disconnect() 2220 { 2221 if (LOG.isDebugEnabled()) 2222 LOG.debug("Disconnecting " + toJVMIDString(myPC) + " from " + this); 2223 2224 disownSCOFields(); 2225 myPM.removeStateManager(this); 2226 jdoFlags = PersistenceCapable.READ_WRITE_OK; 2227 myPC.jdoReplaceFlags(); 2228 2229 disconnecting = true; 2230 2231 try 2232 { 2233 myPC.jdoReplaceStateManager(null); 2234 } 2235 finally 2236 { 2237 disconnecting = false; 2238 } 2239 2240 discardSavedFields(); 2241 myPM = null; 2242 myPC = null; 2243 myID = null; 2244 myLC = null; 2245 cmd = null; 2246 srm = null; 2247 } 2248 2249 2250 public String toString() 2251 { 2252 if (myPC == null) 2253 return "StateManager@" + System.identityHashCode(this) + "(disconnected)"; 2254 else 2255 { 2256 String pcClassName = myPC.getClass().getName(); 2257 2258 return "StateManager:" + pcClassName.substring(pcClassName.lastIndexOf('.') + 1) 2259 + '@' + System.identityHashCode(myPC) + '(' + myID + ')'; 2260 } 2261 } 2262 2263 2264 2265 2266 2267 private static String toJVMIDString(Object obj) 2268 { 2269 if (obj == null) 2270 return "null"; 2271 else 2272 return obj.getClass().getName() + '@' + System.identityHashCode(obj); 2273 } 2274 2275 2276 private static String booleanArrayToString(boolean[] ba) 2277 { 2278 if (ba == null) 2279 return "null"; 2280 2281 StringBuffer sb = new StringBuffer ("["); 2282 2283 for (int i = 0; i < ba.length; ++i) 2284 sb.append(ba[i] ? 'Y' : 'N'); 2285 2286 sb.append(']'); 2287 2288 return sb.toString(); 2289 } 2290 2291 2292 private static String intArrayToString(int[] ia) 2293 { 2294 if (ia == null) 2295 return "null"; 2296 2297 StringBuffer sb = new StringBuffer ("["); 2298 2299 for (int i = 0; i < ia.length; ++i) 2300 { 2301 if (i > 0) 2302 sb.append(','); 2303 2304 sb.append(ia[i]); 2305 } 2306 2307 sb.append(']'); 2308 2309 return sb.toString(); 2310 } 2311 2312 2313 private static String jdoFlagsToString(byte flags) 2314 { 2315 switch (flags) 2316 { 2317 case PersistenceCapable.LOAD_REQUIRED: 2318 return "LOAD_REQUIRED"; 2319 case PersistenceCapable.READ_OK: 2320 return "READ_OK"; 2321 case PersistenceCapable.READ_WRITE_OK: 2322 return "READ_WRITE_OK"; 2323 default: 2324 return "???"; 2325 } 2326 } 2327 2328 2329 private static void dumpPC(PersistenceCapable pc, PrintWriter out) 2330 { 2331 out.println(toJVMIDString(pc)); 2332 2333 if (pc == null) 2334 return; 2335 2336 out.print("jdoStateManager = "); out.println(peekField(pc, "jdoStateManager")); 2337 out.print("jdoFlags = "); 2338 Object flagsObj = peekField(pc, "jdoFlags"); 2339 2340 if (flagsObj instanceof Byte ) 2341 out.println(jdoFlagsToString(((Byte )flagsObj).byteValue())); 2342 else 2343 out.println(flagsObj); 2344 2345 Class c = pc.getClass(); 2346 2347 do 2348 { 2349 String [] fieldNames = helper.getFieldNames(c); 2350 2351 for (int i = 0; i < fieldNames.length; ++i) 2352 { 2353 out.print(fieldNames[i]); out.print(" = "); out.println(peekField(pc, fieldNames[i])); 2354 } 2355 2356 c = c.getSuperclass(); 2357 } while (c != null && PersistenceCapable.class.isAssignableFrom(c)); 2358 } 2359 2360 2361 private static Object peekField(Object obj, String fieldName) 2362 { 2363 try 2364 { 2365 2370 Object value = obj.getClass().getDeclaredField(fieldName).get(obj); 2371 2372 if (value instanceof PersistenceCapable) 2373 return toJVMIDString(value); 2374 else 2375 return value; 2376 } 2377 catch (Exception e) 2378 { 2379 return e.toString(); 2380 } 2381 } 2382 2383 2384 public void dump(PrintWriter out) 2385 { 2386 out.print("myPM = "); out.println(myPM); 2387 out.print("myTX = "); out.println(myTX); 2388 out.print("myID = "); out.println(myID); 2389 out.print("myLC = "); out.println(myLC); 2390 out.print("cmd = "); out.println(cmd); 2391 out.print("srm = "); out.println(srm); 2392 out.print("fieldCount = "); out.println(fieldCount); 2393 out.print("dirty = "); out.println(dirty); 2394 out.print("flushing = "); out.println(flushing); 2395 out.print("changingState = "); out.println(changingState); 2396 out.print("postLoadPending = "); out.println(postLoadPending); 2397 out.print("disconnecting = "); out.println(disconnecting); 2398 out.print("dirtyFields = "); out.println(booleanArrayToString(dirtyFields)); 2399 out.print("defaultFetchGroupFields = "); out.println(booleanArrayToString(defaultFetchGroupFields)); 2400 out.print("secondClassMutableFields = "); out.println(booleanArrayToString(secondClassMutableFields)); 2401 out.print("allFieldNumbers = "); out.println(intArrayToString(allFieldNumbers)); 2402 out.print("persistentFieldNumbers = "); out.println(intArrayToString(persistentFieldNumbers)); 2403 out.print("defaultFetchGroupFieldNumbers = "); out.println(intArrayToString(defaultFetchGroupFieldNumbers)); 2404 out.print("secondClassMutableFieldNumbers = "); out.println(intArrayToString(secondClassMutableFieldNumbers)); 2405 2406 out.println(); 2407 out.print("jdoFlags = "); out.println(jdoFlagsToString(jdoFlags)); 2408 out.print("loadedFields = "); out.println(booleanArrayToString(loadedFields)); 2409 out.print("myPC = "); dumpPC(myPC, out); 2410 2411 out.println(); 2412 out.print("savedFlags = "); out.println(jdoFlagsToString(savedFlags)); 2413 out.print("savedLoadedFields = "); out.println(booleanArrayToString(savedLoadedFields)); 2414 out.print("savedImage = "); dumpPC(savedImage, out); 2415 } 2416} 2417 | Popular Tags |