001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.object.util;
006:
007: import sun.misc.MessageUtils;
008:
009: import com.tc.exception.ExceptionWrapper;
010: import com.tc.exception.ExceptionWrapperImpl;
011:
012: import java.util.Map;
013: import java.util.WeakHashMap;
014:
015: /**
016: * This class extends WeakHashMap but uses reference identity semantics. A key thing is that this
017: * class relies on extending the instrumented version of WeakHashMap supplied by Terracotta in the
018: * boot jar. When this class is initialized, a test will be run to verify that the WeakHashMap
019: * that is loaded is indeed the instrumented version and if it is not, an AssertionError will be
020: * thrown indicating the reason.
021: */
022: public class IdentityWeakHashMap extends WeakHashMap {
023:
024: private static class TestKey {
025: final int val;
026: boolean hashCodeCalled = false;
027: boolean equalsCalled = false;
028:
029: TestKey(int val) {
030: this .val = val;
031: }
032:
033: public int hashCode() {
034: // this shouldn't be happening, IdentityWeakHashMap should be using System.identityHashcode()
035: hashCodeCalled = true;
036: return val;
037: }
038:
039: public boolean equals(Object obj) {
040: // this shouldn't be happening, IdentityWeakHashMap should be using ==
041: equalsCalled = true;
042: return (obj instanceof TestKey)
043: && ((TestKey) obj).val == this .val;
044: }
045: }
046:
047: static {
048: /**
049: * This static block is to validate the WeakHashMap superclass is the DSO instrumented version. If not, this class
050: * will function incorrectly.
051: */
052:
053: IdentityWeakHashMap m = new IdentityWeakHashMap();
054: TestKey k1 = new TestKey(10); // strongly reference the Integer object so that the garbage collector
055: TestKey k2 = new TestKey(10); // will not kick in before the check for m.size().
056: m.put(k1, "first");
057: m.put(k2, "second");
058: if (m.size() != 2 || k1.hashCodeCalled || k1.equalsCalled
059: || k2.hashCodeCalled || k1.equalsCalled) {
060: ExceptionWrapper wrapper = new ExceptionWrapperImpl();
061: String errorMsg = wrapper
062: .wrap("WeakHashMap does not seem to contain the instrumented method.\n"
063: + "IdentityWeakHashMap can only be used with the Terracotta instrumented version of WeakHashMap.\n"
064: + "One possible cause is that WeakHashMap is not contained in the boot jar.");
065: MessageUtils.toStderr(errorMsg);
066: throw new AssertionError(errorMsg);
067: }
068: }
069:
070: public IdentityWeakHashMap(int initialCapacity, float loadFactor) {
071: super (initialCapacity, loadFactor);
072: }
073:
074: public IdentityWeakHashMap(int initialCapacity) {
075: super (initialCapacity);
076: }
077:
078: public IdentityWeakHashMap() {
079: super ();
080: }
081:
082: public IdentityWeakHashMap(Map m) {
083: super (m);
084: }
085:
086: protected int __tc_hash(Object x) {
087: int h = System.identityHashCode(x);
088:
089: h += ~(h << 9);
090: h ^= (h >>> 14);
091: h += (h << 4);
092: h ^= (h >>> 10);
093: return h;
094: }
095:
096: protected boolean __tc_equal(Object obj1, Object obj2) {
097: return obj1 == obj2;
098: }
099:
100: protected Object clone() throws CloneNotSupportedException {
101: return super.clone();
102: }
103:
104: }
|