Source Code Cross Referenced for ObjectTracker.java in  » Database-ORM » beankeeper » hu » netmind » persistence » 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 ORM » beankeeper » hu.netmind.persistence 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * Copyright (C) 2006 NetMind Consulting Bt.
003:         *
004:         * This library is free software; you can redistribute it and/or
005:         * modify it under the terms of the GNU Lesser General Public
006:         * License as published by the Free Software Foundation; either
007:         * version 3 of the License, or (at your option) any later version.
008:         *
009:         * This library is distributed in the hope that it will be useful,
010:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
011:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
012:         * Lesser General Public License for more details.
013:         *
014:         * You should have received a copy of the GNU Lesser General Public
015:         * License along with this library; if not, write to the Free Software
016:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
017:         */package hu.netmind.persistence;
018:
019:        import java.util.*;
020:        import java.lang.ref.WeakReference;
021:        import org.apache.log4j.Logger;
022:
023:        /**
024:         * This class tracks objects' ids and values for different transactions.
025:         * Basically this tracker can answer questions about the state of a
026:         * previously registered object.<br>
027:         * @author Brautigam Robert
028:         * @version Revision: $Revision$
029:         */
030:        public class ObjectTracker implements  TransactionListener,
031:                WeakMapListener {
032:            private static Logger logger = Logger
033:                    .getLogger(ObjectTracker.class);
034:            private static ProfileLogger profLogger = ProfileLogger.getLogger();
035:
036:            private StoreContext context;
037:            private Random random;
038:            private WeakMap objectData;
039:            private HashMap sharedData;
040:
041:            ObjectTracker(StoreContext context) {
042:                this .context = context;
043:                random = new Random();
044:                sharedData = new HashMap();
045:                objectData = new WeakMap();
046:                objectData.setListener(this );
047:                ensureTrackTableExists();
048:                context.getTransactionTracker().addListener(this );
049:            }
050:
051:            /**
052:             * Get the data structure for an object.
053:             */
054:            public ObjectData getObjectData(Object obj) {
055:                // Only the objectData needs to be synchronized, because only one
056:                // transaction can write these objects at a given time. So many
057:                // readers may be using the objectdata at a time, but only
058:                // one can write it.
059:                synchronized (objectData) {
060:                    return (ObjectData) objectData.get(obj);
061:                }
062:            }
063:
064:            /**
065:             * Return whether a given attribute of a given object changed.
066:             */
067:            public boolean hasChanged(ClassInfo info, Object obj,
068:                    String attributeName, Map dbAttributes) {
069:                // If object does no exists, then all attributes are changed. If
070:                // object exists, then the dbAttributes contains the current
071:                // attributes, as found in the database.
072:                if (!exists(obj))
073:                    return true;
074:                // Get values  
075:                Object value = info.getAttributeValue(obj, attributeName);
076:                Object oldValue = getAttributeValue(obj, attributeName);
077:                Object dbValue = dbAttributes.get(attributeName);
078:                // Check nulls
079:                if ((dbValue == null) && (value == null)) {
080:                    logger.debug("both values were null, not changed.");
081:                    return false;
082:                }
083:                if (((dbValue != null) && (value == null))
084:                        || ((dbValue == null) && (value != null))) {
085:                    logger
086:                            .debug("one value was null, and the other non-null, so changed.");
087:                    return true;
088:                }
089:                // Check handled types
090:                Class type = info.getAttributeType(attributeName);
091:                if (context.getTypeHandlerTracker().isHandled(type)) {
092:                    TypeHandler handler = context.getTypeHandlerTracker()
093:                            .getHandler(type);
094:                    boolean result = handler.hasChanged(info, obj,
095:                            attributeName, dbAttributes);
096:                    logger.debug("value was a tracked object, result will be: "
097:                            + result);
098:                    return result;
099:                }
100:                // Check byte array
101:                if (dbValue instanceof  byte[]) {
102:                    boolean result = !Arrays.equals((byte[]) dbValue,
103:                            (byte[]) value);
104:                    logger.debug("values were byte arrays, changed: " + result);
105:                    return result;
106:                }
107:                // Check custom objects, in which case the dbValue is a persistence_id,
108:                // and the 'value' is an object.
109:                if (context.getClassTracker().getType(value.getClass()) == ClassTracker.TYPE_OBJECT) {
110:                    boolean result = !new Long(getIdentifier(value))
111:                            .equals(dbValue);
112:                    logger
113:                            .debug("value was a custom object, it's persistence id changed: "
114:                                    + result);
115:                    return result;
116:
117:                }
118:                // Fallback to equals()
119:                boolean result = !value.equals(dbValue);
120:                logger.debug("comparing values with equals(), changed: "
121:                        + result + " (" + value.getClass().getName()
122:                        + " vs. db " + dbValue.getClass().getName() + ")");
123:                return result;
124:            }
125:
126:            /**
127:             * Determines, whether two objects are of the same database instance.
128:             * Two objects are the same, if their ids equal. Note however, that
129:             * they do not need to contain the same values, or be of same version!
130:             */
131:            public boolean equals(Object o1, Object o2) {
132:                long id1 = getIdentifier(o1);
133:                long id2 = getIdentifier(o2);
134:                return (o1 == o2) || ((id1 != 0) && (id2 != 0) && (id1 == id2));
135:            }
136:
137:            /**
138:             * Return the attribute's last known value. The last known value is
139:             * determined as follows: If the value changed during current transaction,
140:             * the new value is returned, or else the last known saved value is
141:             * returned. That means, if a transaction currently changes this
142:             * attribute, another transaction will see the old value until the
143:             * first transaction commits.
144:             */
145:            public Object getAttributeValue(Object obj, String attributeName) {
146:                ObjectData data = getObjectData(obj);
147:                // Following block does not need synchronizing because only one thread
148:                // can write OR read the data.
149:                //
150:                // Get attribute from transactional attributes first (Note: only
151:                // one transaction can modify the object).
152:                Map txAttributes = (Map) data.getTransactionAttributes();
153:                if (txAttributes != null) {
154:                    Object value = txAttributes.get(attributeName);
155:                    if (value != null)
156:                        return value;
157:                }
158:                // No transactional attributes, so return global ones
159:                return data.getAttributes().get(attributeName);
160:            }
161:
162:            /**
163:             * Update a single attribute. This method simply calls <code>updateObject()</code>.
164:             */
165:            public void updateAttribute(Object obj, String identifier,
166:                    Object value) {
167:                HashMap changes = new HashMap();
168:                changes.put(identifier, value);
169:                updateObject(obj, changes);
170:            }
171:
172:            /**
173:             * Update the attribute's known values with those given. Note, that
174:             * this method will first make the changes only in current transaction,
175:             * and only publish them when the current transaction commits.
176:             */
177:            public void updateObject(Object obj, Map changes) {
178:                // Warning: do not print changes here, because toString() might
179:                // screw up lazy list loading.
180:                logger.debug("updating object.");
181:                // Update object's tracked attributes
182:                ObjectData data = getObjectData(obj);
183:                // Does not need synchronizing
184:                data.getTransactionAttributes().putAll(changes);
185:            }
186:
187:            /**
188:             * Determine whether an object exists.
189:             * @return True, if object exists in store. This means that searches
190:             * will return the object. If this is false, the object cannot be
191:             * found yet.
192:             */
193:            public boolean exists(Object obj) {
194:                ObjectData data = getObjectData(obj);
195:                if (data == null)
196:                    return false;
197:                return data.currentlyExists();
198:            }
199:
200:            /**
201:             * Mark object as existent. If this is inside a transaction,
202:             * the existence will only be permanent, if object is saved inside
203:             * the transaction.
204:             */
205:            public void makeExist(Object obj) {
206:                ObjectData data = getObjectData(obj);
207:                if (data != null)
208:                    data.setCurrentlyExists(true);
209:            }
210:
211:            /**
212:             * Mark an object as non-existent. This happens, if the object gets
213:             * deleted, but there are some object instances that are used.
214:             */
215:            public void makeUnexist(Object obj) {
216:                ObjectData data = getObjectData(obj);
217:                if (data != null) {
218:                    data.setExists(false);
219:                    data.setCurrentlyExists(false);
220:                }
221:            }
222:
223:            /**
224:             * Register an object into the tracker. This means, the object will
225:             * get an id, and associated tracking data structure will be allocated.
226:             * @param obj The object to register.
227:             * @param id The id of object. If this is given (not 0), the object is 
228:             * assumed to exist.
229:             */
230:            public void registerObject(Object obj, long id) {
231:                ObjectData data = getObjectData(obj);
232:                if (data != null)
233:                    return;
234:                // Create object data
235:                data = new ObjectData();
236:                if (id == 0) {
237:                    data.setId(nextId(obj));
238:                    data.setExists(false);
239:                    data.setCurrentlyExists(false);
240:                } else {
241:                    data.setId(id);
242:                    data.setExists(true);
243:                    data.setCurrentlyExists(true);
244:                }
245:                PersistenceMetaData metaData = new PersistenceMetaData();
246:                data.setMetaData(metaData);
247:                metaData.setPersistenceId(new Long(data.getId()));
248:                metaData.setObjectClass(obj.getClass());
249:                synchronized (objectData) {
250:                    objectData.put(obj, data, new Long(data.getId()));
251:                    // Create shared state, if not present
252:                    SharedData sData = data.getSharedData();
253:                    if (sData == null)
254:                        sData = new SharedData();
255:                    else
256:                        sData.setRefCounter(sData.getRefCounter() + 1);
257:                    sharedData.put(new Long(data.getId()), sData);
258:                }
259:                // Profile
260:                profLogger.profile("sharedmap", "Shared data size is: "
261:                        + sharedData.size());
262:            }
263:
264:            /**
265:             * Called when an object leaves the weak map. Note: This is thread-safe
266:             * because it is called from WeakMap, which is handled safely in this
267:             * class.
268:             */
269:            public void notifyValueLeave(Object id) {
270:                // Object is leaving weakmap, so remove shared state too if nescessary.
271:                SharedData data = (SharedData) sharedData.get(id);
272:                // Decrease count, remove if no object reference it
273:                data.setRefCounter(data.getRefCounter() - 1);
274:                if (data.getRefCounter() <= 0)
275:                    sharedData.remove(id);
276:            }
277:
278:            /**
279:             * Get the identifier for a given object.
280:             * @param obj The object to identify.
281:             * @return The identifier, or 0 if the object is not registered.
282:             */
283:            public long getIdentifier(Object obj) {
284:                ObjectData data = getObjectData(obj);
285:                if (data == null)
286:                    return 0;
287:                return data.getId();
288:            }
289:
290:            /**
291:             * Get the meta data associated with the object.
292:             */
293:            public PersistenceMetaData getMetaData(Object obj) {
294:                // Register to be sure
295:                registerObject(obj, 0);
296:                // Get the metadata
297:                return getObjectData(obj).getMetaData();
298:            }
299:
300:            /**
301:             * Ensure that the given table exists.
302:             */
303:            private void ensureTrackTableExists() {
304:                Transaction transaction = context.getTransactionTracker()
305:                        .getTransaction(TransactionTracker.TX_NEW);
306:                transaction.begin();
307:                try {
308:                    // Create table schema
309:                    Map tableSchema = new HashMap();
310:                    tableSchema.put("persistence_id", Long.class);
311:                    tableSchema.put("object_table", String.class);
312:                    Vector keySchema = new Vector();
313:                    keySchema.add("persistence_id");
314:                    // Ensure it exists
315:                    context.getDatabase().ensureTable(transaction,
316:                            "persistence_object_ids", tableSchema, keySchema,
317:                            true);
318:                } catch (StoreException e) {
319:                    transaction.markRollbackOnly();
320:                    throw e;
321:                } catch (Throwable e) {
322:                    transaction.markRollbackOnly();
323:                    throw new StoreException("unexpected exception.", e);
324:                } finally {
325:                    transaction.commit();
326:                }
327:            }
328:
329:            /**
330:             * Generates the next unique id, also it inserts record to
331:             * database, that the given id has been used.
332:             * <i>Implementation note:</i>This methods tries to find a unique
333:             * id until it finds one, possibly looking forever. Method could
334:             * contain a lookup limit, but there is no resonable limit. A chance
335:             * of catching a used id in a 64 bit space with a billion records
336:             * is still one-to-billion.<br>
337:             * <i>Note:</i>This method is thread-safe, it uses the database
338:             * for determining the id is correct.
339:             * @param obj The object to get the id for.
340:             */
341:            private long nextId(Object obj) {
342:                long result = 0;
343:                while (result == 0) {
344:                    Transaction transaction = context.getTransactionTracker()
345:                            .getTransaction(TransactionTracker.TX_NEW);
346:                    transaction.begin();
347:                    try {
348:                        ClassInfo classInfo = context.getClassTracker()
349:                                .getClassInfo(obj.getClass(), obj);
350:                        // Generate random number, and record
351:                        result = random.nextLong() + 1;
352:                        result = Math.abs(result);
353:                        Map entry = new HashMap();
354:                        entry.put("persistence_id", new Long(result));
355:                        entry.put("object_table", classInfo
356:                                .getTableName(classInfo.getSourceEntry()));
357:                        // Insert record
358:                        context.getDatabase().insert(transaction,
359:                                "persistence_object_ids", entry);
360:                    } catch (AlreadyExistsException e) {
361:                        // If already exists
362:                        result = 0;
363:                        transaction.markRollbackOnly();
364:                    } catch (StoreException e) {
365:                        transaction.markRollbackOnly();
366:                        throw e;
367:                    } catch (Throwable e) {
368:                        transaction.markRollbackOnly();
369:                        throw new StoreException("unexpected error.", e);
370:                    } finally {
371:                        transaction.commit();
372:                    }
373:                }
374:                return result;
375:            }
376:
377:            /**
378:             * Called, when transaction tracker commits a transaction successfully.
379:             * This tracker uses it to set object to exists and not exists state.
380:             * @param transaction The transaction which committed.
381:             */
382:            public void transactionCommited(Transaction transaction) {
383:                logger.debug("transaction commited");
384:                // All saved objects will be set to 'exists' state.
385:                List savedObjects = transaction.getSavedObjects();
386:                for (int i = 0; i < savedObjects.size(); i++) {
387:                    // If object was saved, it exists, so set exists flag
388:                    Object obj = ((ObjectWrapper) savedObjects.get(i))
389:                            .getObject();
390:                    ObjectData data = (ObjectData) getObjectData(obj);
391:                    if (data == null)
392:                        logger
393:                                .warn("something may be wrong, an object commited which was not tracked, object was: "
394:                                        + obj);
395:                    else {
396:                        // Object now exists
397:                        data.setExists(true);
398:                        data.setCurrentlyExists(true);
399:                        // Now check, whether object had transactional attributes.
400:                        // If it had, copy them to global ones
401:                        // Note: following block does not need synchronizing
402:                        Map txAttributes = (Map) data
403:                                .getTransactionAttributes();
404:                        if (txAttributes != null) {
405:                            data.setTransactionAttributes(new HashMap());
406:                            data.getAttributes().putAll(txAttributes);
407:                        }
408:                    }
409:                }
410:                // All removed objects will be set to 'not exists' state.
411:                List removedObjects = transaction.getRemovedObjects();
412:                for (int i = 0; i < removedObjects.size(); i++) {
413:                    Object obj = ((ObjectWrapper) removedObjects.get(i))
414:                            .getObject();
415:                    ObjectData data = (ObjectData) getObjectData(obj);
416:                    if (data == null)
417:                        logger
418:                                .warn("something may be wrong, an object commited (for remove) which was not tracked, object was: "
419:                                        + obj);
420:                    else {
421:                        // Clear all data of object. Set exists to 'false'.
422:                        data.setExists(false);
423:                        data.setCurrentlyExists(false);
424:                        data.setAttributes(new HashMap());
425:                        data.setTransactionAttributes(new HashMap());
426:                    }
427:                }
428:            }
429:
430:            /**
431:             * Convert a value of a type to a given target type.
432:             */
433:            public static Object getTypeValue(Object value, Class attrClass) {
434:                Class valueClass = null;
435:                // Check if value is null, note that primitive types will
436:                // have a sane default if confronted with null
437:                if (value == null) {
438:                    if (attrClass.equals(byte.class))
439:                        return new Byte((byte) 0);
440:                    else if (attrClass.equals(double.class))
441:                        return new Double(0);
442:                    else if (attrClass.equals(float.class))
443:                        return new Float(0);
444:                    else if (attrClass.equals(int.class))
445:                        return new Integer(0);
446:                    else if (attrClass.equals(long.class))
447:                        return new Long(0);
448:                    else if (attrClass.equals(short.class))
449:                        return new Short((short) 0);
450:                    else if (attrClass.equals(boolean.class))
451:                        return new Boolean(false);
452:                    else if (attrClass.equals(char.class))
453:                        return new Character('\u0000');
454:                    return null;
455:                }
456:                valueClass = value.getClass();
457:                // Handle primitive types with exceptional circumstances
458:                if ((attrClass.equals(Character.class))
459:                        || (attrClass.equals(char.class))
460:                        && (valueClass.equals(String.class))) {
461:                    if (((String) value).length() > 0)
462:                        return new Character(((String) value).charAt(0));
463:                }
464:                // Byte array
465:                else if (attrClass.equals(byte[].class))
466:                    return value;
467:                // Boolean
468:                else if ((attrClass.equals(Boolean.class) || attrClass
469:                        .equals(boolean.class))
470:                        && ((valueClass.equals(Integer.class)) || (valueClass
471:                                .equals(Long.class)))) {
472:                    return new Boolean(((Number) value).intValue() > 0);
473:                }
474:                // Easy primitive classes
475:                else if (valueClass.equals(String.class)
476:                        || valueClass.equals(Date.class)
477:                        || valueClass.equals(Boolean.class))
478:                    return value;
479:                // Container classes
480:                else if ((value instanceof  Map) || (value instanceof  List))
481:                    return value;
482:                // Not easy number classes
483:                else if (value instanceof  Number) {
484:                    Number number = (Number) value;
485:                    if (attrClass.equals(Byte.class)
486:                            || attrClass.equals(byte.class))
487:                        return new Byte(number.byteValue());
488:                    if (attrClass.equals(Double.class)
489:                            || attrClass.equals(double.class))
490:                        return new Double(number.doubleValue());
491:                    if (attrClass.equals(Float.class)
492:                            || attrClass.equals(float.class))
493:                        return new Float(number.floatValue());
494:                    if (attrClass.equals(Integer.class)
495:                            || attrClass.equals(int.class))
496:                        return new Integer(number.intValue());
497:                    if (attrClass.equals(Long.class)
498:                            || attrClass.equals(long.class))
499:                        return new Long(number.longValue());
500:                    if (attrClass.equals(Short.class)
501:                            || attrClass.equals(short.class))
502:                        return new Short(number.shortValue());
503:                }
504:                // All other objects
505:                return value;
506:            }
507:
508:            /**
509:             * Called, when transaction tracker rolls back a transaction successfully.
510:             * @param transaction The transaction which rolled back.
511:             */
512:            public void transactionRolledback(Transaction transaction) {
513:                logger.debug("transaction rolled back");
514:                // We must discard all transaction references
515:                List savedObjects = transaction.getSavedObjects();
516:                for (int i = 0; i < savedObjects.size(); i++) {
517:                    Object obj = ((ObjectWrapper) savedObjects.get(i))
518:                            .getObject();
519:                    ObjectData data = (ObjectData) getObjectData(obj);
520:                    if (data == null)
521:                        logger
522:                                .warn("something may be wrong, an object rolled back which was not tracked, object was: "
523:                                        + obj);
524:                    else {
525:                        // Set current exists flag to stable exists flag
526:                        data.setCurrentlyExists(data.exists());
527:                        // Does not need synchronizing
528:                        data.setTransactionAttributes(new HashMap());
529:                    }
530:                }
531:                // All removed objects
532:                List removedObjects = transaction.getRemovedObjects();
533:                for (int i = 0; i < removedObjects.size(); i++) {
534:                    Object obj = ((ObjectWrapper) removedObjects.get(i))
535:                            .getObject();
536:                    ObjectData data = (ObjectData) getObjectData(obj);
537:                    if (data == null)
538:                        logger
539:                                .warn("something may be wrong, an object rolled back (for remove) which was not tracked, object was: "
540:                                        + obj);
541:                    else {
542:                        // Set current exists flag to stable exists flag
543:                        data.setCurrentlyExists(data.exists());
544:                        // Does not need synchronizing
545:                        data.setTransactionAttributes(new HashMap());
546:                    }
547:                }
548:            }
549:
550:            /**
551:             * Get an object wrapper for an object which disregards object's
552:             * own equals() and hashCode() methods.
553:             */
554:            public ObjectWrapper getWrapper(Object obj) {
555:                return new ObjectWrapper(obj);
556:            }
557:
558:            /**
559:             * Search for an item in a list based on id.
560:             */
561:            /**
562:             * This is the structure tracked for an object.
563:             */
564:            public class ObjectData implements  Comparable {
565:                private long id;
566:                private boolean exists;
567:                private boolean currentlyExists; // Inside transaction it may differ from 'exists'.
568:                private Map transactionAttributes;
569:                private Map attributes;
570:                private PersistenceMetaData metaData;
571:
572:                public ObjectData() {
573:                    transactionAttributes = new HashMap();
574:                    attributes = new HashMap();
575:                }
576:
577:                public PersistenceMetaData getMetaData() {
578:                    return metaData;
579:                }
580:
581:                public void setMetaData(PersistenceMetaData metaData) {
582:                    this .metaData = metaData;
583:                }
584:
585:                public int compareTo(Object obj) {
586:                    return new Long(id).compareTo(new Long(
587:                            ((ObjectData) obj).id));
588:                }
589:
590:                public SharedData getSharedData() {
591:                    return (SharedData) sharedData.get(new Long(id));
592:                }
593:
594:                public long getId() {
595:                    return id;
596:                }
597:
598:                private void setId(long id) {
599:                    this .id = id;
600:                }
601:
602:                private Map getTransactionAttributes() {
603:                    return transactionAttributes;
604:                }
605:
606:                private void setTransactionAttributes(Map transactionAttributes) {
607:                    this .transactionAttributes = transactionAttributes;
608:                }
609:
610:                public boolean exists() {
611:                    return exists;
612:                }
613:
614:                private void setExists(boolean exists) {
615:                    this .exists = exists;
616:                }
617:
618:                private boolean currentlyExists() {
619:                    return currentlyExists;
620:                }
621:
622:                public void setCurrentlyExists(boolean currentlyExists) {
623:                    this .currentlyExists = currentlyExists;
624:                }
625:
626:                private Map getAttributes() {
627:                    return attributes;
628:                }
629:
630:                private void setAttributes(Map attributes) {
631:                    this .attributes = attributes;
632:                }
633:            }
634:
635:            /**
636:             * This is a structure which is shared for objects of the same id.
637:             */
638:            public class SharedData {
639:                private int refCounter;
640:
641:                public SharedData() {
642:                    refCounter = 1;
643:                }
644:
645:                public int getRefCounter() {
646:                    return refCounter;
647:                }
648:
649:                public void setRefCounter(int refCounter) {
650:                    this .refCounter = refCounter;
651:                }
652:
653:            }
654:
655:            public class ObjectWrapper {
656:                private Object obj;
657:                private long id;
658:
659:                public ObjectWrapper(Object obj) {
660:                    this .obj = obj;
661:                    registerObject(obj, 0);
662:                    this .id = ObjectTracker.this .getIdentifier(obj);
663:                }
664:
665:                public long getIdentifier() {
666:                    return id;
667:                }
668:
669:                public Object getObject() {
670:                    return obj;
671:                }
672:
673:                public int hashCode() {
674:                    return (int) (id >> 32);
675:                }
676:
677:                public boolean equals(Object rhs) {
678:                    if (!(rhs instanceof  ObjectWrapper))
679:                        return false;
680:                    return id == ((ObjectWrapper) rhs).id;
681:                }
682:            }
683:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.