KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > jforum > SessionFacade


1 /*
2  * Copyright (c) Rafael Steil
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms,
6  * with or without modification, are permitted provided
7  * that the following conditions are met:
8  *
9  * 1) Redistributions of source code must retain the above
10  * copyright notice, this list of conditions and the
11  * following disclaimer.
12  * 2) Redistributions in binary form must reproduce the
13  * above copyright notice, this list of conditions and
14  * the following disclaimer in the documentation and/or
15  * other materials provided with the distribution.
16  * 3) Neither the name of "Rafael Steil" nor
17  * the names of its contributors may be used to endorse
18  * or promote products derived from this software without
19  * specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
22  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
23  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
27  * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
32  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
34  * IN CONTRACT, STRICT LIABILITY, OR TORT
35  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
37  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
38  *
39  * This file creation date: 12/03/2004 - 18:47:26
40  * The JForum Project
41  * http://www.jforum.net
42  */

43 package net.jforum;
44
45 import java.sql.Connection JavaDoc;
46 import java.util.ArrayList JavaDoc;
47 import java.util.HashMap JavaDoc;
48 import java.util.Iterator JavaDoc;
49 import java.util.List JavaDoc;
50
51 import net.jforum.cache.CacheEngine;
52 import net.jforum.cache.Cacheable;
53 import net.jforum.dao.DataAccessDriver;
54 import net.jforum.entities.UserSession;
55 import net.jforum.repository.SecurityRepository;
56 import net.jforum.util.preferences.ConfigKeys;
57 import net.jforum.util.preferences.SystemGlobals;
58
59 import org.apache.log4j.Logger;
60
61 /**
62  * @author Rafael Steil
63  * @version $Id: SessionFacade.java,v 1.30 2006/01/29 15:07:00 rafaelsteil Exp $
64  */

65 public class SessionFacade implements Cacheable
66 {
67     private static final Logger logger = Logger.getLogger(SessionFacade.class);
68     
69     private static final String JavaDoc FQN = "sessions";
70     private static final String JavaDoc FQN_LOGGED = FQN + "/logged";
71     private static final String JavaDoc FQN_COUNT = FQN + "/count";
72     private static final String JavaDoc FQN_USER_ID = FQN + "/userId";
73     private static final String JavaDoc ANONYMOUS_COUNT = "anonymousCount";
74     private static final String JavaDoc LOGGED_COUNT = "loggedCount";
75     
76     private static CacheEngine cache;
77
78     /**
79      * @see net.jforum.cache.Cacheable#setCacheEngine(net.jforum.cache.CacheEngine)
80      */

81     public void setCacheEngine(CacheEngine engine)
82     {
83         cache = engine;
84     }
85     
86     /**
87      * Add a new <code>UserSession</code> entry to the session.
88      * This method will make a call to <code>JForum.getRequest.getSession().getId()</code>
89      * to retrieve the session's id
90      *
91      * @param us The user session objetc to add
92      * @see #add(UserSession, String)
93      */

94     public static void add(UserSession us)
95     {
96         add(us, JForumExecutionContext.getRequest().getSession().getId());
97     }
98
99     /**
100      * Registers a new {@link UserSession}.
101      * <p>
102      * If a call to {@link UserSession#getUserId()} return a value different
103      * of <code>SystemGlobals.getIntValue(ConfigKeys.ANONYMOUS_USER_ID)</code>, then
104      * the user will be registered as "logged". Otherwise it will enter as anonymous.
105      * </p>
106      *
107      * <p>
108      * Please note that, in order to keep the number of guest and logged users correct,
109      * it's caller's responsability to {@link #remove(String)} the record before adding it
110      * again if the current session is currently represented as "guest".
111      * </p>
112      *
113      * @param us the UserSession to add
114      * @param sessionId the user's session id
115      */

116     public static void add(UserSession us, String JavaDoc sessionId)
117     {
118         if (us.getSessionId() == null || us.getSessionId().equals("")) {
119             us.setSessionId(sessionId);
120         }
121         
122         synchronized (FQN) {
123             cache.add(FQN, us.getSessionId(), us);
124             
125             if (!us.isBot()) {
126                 if (us.getUserId() != SystemGlobals.getIntValue(ConfigKeys.ANONYMOUS_USER_ID)) {
127                     changeUserCount(LOGGED_COUNT, true);
128                     cache.add(FQN_LOGGED, us.getSessionId(), us);
129                     cache.add(FQN_USER_ID, Integer.toString(us.getUserId()), us.getSessionId());
130                 }
131                 else {
132                     // TODO: check the anonymous IP constraint
133
changeUserCount(ANONYMOUS_COUNT, true);
134                 }
135             }
136         }
137     }
138     
139     private static void changeUserCount(String JavaDoc cacheEntryName, boolean increment)
140     {
141         Integer JavaDoc count = (Integer JavaDoc)cache.get(FQN_COUNT, cacheEntryName);
142         
143         if (count == null) {
144             count = new Integer JavaDoc(0);
145         }
146         
147         if (increment) {
148             count = new Integer JavaDoc(count.intValue() + 1);
149         }
150         else if (count.intValue() > 0) {
151             count = new Integer JavaDoc(count.intValue() - 1);
152         }
153         
154         cache.add(FQN_COUNT, cacheEntryName, count);
155     }
156     
157     /**
158      * Add a new entry to the user's session
159      *
160      * @param name The attribute name
161      * @param value The attribute value
162      */

163     public static void setAttribute(String JavaDoc name, Object JavaDoc value)
164     {
165         JForumExecutionContext.getRequest().getSession().setAttribute(name, value);
166     }
167     
168     /**
169      * Removes an attribute from the session
170      *
171      * @param name The key associated to the the attribute to remove
172      */

173     public static void removeAttribute(String JavaDoc name)
174     {
175         JForumExecutionContext.getRequest().getSession().removeAttribute(name);
176     }
177     
178     /**
179      * Gets an attribute value given its name
180      *
181      * @param name The attribute name to retrieve the value
182      * @return The value as an Object, or null if no entry was found
183      */

184     public static Object JavaDoc getAttribute(String JavaDoc name)
185     {
186         return JForumExecutionContext.getRequest().getSession().getAttribute(name);
187     }
188
189     /**
190      * Remove an entry fro the session map
191      *
192      * @param sessionId The session id to remove
193      */

194     public static void remove(String JavaDoc sessionId)
195     {
196         if (cache == null) {
197             logger.warn("Got a null cache instance. #" + sessionId);
198             return;
199         }
200         
201         logger.info("Removing session " + sessionId);
202         
203         synchronized (FQN) {
204             UserSession us = getUserSession(sessionId);
205             
206             if (us != null) {
207                 cache.remove(FQN_LOGGED, sessionId);
208                 cache.remove(FQN_USER_ID, Integer.toString(us.getUserId()));
209                 
210                 if (us.getUserId() != SystemGlobals.getIntValue(ConfigKeys.ANONYMOUS_USER_ID)) {
211                     changeUserCount(LOGGED_COUNT, false);
212                 }
213                 else {
214                     changeUserCount(ANONYMOUS_COUNT, false);
215                 }
216             }
217             
218             cache.remove(FQN, sessionId);
219         }
220     }
221     
222     /**
223      * Get all registered sessions
224      *
225      * @return <code>ArrayList</code> with the sessions. Each entry
226      * is an <code>UserSession</code> object.
227      */

228     public static List JavaDoc getAllSessions()
229     {
230         synchronized (FQN) {
231             return new ArrayList JavaDoc(cache.getValues(FQN));
232         }
233     }
234     
235     /**
236      * Gets the {@link UserSession} instance of all logged users
237      * @return A list with the user sessions
238      */

239     public static List JavaDoc getLoggedSessions()
240     {
241         synchronized (FQN) {
242             return new ArrayList JavaDoc(cache.getValues(FQN_LOGGED));
243         }
244     }
245     
246     /**
247      * Get the number of logged users
248      * @return the number of logged users
249      */

250     public static int registeredSize()
251     {
252         Integer JavaDoc count = (Integer JavaDoc)cache.get(FQN_COUNT, LOGGED_COUNT);
253
254         return (count == null ? 0 : count.intValue());
255     }
256     
257     /**
258      * Get the number of anonymous users
259      * @return the nuber of anonymous users
260      */

261     public static int anonymousSize()
262     {
263         Integer JavaDoc count = (Integer JavaDoc)cache.get(FQN_COUNT, ANONYMOUS_COUNT);
264
265         return (count == null ? 0 : count.intValue());
266     }
267     
268     public static void clear()
269     {
270         synchronized (FQN) {
271             cache.add(FQN, new HashMap JavaDoc());
272             cache.add(FQN_COUNT, LOGGED_COUNT, new Integer JavaDoc(0));
273             cache.add(FQN_COUNT, ANONYMOUS_COUNT, new Integer JavaDoc(0));
274             cache.remove(FQN_LOGGED);
275             cache.remove(FQN_USER_ID);
276         }
277     }
278     
279     /**
280      * Gets the user's <code>UserSession</code> object
281      *
282      * @return The <code>UserSession</code> associated to the user's session
283      */

284     public static UserSession getUserSession()
285     {
286         return getUserSession(JForumExecutionContext.getRequest().getSession().getId());
287     }
288     
289     /**
290      * Gets an {@link UserSession} by the session id.
291      *
292      * @param sessionId the session's id
293      * @return an <b>immutable</b> UserSession, or <code>null</code> if no entry found
294      */

295     public static UserSession getUserSession(String JavaDoc sessionId)
296     {
297         if (cache != null) {
298             UserSession us = (UserSession)cache.get(FQN, sessionId);
299             return (us != null ? us : null);
300         }
301
302         logger.warn("Got a null cache in getUserSession. #" + sessionId);
303         return null;
304     }
305
306     /**
307      * Gets the number of session elements.
308      *
309      * @return The number of session elements currently online (without bots)
310      */

311     public static int size()
312     {
313         return (anonymousSize() + registeredSize());
314     }
315     
316     /**
317      * Verify if the user in already loaded
318      *
319      * @param username The username to check
320      * @return The session id if the user is already registered into the session,
321      * or <code>null</code> if it is not.
322      */

323     public static String JavaDoc isUserInSession(String JavaDoc username)
324     {
325         int aid = SystemGlobals.getIntValue(ConfigKeys.ANONYMOUS_USER_ID);
326         
327         synchronized (FQN) {
328             for (Iterator JavaDoc iter = cache.getValues(FQN).iterator(); iter.hasNext(); ) {
329                 UserSession us = (UserSession)iter.next();
330                 String JavaDoc thisUsername = us.getUsername();
331                 
332                 if (thisUsername == null) {
333                     continue;
334                 }
335                 
336                 if (us.getUserId() != aid && thisUsername.equals(username)) {
337                     return us.getSessionId();
338                 }
339             }
340         }
341         
342         return null;
343     }
344     
345     /**
346      * Verify if there is an user in the session with the
347      * user id passed as parameter.
348      *
349      * @param userId The user id to check for existance in the session
350      * @return The session id if the user is already registered into the session,
351      * or <code>null</code> if it is not.
352      */

353     public static String JavaDoc isUserInSession(int userId)
354     {
355         return (String JavaDoc)cache.get(FQN_USER_ID, Integer.toString(userId));
356     }
357     
358     /**
359      * Verify is the user is logged in.
360      *
361      * @return <code>true</code> if the user is logged, or <code>false</code> if is
362      * an anonymous user.
363      */

364     public static boolean isLogged()
365     {
366         return "1".equals(SessionFacade.getAttribute("logged"));
367     }
368
369     /**
370      * Persists user session information.
371      * This method will get a <code>Connection</code> making a call to
372      * <code>DBConnection.getImplementation().getConnection()</code>, and
373      * then releasing the connection after the method is processed.
374      *
375      * @param sessionId The session which we're going to persist information
376      * @throws Exception
377      * @see #storeSessionData(String, Connection)
378      */

379     public static void storeSessionData(String JavaDoc sessionId) throws Exception JavaDoc
380     {
381         Connection JavaDoc conn = null;
382         try {
383             conn = DBConnection.getImplementation().getConnection();
384             SessionFacade.storeSessionData(sessionId, conn);
385         }
386         finally {
387             if (conn != null) {
388                 try {
389                     DBConnection.getImplementation().releaseConnection(conn);
390                 }
391                 catch (Exception JavaDoc e) {
392                     logger.warn("Error while releasing a connection: " + e);
393                 }
394             }
395         }
396     }
397
398     /**
399      * Persists user session information.
400      *
401      * @param sessionId The session which we're going to persist
402      * @param conn A <code>Connection</code> to be used to connect to
403      * the database.
404      * @throws Exception
405      * @see #storeSessionData(String)
406      */

407     public static void storeSessionData(String JavaDoc sessionId, Connection JavaDoc conn) throws Exception JavaDoc
408     {
409         UserSession us = SessionFacade.getUserSession(sessionId);
410         if (us != null) {
411             try {
412                 if (us.getUserId() != SystemGlobals.getIntValue(ConfigKeys.ANONYMOUS_USER_ID)) {
413                     DataAccessDriver.getInstance().newUserSessionDAO().update(us, conn);
414                 }
415                 
416                 SecurityRepository.remove(us.getUserId());
417             }
418             catch (Exception JavaDoc e) {
419                 logger.warn("Error storing user session data: " + e, e);
420             }
421         }
422     }
423 }
424
Popular Tags