KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opensubsystems > core > util > CallContext


1 /*
2  * Copyright (c) 2003 - 2007 OpenSubsystems s.r.o. Slovak Republic. All rights reserved.
3  *
4  * Project: OpenSubsystems
5  *
6  * $Id: CallContext.java,v 1.5 2007/01/07 06:14:00 bastafidli Exp $
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; version 2 of the License.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */

21
22 package org.opensubsystems.core.util;
23
24 import java.security.Principal JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Map JavaDoc;
27 import java.util.Stack JavaDoc;
28
29 import org.opensubsystems.core.data.DataObject;
30
31 /**
32  * This class encapsulate context in which certain (method) call execution is
33  * made. This class establishes that every call is made in the context
34  * of user and domain where the user belongs.
35  *
36  * This class is independent from the security implementation, therefore
37  * it doesn't refer to any specific security package. Overriden class actually
38  * implement concept of users and domains as proposed in this class.
39  *
40  * @version $Id: CallContext.java,v 1.5 2007/01/07 06:14:00 bastafidli Exp $
41  * @author Miro Halas
42  * @code.reviewer Miro Halas
43  * @code.reviewed Initial revision
44  */

45 public class CallContext
46 {
47    // Constants ////////////////////////////////////////////////////////////////
48

49    /**
50     * Lock used in synchronized sections.
51     */

52    private static final String JavaDoc IMPL_LOCK = "IMPL_LOCK";
53
54    // Cached values ////////////////////////////////////////////////////////////
55

56    /**
57     * Reference to the instance actually in use.
58     */

59    private static CallContext s_defaultInstance;
60
61    // Attributes ///////////////////////////////////////////////////////////////
62

63    /**
64     * Each thread calling this class will store here information about current user.
65     * Since we support switching of user identities, this variable contains stack
66     * where new user identity is pushed when it's context is established and
67     * from which it is popped, when the context is reset. This has an implication
68     * and that is when new thread is created and it inherits the parent's value,
69     * it in fact inherits the stack and therefore the parent and child would
70     * share the same stack. This is not desirable so the child thread has to
71     * create it's own stack and copy the content of the parent stack into it
72     * so that from that point these two stacks can be manipulated separately.
73     * What is the questions is if all identities on the stack should be copied
74     * or only the current one. For now we copy all of them
75     */

76    private ThreadLocal JavaDoc m_currentUser;
77
78    /**
79     * Each thread calling this class will store here information about current session.
80     * The same discussion about stack as for m_currentUser applies to this class.
81     */

82    private ThreadLocal JavaDoc m_currentSession;
83
84    /**
85     * Each thread calling this class will store here error or information messages
86     * produced during call, which will can be later displayed to the user.
87     */

88    private ThreadLocal JavaDoc m_messages;
89
90    /**
91     * Generic cache where anybody can cache anything for the context under a key.
92     */

93    private ThreadLocal JavaDoc m_cache;
94
95    // Factory methods //////////////////////////////////////////////////////////
96

97    /**
98     * Get the default instance.
99     *
100     * @return CallContext
101     */

102    public static CallContext getInstance(
103    )
104    {
105       if (s_defaultInstance == null)
106       {
107          // Only if the default instance wasn't set by other means create a new one
108
// Synchronize just for the creation
109
synchronized (IMPL_LOCK)
110          {
111             if (s_defaultInstance == null)
112             {
113                setInstance(new CallContext());
114             }
115          }
116       }
117       
118       return s_defaultInstance;
119    }
120    
121    /**
122     * Set the default instance. This instance will be returned by getInstance
123     * method until it is changed.
124     *
125     * @param defaultInstance - new default instance
126     * @see #getInstance
127     */

128    public static void setInstance(
129       CallContext defaultInstance
130    )
131    {
132       if (GlobalConstants.ERROR_CHECKING)
133       {
134          
135          assert defaultInstance != null : "Default instance cannot be null";
136       }
137       
138       synchronized (IMPL_LOCK)
139       {
140          s_defaultInstance = defaultInstance;
141       }
142    }
143    
144    // Constructors /////////////////////////////////////////////////////////////
145

146    /**
147     * Default constructor.
148     */

149    public CallContext(
150    )
151    {
152       // Make it inheritable so that SWT background loaders can act on behalf
153
// of user who is using
154
m_currentUser = new InheritableThreadLocal JavaDoc()
155       {
156          protected Object JavaDoc childValue(
157              Object JavaDoc parentValue
158          )
159          {
160             Stack JavaDoc childStack = null;
161                                 
162             if ((parentValue != null)
163                && (!((Stack JavaDoc)parentValue).isEmpty()))
164             {
165                // See discussion above why we need to copy this
166
childStack = new Stack JavaDoc();
167                childStack.addAll((Stack JavaDoc)parentValue);
168             }
169                                 
170             return childStack;
171          }
172       };
173       m_currentSession = new InheritableThreadLocal JavaDoc()
174       {
175          protected Object JavaDoc childValue(
176              Object JavaDoc parentValue
177          )
178          {
179             Stack JavaDoc childStack = null;
180                                 
181             if ((parentValue != null)
182                && (!((Stack JavaDoc)parentValue).isEmpty()))
183             {
184                // See discussion above why we need to copy this
185
childStack = new Stack JavaDoc();
186                childStack.addAll((Stack JavaDoc)parentValue);
187             }
188                                 
189             return childStack;
190          }
191       };
192       // Error messages are not inheritable so that the thread don't write
193
// is own error message to parent. If it would be inheritable and the
194
// child value is not overriden as above, every error messages produced
195
// by child thread would be visible by parent
196
m_messages = new ThreadLocal JavaDoc();
197       m_cache = new ThreadLocal JavaDoc();
198    }
199    
200    // Logic ////////////////////////////////////////////////////////////////////
201

202    /**
203     * Get identification of current user.
204     *
205     * @return Principal - current user identification or null if not known
206     */

207    public Principal JavaDoc getCurrentUser(
208    )
209    {
210       Stack JavaDoc userStack = (Stack JavaDoc)m_currentUser.get();
211
212       if ((userStack == null) || (userStack.isEmpty()))
213       {
214          return null;
215       }
216       
217       return (Principal JavaDoc)userStack.peek();
218    }
219
220    /**
221     * Get identification of current session, which is jus a unique string which
222     * can identify the each individual session established between client and
223     * application.
224     *
225     * @return String - current session identification or null if not known
226     */

227    public String JavaDoc getCurrentSession(
228    )
229    {
230       Stack JavaDoc sessionStack = (Stack JavaDoc)m_currentSession.get();
231
232       if ((sessionStack == null) || (sessionStack.isEmpty()))
233       {
234          return null;
235       }
236       
237       return (String JavaDoc)sessionStack.peek();
238    }
239
240    /**
241     * Get curent user ID.
242     *
243     * @return int - current user ID
244     */

245    public int getCurrentUserId(
246    )
247    {
248       return DataObject.NEW_ID;
249    }
250
251    /**
252     * Set who is the current user and session for this call context.
253     * Values are stored in stack.
254     *
255     * @param user - information about user who is making the call.
256     * @param session - information about session in whic user is making the call.
257     */

258    public void setCurrentUserAndSession(
259       Principal JavaDoc user,
260       String JavaDoc session
261    )
262    {
263       Stack JavaDoc userStack = (Stack JavaDoc)(m_currentUser.get());
264       if (userStack == null)
265       {
266          m_currentUser.set(new Stack JavaDoc());
267          userStack = (Stack JavaDoc)(m_currentUser.get());
268       }
269       userStack.push(user);
270
271       Stack JavaDoc sessionStack = (Stack JavaDoc)(m_currentSession.get());
272       if (sessionStack == null)
273       {
274          m_currentSession.set(new Stack JavaDoc());
275          sessionStack = (Stack JavaDoc)(m_currentSession.get());
276       }
277       sessionStack.push(session);
278    }
279
280    /**
281     * Removes who is the current user session for this call context from stack.
282     * After this call, the current user and session will be null.
283     */

284    public void resetCurrentUserAndSession(
285    )
286    {
287       Stack JavaDoc userStack = (Stack JavaDoc)(m_currentUser.get());
288       if ((userStack != null) && (!userStack.isEmpty()))
289       {
290          userStack.pop();
291       }
292       Stack JavaDoc sessionStack = (Stack JavaDoc)(m_currentSession.get());
293       if ((sessionStack != null) && (!sessionStack.isEmpty()))
294       {
295          sessionStack.pop();
296       }
297    }
298
299    /**
300     * Get curent domain ID, which can be used to limit current user or session
301     * to access only data in this domain. Domain is just partition to which data
302     * might be allocated.
303     *
304     * @return int - current domain ID
305     */

306    public int getCurrentDomainId(
307    )
308    {
309       return DataObject.NEW_ID;
310    }
311
312    /**
313     * Get messages to display to user for current call.
314     *
315     * @return Messages - error or information messages to display to user
316     * related to current call, never null
317     */

318    public Messages getMessages(
319    )
320    {
321       Messages msgs = null;
322       
323       msgs = (Messages)m_messages.get();
324       
325       if (msgs == null)
326       {
327          msgs = new Messages();
328          setMessages(msgs);
329       }
330       
331       return msgs;
332    }
333
334    /**
335     * Set the error or information message object to collect messages to display
336     * to user for current call
337     *
338     * @param msgs - messages for current call
339     */

340    protected void setMessages(
341       Messages msgs
342    )
343    {
344       m_messages.set(msgs);
345    }
346
347    /**
348     * Removes all messages for current call. After this call, there won't be
349     * any error or information messages to display to the user.
350     */

351    public void resetMessages(
352    )
353    {
354       m_messages.set(null);
355    }
356
357    /**
358     * Get custom cache for given key.
359     *
360     * @param strCacheKey - key for which to get cache
361     * @return Map - cache registered under given key. This will always return Map
362     * and never null.
363     */

364    public Map JavaDoc getCache(
365       String JavaDoc strCacheKey
366    )
367    {
368       Map JavaDoc cache;
369       Map JavaDoc customcache;
370       
371       cache = (Map JavaDoc)m_cache.get();
372       
373       if (cache == null)
374       {
375          cache = new HashMap JavaDoc();
376          setCache(cache);
377       }
378       customcache = (Map JavaDoc)cache.get(strCacheKey);
379       if (customcache == null)
380       {
381          customcache = new HashMap JavaDoc();
382          cache.put(strCacheKey, customcache);
383       }
384       
385       return customcache;
386    }
387
388    /**
389     * Set custom cache for this call context
390     *
391     * @param cache - cache for current call context
392     */

393    protected void setCache(
394       Map JavaDoc cache
395    )
396    {
397       m_cache.set(cache);
398    }
399
400    /**
401     * Removes all cached items for current custom cache.
402     */

403    public void resetCache(
404    )
405    {
406       m_cache.set(null);
407    }
408
409    /**
410     * Removes context (all information) for current call from stack.
411     */

412    public void reset(
413    )
414    {
415       resetCurrentUserAndSession();
416       resetMessages();
417       resetCache();
418    }
419 }
420
Popular Tags