KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > object > tx > ChangeListenerCollection


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
3  */

4 package com.tc.object.tx;
5
6 import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList;
7
8 import com.tc.util.Assert;
9
10 import java.lang.reflect.Method JavaDoc;
11 import java.util.Collection JavaDoc;
12 import java.util.IdentityHashMap JavaDoc;
13 import java.util.Iterator JavaDoc;
14 import java.util.Map JavaDoc;
15
16 /**
17  * L1 side change listener collection. At the moment the class doesn't do too much except hide the fact that we are
18  * using a CopyOnWriteArrayList as the actual implementation. In the future, we could hook into the add/remove methods
19  * to intelligently register/de-register change event interest with L2. Currently, once you register for change events,
20  * you'll ALWAYS get them forever
21  */

22 public class ChangeListenerCollection implements Collection JavaDoc {
23   private final Collection JavaDoc listeners = new CopyOnWriteArrayList();
24   private final String JavaDoc callbackMethod;
25   private final Map JavaDoc methodRefs = new IdentityHashMap JavaDoc();
26   private final Class JavaDoc[] callbackSignature;
27
28   public static class NoSuchCallbackException extends RuntimeException JavaDoc {
29     public NoSuchCallbackException(String JavaDoc msg) {
30       super(msg);
31     }
32   }
33
34   public ChangeListenerCollection(String JavaDoc callbackMethod) {
35     super();
36     Assert.assertNotNull("callbackmethod", callbackMethod);
37     this.callbackMethod = callbackMethod;
38     this.callbackSignature = new Class JavaDoc[] { Iterator JavaDoc.class };
39   }
40
41   public synchronized boolean add(Object JavaDoc obj) {
42     if (obj == null) { throw new NullPointerException JavaDoc("null not permitted in change listener collection"); }
43     findCallback(obj);
44     return listeners.add(obj);
45   }
46
47   private Method JavaDoc findCallback(Object JavaDoc o) {
48     // NOTE: you might be tempted to store the callback references by object.getClass() (not by instance). If you do
49
// that, you can't just drop the method on collection.remove(). You'd need to wait until all instance of that class
50
// are removed from the collection. Either that or never remove method references once you've looked one up for each
51
// class, but don't do that ;-). For now, store/remove a method reference per member of the collection
52

53     Assert.assertNotNull(o);
54
55     if (!methodRefs.containsKey(o)) {
56       try {
57         Method JavaDoc method = o.getClass().getDeclaredMethod(callbackMethod, callbackSignature);
58         method.setAccessible(true);
59         methodRefs.put(o, method);
60       } catch (Exception JavaDoc e) {
61         // make formatter sane
62
throw new NoSuchCallbackException(e.getClass().getName() + " occured trying to locate callback method named "
63                                           + callbackMethod + " on class " + o.getClass());
64       }
65     }
66
67     return (Method JavaDoc) methodRefs.get(o);
68   }
69
70   public boolean addAll(Collection JavaDoc c) {
71     throw new UnsupportedOperationException JavaDoc();
72   }
73
74   public synchronized void clear() {
75     listeners.clear();
76     methodRefs.clear();
77   }
78
79   public boolean contains(Object JavaDoc o) {
80     return listeners.contains(o);
81   }
82
83   public boolean containsAll(Collection JavaDoc c) {
84     throw new UnsupportedOperationException JavaDoc();
85   }
86
87   public boolean equals(Object JavaDoc obj) {
88     return this == obj;
89   }
90
91   public int hashCode() {
92     return listeners.hashCode();
93   }
94
95   public boolean isEmpty() {
96     return listeners.isEmpty();
97   }
98
99   public Iterator JavaDoc iterator() {
100     final Iterator JavaDoc internalIter = listeners.iterator();
101
102     return new Iterator JavaDoc() {
103       public void remove() {
104         // if we're going to support this, we need a way to clean up the methodRefs collection upon remove
105
throw new UnsupportedOperationException JavaDoc();
106       }
107
108       public boolean hasNext() {
109         return internalIter.hasNext();
110       }
111
112       public Object JavaDoc next() {
113         return internalIter.next();
114       }
115     };
116   }
117
118   public synchronized boolean remove(Object JavaDoc o) {
119     if (null == o) { return false; }
120     methodRefs.remove(o);
121     return listeners.remove(o);
122   }
123
124   public boolean removeAll(Collection JavaDoc c) {
125     throw new UnsupportedOperationException JavaDoc();
126   }
127
128   public boolean retainAll(Collection JavaDoc c) {
129     throw new UnsupportedOperationException JavaDoc();
130   }
131
132   public int size() {
133     return listeners.size();
134   }
135
136   public Object JavaDoc[] toArray() {
137     return listeners.toArray();
138   }
139
140   public Object JavaDoc[] toArray(Object JavaDoc[] a) {
141     return listeners.toArray(a);
142   }
143
144   public String JavaDoc toString() {
145     StringBuffer JavaDoc buf = new StringBuffer JavaDoc('[');
146
147     final Iterator JavaDoc iter = listeners.iterator();
148     boolean hasNext = iter.hasNext();
149     while (hasNext) {
150       Object JavaDoc obj = iter.next();
151       buf.append(obj == this ? "(this collection)" : String.valueOf(obj));
152       hasNext = iter.hasNext();
153       if (hasNext) buf.append(", ");
154     }
155
156     return buf.append(']').toString();
157   }
158
159   synchronized Method JavaDoc getCallbackFor(Object JavaDoc obj) {
160     Assert.assertNotNull(obj);
161     return (Method JavaDoc) methodRefs.get(obj);
162   }
163 }
Popular Tags