KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > directwebremoting > impl > DefaultScriptSessionManager


1 /*
2  * Copyright 2005 Joe Walker
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 at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * 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 and
14  * limitations under the License.
15  */

16 package org.directwebremoting.impl;
17
18 import java.util.ArrayList JavaDoc;
19 import java.util.Collection JavaDoc;
20 import java.util.HashMap JavaDoc;
21 import java.util.HashSet JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.Set JavaDoc;
26
27 import org.directwebremoting.extend.PageNormalizer;
28 import org.directwebremoting.extend.RealScriptSession;
29 import org.directwebremoting.extend.ScriptSessionManager;
30 import org.directwebremoting.util.Logger;
31
32 /**
33  * A default implmentation of ScriptSessionManager.
34  * <p>There are synchronization constraints on this class that could be broken
35  * by subclasses. Specifically anyone accessing either <code>sessionMap</code>
36  * or <code>pageSessionMap</code> must be holding the <code>sessionLock</code>.
37  * <p>In addition you should note that {@link DefaultScriptSession} and
38  * {@link DefaultScriptSessionManager} make calls to each other and you should
39  * take care not to break any constraints in inheriting from these classes.
40  * @author Joe Walker [joe at getahead dot ltd dot uk]
41  */

42 public class DefaultScriptSessionManager implements ScriptSessionManager
43 {
44     /* (non-Javadoc)
45      * @see org.directwebremoting.ScriptSessionManager#getScriptSession(java.lang.String)
46      */

47     public RealScriptSession getScriptSession(String JavaDoc id)
48     {
49         maybeCheckTimeouts();
50
51         synchronized (sessionLock)
52         {
53             DefaultScriptSession scriptSession = (DefaultScriptSession) sessionMap.get(id);
54             if (scriptSession == null)
55             {
56                 scriptSession = new DefaultScriptSession(id, this);
57                 sessionMap.put(id, scriptSession);
58             }
59             else
60             {
61                 scriptSession.updateLastAccessedTime();
62             }
63
64             return scriptSession;
65         }
66     }
67
68     /* (non-Javadoc)
69      * @see org.directwebremoting.ScriptSessionManager#setPageForScriptSession(org.directwebremoting.extend.RealScriptSession, java.lang.String)
70      */

71     public void setPageForScriptSession(RealScriptSession scriptSession, String JavaDoc page)
72     {
73         String JavaDoc normalizedPage = pageNormalizer.normalizePage(page);
74         synchronized (sessionLock)
75         {
76             Set JavaDoc pageSessions = (Set JavaDoc) pageSessionMap.get(normalizedPage);
77             if (pageSessions == null)
78             {
79                 pageSessions = new HashSet JavaDoc();
80                 pageSessionMap.put(normalizedPage, pageSessions);
81             }
82
83             pageSessions.add(scriptSession);
84         }
85     }
86
87     /* (non-Javadoc)
88      * @see org.directwebremoting.ScriptSessionManager#getScriptSessionsByPage(java.lang.String)
89      */

90     public Collection JavaDoc getScriptSessionsByPage(String JavaDoc page)
91     {
92         String JavaDoc normalizedPage = pageNormalizer.normalizePage(page);
93         synchronized (sessionLock)
94         {
95             Set JavaDoc pageSessions = (Set JavaDoc) pageSessionMap.get(normalizedPage);
96             if (pageSessions == null)
97             {
98                 pageSessions = new HashSet JavaDoc();
99             }
100
101             Set JavaDoc reply = new HashSet JavaDoc();
102             reply.addAll(pageSessions);
103             return reply;
104         }
105     }
106
107     /* (non-Javadoc)
108      * @see org.directwebremoting.ScriptSessionManager#getAllScriptSessions()
109      */

110     public Collection JavaDoc getAllScriptSessions()
111     {
112         synchronized (sessionLock)
113         {
114             Set JavaDoc reply = new HashSet JavaDoc();
115             reply.addAll(sessionMap.values());
116             return reply;
117         }
118     }
119
120     /**
121      * Remove the given session from the list of sessions that we manage, and
122      * leave it for the GC vultures to pluck.
123      * @param scriptSession The session to get rid of
124      */

125     protected void invalidate(RealScriptSession scriptSession)
126     {
127         // Can we think of a reason why we need to sync both together?
128
// It feels like a deadlock risk to do so
129
synchronized (sessionLock)
130         {
131             RealScriptSession removed = (RealScriptSession) sessionMap.remove(scriptSession.getId());
132             if (!scriptSession.equals(removed))
133             {
134                 log.error("ScriptSession already removed from manager. scriptSession=" + scriptSession + " removed=" + removed);
135             }
136
137             int removeCount = 0;
138             for (Iterator JavaDoc it = pageSessionMap.values().iterator(); it.hasNext();)
139             {
140                 Set JavaDoc pageSessions = (Set JavaDoc) it.next();
141                 boolean isRemoved = pageSessions.remove(scriptSession);
142
143                 if (isRemoved)
144                 {
145                     removeCount++;
146                 }
147             }
148
149             if (removeCount != 1)
150             {
151                 log.error("DefaultScriptSessionManager.invalidate(): removeCount=" + removeCount + " when invalidating: " + scriptSession);
152             }
153         }
154     }
155
156     /**
157      * If we call {@link #checkTimeouts()} too often is could bog things down so
158      * we only check every one in a while (default 30 secs); this checks to see
159      * of we need to check, and checks if we do.
160      */

161     protected void maybeCheckTimeouts()
162     {
163         long now = System.currentTimeMillis();
164         if (now - scriptSessionCheckTime > lastSessionCheckAt)
165         {
166             checkTimeouts();
167         }
168     }
169
170     /**
171      * Do a check on all the known sessions to see if and have timeout and need
172      * removing.
173      */

174     protected void checkTimeouts()
175     {
176         long now = System.currentTimeMillis();
177         List JavaDoc timeouts = new ArrayList JavaDoc();
178
179         synchronized (sessionLock)
180         {
181             for (Iterator JavaDoc it = sessionMap.values().iterator(); it.hasNext();)
182             {
183                 DefaultScriptSession session = (DefaultScriptSession) it.next();
184
185                 if (session.isInvalidated())
186                 {
187                     continue;
188                 }
189
190                 long age = now - session.getLastAccessedTime();
191                 if (age > scriptSessionTimeout)
192                 {
193                     timeouts.add(session);
194                 }
195             }
196
197             for (Iterator JavaDoc it = timeouts.iterator(); it.hasNext();)
198             {
199                 DefaultScriptSession session = (DefaultScriptSession) it.next();
200                 session.invalidate();
201             }
202         }
203     }
204
205     /* (non-Javadoc)
206      * @see org.directwebremoting.ScriptSessionManager#getScriptSessionTimeout()
207      */

208     public long getScriptSessionTimeout()
209     {
210         return scriptSessionTimeout;
211     }
212
213     /* (non-Javadoc)
214      * @see org.directwebremoting.ScriptSessionManager#setScriptSessionTimeout(long)
215      */

216     public void setScriptSessionTimeout(long timeout)
217     {
218         this.scriptSessionTimeout = timeout;
219     }
220
221     /**
222      * Accessfor for the PageNormalizer.
223      * @param pageNormalizer The new PageNormalizer
224      */

225     public void setPageNormalizer(PageNormalizer pageNormalizer)
226     {
227         this.pageNormalizer = pageNormalizer;
228     }
229
230     /**
231      * @param scriptSessionCheckTime the scriptSessionCheckTime to set
232      */

233     public void setScriptSessionCheckTime(long scriptSessionCheckTime)
234     {
235         this.scriptSessionCheckTime = scriptSessionCheckTime;
236     }
237
238     /**
239      * By default we check for sessions that need expiring every 30 seconds
240      */

241     protected static final long DEFAULT_SESSION_CHECK_TIME = 30000;
242
243     /**
244      * How we turn pages into the canonical form.
245      */

246     protected PageNormalizer pageNormalizer;
247
248     /**
249      * How long do we wait before we timeout script sessions?
250      */

251     protected long scriptSessionTimeout = DEFAULT_TIMEOUT_MILLIS;
252
253     /**
254      * How often do we check for script sessions that need timing out
255      */

256     protected long scriptSessionCheckTime = DEFAULT_SESSION_CHECK_TIME;
257
258     /**
259      * We check for sessions that need timing out every
260      * {@link #scriptSessionCheckTime}; this is when we last checked.
261      */

262     protected long lastSessionCheckAt = System.currentTimeMillis();
263
264     /**
265      * What we synchronize against when we want to access either sessionMap or
266      * pageSessionMap
267      */

268     protected final Object JavaDoc sessionLock = new Object JavaDoc();
269
270     /**
271      * The map of all the known sessions
272      * <p>GuardedBy("sessionLock")
273      */

274     protected Map JavaDoc sessionMap = new HashMap JavaDoc();
275
276     /**
277      * The map of pages that have sessions
278      * <p>GuardedBy("sessionLock")
279      */

280     protected Map JavaDoc pageSessionMap = new HashMap JavaDoc();
281
282     /**
283      * The log stream
284      */

285     private static final Logger log = Logger.getLogger(DefaultScriptSessionManager.class);
286 }
287
Popular Tags