001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.util;
005:
006: import com.tc.object.SerializationUtil;
007: import com.tc.object.TCObject;
008: import com.tc.object.bytecode.ManagerUtil;
009: import com.tc.object.lockmanager.api.LockLevel;
010:
011: import java.util.Collection;
012: import java.util.Hashtable;
013: import java.util.Iterator;
014: import java.util.Map.Entry;
015:
016: public class HashtableValuesWrapper implements Collection {
017:
018: private final Collection realValues;
019: private final Hashtable hashtable;
020:
021: public HashtableValuesWrapper(Hashtable hashtable,
022: Collection realValues) {
023: this .hashtable = hashtable;
024: this .realValues = realValues;
025: }
026:
027: public final boolean add(Object o) {
028: return realValues.add(o);
029: }
030:
031: public final boolean addAll(Collection c) {
032: return realValues.addAll(c);
033: }
034:
035: public final void clear() {
036: realValues.clear();
037: }
038:
039: public final boolean contains(Object o) {
040: return realValues.contains(o);
041: }
042:
043: public final boolean containsAll(Collection c) {
044: return realValues.containsAll(c);
045: }
046:
047: public final boolean equals(Object o) {
048: return realValues.equals(o);
049: }
050:
051: public final int hashCode() {
052: return realValues.hashCode();
053: }
054:
055: public final boolean isEmpty() {
056: return realValues.isEmpty();
057: }
058:
059: public final Iterator iterator() {
060: return new IteratorWrapper(hashtable, realValues.iterator());
061: }
062:
063: public final boolean remove(Object o) {
064: Iterator iter = iterator();
065: if (o == null) {
066: while (iter.hasNext()) {
067: if (iter.next() == null) {
068: iter.remove();
069: return true;
070: }
071: }
072: } else {
073: while (iter.hasNext()) {
074: if (o.equals(iter.next())) {
075: iter.remove();
076: return true;
077: }
078: }
079: }
080: return false;
081: }
082:
083: public final boolean removeAll(Collection c) {
084: boolean modified = false;
085: Iterator iter = iterator();
086: while (iter.hasNext()) {
087: if (c.contains(iter.next())) {
088: iter.remove();
089: modified = true;
090: }
091: }
092: return modified;
093: }
094:
095: public final boolean retainAll(Collection c) {
096: boolean modified = false;
097: Iterator i = iterator();
098: while (i.hasNext()) {
099: if (!c.contains(i.next())) {
100: i.remove();
101: modified = true;
102: }
103: }
104: return modified;
105: }
106:
107: public final int size() {
108: return realValues.size();
109: }
110:
111: public final Object[] toArray() {
112: return realValues.toArray();
113: }
114:
115: public final Object[] toArray(Object[] a) {
116: return realValues.toArray(a);
117: }
118:
119: private static class IteratorWrapper implements Iterator {
120:
121: private final Iterator realIterator;
122: private final Hashtable hashtable;
123: private Object lastValue;
124:
125: public IteratorWrapper(Hashtable hashtable,
126: Iterator realIterator) {
127: this .hashtable = hashtable;
128: this .realIterator = realIterator;
129: }
130:
131: public final boolean hasNext() {
132: return realIterator.hasNext();
133: }
134:
135: public final Object next() {
136: lastValue = realIterator.next();
137: return lastValue;
138: }
139:
140: public final void remove() {
141: // XXX: This linear scan of the hashtable to find the proper key is bad. The only way to it (I think) would be to
142: // instrument the actual hastable.values.iterator.remove code that has access to the key object right then and
143: // there
144: ManagerUtil.monitorEnter(hashtable, LockLevel.WRITE);
145:
146: try {
147: TCObject tco = ManagerUtil
148: .lookupExistingOrNull(hashtable);
149: Object key = null;
150: if (tco != null) {
151: // find the key object iff this is a managed hashtable
152: for (Iterator i = hashtable.entrySet().iterator(); i
153: .hasNext();) {
154: Entry entry = (Entry) i.next();
155: if (entry.getValue().equals(lastValue)) {
156: key = entry.getKey();
157: break;
158: }
159: }
160:
161: if (key == null) {
162: throw new AssertionError(
163: "Did not find key for value "
164: + lastValue);
165: }
166: }
167:
168: realIterator.remove();
169:
170: // the real itearator can throw an exception. Do DSO work iff no exception thrown
171: if (tco != null) {
172: ManagerUtil.logicalInvoke(hashtable,
173: SerializationUtil.REMOVE_KEY_SIGNATURE,
174: new Object[] { key });
175: }
176: } finally {
177: ManagerUtil.monitorExit(hashtable);
178: }
179: }
180: }
181:
182: }
|