001    package org.springframework.richclient.application.session;
002    
003    import org.springframework.binding.value.support.PropertyChangeSupport;
004    import org.springframework.context.ApplicationEvent;
005    import org.springframework.context.ApplicationListener;
006    import org.springframework.richclient.application.Application;
007    import org.springframework.richclient.security.LoginEvent;
008    import org.springframework.richclient.security.LogoutEvent;
009    import org.springframework.security.Authentication;
010    
011    import java.beans.PropertyChangeListener;
012    import java.util.HashMap;
013    import java.util.Map;
014    
015    /**
016     * This object is a singleton that will: act as a storage for session and
017     * user variables,  registers itself on  ApplicationEvents and can be used
018     * to monitor changes on the contained variables.
019     *
020     * @author Jan Hoskens
021     *
022     */
023    public final class ApplicationSession implements ApplicationListener
024    {
025    
026        /** Holds the singleton instance. */
027        private static final ApplicationSession INSTANCE = new ApplicationSession();
028    
029        /** Custom initialising code/variables will be passed by an initialiser. */
030        private ApplicationSessionInitializer applicationSessionInitializer;
031    
032        /** Handler managing listeners registered on properties. */
033        private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
034    
035        /** Property that can be monitored. */
036        public static final String USER = "user";
037    
038        /** Property that can be monitored. */
039        public static final String USER_ATTRIBUTES = "userAttributes";
040    
041        /** Property that can be monitored. */
042        public static final String SESSION_ATTRIBUTES = "sessionAttributes";
043    
044        /** User attributes map. */
045        private Map<String, Object> userAttributes = new HashMap<String, Object>();
046    
047        /** Session attributes map. */
048        private Map<String, Object> sessionAttributes = new HashMap<String, Object>();
049    
050    
051        /**
052         * Private constructor: Singleton Pattern.
053         */
054        private ApplicationSession()
055        {
056        }
057    
058        /**
059         * Get the instance: Singleton Pattern.
060         *
061         * @return the ApplicationSession.
062         */
063        public static ApplicationSession getSession()
064        {
065            return INSTANCE;
066        }
067    
068        /**
069         * Handle events that influence the session/user context.
070         */
071        public void onApplicationEvent(ApplicationEvent event)
072        {
073            if ((event instanceof LoginEvent)
074                    && (event.getSource() != LoginEvent.NO_AUTHENTICATION))
075                handleLoginEvent((LoginEvent) event);
076            else if ((event instanceof LogoutEvent))
077                handleLogoutEvent((LogoutEvent) event);
078        }
079    
080        /**
081         * When a correct login occurs, read all relevant userinformation into
082         * session.
083         *
084         * @param event
085         *            the loginEvent that triggered this handler.
086         */
087        protected void handleLoginEvent(LoginEvent event)
088        {
089            ApplicationSessionInitializer asi = getApplicationSessionInitializer();
090            if (asi != null)
091            {
092                asi.initializeUser();
093                Map<String, Object> userAttributes = asi.getUserAttributes();
094                if (userAttributes != null)
095                {
096                    setUserAttributes(userAttributes);
097                }
098            }
099            Authentication auth = (Authentication) event.getSource();
100            propertyChangeSupport.firePropertyChange(USER, null, auth);
101        }
102    
103        /**
104         * When a logout occurs, remove all user related information from the
105         * session.
106         *
107         * @param event
108         *            the logoutEvent that triggered this handler.
109         */
110        protected void handleLogoutEvent(LogoutEvent event)
111        {
112            clearUser();
113            Authentication auth = (Authentication) event.getSource();
114            propertyChangeSupport.firePropertyChange(USER, auth, null);
115        }
116    
117        /**
118         * Set an initializer object containing vars/commands and custom init code.
119         *
120         * @param applicationSessionInitializer The application session initializer
121         */
122        public void setApplicationSessionInitializer(ApplicationSessionInitializer applicationSessionInitializer)
123        {
124            this.applicationSessionInitializer = applicationSessionInitializer;
125        }
126    
127        /**
128         * @return the applicationSessionInitializer.
129         */
130        public ApplicationSessionInitializer getApplicationSessionInitializer()
131        {
132            if (applicationSessionInitializer == null)
133            {
134                applicationSessionInitializer = Application.instance()
135                        .getLifecycleAdvisor().getApplicationSessionInitializer();
136            }
137            return applicationSessionInitializer;
138        }
139    
140        /**
141         * Register a listener on the specified property.
142         *
143         * @param property
144         *            Property to monitor.
145         * @param listener
146         *            PropertyChangeListener to add.
147         */
148        public void addPropertyChangeListener(String property, PropertyChangeListener listener)
149        {
150            propertyChangeSupport.addPropertyChangeListener(property, listener);
151        }
152    
153        /**
154         * Unregister a listener from the specified property.
155         *
156         * @param property
157         *            Property that currently is being monitored.
158         * @param listener
159         *            PropertyChangeListener to remove.
160         */
161        public void removePropertyChangeListener(String property, PropertyChangeListener listener)
162        {
163            propertyChangeSupport.removePropertyChangeListener(property, listener);
164        }
165    
166        /**
167         * Initialize the session attributes.
168         */
169        public void initializeSession()
170        {
171            ApplicationSessionInitializer asi = getApplicationSessionInitializer();
172            if (asi != null)
173            {
174                asi.initializeSession();
175                Map<String, Object> sessionAttributes = asi.getSessionAttributes();
176                if (sessionAttributes != null)
177                {
178                        setSessionAttributes(sessionAttributes);
179                }
180                propertyChangeSupport.firePropertyChange(SESSION_ATTRIBUTES, null, sessionAttributes);
181            }
182        }
183    
184        /**
185         * gets a named attribute of the user associated to this context
186         *
187         * @param key
188         *            name of the attribute
189         * @return the attribute value (attribute values are strings)
190         */
191        public Object getUserAttribute(String key)
192        {
193            return this.getUserAttribute(key, null);
194        }
195    
196        /**
197         * Get a value from the user attributes map.
198         *
199         * @param key
200         *            name of the attribute
201         * @param defaultValue
202         *            a default value to return if no value is found.
203         * @return the attribute value
204         */
205        public Object getUserAttribute(String key, Object defaultValue)
206        {
207            Object attributeValue = this.userAttributes.get(key);
208            if (attributeValue == null)
209                attributeValue = defaultValue;
210            return attributeValue;
211        }
212    
213        /**
214         * Add a key/value pair to the user attributes map.
215         *
216         * @param key
217         *            a unique string code.
218         * @param newValue
219         *            the associated value.
220         */
221        public void setUserAttribute(String key, Object newValue)
222        {
223            Object oldValue = userAttributes.put(key, newValue);
224            propertyChangeSupport.firePropertyChange(key, oldValue, newValue);
225            propertyChangeSupport.firePropertyChange(USER_ATTRIBUTES, null, userAttributes);
226        }
227    
228        /**
229         * Add the given key/value pairs to the user attributes.
230         *
231         * @param attributes
232         *            a map of key/value pairs.
233         */
234        public void setUserAttributes(Map<String, Object> attributes)
235        {
236            userAttributes.putAll(attributes);
237            propertyChangeSupport.firePropertyChange(USER_ATTRIBUTES, null, userAttributes);
238        }
239    
240        /**
241         * Clear all user attributes.
242         */
243        public void clearUser()
244        {
245            this.userAttributes.clear();
246            propertyChangeSupport.firePropertyChange(USER_ATTRIBUTES, null, null);
247        }
248    
249        /**
250         * Get a value from the session attributes map.
251         *
252         * @param key
253         *            name of the attribute
254         * @return the attribute value
255         */
256        public Object getSessionAttribute(String key)
257        {
258            return this.getSessionAttribute(key, null);
259        }
260    
261        /**
262         * Get a value from the session attributes map.
263         *
264         * @param key a unique string code
265         * @param defaultValue the default value if not found
266         * @return The session attibute or the default value if not found
267         */
268        public Object getSessionAttribute(String key, Object defaultValue)
269        {
270            Object attributeValue = this.sessionAttributes.get(key);
271            if (attributeValue == null)
272                attributeValue = defaultValue;
273            return attributeValue;
274        }
275    
276        /**
277         * Add a key/value pair to the session attributes map.
278         *
279         * @param key
280         *            a unique string code.
281         * @param newValue
282         *            the associated value.
283         */
284        public void setSessionAttribute(String key, Object newValue)
285        {
286            Object oldValue = sessionAttributes.put(key, newValue);
287            propertyChangeSupport.firePropertyChange(key, oldValue, newValue);
288            propertyChangeSupport.firePropertyChange(SESSION_ATTRIBUTES, null, sessionAttributes);
289        }
290    
291        /**
292         * Add the given key/value pairs to the session attributes.
293         *
294         * @param attributes
295         *            a map of key/value pairs.
296         */
297        public void setSessionAttributes(Map<String, Object> attributes)
298        {
299            this.sessionAttributes.putAll(attributes);
300            propertyChangeSupport.firePropertyChange(SESSION_ATTRIBUTES, null, sessionAttributes);
301        }
302    
303        /**
304         * Clear all session attributes.
305         */
306        public void clearSession()
307        {
308            this.sessionAttributes.clear();
309            propertyChangeSupport.firePropertyChange(SESSION_ATTRIBUTES, null, sessionAttributes);
310        }
311    
312        /**
313         * Get a value from the user OR session attributes map.
314         *
315         * @param key
316         *            name of the attribute
317         * @return the attribute value
318         */
319        public Object getAttribute(String key)
320        {
321            return getAttribute(key, null);
322        }
323    
324        /**
325         * Get a value from the user OR session attributes map.
326         *
327         * @param key
328         *            name of the attribute
329         * @param defaultValue
330         *            a default value to return if no value is found.
331         * @return the attribute value
332         */
333        public Object getAttribute(String key, Object defaultValue)
334        {
335            Object attributeValue = getUserAttribute(key, null);
336            if (attributeValue != null)
337                return attributeValue;
338            attributeValue = getSessionAttribute(key, null);
339            if (attributeValue != null)
340                return attributeValue;
341            return defaultValue;
342        }
343    }