1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.gridsystems.innergrid.kernel.genericutils;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.concurrent.atomic.AtomicLong;
26
27 import org.apache.commons.lang.NullArgumentException;
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31 import com.gridsystems.exceptions.PagedRequestException;
32 import com.gridsystems.exceptions.PagedRequestNotAllowedException;
33 import com.gridsystems.exceptions.PagedRequestNotFoundException;
34 import com.gridsystems.innergrid.kernel.server.KernelContext;
35
36
37
38
39
40
41
42
43
44
45 public final class PagedRequestManager<E extends PagedRequest<?>> {
46
47
48
49 private static final long DEFAULT_TIMEOUT = 200000;
50
51
52
53
54 private static final long DEFAULT_SLEEP = 60000;
55
56
57
58
59 private static final Log LOG = LogFactory.getLog(PagedRequestManager.class);
60
61
62
63
64 private static final AtomicLong CLEAN_THREAD_ID = new AtomicLong(0);
65
66
67
68
69 private CleaningThread cleanThread = null;
70
71
72
73
74
75 private long timeoutThreshold = DEFAULT_TIMEOUT;
76
77
78
79
80 private long cleanSleep = DEFAULT_SLEEP;
81
82
83
84
85 private Map<Long, E> pagedRequests
86 = Collections.synchronizedMap(new HashMap<Long, E>());
87
88
89
90
91 public PagedRequestManager() {
92 }
93
94
95
96
97 @Override protected void finalize() throws Throwable {
98 removeAllPagedRequest();
99 super.finalize();
100 }
101
102
103
104
105 private void initCleaner() {
106 if (this.cleanThread == null) {
107 this.cleanThread = new CleaningThread(CLEAN_THREAD_ID.addAndGet(1L));
108 this.cleanThread.start();
109 }
110 }
111
112
113
114
115 private void disposeCleaner() {
116 if (this.cleanThread != null) {
117 this.cleanThread.interrupt();
118 this.cleanThread = null;
119 }
120 }
121
122
123
124
125
126
127
128 public void addPagedRequest(E req) throws NullArgumentException {
129 if (req == null) {
130 throw new NullArgumentException("req");
131 }
132
133 initCleaner();
134 pagedRequests.put(Long.valueOf(req.getId()), req);
135 }
136
137
138
139
140
141
142
143
144
145
146 public E getPagedRequest(long id)
147 throws PagedRequestNotFoundException, PagedRequestNotAllowedException {
148 return getPagedRequest(id, true);
149 }
150
151
152
153
154
155
156
157
158
159
160
161 private E getPagedRequest(long id, boolean secure)
162 throws PagedRequestNotFoundException, PagedRequestNotAllowedException {
163 E req = pagedRequests.get(id);
164
165 if (req == null) {
166 throw new PagedRequestNotFoundException();
167 }
168
169 String currentUserName = KernelContext.getContext().getUserName();
170 if (secure && (currentUserName != null) && !currentUserName.equals(req.getUser())) {
171 throw new PagedRequestNotAllowedException();
172 }
173
174 return req;
175 }
176
177
178
179
180
181 public List<E> getAllPagedRequests() {
182 List<E> list = new ArrayList<E>(pagedRequests.values());
183 return list;
184 }
185
186
187
188
189
190
191 public int getPagedRequestsSize() {
192 return pagedRequests.size();
193 }
194
195
196
197
198 public void removeAllPagedRequest() {
199 final int count = this.pagedRequests.keySet().size();
200 Long[] ids = this.pagedRequests.keySet().toArray(new Long[count]);
201 for (Long id : ids) {
202 try {
203 removePagedRequest(id, false);
204 } catch (PagedRequestException e) {
205 LOG.error("Exception thrown when removing paged request " + id, e);
206 }
207 }
208 }
209
210
211
212
213
214
215
216
217
218 public void removePagedRequest(long id)
219 throws PagedRequestNotFoundException, PagedRequestNotAllowedException {
220 removePagedRequest(id, true);
221 }
222
223
224
225
226
227
228
229
230
231
232 private void removePagedRequest(long id, boolean secure)
233 throws PagedRequestNotFoundException, PagedRequestNotAllowedException {
234
235 E pr = getPagedRequest(id, secure);
236
237 try {
238 pr.clear();
239 } catch (Exception e) {
240 LOG.error("Unable to clear Paged Request number " + id);
241 }
242
243
244 pagedRequests.remove(id);
245
246 if (pagedRequests.isEmpty()) {
247 disposeCleaner();
248 }
249 }
250
251
252
253
254
255
256
257 @Override public String toString() {
258 return "PagedRequestManager { requests number = " + pagedRequests.size()
259 + ", timeout limit = " + timeoutThreshold + " }";
260 }
261
262
263
264
265 class CleaningThread extends Thread {
266
267
268
269
270 public CleaningThread(long id) {
271 setName("CleaningThread-" + id);
272 setDaemon(true);
273 }
274
275
276
277
278
279 @Override public void run() {
280 while (!isInterrupted()) {
281
282 long now = System.currentTimeMillis();
283 ArrayList<E> toRemove = new ArrayList<E>();
284 synchronized (pagedRequests) {
285 Iterator<E> it = pagedRequests.values().iterator();
286 while (it.hasNext()) {
287 E pr = it.next();
288 if (now - pr.getLastAccessTime() > timeoutThreshold) {
289 toRemove.add(pr);
290 }
291 }
292 }
293
294
295 Iterator<E> it = toRemove.iterator();
296 while (it.hasNext()) {
297 E req = it.next();
298 long id = req.getId();
299 try {
300 removePagedRequest(id, false);
301 } catch (PagedRequestNotFoundException e) {
302 LOG.warn("Paged Request " + id + " could not be removed: not found");
303 } catch (PagedRequestNotAllowedException e) {
304 LOG.warn("Paged Request " + id + " could not be removed: not allowed");
305 }
306 }
307
308
309 try {
310 Thread.sleep(cleanSleep);
311 } catch (InterruptedException e) { }
312 }
313 }
314 }
315 }