001: /*
002: * RimfaxeHttpSession.java
003: *
004: *
005: * Copyright (c) 2003 Rimfaxe ApS (www.rimfaxe.com).
006: * All rights reserved.
007: *
008: * This package is written by Lars Andersen <lars@rimfaxe.com>
009: * and licensed by Rimfaxe ApS.
010: *
011: * Redistribution and use in source and binary forms, with or without
012: * modification, are permitted provided that the following conditions
013: * are met:
014: *
015: * 1. Redistributions of source code must retain the above copyright
016: * notice, this list of conditions and the following disclaimer.
017: *
018: * 2. Redistributions in binary form must reproduce the above copyright
019: * notice, this list of conditions and the following disclaimer in
020: * the documentation and/or other materials provided with the
021: * distribution.
022: *
023: * 3. The end-user documentation included with the redistribution, if
024: * any, must include the following acknowlegement:
025: * "This product includes software developed by Rimfaxe ApS
026: (www.rimfaxe.com)"
027: * Alternately, this acknowlegement may appear in the software itself,
028: * if and wherever such third-party acknowlegements normally appear.
029: *
030: * 4. The names "Rimfaxe", "Rimfaxe Software", "Lars Andersen" and
031: * "Rimfaxe WebServer" must not be used to endorse or promote products
032: * derived from this software without prior written permission. For written
033: * permission, please contact info@rimfaxe.com
034: *
035: * 5. Products derived from this software may not be called "Rimfaxe"
036: * nor may "Rimfaxe" appear in their names without prior written
037: * permission of the Rimfaxe ApS.
038: *
039: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
040: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
041: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
042: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
043: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
044: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
045: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
046: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
047: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
048: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
049: * SUCH DAMAGE.
050: *
051: */
052:
053: package com.rimfaxe.webserver.servletapi;
054:
055: import javax.servlet.http.Cookie;
056: import javax.servlet.http.HttpSession;
057: import javax.servlet.http.HttpSessionBindingEvent;
058: import javax.servlet.http.HttpSessionBindingListener;
059: import javax.servlet.http.HttpSessionContext;
060:
061: import java.util.Enumeration;
062: import java.util.Hashtable;
063:
064: import com.rimfaxe.webserver.VirtualHost;
065:
066: public class RimfaxeHttpSession implements HttpSession {
067:
068: private VirtualHost virtualhost;
069: private com.rimfaxe.webserver.WebContext webcontext;
070:
071: private String id = null;
072:
073: private long creationTime = -1;
074: private long lastAccessedTime = -1;
075:
076: //private boolean isValid = false;
077: private boolean isNew = false;
078:
079: private Cookie cookie = null;
080:
081: private Hashtable values = null;
082:
083: private int maxidle = 30 * 60; // default 30 minutes
084:
085: /**
086: * Returns the identifier assigned to this session. An HttpSession's
087: * identifier is a unique string that is created and maintained by
088: * HttpSessionContext.
089: * @return the identifier assigned to this session
090: */
091: public String getId() {
092: return id;
093: }
094:
095: /**
096: * Returns the context in which this session is bound.
097: * @return the context in which this session is bound.
098: * @deprecated since jsdk2.1
099: * IGNORE
100: */
101: public HttpSessionContext getSessionContext() {
102: return null;
103: }
104:
105: public javax.servlet.ServletContext getServletContext() {
106: return (javax.servlet.ServletContext) webcontext
107: .getServletContext();
108: }
109:
110: /**
111: * Returns the object bound with the specified name in this session, or
112: * <code>null</code> if no object is bound under the name.
113: * @param name a string specifying the name of the object
114: * @return the object with the specified name
115: */
116: public Object getAttribute(String name) {
117: return getValue(name);
118: }
119:
120: /**
121: * Returns an <code>Enumeration</code> of <code>String</code> objects
122: * containing the names of all the objects bound to this session.
123: * @return an <code>Enumeration</code> of <code>String</code> objects
124: * specifying the names of all the objects bound to this session
125: */
126: public Enumeration getAttributeNames() {
127: return values.keys();
128: }
129:
130: /**
131: * Binds an object to this session, using the name specified.
132: * If an object of the same name is already bound to the session,
133: * the object is replaced.
134: *
135: * <p>After this method executes, and if the object
136: * implements <code>HttpSessionBindingListener</code>,
137: * the container calls
138: * <code>HttpSessionBindingListener.valueBound</code>.
139: *
140: * @param name the name to which the object is bound; cannot be null
141: * @param value the object to be bound; cannot be null
142: */
143: public void setAttribute(String name, Object value) {
144: putValue(name, value);
145: }
146:
147: /**
148: * Removes the object bound with the specified name from
149: * this session. If the session does not have an object
150: * bound with the specified name, this method does nothing.
151: *
152: * <p>After this method executes, and if the object
153: * implements <code>HttpSessionBindingListener</code>,
154: * the container calls
155: * <code>HttpSessionBindingListener.valueUnbound</code>.
156: *
157: * @param name the name of the object to remove from this session
158: */
159: public void removeAttribute(String name) {
160: removeValue(name);
161: }
162:
163: /**
164: * Returns the time at which this session representation was created,
165: * in milliseconds since midnight, January 1, 1970 UTC.
166: * @return the time when the session was created
167: */
168: public long getCreationTime() {
169: return creationTime;
170: }
171:
172: /**
173: * Returns the last time the client sent a request carrying the identifier
174: * assigned to the session. Time is expressed as milliseconds
175: * since midnight, January 1, 1970 UTC. Application level operations,
176: * such as getting or setting a value associated with the session,
177: * does not affect the access time.
178: * @return the last time the client sent a request carrying the identifier
179: * assigned to the session.
180: */
181: public long getLastAccessedTime() {
182: return lastAccessedTime;
183: }
184:
185: public void setLastAccessedTime() {
186: lastAccessedTime = System.currentTimeMillis();
187: }
188:
189: /**
190: * Causes this representation of the session to be invalidated and removed
191: * from its context.
192: */
193: public void invalidate() {
194:
195: Enumeration names = values.keys();
196: while (names.hasMoreElements()) {
197: String name = (String) (names.nextElement());
198: removeValue(name);
199: }
200:
201: this .virtualhost.getSessionStore().removeSessionObject(id);
202:
203: }
204:
205: /**
206: * Returns the object bound to the given name in the session's application
207: * layer data. Returns null if there is no such binding.
208: * @param name - the name of the binding to find
209: * @return the value bound to that name, or null if the binding does
210: * not exist.
211: */
212: public Object getValue(String name) {
213:
214: return values.get(name);
215: }
216:
217: /**
218: * Binds the specified object into the session's application layer data
219: * with the given name. Any existing binding with the same name
220: * is replaced. New (or existing) values that implement the
221: * HttpSessionBindingListener interface will call its valueBound() method.
222: * @param name - the name to which the data object will be bound.
223: * This parameter cannot be null.
224: * @param value - the data object to be bound. This parameter cannot
225: * be null.
226: */
227: public void putValue(String name, Object value) {
228: removeValue(name);
229: // null check added in accordance with servlet api, tk. 23.10.2001
230: if (value != null) {
231: values.put(name, value);
232: if (value instanceof HttpSessionBindingListener)
233: valueBound((HttpSessionBindingListener) value, name);
234: }
235: }
236:
237: /**
238: * Removes the object bound to the given name in the session's application
239: * layer data. Does nothing if there is no object bound to the
240: * given name. The value that implements the HttpSessionBindingListener
241: * interface will call its valueUnbound() method.
242: * @param name - the name of the object to remove
243: *
244: */
245: public void removeValue(String name) {
246:
247: Object value = values.get(name);
248: if (value != null) {
249: values.remove(name);
250: if (value instanceof HttpSessionBindingListener)
251: valueUnbound((HttpSessionBindingListener) value, name);
252: }
253: }
254:
255: protected void valueBound(HttpSessionBindingListener value,
256: String name) {
257: value.valueBound(new HttpSessionBindingEvent(this , name));
258: }
259:
260: protected void valueUnbound(HttpSessionBindingListener value,
261: String name) {
262: value.valueUnbound(new HttpSessionBindingEvent(this , name));
263: }
264:
265: /**
266: * Returns an array of the names of all the application layer data objects
267: * bound into the session. For example, if you want to delete
268: * all of the data objects bound into the session, use this method to
269: * obtain their names.
270: * @return an array containing the names of all of the application layer
271: * data objects bound into the session
272: *
273: */
274: public String[] getValueNames()
275: {
276:
277: String names[] = new String[values.size()];
278: Enumeration enum = values.keys();
279: int i = 0;
280: while (enum.hasMoreElements())
281: names[i++] = (String)enum.nextElement();
282: return names;
283: }
284:
285: /**
286: * A session is considered to be "new" if it has been created by the
287: * server, but the client has not yet acknowledged joining the
288: * session. For example, if the server supported only cookie-based
289: * sessions and the client had completely disabled the use of
290: * cookies, then calls to HttpServletRequest.getSession() would always
291: * return "new" sessions.
292: * @return true if the session has been created by the server but the
293: * client has not yet acknowledged joining the session; false otherwise
294: *
295: */
296: public boolean isNew() {
297: return isNew;
298: }
299:
300: protected void setNoMoreNew() {
301: isNew = false;
302: }
303:
304: protected boolean isValid() {
305: return true;
306: }
307:
308: protected Cookie getCookie() {
309: return cookie;
310: }
311:
312: public void setMaxInactiveInterval(int interval) {
313: maxidle = interval;
314: }
315:
316: public int getMaxInactiveInterval() {
317: return maxidle;
318: }
319:
320: public void setID(String id) {
321: this .id = id;
322: }
323:
324: public boolean hasExpired() {
325:
326: long now = System.currentTimeMillis();
327: long expiration = lastAccessedTime + (maxidle * 1000);
328:
329: //System.out.println("Session age = "+(now-lastAccessedTime));
330:
331: if (expiration < now) {
332: //System.out.println("Session has expired");
333: return true;
334: }
335: return false;
336: }
337:
338: public RimfaxeHttpSession(Cookie cookie,
339: com.rimfaxe.webserver.WebContext ctx) {
340: this .values = new Hashtable();
341: this .creationTime = System.currentTimeMillis();
342: this .lastAccessedTime = creationTime;
343: this .cookie = cookie;
344:
345: isNew = true;
346: this.virtualhost = ctx.getVirtualHost();
347: this.webcontext = ctx;
348:
349: maxidle = ctx.getSessionExpirationInterval();
350: }
351:
352: }
|