Source Code Cross Referenced for TransactionAssembler.java in  » Database-DBMS » JODB » com » mobixess » jodb » core » transaction » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » JODB » com.mobixess.jodb.core.transaction 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         * Copyright Mobixess Inc. 2007
0003:         */package com.mobixess.jodb.core.transaction;
0004:
0005:        import java.io.IOException;
0006:        import java.lang.reflect.Array;
0007:        import java.lang.reflect.Field;
0008:        import java.nio.ByteBuffer;
0009:        import java.util.Iterator;
0010:        import java.util.Map;
0011:        import java.util.Random;
0012:        import java.util.Vector;
0013:        import java.util.logging.Level;
0014:        import java.util.logging.Logger;
0015:
0016:        import com.mobixess.jodb.core.IllegalClassTypeException;
0017:        import com.mobixess.jodb.core.JODBConfig;
0018:        import com.mobixess.jodb.core.JodbIOException;
0019:        import com.mobixess.jodb.core.agent.JODBAgent;
0020:        import com.mobixess.jodb.core.index.IndexingRecord;
0021:        import com.mobixess.jodb.core.index.JODBIndexingRootAgent;
0022:        import com.mobixess.jodb.core.io.IOTicket;
0023:        import com.mobixess.jodb.core.io.IRandomAccessDataBuffer;
0024:        import com.mobixess.jodb.core.io.IOBase;
0025:        import com.mobixess.jodb.core.io.JODBIOBase;
0026:        import com.mobixess.jodb.core.io.JODBOperationContext;
0027:        import com.mobixess.jodb.core.io.ObjectDataContainer;
0028:        import com.mobixess.jodb.core.io.ObjectDataContainer.FieldsIterator;
0029:        import com.mobixess.jodb.core.plugin.IClassProcessor;
0030:        import com.mobixess.jodb.core.plugin.JODBPluginRegistry;
0031:        import com.mobixess.jodb.core.transaction.JODBSession.ClassDescriptor;
0032:        import com.mobixess.jodb.core.transaction.JODBSession.FieldAndIDRecord;
0033:        import com.mobixess.jodb.core.transaction.TransactionUtils.DataContainersCache;
0034:        import com.mobixess.jodb.util.PrimitiveJavaTypesUtil;
0035:        import com.mobixess.jodb.util.Utils;
0036:
0037:        /**
0038:         * @author Mobixess
0039:         *
0040:         */
0041:        public class TransactionAssembler {
0042:
0043:            public final static byte TRANSACTION_REPLACEMENT_ENTRY_TYPE_STATIC = 0xf;
0044:            public final static byte TRANSACTION_REPLACEMENT_ENTRY_TYPE_REDIRECTOR = 0x7f;
0045:            private static Logger _logger = Utils
0046:                    .getLogger(TransactionAssembler.class.getName());
0047:            private final static long MAX_ABSOLUTE_SHORT_ADDR = 0xFFFFFFFFL;
0048:            //WARNING: this is hard transaction limit. 
0049:            private final static long TRANSACTION_SIZE_LIMIT = Math.min(
0050:                    Integer.MAX_VALUE, -Integer.MIN_VALUE) / 2;
0051:
0052:            /**
0053:             * 
0054:             * @param context
0055:             * @param tContainer
0056:             * @throws IOException
0057:             * @throws IllegalClassTypeException
0058:             */
0059:            public static void assembleTransactionData(
0060:                    JODBOperationContext context,
0061:                    TransactionContainer tContainer) throws IOException,
0062:                    IllegalClassTypeException {
0063:                if (tContainer.isAgentsMode()) {
0064:                    //make sure the root agent processed first
0065:                    JODBIndexingRootAgent indexingRootAgent = context
0066:                            .getIndexingRootAgent();
0067:                    if (tContainer.getHandleForObject(indexingRootAgent) != null) {
0068:                        assembleTransactionDataForObject(context,
0069:                                indexingRootAgent, tContainer);
0070:                    }
0071:                }
0072:                Map<Object, TransactionHandle> transactionObjects = tContainer
0073:                        .getTransactionObjects();
0074:                Iterator<Object> iter = transactionObjects.keySet().iterator();
0075:                while (iter.hasNext()) {
0076:                    tContainer.resetTransactionBufferToEnd();
0077:                    Object element = iter.next();
0078:                    assembleTransactionDataForObject(context, element,
0079:                            tContainer);
0080:                }
0081:            }
0082:
0083:            private static long estimateHeaderAndAuxDataLength(
0084:                    TransactionHandle tHandle, /*int classHierarhyLen,*/
0085:                    boolean translated) {
0086:                long lengthEstimate = 0;
0087:                lengthEstimate += 2; // mask
0088:                if (tHandle.generateUID()) {
0089:                    lengthEstimate += 8; // uid
0090:                }
0091:                if (tHandle.generateCreationTS()) {
0092:                    lengthEstimate += 8; // creation TS
0093:                }
0094:                if (tHandle.generateModificationTS()) {
0095:                    lengthEstimate += 8; // modification TS
0096:                }
0097:
0098:                lengthEstimate += 2;// class hierarhy
0099:                if (translated) {
0100:                    lengthEstimate += 2;
0101:                }
0102:                //        lengthEstimate += 2; //class names counter
0103:                //        lengthEstimate += 2 * classHierarhyLen;// class hierarhy
0104:                return lengthEstimate;
0105:            }
0106:
0107:            private static long estimateObjectLength(TransactionHandle tHandle, /*int classHierarhyLen,*/
0108:            int fieldsWithAbsoluteLen, int fieldsWithRelativeLen,
0109:                    ClassDescriptor classDescriptor, boolean translated)
0110:                    throws JodbIOException {
0111:                long lengthEstimate = estimateHeaderAndAuxDataLength(tHandle,
0112:                        translated);
0113:
0114:                if (fieldsWithAbsoluteLen > 0) {
0115:                    lengthEstimate += 2; // directly addressed fields count
0116:                    lengthEstimate += (2 + 8) * fieldsWithAbsoluteLen;// size for fields ids and pointers
0117:                }
0118:
0119:                if (fieldsWithRelativeLen > 0) {
0120:                    lengthEstimate += 2; // inderectly addressed fields count
0121:                    lengthEstimate += (2 + 4) * fieldsWithRelativeLen;// size for fields ids and pointers
0122:                }
0123:
0124:                if (classDescriptor != null) {
0125:                    lengthEstimate += 2; // inderectly addressed fields count
0126:                    lengthEstimate += classDescriptor
0127:                            .getPrimitiveFieldsStorageEstimate(2);
0128:                }
0129:                return lengthEstimate;
0130:            }
0131:
0132:            private static long estimateArrayObjectLength(
0133:                    JODBOperationContext context, TransactionHandle tHandle,
0134:                    Object array, ClassDescriptor classDescriptor,
0135:                    ByteHolder elementsSizeOutParam, boolean translated)
0136:                    throws JodbIOException {
0137:                int arraySize = Array.getLength(array);
0138:                long lengthEstimate = estimateObjectLength(tHandle, 0, 0, null,
0139:                        translated);//header
0140:                lengthEstimate += 4; //array length entry
0141:                lengthEstimate += 1; //array's element size entry
0142:                if (classDescriptor.isPrimitiveArray()) {
0143:                    elementsSizeOutParam._value = (byte) PrimitiveJavaTypesUtil
0144:                            .getDataOutputWriteLen(classDescriptor
0145:                                    .getArrayType());
0146:                    lengthEstimate += elementsSizeOutParam._value * arraySize;
0147:                } else {
0148:                    JODBSession session = context.getSession();
0149:                    TransactionContainer tContainer = context
0150:                            .getTransactionContainer();
0151:                    long transactionOffset = context.getTransactionOffset();
0152:                    boolean newArray = tHandle.isNewObject();
0153:                    elementsSizeOutParam._value = 4;
0154:                    for (int i = 0; i < arraySize; i++) {
0155:                        Object value = Array.get(array, i);
0156:                        if (value == null) {
0157:                            continue;
0158:                        }
0159:
0160:                        TransactionHandle valueTransactionHandle = tContainer
0161:                                .getHandleForObject(value);
0162:                        if (valueTransactionHandle == null) {
0163:                            continue;
0164:                        }
0165:
0166:                        if (newArray) {
0167:                            if (!valueTransactionHandle.isNewObject()) {
0168:                                long valueObjectOffset = valueTransactionHandle
0169:                                        .getHandle().getObjectEntryOffset();
0170:                                if (valueObjectOffset > MAX_ABSOLUTE_SHORT_ADDR
0171:                                        && transactionOffset
0172:                                                - valueObjectOffset > TRANSACTION_SIZE_LIMIT) {
0173:                                    elementsSizeOutParam._value = 8;
0174:                                    break;
0175:                                }
0176:                            }
0177:                        } else {
0178:                            if (valueTransactionHandle.isNewObject()) {
0179:                                if (transactionOffset > MAX_ABSOLUTE_SHORT_ADDR
0180:                                        - TRANSACTION_SIZE_LIMIT) {
0181:                                    elementsSizeOutParam._value = 8;
0182:                                    break;
0183:                                }
0184:                            } else {
0185:                                long valueObjectOffset = valueTransactionHandle
0186:                                        .getHandle().getObjectEntryOffset();
0187:                                if (valueObjectOffset > MAX_ABSOLUTE_SHORT_ADDR) {
0188:                                    elementsSizeOutParam._value = 8;
0189:                                    break;
0190:                                }
0191:                            }
0192:                        }
0193:
0194:                        PersistentObjectHandle objectHandle = session
0195:                                .getHandleForActiveObject(value);
0196:                        if (newArray) {
0197:
0198:                        }
0199:                        if (objectHandle == null) {
0200:                            continue;
0201:                        }
0202:                        if (objectHandle.getObjectEntryOffset() > MAX_ABSOLUTE_SHORT_ADDR) {
0203:                            elementsSizeOutParam._value = 8;
0204:                            break;
0205:                        }
0206:                    }
0207:                    lengthEstimate += elementsSizeOutParam._value * arraySize
0208:                            + arraySize / 8 + 1;
0209:                }
0210:                return lengthEstimate;
0211:            }
0212:
0213:            private static int composeEntryID(short entryID, long length) {
0214:                int lenModifierID = 0;
0215:                if (length <= 0xff) {
0216:                    lenModifierID = JODBIOBase.LEN_MODIFIER_BYTE;
0217:                } else if (length > 0xFFFF) {
0218:                    lenModifierID = JODBIOBase.LEN_MODIFIER_LONG;
0219:                }
0220:                return entryID | lenModifierID;
0221:            }
0222:
0223:            private static void classifyFields(Object object,
0224:                    ClassDescriptor classDescr,
0225:                    Map<Object, TransactionHandle> transactionObjects,
0226:                    Vector<ObjectFieldRecord> fieldsWithAbsoluteAddr,
0227:                    Vector<ObjectFieldRecord> fieldsWithRelativeAddr,
0228:                    Vector<Field> primitiveFields) throws IOException {
0229:                FieldAndIDRecord[] fields = classDescr.getFields();
0230:                for (int i = 0; i < fields.length; i++) {
0231:                    Field next = fields[i]._field;
0232:                    if (next.getType().isPrimitive()) {
0233:                        primitiveFields.add(next);
0234:                        continue;
0235:                    }
0236:                    Object value;
0237:                    try {
0238:                        value = next.get(object);
0239:                    } catch (Exception e) {
0240:                        e.printStackTrace();
0241:                        throw new JodbIOException(e);
0242:                    }
0243:                    TransactionHandle childObjectHandle = transactionObjects
0244:                            .get(value);
0245:                    if (value == null || childObjectHandle == null
0246:                            || childObjectHandle.is_DELETE_Transaction()) {
0247:                        //null fieds may not require
0248:                        //nullFields.add(next);
0249:                    } else {
0250:                        if (!childObjectHandle.isNewObject()) {
0251:                            fieldsWithAbsoluteAddr.add(new ObjectFieldRecord(
0252:                                    next, value));
0253:                        } else {
0254:                            fieldsWithRelativeAddr.add(new ObjectFieldRecord(
0255:                                    next, value));
0256:                        }
0257:                    }
0258:                }
0259:            }
0260:
0261:            private static void writeEntryLenForID(int id, long length,
0262:                    IRandomAccessDataBuffer dataBuffer) throws IOException {
0263:                switch (id & ~JODBIOBase.LEN_MODIFIER_EXCLUSION_MASK) {//reserve space for length 
0264:                case JODBIOBase.LEN_MODIFIER_BYTE:
0265:                    dataBuffer.writeByte((byte) length);
0266:                    break;
0267:                case JODBIOBase.LEN_MODIFIER_LONG:
0268:                    dataBuffer.writeLong(length);
0269:                    break;
0270:                default:
0271:                    dataBuffer.writeShort((short) length);
0272:                }
0273:            }
0274:
0275:            private static int formPrimaryObjectMask(int initalMask,
0276:                    boolean fieldsWithAbsoluteAddr,
0277:                    boolean fieldsWithRelativeAddr, boolean primitiveFields,
0278:                    boolean translated, TransactionHandle tHandle,
0279:                    ClassDescriptor classDescr) {
0280:                if (fieldsWithAbsoluteAddr) {
0281:                    initalMask = ObjectDataContainer
0282:                            .addDirectlyAddressedFieldsBit(initalMask);
0283:                }
0284:                if (fieldsWithRelativeAddr) {
0285:                    initalMask = ObjectDataContainer
0286:                            .addRelativelyAddressedFieldsID(initalMask);
0287:                }
0288:                if (primitiveFields) {
0289:                    initalMask = ObjectDataContainer
0290:                            .addPrimitiveFieldsBit(initalMask);
0291:                }
0292:
0293:                if (translated) {
0294:                    initalMask = ObjectDataContainer
0295:                            .addTranslatedBit(initalMask);
0296:                }
0297:
0298:                if (tHandle.generateCreationTS()) {
0299:                    initalMask = ObjectDataContainer
0300:                            .addCreationTSFieldBit(initalMask);
0301:                }
0302:
0303:                if (tHandle.generateModificationTS()) {
0304:                    initalMask = ObjectDataContainer
0305:                            .addModificationTSFieldBit(initalMask);
0306:                }
0307:
0308:                if (classDescr.isArray()) {
0309:                    initalMask = ObjectDataContainer.addArrayIDBit(initalMask);
0310:                }
0311:                return initalMask;
0312:            }
0313:
0314:            private static int formSecondaryObjectMask(int initalMask,
0315:                    boolean isAgentObject) {
0316:                if (isAgentObject) {
0317:                    initalMask = ObjectDataContainer.addAgentBit(initalMask);
0318:                }
0319:                return initalMask;
0320:            }
0321:
0322:            private static long assembleTransactionDataForObject(
0323:                    JODBOperationContext context, Object rootObject,
0324:                    TransactionContainer tContainer) throws IOException,
0325:                    IllegalClassTypeException {
0326:                DataContainersCache dataContainersCache = TransactionUtils
0327:                        .getObjectDataContainerCache();
0328:                ObjectDataContainer persistentCopyObjectDataContainer = dataContainersCache
0329:                        .pullObjectDataContainer();
0330:                try {
0331:                    return writeObjects(context, rootObject, tContainer,
0332:                            persistentCopyObjectDataContainer);
0333:                } finally {
0334:                    dataContainersCache
0335:                            .pushObjectDataContainer(persistentCopyObjectDataContainer);
0336:                    tContainer.fireOnCommitFinished(rootObject, context
0337:                            .getSession());
0338:                }
0339:            }
0340:
0341:            /**
0342:             * 
0343:             * @param context
0344:             * @param rootObject
0345:             * @param tContainer
0346:             * @param persistentCopyObjectDataContainer - data container to read already persisted copy if applicable
0347:             * @return
0348:             * @throws IOException
0349:             * @throws IllegalClassTypeException
0350:             */
0351:            private static long writeObjects(JODBOperationContext context,
0352:                    Object rootObject, TransactionContainer tContainer,
0353:                    ObjectDataContainer persistentCopyObjectDataContainer)
0354:                    throws IOException, IllegalClassTypeException {
0355:                //TODO add verification "fields count" < short
0356:                Map<Object, TransactionHandle> transactionObjects = tContainer
0357:                        .getTransactionObjects();
0358:                TransactionHandle tHandle = transactionObjects.get(rootObject);
0359:                if (tHandle == null) {
0360:                    throw new IOException("transaction handle unavailable");
0361:                }
0362:                if (!tContainer.isAgentsMode() && tHandle.isAgent()) {
0363:                    return 0;
0364:                }
0365:                IOTicket ioTicket = context.getIoTicket();
0366:                JODBSession session = context.getSession();
0367:                if (tHandle.isTranslated()) {
0368:                    return tHandle.getTransactionOffset();
0369:                }
0370:                tContainer
0371:                        .fireOnCommitStarted(rootObject, context.getSession());
0372:                if (tHandle.is_DELETE_Transaction()) {
0373:                    deleteObject(ioTicket, session, tHandle, tContainer);
0374:                    return -1;
0375:                }
0376:                IOBase base = ioTicket.getBase();
0377:
0378:                IClassProcessor classProcessor = JODBPluginRegistry
0379:                        .getInstance().getClassProcessor(rootObject.getClass());
0380:
0381:                Object objectToPersist = classProcessor.translate(rootObject);
0382:
0383:                ClassDescriptor classDescr = session
0384:                        .getDescriptorForClass(objectToPersist.getClass());
0385:                FieldAndIDRecord[] fields = classDescr.getFields();
0386:
0387:                Vector<IndexingRecord> indexes = null;
0388:
0389:                Class rootObjectType = rootObject.getClass();
0390:                int rootObjectClassID;
0391:                if (rootObjectType.isArray()) {
0392:                    rootObjectClassID = base
0393:                            .getOrSetClassTypeSubstitutionID(rootObjectType
0394:                                    .getComponentType().getName());
0395:                } else {
0396:                    rootObjectClassID = base
0397:                            .getOrSetClassTypeSubstitutionID(rootObjectType
0398:                                    .getName());
0399:                    indexes = TransactionUtils.getObjectDataContainerCache()
0400:                            .pullVector();
0401:                    JODBIndexingRootAgent indexingAgent = context
0402:                            .getIndexingRootAgent();
0403:                    indexingAgent.getAgentsForClassId(indexes,
0404:                            rootObjectClassID);
0405:                    if (indexes.size() == 0) {
0406:                        //no indexes for this class
0407:                        TransactionUtils.getObjectDataContainerCache()
0408:                                .pushVector(indexes);
0409:                        indexes = null;
0410:                    }
0411:                }
0412:                tHandle.setIndexes(indexes);
0413:                //String[] classTypes = classDescr.getTypes();
0414:
0415:                if (checkActiveObjectUnchanged(classProcessor, context,
0416:                        objectToPersist, tHandle,
0417:                        persistentCopyObjectDataContainer, indexes)) {//should not happen in recursive sub call
0418:                    tHandle.setIndexes(null);//reset indexes info in handle to prevent post processing
0419:                    long offset = tHandle.getHandle().getObjectEntryOffset();//JODBIOUtils.addAbsoluteOffsetIdentifierBit(tHandle.getHandle().getObjectEntryOffset());
0420:                    tHandle.setTransactionOffset(offset);
0421:                    if (classDescr.isArray()) {
0422:                        if (classDescr.isPrimitiveArray()) {
0423:                            return offset;
0424:                        }
0425:                        int arrayLen = Array.getLength(objectToPersist);
0426:                        for (int i = 0; i < arrayLen; i++) {
0427:                            Object childObj = Array.get(objectToPersist, i);
0428:                            if (childObj == null
0429:                                    || transactionObjects.get(childObj) == null) {
0430:                                continue;
0431:                            }
0432:                            assembleTransactionDataForObject(context, childObj,
0433:                                    tContainer);
0434:                        }
0435:                    } else {
0436:                        try {
0437:                            for (int i = 0; i < fields.length; i++) {
0438:                                Field field = fields[i]._field;
0439:                                if (field.getType().isPrimitive()) {
0440:                                    continue;
0441:                                }
0442:                                Object childObj = field.get(objectToPersist);
0443:                                if (childObj == null
0444:                                        || transactionObjects.get(childObj) == null) {
0445:                                    continue;
0446:                                }
0447:                                assembleTransactionDataForObject(context,
0448:                                        childObj, tContainer);
0449:                            }
0450:                        } catch (Exception e) {
0451:                            e.printStackTrace();
0452:                            throw new JodbIOException(e);
0453:                        }
0454:                    }
0455:                    return offset;
0456:                }
0457:
0458:                IRandomAccessDataBuffer transactionFile = tContainer
0459:                        .getTransactionNewDataFile();
0460:                transactionFile.resetToEnd();
0461:
0462:                Vector<ObjectFieldRecord> fieldsWithAbsoluteAddr = new Vector<ObjectFieldRecord>();
0463:                Vector<ObjectFieldRecord> fieldsWithRelativeAddr = new Vector<ObjectFieldRecord>();
0464:                Vector<Field> primitiveFields = new Vector<Field>();
0465:
0466:                if (!classDescr.isArray()) {
0467:                    classifyFields(objectToPersist, classDescr,
0468:                            transactionObjects, fieldsWithAbsoluteAddr,
0469:                            fieldsWithRelativeAddr, primitiveFields);
0470:                }
0471:
0472:                long objectIDOffset = transactionFile.getCursorOffset();
0473:
0474:                tHandle.setTransactionOffset(objectIDOffset);
0475:
0476:                if (JODBConfig.DEBUG) {
0477:                    _logger.info(" >>> Transaction: Object "
0478:                            + rootObject.getClass() + " " + rootObject
0479:                            + " start offset =" + objectIDOffset);
0480:                }
0481:
0482:                boolean translated = rootObject != objectToPersist;
0483:                byte arrayElementSize = 0;
0484:                long lengthEstimate;
0485:                if (!classDescr.isArray()) {
0486:                    lengthEstimate = estimateObjectLength(tHandle,
0487:                            fieldsWithAbsoluteAddr.size(),
0488:                            fieldsWithRelativeAddr.size(), classDescr,
0489:                            translated);
0490:                } else {
0491:                    ByteHolder byteHolder = new ByteHolder();
0492:                    lengthEstimate = estimateArrayObjectLength(context,
0493:                            tHandle, objectToPersist, classDescr, byteHolder,
0494:                            translated);
0495:                    arrayElementSize = byteHolder._value;
0496:                }
0497:
0498:                int objId = composeEntryID(JODBIOBase.ENTRY_OBJECT_ID,
0499:                        lengthEstimate);
0500:                int objIdWithRedirectionBit = tHandle.isNewObject() ? objId
0501:                        : JODBIOBase.addRedirectedObjectModifier(objId);
0502:                transactionFile.writeShort(objIdWithRedirectionBit);
0503:                writeEntryLenForID(objId, 0, transactionFile);//reserve space for length
0504:
0505:                long objectBodyOffset = transactionFile.getCursorOffset();
0506:
0507:                //        if(JODBConfig.DEBUG){
0508:                //            _logger.info("Transaction: Object "+rootObject.getClass()+" "+rootObject+" header len ="+headerLen);
0509:                //        }
0510:
0511:                int primaryMask = formPrimaryObjectMask(0,
0512:                        fieldsWithAbsoluteAddr.size() > 0,
0513:                        fieldsWithRelativeAddr.size() > 0, primitiveFields
0514:                                .size() > 0, translated, tHandle, classDescr);
0515:                ;
0516:
0517:                transactionFile.writeByte(primaryMask);
0518:
0519:                int secondaryMask = formSecondaryObjectMask(0, tHandle
0520:                        .isAgent());
0521:
0522:                transactionFile.writeByte(secondaryMask);
0523:
0524:                tHandle.setTranslatedObjectDataMask((byte) primaryMask);
0525:
0526:                //
0527:                if (tHandle.generateUID()) {
0528:                    Random random = new Random();
0529:                    transactionFile.writeLong(random.nextLong());
0530:                }
0531:                long time = System.currentTimeMillis();
0532:                if (tHandle.generateCreationTS()) {
0533:                    transactionFile.writeLong(time);
0534:                }
0535:                if (tHandle.generateModificationTS()) {
0536:                    transactionFile.writeLong(time);
0537:                }
0538:
0539:                //
0540:                transactionFile.writeShort(rootObjectClassID);
0541:
0542:                if (translated) {
0543:                    int translatedObjectClassID = base
0544:                            .getOrSetClassTypeSubstitutionID(classDescr
0545:                                    .getTypes()[0]);// base.getOrSetClassTypeSubstitutionID( objectToPersist.getClass().getName());
0546:                    transactionFile.writeShort(translatedObjectClassID);
0547:                }
0548:
0549:                //        transactionFile.writeShort(classTypes.length);
0550:                //        
0551:                //        for (int i = 0; i < classTypes.length; i++) {
0552:                //            int id = base.getOrSetClassTypeSubstitutionID(classTypes[i]);
0553:                //            transactionFile.writeShort(id);
0554:                //        }
0555:
0556:                if (fieldsWithAbsoluteAddr.size() > 0) {//with absolute offsets
0557:                    transactionFile.writeShort(fieldsWithAbsoluteAddr.size());
0558:                    for (int i = 0; i < fieldsWithAbsoluteAddr.size(); i++) {//writing links of unchanged objects
0559:                        ObjectFieldRecord next = fieldsWithAbsoluteAddr
0560:                                .elementAt(i);
0561:                        int id = base.getOrSetFieldSubstitutionID(next._field);
0562:                        transactionFile.writeShort(id);
0563:                        TransactionHandle valueHandle = transactionObjects
0564:                                .get(next._value);
0565:                        transactionFile.writeLong(valueHandle.getHandle()
0566:                                .getObjectEntryOffset());
0567:                    }
0568:                }
0569:
0570:                long objectsWithRelativeAddrStartOffsetShift = -1;
0571:                if (fieldsWithRelativeAddr.size() > 0) {//with relative offsets
0572:                    transactionFile.writeShort(fieldsWithRelativeAddr.size());
0573:                    objectsWithRelativeAddrStartOffsetShift = transactionFile
0574:                            .getCursorOffset()
0575:                            - objectIDOffset;
0576:                    transactionFile.setLength(transactionFile.length()
0577:                            + fieldsWithRelativeAddr.size() * (2 + 4));
0578:                    transactionFile.seek(transactionFile.length());
0579:                }
0580:
0581:                if (primitiveFields.size() > 0) {
0582:                    transactionFile.writeShort(primitiveFields.size());
0583:                }
0584:                for (int i = 0; i < primitiveFields.size(); i++) {
0585:                    Field next = primitiveFields.elementAt(i);
0586:                    int id = base.getOrSetFieldSubstitutionID(next);
0587:                    transactionFile.writeShort(id);
0588:                    IndexingRecord record = IndexingRecord.findIndexingRecord(
0589:                            id, indexes);
0590:                    if (record != null) {
0591:                        //ByteBuffer currentlyPersistedValue = record.getPersistedDataBuffer();
0592:                        ByteBuffer pendingValue = record.getPendingDataBuffer();
0593:                        pendingValue.clear();
0594:                        PrimitiveJavaTypesUtil.primitiveToByteBuffer(
0595:                                objectToPersist, next, pendingValue);
0596:                        pendingValue.flip();
0597:                        transactionFile.getChannel().write(pendingValue);
0598:                        pendingValue.rewind();
0599:                    } else {
0600:                        try {
0601:                            Utils.writePrimitive(objectToPersist, next,
0602:                                    transactionFile);
0603:                        } catch (Exception e) {
0604:                            throw new JodbIOException(e);
0605:                        }
0606:                    }
0607:                }
0608:
0609:                long arrayDataShift = 0;
0610:                if (classDescr.isArray()) {
0611:                    int arrayLength = Array.getLength(objectToPersist);
0612:                    transactionFile.writeInt(arrayLength);
0613:                    transactionFile.writeByte(arrayElementSize);//write length of each element in array
0614:                    arrayDataShift = transactionFile.getCursorOffset()
0615:                            - objectIDOffset;
0616:                    boolean primitive = classDescr.isPrimitiveArray();
0617:                    if (primitive) {//completely write primitive array
0618:                        try {
0619:                            Utils.writePrimitiveArray(objectToPersist,
0620:                                    classDescr.getArrayType(), 0, arrayLength,
0621:                                    transactionFile);
0622:                        } catch (Exception e) {
0623:                            _logger.log(Level.SEVERE, "", e);
0624:                            throw new JodbIOException(e);
0625:                        }
0626:                    } else {//reserve space for references
0627:                        long spaceToReserve = arrayElementSize * arrayLength;
0628:                        long slotMasksTotal = arrayLength / 8;
0629:                        if (slotMasksTotal * 8 != arrayLength) {
0630:                            slotMasksTotal++;//trailing mask entry for slot <8
0631:                        }
0632:                        spaceToReserve += slotMasksTotal;
0633:                        if (transactionFile.getCursorOffset() + spaceToReserve > transactionFile
0634:                                .length()) {
0635:                            transactionFile.setLength(transactionFile
0636:                                    .getCursorOffset()
0637:                                    + spaceToReserve);
0638:                        }
0639:                        transactionFile.skip(spaceToReserve);
0640:
0641:                    }
0642:                }
0643:
0644:                if (JODBConfig.DEBUG) {
0645:                    _logger.info(" <<< Transaction: Object "
0646:                            + rootObject.getClass() + " " + rootObject
0647:                            + " end offset ="
0648:                            + transactionFile.getCursorOffset());
0649:                }
0650:
0651:                long objectEndOffset = transactionFile.getCursorOffset();
0652:                long objectBodyLength = objectEndOffset - objectBodyOffset;
0653:                if (lengthEstimate < objectBodyLength) {
0654:                    throw new JodbIOException("Object length estimate error");
0655:                }
0656:                //long targetObjectBodyLength = objectBodyLength;
0657:
0658:                if (!tHandle.isNewObject()) {
0659:                    DataContainersCache dataContainersCache = TransactionUtils
0660:                            .getObjectDataContainerCache();
0661:                    ObjectDataContainer existingObjectHeaderData = dataContainersCache
0662:                            .pullObjectDataContainer();// tContainer.getTempObjectDataContainer();
0663:
0664:                    //ioTicket.getRandomAccessBuffer().seek(tHandle.getHandle().getObjectEntryOffset());
0665:                    //JODBIOUtils.readObjectHeader(ioTicket, existingObjectHeaderData, false);
0666:                    existingObjectHeaderData.readHeader(ioTicket
0667:                            .getRandomAccessBuffer(), tHandle.getHandle()
0668:                            .getObjectEntryOffset(), false);
0669:                    tHandle.setTransactionOffset(existingObjectHeaderData
0670:                            .getOffset());//JODBIOUtils.addAbsoluteOffsetIdentifierBit(existingObjectHeaderData.getOffset()));//if object already existed than alvays point to initial object position
0671:                    long redirectorOffset = existingObjectHeaderData
0672:                            .isRedirection() ? existingObjectHeaderData
0673:                            .getOffset() : -1;
0674:                    if (objectBodyLength > existingObjectHeaderData
0675:                            .getBodyLength()
0676:                            || fieldsWithRelativeAddr.size() > 0) {
0677:                        if (existingObjectHeaderData.isRedirection()) {
0678:                            //redirection entry space is too small, let see what is under redirection offset
0679:                            //ioTicket.getRandomAccessBuffer().seek(existingObjectHeaderData.getRedirectionOffset());
0680:                            long existingObjectRedirectionOffset = existingObjectHeaderData
0681:                                    .getRedirectionOffset();
0682:                            existingObjectHeaderData.reset();
0683:                            existingObjectHeaderData.readHeader(ioTicket
0684:                                    .getRandomAccessBuffer(),
0685:                                    existingObjectRedirectionOffset, true);
0686:                            //JODBIOUtils.readObjectHeader(ioTicket, existingObjectHeaderData, true);
0687:                        }
0688:                    }
0689:
0690:                    if (objectBodyLength <= existingObjectHeaderData
0691:                            .getBodyLength()
0692:                            && fieldsWithRelativeAddr.size() == 0) {
0693:                        boolean isRedirection = existingObjectHeaderData
0694:                                .isRedirection();
0695:                        long redirectionOffset = existingObjectHeaderData
0696:                                .getRedirectionOffset();
0697:                        //long targetObjectBodyLength = existingObjectHeaderData.getBodyLength();//length for new object's header
0698:
0699:                        //object id(length bits) may change as we fit to maybe bigger space
0700:                        objId = JODBIOBase.ENTRY_OBJECT_ID
0701:                                | existingObjectHeaderData
0702:                                        .getLengthModifierFromID();// composeEntryID( JODBIOBase.ENTRY_OBJECT_ID, targetObjectBodyLength);
0703:
0704:                        if (existingObjectHeaderData.isRedirectedObject()) {
0705:                            objIdWithRedirectionBit = JODBIOBase
0706:                                    .addRedirectedObjectModifier(objId);//this is redirected entry
0707:                        } else {
0708:                            objIdWithRedirectionBit = objId;
0709:                        }
0710:
0711:                        if (isRedirection) {//if we fit into redirection record than delete record under redirection offset
0712:                            deleteObject(ioTicket, session, redirectionOffset,
0713:                                    tContainer);//delete/backup record under redirection offset
0714:                        }
0715:
0716:                        //object can fit to old spot, write it to replacements file insteard of transaction file
0717:                        IRandomAccessDataBuffer replacementsFile = tContainer
0718:                                .getTransactionReplacementsDataFile();
0719:                        replacementsFile.resetToEnd();
0720:                        replacementsFile
0721:                                .writeByte(TRANSACTION_REPLACEMENT_ENTRY_TYPE_STATIC);
0722:                        replacementsFile.writeLong(existingObjectHeaderData
0723:                                .getOffset());
0724:                        long replacementLengthEntryOffset = replacementsFile
0725:                                .getCursorOffset();
0726:                        replacementsFile.writeLong(0);//reserve space for replacement length entry. //TODO skip faster?
0727:                        long newObjectIDOffset = replacementsFile
0728:                                .getCursorOffset();
0729:
0730:                        replacementsFile.writeShort(objIdWithRedirectionBit);//write new ID to replacements file
0731:                        writeEntryLenForID(objId, objectBodyLength,
0732:                                replacementsFile);//write length of replacements file, could be bigger than actual object's data occupies
0733:
0734:                        long newObjectBodyOffset = replacementsFile
0735:                                .getCursorOffset();
0736:                        //return to write actual length of replacement entry
0737:                        replacementsFile.seek(replacementLengthEntryOffset);
0738:                        replacementsFile.writeLong(newObjectBodyOffset
0739:                                - newObjectIDOffset + objectBodyLength);
0740:                        replacementsFile.seek(newObjectBodyOffset);//back to the header end
0741:
0742:                        transactionFile
0743:                                .transferTo(objectBodyOffset, objectBodyLength,
0744:                                        replacementsFile.getChannel());
0745:                        transactionFile.seek(objectIDOffset);//return position in transaction file to the start of object(like it wasn't here)
0746:                        transactionFile.setLength(objectIDOffset);//truncate "new data" file
0747:                        objectIDOffset = newObjectIDOffset;//this now offset in replacements file
0748:                        objectBodyOffset = newObjectBodyOffset;
0749:                        objectBodyLength = existingObjectHeaderData
0750:                                .getBodyLength();//length for new object
0751:                        transactionFile = replacementsFile;
0752:                        replacementsFile.resetToEnd();//replacements file to the end
0753:                        objectEndOffset = replacementsFile.getCursorOffset();
0754:                    } else {
0755:                        if (redirectorOffset != -1) {
0756:                            //this is record under redirection offset
0757:                            deleteObject(ioTicket, session,
0758:                                    existingObjectHeaderData.getOffset(),
0759:                                    tContainer);
0760:                        }
0761:                        IRandomAccessDataBuffer replacementsFile = tContainer
0762:                                .getTransactionReplacementsDataFile();
0763:                        long offset = tHandle.getHandle()
0764:                                .getObjectEntryOffset();//offset of record that will be replaced with redirector
0765:                        //backupObject(ioTicket, offset, tContainer);
0766:                        //write redirector entry with relative offset
0767:                        replacementsFile
0768:                                .writeByte(TRANSACTION_REPLACEMENT_ENTRY_TYPE_REDIRECTOR);
0769:                        replacementsFile.writeLong(offset);
0770:                        replacementsFile.writeLong(objectIDOffset);//relative offset in new data transaction file
0771:                    }
0772:                    dataContainersCache
0773:                            .pushObjectDataContainer(existingObjectHeaderData);
0774:                }
0775:
0776:                for (int i = 0; i < fieldsWithRelativeAddr.size(); i++) {
0777:                    ObjectFieldRecord next = fieldsWithRelativeAddr
0778:                            .elementAt(i);
0779:                    next._offset = assembleTransactionDataForObject(context,
0780:                            next._value, tContainer);
0781:                    //            if(JODBIOUtils.isAbsoluteOffset(next._offset)){
0782:                    //                throw new IOException("internal transaction error");
0783:                    //            }
0784:                }
0785:
0786:                if (classDescr.isArray() && !classDescr.isPrimitiveArray()) {
0787:                    int arrayLength = Array.getLength(objectToPersist);
0788:                    for (int i = 0; i < arrayLength; i++) {
0789:                        Object value = Array.get(objectToPersist, i);
0790:                        if (value == null) {
0791:                            continue;
0792:                        }
0793:                        TransactionHandle transactionHandle = transactionObjects
0794:                                .get(value);
0795:                        if (transactionHandle == null
0796:                                || transactionHandle.isTranslated()) {
0797:                            continue;
0798:                        }
0799:                        if (transactionHandle.isNewObject()) {//only write new objects as we need relative offset, the offset for existing objects already known
0800:                            assembleTransactionDataForObject(context, value,
0801:                                    tContainer);
0802:                        }
0803:                    }
0804:                }
0805:
0806:                transactionFile.seek(objectIDOffset + 2);
0807:
0808:                writeEntryLenForID(objId, objectBodyLength, transactionFile);//TODO make sure the same size estimate is used
0809:
0810:                if (fieldsWithRelativeAddr.size() > 0) {
0811:                    transactionFile.seek(objectIDOffset
0812:                            + objectsWithRelativeAddrStartOffsetShift);
0813:                    //            if(JODBConfig.DEBUG){
0814:                    //                _logger.info("Transaction: Object "+rootObject.getClass()+" "+rootObject+" fields with relative pos ="+transactionFile.getCursorOffset());
0815:                    //            }
0816:                }
0817:                for (int i = 0; i < fieldsWithRelativeAddr.size(); i++) {
0818:                    ObjectFieldRecord next = fieldsWithRelativeAddr
0819:                            .elementAt(i);
0820:                    int id = base.getOrSetFieldSubstitutionID(next._field);
0821:                    transactionFile.writeShort(id);
0822:                    transactionFile.writeInt((int) (next._offset
0823:                            - transactionFile.getCursorOffset() - 4));//4 bytes to assume the position after offset entry
0824:                }
0825:
0826:                if (classDescr.isArray() && !classDescr.isPrimitiveArray()) {
0827:                    transactionFile.seek(objectIDOffset + arrayDataShift);
0828:                    int arrayLength = Array.getLength(objectToPersist);
0829:                    int slotMask = 0;
0830:                    int slotCounter = 0;
0831:                    for (int i = 0; i < arrayLength; i++, slotCounter++) {
0832:                        if (slotCounter == 8) {
0833:                            transactionFile.writeByte(slotMask);
0834:                            slotCounter = 0;
0835:                            slotMask = 0;
0836:                        }
0837:                        Object value = Array.get(objectToPersist, i);
0838:                        TransactionHandle cellValueTransactionHandle;
0839:                        if (value == null
0840:                                || (cellValueTransactionHandle = transactionObjects
0841:                                        .get(value)) == null) {
0842:                            //transaction handle can be null only if this object is last in depth 
0843:                            if (arrayElementSize == 4) {
0844:                                transactionFile.writeInt(0);
0845:                            } else {
0846:                                transactionFile.writeLong(0);
0847:                            }
0848:                            continue;
0849:                        }
0850:                        if (cellValueTransactionHandle.isNewObject()
0851:                                & !cellValueTransactionHandle.isTranslated()) {
0852:                            throw new IOException();
0853:                        }
0854:                        long offset;
0855:                        boolean absoluteOffset;
0856:                        if (!cellValueTransactionHandle.isNewObject()) {
0857:                            offset = cellValueTransactionHandle.getHandle()
0858:                                    .getObjectEntryOffset();
0859:                            absoluteOffset = true;
0860:                            if (offset > MAX_ABSOLUTE_SHORT_ADDR
0861:                                    && arrayElementSize == 4) {
0862:                                if (tHandle.isNewObject()) {
0863:                                    //try relative address
0864:                                    if (context.getTransactionOffset() - offset > TRANSACTION_SIZE_LIMIT) {
0865:                                        throw new JodbIOException(
0866:                                                "Illegal array size estimation TRANSACTION_SIZE_LIMIT");
0867:                                    }
0868:                                    offset = offset
0869:                                            - (context.getTransactionOffset()
0870:                                                    + transactionFile
0871:                                                            .getCursorOffset() + arrayElementSize);
0872:                                    absoluteOffset = false;
0873:                                } else {
0874:                                    throw new JodbIOException(
0875:                                            "Illegal array size estimation");
0876:                                }
0877:                            }
0878:                        } else {
0879:                            if (tHandle.isNewObject()) {//definitely relative offset 
0880:                                offset = cellValueTransactionHandle
0881:                                        .getTransactionOffset()
0882:                                        - (transactionFile.getCursorOffset() + arrayElementSize);
0883:                                absoluteOffset = false;
0884:                            } else {//only absolute addr from here
0885:                                offset = cellValueTransactionHandle
0886:                                        .getTransactionOffset();
0887:                                if (arrayElementSize == 4
0888:                                        && offset > MAX_ABSOLUTE_SHORT_ADDR
0889:                                                - TRANSACTION_SIZE_LIMIT) {
0890:                                    throw new JodbIOException(
0891:                                            "Illegal array size estimation > MAX_ABSOLUTE_SHORT_ADDR - TRANSACTION_SIZE_LIMIT");
0892:                                }
0893:                                offset += context.getTransactionOffset();
0894:                                absoluteOffset = true;
0895:                            }
0896:
0897:                        }
0898:                        if (arrayElementSize == 4) {
0899:                            transactionFile.writeInt((int) offset);
0900:                        } else {
0901:                            transactionFile.writeLong(offset);
0902:                        }
0903:                        if (absoluteOffset) {
0904:                            slotMask |= 1 << slotCounter;//absolute address
0905:                        }
0906:                    }
0907:                    if (slotCounter != 0) {//write trailing mask entry
0908:                        transactionFile.writeByte(slotMask);
0909:                        slotCounter = 0;
0910:                        slotMask = 0;
0911:                    }
0912:                }
0913:
0914:                transactionFile.seek(objectEndOffset);
0915:                return tHandle.getTransactionOffset();
0916:            }
0917:
0918:            private static void deleteObject(IOTicket ioTicket,
0919:                    JODBSession session, TransactionHandle transactionHandle,
0920:                    TransactionContainer tContainer) throws IOException {
0921:                PersistentObjectHandle handle = transactionHandle.getHandle();
0922:                long persistentObjectOffset = handle.getObjectEntryOffset();
0923:                transactionHandle.setTransactionOffset(0);
0924:                deleteObject(ioTicket, session, persistentObjectOffset,
0925:                        tContainer);
0926:            }
0927:
0928:            private static void deleteObject(IOTicket ioTicket,
0929:                    JODBSession session, long persistentObjectOffset,
0930:                    TransactionContainer tContainer) throws IOException {
0931:                //ioTicket.getRandomAccessBuffer().seek(persistentObjectOffset);
0932:                IRandomAccessDataBuffer replacementsFile = tContainer
0933:                        .getTransactionReplacementsDataFile();
0934:                DataContainersCache dataContainersCache = TransactionUtils
0935:                        .getObjectDataContainerCache();
0936:                ObjectDataContainer container = dataContainersCache
0937:                        .pullObjectDataContainer();
0938:                //JODBIOUtils.readObjectHeader(ioTicket, container, false);
0939:                container.readHeader(ioTicket.getRandomAccessBuffer(),
0940:                        persistentObjectOffset, false);
0941:                replacementsFile
0942:                        .writeByte(TRANSACTION_REPLACEMENT_ENTRY_TYPE_STATIC);
0943:                replacementsFile.writeLong(persistentObjectOffset);//write offset of object to replace
0944:                replacementsFile.writeLong(0);//reserving space for entry's length
0945:                long entryOffsetStart = replacementsFile.getCursorOffset();
0946:                TransactionUtils.writeEmptyObjectEntry(replacementsFile,
0947:                        container.getBodyLength());
0948:                long entryEnd = replacementsFile.getCursorOffset();
0949:                long entryLength = entryEnd - entryOffsetStart;
0950:                replacementsFile.seek(entryOffsetStart - 8);//go back to entry's length
0951:                replacementsFile.writeLong(entryLength);
0952:                if (container.isRedirection()) {
0953:                    persistentObjectOffset = container.getOffset();
0954:                    deleteObject(ioTicket, session, persistentObjectOffset,
0955:                            tContainer);
0956:                }
0957:                dataContainersCache.pushObjectDataContainer(container);
0958:                replacementsFile.seek(entryEnd);
0959:            }
0960:
0961:            private static boolean checkActiveObjectUnchanged(
0962:                    IClassProcessor processor, JODBOperationContext context,
0963:                    Object obj, TransactionHandle tHandle,
0964:                    ObjectDataContainer persistentCopyObjectDataContainer,
0965:                    Vector<IndexingRecord> indexes) throws IOException,
0966:                    IllegalClassTypeException {
0967:                //TODO add mask verification
0968:                if (tHandle.isUnchanged()) {
0969:                    return true;
0970:                }
0971:                if (tHandle.isNewObject()) {
0972:                    return false;
0973:                }
0974:
0975:                FieldsIterator fieldsIterator = persistentCopyObjectDataContainer
0976:                        .readObject(context, tHandle.getHandle()
0977:                                .getObjectEntryOffset(), true, indexes);
0978:                if (fieldsIterator == null) {
0979:                    return false;
0980:                }
0981:                return processor.equals(obj, persistentCopyObjectDataContainer,
0982:                        context, null);
0983:
0984:            }
0985:
0986:            private static class ByteHolder {
0987:                public byte _value;
0988:
0989:                public ByteHolder() {
0990:                }
0991:
0992:                /**
0993:                 * @param value
0994:                 */
0995:                public ByteHolder(byte value) {
0996:                    super ();
0997:                    _value = value;
0998:                }
0999:
1000:            }
1001:
1002:            private static class ObjectFieldRecord {
1003:                public Field _field;
1004:                public Object _value;
1005:                public long _offset;
1006:
1007:                public ObjectFieldRecord(Field field, Object value) {
1008:                    super();
1009:                    _field = field;
1010:                    _value = value;
1011:                }
1012:
1013:            }
1014:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.