1/*2 * Copyright 2000-2002,2004 The Apache Software Foundation.3 * 4 * Licensed under the Apache License, Version 2.0 (the "License");5 * you may not use this file except in compliance with the License.6 * You may obtain a copy of the License at7 * 8 * http://www.apache.org/licenses/LICENSE-2.09 * 10 * Unless required by applicable law or agreed to in writing, software11 * distributed under the License is distributed on an "AS IS" BASIS,12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13 * See the License for the specific language governing permissions and14 * limitations under the License.15 */1617// package18packageorg.apache.jetspeed.services.statemanager;
1920// imports21import java.util.Iterator;
22import java.util.HashMap;
23import java.util.Map;
24import java.util.Set;
25import java.util.Collections;
26import javax.servlet.ServletConfig;
27import javax.servlet.http.HttpSession;
2829import org.apache.turbine.services.TurbineBaseService;
30import org.apache.turbine.services.InitializationException;
31import org.apache.turbine.util.RunData;
3233import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
34import org.apache.jetspeed.services.logging.JetspeedLogger;
35import org.apache.jetspeed.services.statemanager.StateManagerService;
36import org.apache.jetspeed.services.statemanager.SessionStateBindingListener;
3738/***39* <p>BaseStateManagerService is a Turbine Service implementation of the40* StateManagerService.</p>41* <p>Each SessionState is stored in a Map, storing the names and values42* 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.StateManagerService47* @see org.apache.jetspeed.services.statemanager.SessionState48* @author <a href="mailto:ggolden@apache.org">Glenn R. Golden</a>49*/50publicabstractclassBaseStateManagerService51extends TurbineBaseService
52 implements StateManagerService53 {
54/***55 * Static initialization of the logger for this class56 */57privatestaticfinalJetspeedLogger logger = JetspeedLogFactoryService.getLogger(BaseStateManagerService.class.getName());
5859/*** map of thread to http session for that thread. */60protected Map m_httpSessions = null;
6162/********************************************************************************63 * Abstract methods64 *******************************************************************************/6566/***67 * Initialize the states storage.68 */69protectedabstractvoid initStates();
7071/***72 * Cleanup the states storage.73 */74protectedabstractvoid shutdownStates();
7576/***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 */81protectedabstract Map getState( String key );
8283/***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 */88protectedabstractvoid addState( String key, Map state );
8990/***91 * Remove a state from the states we are managing.92 * @param key The state key.93 */94protectedabstractvoid removeState( String key );
9596/***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 */101protectedabstract String[] getStateKeys( String start );
102103/***104 * retire the attributes of the state.105 * @param key The state key.106 * @param state The Map of attributes to retire.107 */108protectedvoid retireAttributes( String key, Map state )
109 {
110if (state == null) return;
111112 Set attributes = state.entrySet();
113synchronized (state)
114 {
115 Iterator i = attributes.iterator();
116while (i.hasNext())
117 {
118 Map.Entry attribute = (Map.Entry) i.next();
119 unBindAttributeValue(key, (String)attribute.getKey(), attribute.getValue());
120 }
121 }
122123// remove all attributes124 state.clear();
125126 } // retireAttributes127128/***129 * If the object is a SessionStateBindingListener, unbind it130 * @param stateKey The state key.131 * @param attributeName The attribute name.132 * @param attribute The attribute object133 */134protectedvoid unBindAttributeValue( String stateKey, String attributeName, Object attribute )
135 {
136// if this object wants session binding notification137if ((attribute != null) && (attribute instanceof SessionStateBindingListener))
138 {
139try140 {
141 ((SessionStateBindingListener)attribute)
142 .valueUnbound(stateKey, attributeName);
143 }
144catch (Throwable e)
145 {
146 logger.warn("JetspeedStateManagerService.unBindAttributeValue: unbinding exception: ", e);
147 }
148 }
149150 } // unBindAttributeValue151152/***153 * If the object is a SessionStateBindingListener, bind it154 * @param stateKey The state key.155 * @param attributeName The attribute name.156 * @param attribute The attribute object157 */158protectedvoid bindAttributeValue( String stateKey, String attributeName, Object attribute )
159 {
160// if this object wants session binding notification161if ((attribute != null) && (attribute instanceof SessionStateBindingListener))
162 {
163try164 {
165 ((SessionStateBindingListener)attribute)
166 .valueBound(stateKey, attributeName);
167 }
168catch (Throwable e)
169 {
170 logger.warn("JetspeedStateManagerService.bindAttributeValue: unbinding exception: ", e);
171 }
172 }
173174 } // bindAttributeValue175176/********************************************************************************177 * Service implementation178 *******************************************************************************/179180/***181 * Performs early initialization.182 *183 * @param config A ServletConfing to use for initialization184 * activities.185 * @exception InitializationException, if initialization of this186 * class was not successful.187 */188publicvoid init( ServletConfig config )
189 throws InitializationException
190 {
191super.init(config);
192193 } // init194195/***196 * Performs early initialization.197 *198 * @param data An RunData to use for initialization activities.199 * @exception InitializationException, if initialization of this200 * class was not successful.201 */202publicvoid init( RunData data )
203 throws InitializationException
204 {
205super.init(data);
206207 } // init208209/***210 * Performs late initialization.211 *212 * If your class relies on early initialization, and the object it213 * expects was not received, you can use late initialization to214 * throw an exception and complain.215 *216 * @exception InitializationException, if initialization of this217 * class was not successful.218 */219publicvoid init()
220 throws InitializationException
221 {
222super.init();
223224// allocate a thread-safe map to store the "current" http session for each thread225 m_httpSessions = Collections.synchronizedMap(new HashMap());
226227// create our states storage228 initStates();
229230 } // init231232/***233 * Returns to uninitialized state.234 *235 * You can use this method to release resources thet your Service236 * allocated when Turbine shuts down.237 */238publicvoid shutdown()
239 {
240 m_httpSessions.clear();
241 m_httpSessions = null;
242 shutdownStates();
243super.shutdown();
244245 } // shutdown246247/********************************************************************************248 * StateManagerService implementation249 *******************************************************************************/250251/***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 */257public Object getAttribute ( String key, String name )
258 {
259 Map state = getState(key);
260if (state == null) returnnull;
261return state.get(name);
262263 } // getAttribute264265/***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 */271publicvoid setAttribute( String key, String name, Object value )
272 {
273 Map state = getState(key);
274if (state == null)
275 {
276// create a synchronized map to store the state attributes277 state = Collections.synchronizedMap(new HashMap());
278 addState(key, state);
279 }
280281// get the old, if any282 Object old = getAttribute(key, name);
283284// store the new285 state.put(name, value);
286287// if there was an old value, unbind it288if (old != null)
289 {
290 unBindAttributeValue(key, name, old);
291 }
292293// bind the new294 bindAttributeValue(key, name, value);
295296 } // setAttribute297298/***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 */303publicvoid removeAttribute( String key, String name )
304 {
305 Map state = getState(key);
306if (state == null) return;
307308// get the old, if any309 Object old = getAttribute(key, name);
310311// remove312 state.remove(name);
313314// if the state is now empty, remove it315if (state.isEmpty())
316 {
317 removeState(key);
318 }
319320// if there was an old value, unbind it321if (old != null)
322 {
323 unBindAttributeValue(key, name, old);
324 }
325326 } // removeAttribute327328/***329 * Remove all state attribute of the keyed state.330 * @param key The state key.331 */332publicvoid clear( String key )
333 {
334 Map state = getState(key);
335if (state == null) return;
336337// notify all attribute and clear the state338 retireAttributes(key, state);
339340// and forget about it341 removeState(key);
342343 } // clear344345/***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 */350public String[] getAttributeNames( String key )
351 {
352 Map state = (Map) getState(key);
353if (state == null) returnnull;
354if (state.size() == 0) returnnull;
355356// put the names into an array for return357return (String[]) state.keySet().toArray(new String[state.size()]);
358359 } // getAttributeNames360361/***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 */366publicSessionState getSessionState( String key )
367 {
368returnnew MySessionState(key, this);
369370 } // getSessionState371372/***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 */377publicSessionState getCurrentSessionState()
378 {
379 HttpSession session = (HttpSession) m_httpSessions.get(Thread.currentThread());
380if (session == null) returnnull;
381382return getSessionState(session.getId());
383384 } // getCurrentSessionState385386/***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 */391publicSessionState getCurrentSessionState( String key )
392 {
393 HttpSession session = (HttpSession) m_httpSessions.get(Thread.currentThread());
394if (session == null) returnnull;
395396return getSessionState(session.getId() + key);
397398 } // getCurrentSessionState399400/***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 */404publicsynchronizedvoid retireState( String keyStart )
405 {
406// get the current state keys into an array407 String keys[] = getStateKeys(keyStart);
408if (keys == null) return;
409410// clear them411for (int i = 0; i < keys.length; i++)
412 {
413 clear(keys[i]);
414 }
415416 } // retireState417418/***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 */424publicvoid setCurrentContext( HttpSession session )
425 {
426// store the session associated with this thread427 m_httpSessions.put(Thread.currentThread(), session);
428429 } // setCurrentContext430431/***432 * Clear the "current context for this thread -433 * Call at the end of each request, balanced with calls to setCurrentContext()434 */435publicvoid clearCurrentContext()
436 {
437// clear the session associated with this thread438 m_httpSessions.remove(Thread.currentThread());
439440 } // clearCurrentContext441442/********************************************************************************443 * SessionState implementation444 *******************************************************************************/445446/***447 * A SessionState implementation, as covers to this service, storing the key.448 */449privateclass MySessionState
450 implements SessionState451 {
452/*** The state key. */453private String m_key = null;
454455/*** The StateManagerService object. */456privateBaseStateManagerService m_service = null;
457458/***459 * Construct.460 * @param key The state key.461 * @param service The JetspeedStateManagerService instance.462 */463public MySessionState( String key,
464BaseStateManagerService service)
465 {
466 m_key = key;
467 m_service = service;
468469 } // MySessionState470471/***472 * Access the named attribute.473 * @param name The attribute name.474 * @return The named attribute value.475 */476public Object getAttribute( String name )
477 {
478return m_service.getAttribute(m_key, name);
479480 } // getAttribute481482/***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 */487publicvoid setAttribute( String name, Object value )
488 {
489 m_service.setAttribute(m_key, name, value);
490491 } // setAttribute492493/***494 * Remove the named attribute, if it exists.495 * @param name The attribute name.496 */497publicvoid removeAttribute( String name )
498 {
499 m_service.removeAttribute(m_key, name);
500501 } // removeAttribute502503/***504 * Remove all attributes.505 */506publicvoid clear()
507 {
508 m_service.clear(m_key);
509510 } // clear511512/***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 */516public String[] getAttributeNames()
517 {
518return m_service.getAttributeNames(m_key);
519520 } // getAttributeNames521522/***523 * Access the full unique StateManager key for the SessionState.524 * @return the full unique StateManager key for the SessionState.525 */526public String getKey()
527 {
528return m_key;
529530 } // getKey531532/***533 * Retire, forget about and clean up this state.534 */535publicvoid retire()
536 {
537 m_service.retireState(m_key);
538539 } // retire540541 } // class MySessionState542543 } // BaseStateManagerService544545/***********************************************************************************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