1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.jetspeed.services.statemanager;
19
20
21 import java.util.Iterator;
22 import java.util.HashMap;
23 import java.util.Map;
24 import java.util.Set;
25 import java.util.Collections;
26 import javax.servlet.ServletConfig;
27 import javax.servlet.http.HttpSession;
28
29 import org.apache.turbine.services.TurbineBaseService;
30 import org.apache.turbine.services.InitializationException;
31 import org.apache.turbine.util.RunData;
32
33 import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
34 import org.apache.jetspeed.services.logging.JetspeedLogger;
35 import org.apache.jetspeed.services.statemanager.StateManagerService;
36 import org.apache.jetspeed.services.statemanager.SessionStateBindingListener;
37
38 /***
39 * <p>BaseStateManagerService is a Turbine Service implementation of the
40 * StateManagerService.</p>
41 * <p>Each SessionState is stored in a Map, storing the names and values
42 * of the state attributes.</p>
43 * <p>The set of states managed is stored in some specific way by extension classes.</p>
44 * <p>See the proposal: jakarta-jetspeed/proposals/StateManager.txt for more details.</p>
45 * @version $Revision: 1.5 $
46 * @see org.apache.jetspeed.services.statemanager.StateManagerService
47 * @see org.apache.jetspeed.services.statemanager.SessionState
48 * @author <a href="mailto:ggolden@apache.org">Glenn R. Golden</a>
49 */
50 public abstract class BaseStateManagerService
51 extends TurbineBaseService
52 implements StateManagerService
53 {
54 /***
55 * Static initialization of the logger for this class
56 */
57 private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(BaseStateManagerService.class.getName());
58
59 /*** map of thread to http session for that thread. */
60 protected Map m_httpSessions = null;
61
62 /********************************************************************************
63 * Abstract methods
64 *******************************************************************************/
65
66 /***
67 * Initialize the states storage.
68 */
69 protected abstract void initStates();
70
71 /***
72 * Cleanup the states storage.
73 */
74 protected abstract void shutdownStates();
75
76 /***
77 * Access the Map which is the set of attributes for a state.
78 * @param key The state key.
79 * @return The Map which is the set of attributes for a state.
80 */
81 protected abstract Map getState( String key );
82
83 /***
84 * Add a new state to the states we are managing.
85 * @param key The state key.
86 * @param state The Map which is the set of attributes for the state.
87 */
88 protected abstract void addState( String key, Map state );
89
90 /***
91 * Remove a state from the states we are managing.
92 * @param key The state key.
93 */
94 protected abstract void removeState( String key );
95
96 /***
97 * Access an array of the keys of all states managed, those that start with the parameter.
98 * @param start The starting string used to select the keys.
99 * @return an array of the keys of all states managed.
100 */
101 protected abstract String[] getStateKeys( String start );
102
103 /***
104 * retire the attributes of the state.
105 * @param key The state key.
106 * @param state The Map of attributes to retire.
107 */
108 protected void retireAttributes( String key, Map state )
109 {
110 if (state == null) return;
111
112 Set attributes = state.entrySet();
113 synchronized (state)
114 {
115 Iterator i = attributes.iterator();
116 while (i.hasNext())
117 {
118 Map.Entry attribute = (Map.Entry) i.next();
119 unBindAttributeValue(key, (String)attribute.getKey(), attribute.getValue());
120 }
121 }
122
123
124 state.clear();
125
126 }
127
128 /***
129 * If the object is a SessionStateBindingListener, unbind it
130 * @param stateKey The state key.
131 * @param attributeName The attribute name.
132 * @param attribute The attribute object
133 */
134 protected void unBindAttributeValue( String stateKey, String attributeName, Object attribute )
135 {
136
137 if ((attribute != null) && (attribute instanceof SessionStateBindingListener))
138 {
139 try
140 {
141 ((SessionStateBindingListener)attribute)
142 .valueUnbound(stateKey, attributeName);
143 }
144 catch (Throwable e)
145 {
146 logger.warn("JetspeedStateManagerService.unBindAttributeValue: unbinding exception: ", e);
147 }
148 }
149
150 }
151
152 /***
153 * If the object is a SessionStateBindingListener, bind it
154 * @param stateKey The state key.
155 * @param attributeName The attribute name.
156 * @param attribute The attribute object
157 */
158 protected void bindAttributeValue( String stateKey, String attributeName, Object attribute )
159 {
160
161 if ((attribute != null) && (attribute instanceof SessionStateBindingListener))
162 {
163 try
164 {
165 ((SessionStateBindingListener)attribute)
166 .valueBound(stateKey, attributeName);
167 }
168 catch (Throwable e)
169 {
170 logger.warn("JetspeedStateManagerService.bindAttributeValue: unbinding exception: ", e);
171 }
172 }
173
174 }
175
176 /********************************************************************************
177 * Service implementation
178 *******************************************************************************/
179
180 /***
181 * Performs early initialization.
182 *
183 * @param config A ServletConfing to use for initialization
184 * activities.
185 * @exception InitializationException, if initialization of this
186 * class was not successful.
187 */
188 public void init( ServletConfig config )
189 throws InitializationException
190 {
191 super.init(config);
192
193 }
194
195 /***
196 * Performs early initialization.
197 *
198 * @param data An RunData to use for initialization activities.
199 * @exception InitializationException, if initialization of this
200 * class was not successful.
201 */
202 public void init( RunData data )
203 throws InitializationException
204 {
205 super.init(data);
206
207 }
208
209 /***
210 * Performs late initialization.
211 *
212 * If your class relies on early initialization, and the object it
213 * expects was not received, you can use late initialization to
214 * throw an exception and complain.
215 *
216 * @exception InitializationException, if initialization of this
217 * class was not successful.
218 */
219 public void init()
220 throws InitializationException
221 {
222 super.init();
223
224
225 m_httpSessions = Collections.synchronizedMap(new HashMap());
226
227
228 initStates();
229
230 }
231
232 /***
233 * Returns to uninitialized state.
234 *
235 * You can use this method to release resources thet your Service
236 * allocated when Turbine shuts down.
237 */
238 public void shutdown()
239 {
240 m_httpSessions.clear();
241 m_httpSessions = null;
242 shutdownStates();
243 super.shutdown();
244
245 }
246
247 /********************************************************************************
248 * StateManagerService implementation
249 *******************************************************************************/
250
251 /***
252 * Access the named attribute of the keyed state.
253 * @param key The state key.
254 * @param name The attribute name.
255 * @return The named attribute value of the keyed state.
256 */
257 public Object getAttribute ( String key, String name )
258 {
259 Map state = getState(key);
260 if (state == null) return null;
261 return state.get(name);
262
263 }
264
265 /***
266 * Set the named state attribute of the keyed state with the provided object.
267 * @param key The state key.
268 * @param name The attribute name.
269 * @param value The new value of the attribute (any object type).
270 */
271 public void setAttribute( String key, String name, Object value )
272 {
273 Map state = getState(key);
274 if (state == null)
275 {
276
277 state = Collections.synchronizedMap(new HashMap());
278 addState(key, state);
279 }
280
281
282 Object old = getAttribute(key, name);
283
284
285 state.put(name, value);
286
287
288 if (old != null)
289 {
290 unBindAttributeValue(key, name, old);
291 }
292
293
294 bindAttributeValue(key, name, value);
295
296 }
297
298 /***
299 * Remove the named state attribute of the keyed state, if it exists.
300 * @param key The state key.
301 * @param name The attribute name.
302 */
303 public void removeAttribute( String key, String name )
304 {
305 Map state = getState(key);
306 if (state == null) return;
307
308
309 Object old = getAttribute(key, name);
310
311
312 state.remove(name);
313
314
315 if (state.isEmpty())
316 {
317 removeState(key);
318 }
319
320
321 if (old != null)
322 {
323 unBindAttributeValue(key, name, old);
324 }
325
326 }
327
328 /***
329 * Remove all state attribute of the keyed state.
330 * @param key The state key.
331 */
332 public void clear( String key )
333 {
334 Map state = getState(key);
335 if (state == null) return;
336
337
338 retireAttributes(key, state);
339
340
341 removeState(key);
342
343 }
344
345 /***
346 * Access an array of all names of attributes stored in the keyed state.
347 * @param key The state key.
348 * @return An array of all names of attributes stored in the keyed state.
349 */
350 public String[] getAttributeNames( String key )
351 {
352 Map state = (Map) getState(key);
353 if (state == null) return null;
354 if (state.size() == 0) return null;
355
356
357 return (String[]) state.keySet().toArray(new String[state.size()]);
358
359 }
360
361 /***
362 * Access an SessionState object with the given key.
363 * @param key The SessionState key.
364 * @return an SessionState object with the given key.
365 */
366 public SessionState getSessionState( String key )
367 {
368 return new MySessionState(key, this);
369
370 }
371
372 /***
373 * Access the SessionState object associated with the current request's http session.
374 * The session id is used as the key.
375 * @return an SessionState object associated with the current request's http session.
376 */
377 public SessionState getCurrentSessionState()
378 {
379 HttpSession session = (HttpSession) m_httpSessions.get(Thread.currentThread());
380 if (session == null) return null;
381
382 return getSessionState(session.getId());
383
384 }
385
386 /***
387 * Access the SessionState object associated with the current request's http session with the given key.
388 * @param key The string to add to the session id to form the SessionState key.
389 * @return an SessionState object associated with the current request's http session with the given key.
390 */
391 public SessionState getCurrentSessionState( String key )
392 {
393 HttpSession session = (HttpSession) m_httpSessions.get(Thread.currentThread());
394 if (session == null) return null;
395
396 return getSessionState(session.getId() + key);
397
398 }
399
400 /***
401 * Retire, forget about and clean up all states that start with the given key.
402 * @param keyStart The beginning of the key of the states to clean up.
403 */
404 public synchronized void retireState( String keyStart )
405 {
406
407 String keys[] = getStateKeys(keyStart);
408 if (keys == null) return;
409
410
411 for (int i = 0; i < keys.length; i++)
412 {
413 clear(keys[i]);
414 }
415
416 }
417
418 /***
419 * Set the "current" context for this thread -
420 * Call this at the start of each request, and call %%% at the end.
421 * getCurrentSession() uses this for the session state key.
422 * @param session the HttpSession of the current request.
423 */
424 public void setCurrentContext( HttpSession session )
425 {
426
427 m_httpSessions.put(Thread.currentThread(), session);
428
429 }
430
431 /***
432 * Clear the "current context for this thread -
433 * Call at the end of each request, balanced with calls to setCurrentContext()
434 */
435 public void clearCurrentContext()
436 {
437
438 m_httpSessions.remove(Thread.currentThread());
439
440 }
441
442 /********************************************************************************
443 * SessionState implementation
444 *******************************************************************************/
445
446 /***
447 * A SessionState implementation, as covers to this service, storing the key.
448 */
449 private class MySessionState
450 implements SessionState
451 {
452 /*** The state key. */
453 private String m_key = null;
454
455 /*** The StateManagerService object. */
456 private BaseStateManagerService m_service = null;
457
458 /***
459 * Construct.
460 * @param key The state key.
461 * @param service The JetspeedStateManagerService instance.
462 */
463 public MySessionState( String key,
464 BaseStateManagerService service)
465 {
466 m_key = key;
467 m_service = service;
468
469 }
470
471 /***
472 * Access the named attribute.
473 * @param name The attribute name.
474 * @return The named attribute value.
475 */
476 public Object getAttribute( String name )
477 {
478 return m_service.getAttribute(m_key, name);
479
480 }
481
482 /***
483 * Set the named attribute value to the provided object.
484 * @param name The attribute name.
485 * @param value The value of the attribute (any object type).
486 */
487 public void setAttribute( String name, Object value )
488 {
489 m_service.setAttribute(m_key, name, value);
490
491 }
492
493 /***
494 * Remove the named attribute, if it exists.
495 * @param name The attribute name.
496 */
497 public void removeAttribute( String name )
498 {
499 m_service.removeAttribute(m_key, name);
500
501 }
502
503 /***
504 * Remove all attributes.
505 */
506 public void clear()
507 {
508 m_service.clear(m_key);
509
510 }
511
512 /***
513 * Access an array of all names of attributes stored in the SessionState.
514 * @return An array of all names of attribute stored in the SessionState.
515 */
516 public String[] getAttributeNames()
517 {
518 return m_service.getAttributeNames(m_key);
519
520 }
521
522 /***
523 * Access the full unique StateManager key for the SessionState.
524 * @return the full unique StateManager key for the SessionState.
525 */
526 public String getKey()
527 {
528 return m_key;
529
530 }
531
532 /***
533 * Retire, forget about and clean up this state.
534 */
535 public void retire()
536 {
537 m_service.retireState(m_key);
538
539 }
540
541 }
542
543 }
544
545 /***********************************************************************************
546 *
547 * $Header: /home/cvs/jakarta-jetspeed/src/java/org/apache/jetspeed/services/statemanager/BaseStateManagerService.java,v 1.5 2004/02/23 03:38:28 jford Exp $
548 *
549 **********************************************************************************/
550