1 |
| |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| |
8 |
| package org.jboss.cache.pojo.impl; |
9 |
| |
10 |
| import org.apache.commons.logging.Log; |
11 |
| import org.apache.commons.logging.LogFactory; |
12 |
| import org.jboss.aop.advice.Interceptor; |
13 |
| import org.jboss.aop.proxy.ClassProxy; |
14 |
| import org.jboss.cache.Cache; |
15 |
| import org.jboss.cache.CacheException; |
16 |
| import org.jboss.cache.CacheSPI; |
17 |
| import org.jboss.cache.Fqn; |
18 |
| import org.jboss.cache.pojo.PojoCacheException; |
19 |
| import org.jboss.cache.pojo.collection.CollectionInterceptorUtil; |
20 |
| import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor; |
21 |
| import org.jboss.cache.pojo.interceptors.dynamic.BaseInterceptor; |
22 |
| |
23 |
| import java.util.Iterator; |
24 |
| import java.util.List; |
25 |
| import java.util.Map; |
26 |
| import java.util.Set; |
27 |
| |
28 |
| |
29 |
| |
30 |
| |
31 |
| |
32 |
| |
33 |
| |
34 |
| |
35 |
| class CollectionClassHandler |
36 |
| { |
37 |
| private final Log log = LogFactory.getLog(CollectionClassHandler.class); |
38 |
| private Cache<Object, Object> cache_; |
39 |
| private PojoCacheImpl pCache_; |
40 |
| private InternalHelper internal_; |
41 |
| |
42 |
499
| public CollectionClassHandler(PojoCacheImpl pCache, InternalHelper internal)
|
43 |
| { |
44 |
499
| pCache_ = pCache;
|
45 |
499
| cache_ = pCache_.getCache();
|
46 |
499
| internal_ = internal;
|
47 |
| } |
48 |
| |
49 |
75
| Object get(Fqn fqn, Class clazz, PojoInstance pojoInstance)
|
50 |
| throws CacheException |
51 |
| { |
52 |
75
| Object obj = null;
|
53 |
75
| try
|
54 |
| { |
55 |
75
| if (Map.class.isAssignableFrom(clazz))
|
56 |
| { |
57 |
6
| Object map = clazz.newInstance();
|
58 |
6
| obj = CollectionInterceptorUtil.createMapProxy(pCache_, fqn, clazz, (Map) map);
|
59 |
| } |
60 |
69
| else if (List.class.isAssignableFrom(clazz))
|
61 |
| { |
62 |
64
| Object list = clazz.newInstance();
|
63 |
64
| obj = CollectionInterceptorUtil.createListProxy(pCache_, fqn, clazz, (List) list);
|
64 |
| } |
65 |
5
| else if (Set.class.isAssignableFrom(clazz))
|
66 |
| { |
67 |
5
| Object set = clazz.newInstance();
|
68 |
5
| obj = CollectionInterceptorUtil.createSetProxy(pCache_, fqn, clazz, (Set) set);
|
69 |
| } |
70 |
| } |
71 |
| catch (Exception e) |
72 |
| { |
73 |
0
| throw new CacheException("failure creating proxy", e);
|
74 |
| } |
75 |
| |
76 |
75
| return obj;
|
77 |
| } |
78 |
| |
79 |
1673
| void put(Fqn fqn, Fqn referencingFqn, Object obj) throws CacheException
|
80 |
| { |
81 |
1673
| boolean isCollection = false;
|
82 |
| |
83 |
1673
| CachedType type = null;
|
84 |
1673
| if (obj instanceof ClassProxy)
|
85 |
| { |
86 |
0
| throw new IllegalStateException("CollectionClassHandler.put(): obj is an ClassProxy instance " + obj);
|
87 |
| } |
88 |
| |
89 |
1673
| type = pCache_.getCachedType(obj.getClass());
|
90 |
| |
91 |
| |
92 |
1673
| if (!(obj instanceof Map || obj instanceof List || obj instanceof Set))
|
93 |
| { |
94 |
0
| return;
|
95 |
| } |
96 |
| |
97 |
| |
98 |
1673
| PojoInstance pojoInstance = InternalHelper.initializeAopInstance(referencingFqn);
|
99 |
1673
| pojoInstance.set(obj);
|
100 |
1673
| pojoInstance.setPojoClass(type.getType());
|
101 |
1673
| cache_.put(fqn, PojoInstance.KEY, pojoInstance);
|
102 |
| |
103 |
1673
| if (obj instanceof Map)
|
104 |
| { |
105 |
104
| if (log.isDebugEnabled())
|
106 |
| { |
107 |
0
| log.debug("collectionPutObject(): aspectized obj is a Map type of size: " + ((Map) obj).size());
|
108 |
| } |
109 |
| |
110 |
| |
111 |
104
| Map map = (Map) obj;
|
112 |
104
| if (!(obj instanceof ClassProxy))
|
113 |
| { |
114 |
104
| Class clazz = obj.getClass();
|
115 |
104
| try
|
116 |
| { |
117 |
104
| obj = CollectionInterceptorUtil.createMapProxy(pCache_, fqn, clazz, (Map) obj);
|
118 |
| } |
119 |
| catch (Exception e) |
120 |
| { |
121 |
0
| throw new CacheException("failure creating proxy", e);
|
122 |
| } |
123 |
| |
124 |
104
| checkMapRecursion(map, obj);
|
125 |
| } |
126 |
| |
127 |
104
| isCollection = true;
|
128 |
| |
129 |
104
| for (Iterator i = map.entrySet().iterator(); i.hasNext();)
|
130 |
| { |
131 |
204
| Map.Entry entry = (Map.Entry) i.next();
|
132 |
204
| ((Map) obj).put(entry.getKey(), entry.getValue());
|
133 |
| } |
134 |
| |
135 |
| } |
136 |
1569
| else if (obj instanceof List)
|
137 |
| { |
138 |
1508
| if (log.isDebugEnabled())
|
139 |
| { |
140 |
0
| log.debug("collectionPutObject(): aspectized obj is a List type of size: "
|
141 |
| + ((List) obj).size()); |
142 |
| } |
143 |
| |
144 |
1508
| List list = (List) obj;
|
145 |
| |
146 |
| |
147 |
1508
| if (!(obj instanceof ClassProxy))
|
148 |
| { |
149 |
1508
| Class clazz = obj.getClass();
|
150 |
1508
| try
|
151 |
| { |
152 |
1508
| obj = CollectionInterceptorUtil.createListProxy(pCache_, fqn, clazz, (List) obj);
|
153 |
| } |
154 |
| catch (Exception e) |
155 |
| { |
156 |
0
| throw new CacheException("failure creating proxy", e);
|
157 |
| } |
158 |
| |
159 |
1508
| checkListRecursion(list, obj);
|
160 |
| } |
161 |
| |
162 |
1508
| isCollection = true;
|
163 |
| |
164 |
1508
| for (Iterator i = list.iterator(); i.hasNext();)
|
165 |
| { |
166 |
3134
| ((List) obj).add(i.next());
|
167 |
| } |
168 |
| |
169 |
| } |
170 |
61
| else if (obj instanceof Set)
|
171 |
| { |
172 |
61
| if (log.isDebugEnabled())
|
173 |
| { |
174 |
0
| log.debug("collectionPutObject(): aspectized obj is a Set type of size: "
|
175 |
| + ((Set) obj).size()); |
176 |
| } |
177 |
| |
178 |
61
| Set set = (Set) obj;
|
179 |
| |
180 |
| |
181 |
61
| if (!(obj instanceof ClassProxy))
|
182 |
| { |
183 |
61
| Class clazz = obj.getClass();
|
184 |
61
| try
|
185 |
| { |
186 |
61
| obj = CollectionInterceptorUtil.createSetProxy(pCache_, fqn, clazz, (Set) obj);
|
187 |
| } |
188 |
| catch (Exception e) |
189 |
| { |
190 |
0
| throw new CacheException("failure creating proxy", e);
|
191 |
| } |
192 |
| |
193 |
61
| checkSetRecursion(set, obj);
|
194 |
| } |
195 |
| |
196 |
61
| isCollection = true;
|
197 |
| |
198 |
61
| for (Iterator i = set.iterator(); i.hasNext();)
|
199 |
| { |
200 |
120
| ((Set) obj).add(i.next());
|
201 |
| } |
202 |
| |
203 |
| } |
204 |
| |
205 |
1672
| if (isCollection)
|
206 |
| { |
207 |
| |
208 |
1672
| pojoInstance.set(obj);
|
209 |
| |
210 |
1672
| BaseInterceptor baseInterceptor = (BaseInterceptor) CollectionInterceptorUtil.getInterceptor(
|
211 |
| (ClassProxy) obj); |
212 |
1672
| baseInterceptor.setAopInstance(pojoInstance);
|
213 |
| } |
214 |
| } |
215 |
| |
216 |
1508
| private void checkListRecursion(List list, Object obj)
|
217 |
| { |
218 |
1508
| while (true)
|
219 |
| { |
220 |
1509
| int i = list.indexOf(list);
|
221 |
1508
| if (i == -1) break;
|
222 |
| |
223 |
1
| list.remove(list);
|
224 |
1
| list.add(i, obj);
|
225 |
| } |
226 |
| } |
227 |
| |
228 |
61
| private void checkSetRecursion(Set set, Object obj)
|
229 |
| { |
230 |
61
| if (set.remove(set))
|
231 |
| { |
232 |
0
| set.add(obj);
|
233 |
0
| throw new PojoCacheException("CollectionClassHandler.checkSetRecursion(): " +
|
234 |
| "detect a recursive set (e.g., set inside the same set). This will fail to " + |
235 |
| "replicate even outside of PojoCache with HashSet. " + set); |
236 |
| } |
237 |
| } |
238 |
| |
239 |
104
| private void checkMapRecursion(Map map, Object obj)
|
240 |
| { |
241 |
104
| Map m = java.util.Collections.unmodifiableMap(map);
|
242 |
| |
243 |
104
| for (Object k : m.keySet())
|
244 |
| { |
245 |
204
| if (m == k)
|
246 |
| { |
247 |
0
| throw new PojoCacheException("CollectionClassHandler.checkMapRecursion(): " +
|
248 |
| " Can't handle the recursion map where it is nested in a constant key " + map); |
249 |
| } |
250 |
| |
251 |
204
| Object v = m.get(k);
|
252 |
204
| if (v == map)
|
253 |
| { |
254 |
0
| throw new PojoCacheException("CollectionClassHandler.checkMapRecursion(): " +
|
255 |
| "detect a recursive map (e.g., map inside the same map). This will fail to " + |
256 |
| "replicate even outside of PojoCache with HashMap because of hashCode. " + map); |
257 |
| |
258 |
| |
259 |
| } |
260 |
| } |
261 |
| } |
262 |
| |
263 |
1332
| Object remove(Fqn fqn, Object obj) throws CacheException
|
264 |
| { |
265 |
1332
| if (!(obj instanceof ClassProxy))
|
266 |
| { |
267 |
0
| throw new PojoCacheException("CollectionClassHandler.collectionRemoveObject(): object is not a proxy :" + obj);
|
268 |
| } |
269 |
| |
270 |
1332
| Interceptor interceptor = CollectionInterceptorUtil.getInterceptor((ClassProxy) obj);
|
271 |
1332
| boolean removeFromCache = true;
|
272 |
| |
273 |
1332
| ((AbstractCollectionInterceptor) interceptor).detach(removeFromCache);
|
274 |
1332
| return ((AbstractCollectionInterceptor) interceptor).getCurrentCopy();
|
275 |
| } |
276 |
| } |