1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.uif.util;
17
18 import java.lang.ref.Reference;
19 import java.lang.ref.WeakReference;
20 import java.lang.reflect.Field;
21 import java.lang.reflect.Modifier;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Queue;
27 import java.util.WeakHashMap;
28 import java.util.concurrent.ConcurrentLinkedQueue;
29
30
31
32
33
34
35
36
37
38
39
40
41 public final class RecycleUtils {
42
43
44
45
46 private final static Map<Class<?>, Reference<Queue<Object>>> RECYCLE =
47 Collections.synchronizedMap(new WeakHashMap<Class<?>, Reference<Queue<Object>>>());
48
49
50
51
52 private final static Map<Class<?>, List<Field>> FIELD_CACHE =
53 Collections.synchronizedMap(new WeakHashMap<Class<?>, List<Field>>());
54
55
56
57
58
59
60
61
62
63
64 public static <T> T getRecycledInstance(Class<T> c) {
65 return c.cast(getRecycleQueue(c).poll());
66 }
67
68
69
70
71
72
73
74
75
76
77 public static <T> T getInstance(Class<T> c) {
78 T rv = getRecycledInstance(c);
79
80 if (rv == null) {
81 try {
82 rv = c.newInstance();
83 } catch (InstantiationException e) {
84 throw new IllegalStateException("Unabled to instantiate " + c);
85 } catch (IllegalAccessException e) {
86 throw new IllegalStateException("Unabled to instantiate " + c);
87 }
88 }
89
90 return rv;
91 }
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 public static void recycle(Object instance) {
107 if (instance != null) {
108 getRecycleQueue(instance.getClass()).offer(instance);
109 }
110 }
111
112
113
114
115
116
117
118 public static <T> void clean(T instance) {
119 clean(instance, Object.class);
120 }
121
122
123
124
125
126
127
128
129 public static <T> void clean(T instance, Class<? super T> top) {
130 Class<?> c = instance.getClass();
131 while (c != null && c != top && top.isAssignableFrom(c)) {
132
133 List<Field> fields;
134 synchronized (FIELD_CACHE) {
135
136 fields = FIELD_CACHE.get(c);
137 if (fields == null) {
138 Field[] declared = c.getDeclaredFields();
139 fields = new ArrayList<Field>(declared.length);
140
141
142 for (Field field : fields) {
143 if ((field.getModifiers() & Modifier.STATIC) != Modifier.STATIC) {
144 field.setAccessible(true);
145 fields.add(field);
146 }
147 }
148
149 fields = Collections.unmodifiableList(fields);
150 FIELD_CACHE.put(c, fields);
151 }
152 }
153
154 for (Field field : fields) {
155 try {
156 Class<?> type = field.getType();
157
158 if (type.isPrimitive()) {
159
160 if (type == Integer.TYPE) {
161 field.set(instance, 0);
162 } else if (type == Boolean.TYPE) {
163 field.set(instance, false);
164 } else if (type == Long.TYPE) {
165 field.set(instance, 0L);
166 } else if (type == Character.TYPE) {
167 field.set(instance, '\0');
168 } else if (type == Double.TYPE) {
169 field.set(instance, 0.0);
170 } else if (type == Float.TYPE) {
171 field.set(instance, 0.0f);
172 } else if (type == Short.TYPE) {
173 field.set(instance, (short) 0);
174 } else if (type == Byte.TYPE) {
175 field.set(instance, (byte) 0);
176 }
177
178 } else {
179 field.set(instance, null);
180 }
181
182 } catch (IllegalAccessException e) {
183 throw new IllegalStateException("Unexpected error setting " + field, e);
184 }
185 }
186
187 c = c.getSuperclass();
188 }
189 }
190
191
192
193
194
195
196 private static Queue<Object> getRecycleQueue(Class<?> c) {
197 synchronized (RECYCLE) {
198 Reference<Queue<Object>> recycleQueueRef = RECYCLE.get(c);
199 Queue<Object> recycleQueue = recycleQueueRef == null ? null : recycleQueueRef.get();
200 if (recycleQueue == null) {
201 recycleQueue = new ConcurrentLinkedQueue<Object>();
202 RECYCLE.put(c, new WeakReference<Queue<Object>>(recycleQueue));
203 }
204
205 return recycleQueue;
206 }
207 }
208
209
210
211
212 private RecycleUtils() {}
213
214 }