• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Techniques for Automated Software Evolution
 

Techniques for Automated Software Evolution

on

  • 609 views

For a variety of reasons, modern, non-trivial software systems must evolve to cope with change, including alterations in stakeholder requirements, environments in which the software is deployed, and ...

For a variety of reasons, modern, non-trivial software systems must evolve to cope with change, including alterations in stakeholder requirements, environments in which the software is deployed, and dependent technologies, e.g., frameworks. Unfortunately, evolution and maintenance is an expensive, time-consuming, and error-prone task, especially when the system in question is large and complex. Typically, a change to a single program element requires changes to related, and often seemingly unrelated, elements scattered throughout the source code.

To address this problem, approaches have emerged to mechanically assist developers with a wide range of software evolution and maintenance tasks, including migrating code to a new framework version, translating existing code to a new platform, and restructuring code to mirror an improved design. This assistance is typically provided in the form of extensions (plug-ins) to integrated development environments (IDEs) that afford (semi-) automated aid in carrying out these tasks, thus easing the burden associated with evolution and maintenance. In some approaches, the corresponding plug-in keeps track of the elements relevant to the change being implemented, with the IDE displaying only those elements. Other approaches attempt to automatically restructure code to improve such features as type safety while preserving semantics.

Although existing approaches are useful in alleviating some of the burden associated with software evolution and maintenance, there are a number of situations where developers are still required to complete evolution and maintenance tasks manually. These include but are not limited to upgrading legacy Java software to take advantage of many other available features of the modern Java language, replacing certain usages of Java collections with custom type hierarchies, and updating software composition specifications to cope with change. Automated approaches to assist developers with such cumbersome and error-prone tasks would be extremely useful in evolving and maintaining large, complex systems.

In this thesis, I explore and develop a number of new techniques that can be of great value to software developers in evolving code to accommodate change. The first of these is an automated refactoring which upgrades legacy Java code to use proper language enumeration (enum) types, a feature of the modern Java language. I have developed an approach that preserves semantics and that allows us to migrate legacy applications by automatically replacing a predominantly used pattern with suitable use of enums.

For the second technique, I explore and develop an automated approach to assist developers in maintaining pointcuts in evolving Aspect-Oriented (AO) programs. AO languages enable developers to better encapsulate crosscutting concern (CCC) implementations by allowing them to create an expression (a pointcut) which specifies well-defined points (join points) in a program's execution where code corresponding to a CCC (an aspect) should apply. However, changes to the underlying program (base-code) may invalidate pointcuts, leaving developers to manually update pointcuts to capture the intended join points. I have developed an approach that mechanically aids developers in suitably updating pointcuts upon changes to the base-code by analyzing arbitrarily deep structural commonalities between program elements associated with pointcuts in a particular software version. The extracted patterns are then applied to later versions to suggest additional join points that may require inclusion.

The third technique I explore in this thesis pertains to reasoning about the behavior of AO programs. As previously noted, AOP facilitates localized implementations of CCCs by allowing developers to encapsulate code realizing a CCC that would otherwise be scattered throughout many system modules and/or intertwined with code realizing the primary functionality of a module. Theref

Statistics

Views

Total Views
609
Views on SlideShare
601
Embed Views
8

Actions

Likes
0
Downloads
13
Comments
0

2 Embeds 8

http://www.techgig.com 5
http://www.linkedin.com 3

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Techniques for Automated Software Evolution Techniques for Automated Software Evolution Presentation Transcript

    • Techniques for Automated Software Evolution PhD Dissertation by Raffi Khatchadourian Computer Science & Engineering Ohio State University Advisor: Neelam Soundarajan Committee: Atanas Rountev, Paul Sivilotti, Paul Evans 1
    • Biography• Born in New York, NY and raised in Edison, NJ.• First generation American. • Family immigrated from Sofia, Bulgaria.• Graduated from Monmouth University in 2004 with a B.S. in Computer Science.• Worked as: • A Software Engineer at State of New Jersey Office of Information Technology in Trenton, NJ. • A UNIX Systems Administrator for pharmaceutical website in Toms River, NJ.• Entered PhD program at OSU in September, 2005.• M.S. in Computer Science from OSU in March, 2010.• Start as an RF (wireless) Systems Integration Engineer on the iPhone development team at Apple Inc. in Cupertino, CA on Monday (4/4/2011). 2
    • Publication Highlights• Raffi Khatchadourian, Phil Greenwood, Awais Rashid, and Guoqing Xu. Pointcut rejuvenation: Recovering pointcut expressions in evolving aspect-oriented software. IEEE Transactions on Software Engineering, 99(PrePrints), 2011. ISSN 0098-5589.• Raffi Khatchadourian, Phil Greenwood, Awais Rashid, and Guoqing Xu. Pointcut rejuvenation: Recovering pointcut expressions in evolving aspect-oriented software. In Proceedings of the 24th International Conference on Automated Software Engineering (ASE ’09), pages 575–579, Auckland, New Zealand, November 2009. IEEE/ACM.• Raffi Khatchadourian, Johan Dovland, and Neelam Soundarajan. Enforcing behavioral constraints in evolving aspect-oriented programs. In Proceedings of the 7th International Workshop on Foundations of Aspect- Oriented Languages (FOAL ’08) at the 7th International Conference on Aspect- Oriented Software Development (AOSD ’08), pages 19–28, Brussels, Belgium, April 2008. ACM.• Raffi Khatchadourian, Jason Sawin, and Atanas Rountev. Automated refactoring of legacy Java software to enumerated types. In Proceedings of the 23rd International Conference on Software Maintenance (ICSM ’07), pages 224–233, Paris, France, October 2007. IEEE.• Peer-reviewed totals (2005-): 1 paper to appear in a journal, 5 papers appearing in conference proceedings, and 5 papers appearing in workshop proceedings. 3
    • Activity Highlights• Helped develop new Applied Software Engineering course ECE/CSE 668 based on Challenge-X hybrid SUV automobile simulation at OSU CAR in 2006.• Summer intern at Bell Labs under Rick Hull and Kedar Namjoshi (program language design for shared-experience, multimedia, multi- protocol, event-driven applications) in 2007.• Visiting Graduate Research Associate with the Aspect-Oriented Software Engineering (AOSE) Group at the Computing Department of Lancaster University, UK under Awais Rashid in 2008.• Visiting Researcher with the Programming Principles and Practices (PPP) Group at the Department of Graphics and Computer Science of the University of Tokyo under Hidehiko Masuhara in 2010.• Proposed project mentor for Google Summer of Code (GSoC) in 2009 and 2010. Project based on refactoring to enumerated types in Java.• Organizing committee member (Web Chair) for the European Conference on Object-Oriented Programming (ECOOP). 4
    • Award Highlights• Japan Society for the Promotion of Science (JSPS) Summer Program Fellowship Recipient in 2010.• National Science Foundation (NSF) East Asia and Pacific Summer Institutes (EAPSI) Award Recipient in 2010.• Ohio State University Department of Computer Science & Engineering Graduate Teaching Award Recipient in 2010. 5
    • Motivation 6
    • Motivation• Software changes over time: 6
    • Motivation• Software changes over time: • Requirements evolve 6
    • Motivation• Software changes over time: • Requirements evolve • New platforms emerge (e.g., mobile devices) 6
    • Motivation• Software changes over time: • Requirements evolve • New platforms emerge (e.g., mobile devices) • Frameworks change (e.g., XML vs. annotation-based) 6
    • Motivation 7
    • MotivationChanging and/or maintaining large, complex softwaresystems can be non-trivial: Tedious: May require changing many lines of code. Error-prone: Changes may be implemented incorrectly. Omission- May opportunities to produce better prone: code. 7
    • MotivationChanging and/or maintaining large, complex softwaresystems can be non-trivial: Tedious: May require changing many lines of code. Error-prone: Changes may be implemented incorrectly. Omission- May opportunities to produce better prone: code. 7
    • Motivation Adding a parameter to aChanging and/or maintaining large, complex softwaresystems can be non-trivial: method Tedious: May require changing many lines of code. Error-prone: Changes may be implemented incorrectly. Omission- May opportunities to produce better prone: code. 7
    • MotivationChanging and/or maintaining large, complex softwaresystems can be non-trivial: Tedious: May require changing many lines of code. Error-prone: Changes may be implemented incorrectly. Omission- May opportunities to produce better prone: code. 7
    • Motivation Removing aChanging and/or maintaining large, complex softwaresystemsparameter maymethod can be non-trivial: alter overloading to Tedious: May require changing many lines of overriding code. Error-prone: Changes may be implemented incorrectly. Omission- May opportunities to produce better prone: code. 7
    • MotivationChanging and/or maintaining large, complex softwaresystems can be non-trivial: Tedious: May require changing many lines of code. Error-prone: Changes may be implemented incorrectly. Omission- May opportunities to produce better prone: code. 7
    • MotivationChanging and/or maintaining large, complex softwaresystems can be non-trivial: Tedious: May require changing many lines of code. HashTable vs. Error-prone: Changes may be implemented incorrectly. HashMap Omission- May opportunities to produce better prone: code. 7
    • MotivationChanging and/or maintaining large, complex softwaresystems can be non-trivial: Tedious: May require changing many lines of code. Error-prone: Changes may be implemented incorrectly. Omission- May opportunities to produce better prone: code. 7
    • Approach 8
    • Approach• Approaches made to provide mechanical assistance in evolution tasks. 8
    • Approach• Approaches made to provide mechanical assistance in evolution tasks.• Typically in the form of plug-ins to IDEs. 8
    • Approach• Approaches made to provide mechanical assistance in evolution tasks.• Typically in the form of plug-ins to IDEs.• Ease the burden of software maintenance and evolution. 8
    • Approach Restrict workspace to only• Approaches made to displays elements provide mechanical relevant to the assistance in evolution task tasks.• Typically in the form of plug-ins to IDEs.• Ease the burden of software maintenance and evolution. 8
    • Approach Restrict workspace to only• Approaches made to displays elements provide mechanical relevant to the assistance in evolution task tasks.• Typically in the form of plug-ins to IDEs. Restructure•code the burden of Ease while preserving semantics (i.e., software maintenance and evolution. refactoring) 8
    • Thesis Outline 9
    • Thesis Outline• For my thesis, I have pursed three directions: 9
    • Thesis Outline• For my thesis, I have pursed three directions: 1. Mechanically alleviate burden of fragile pointcuts in Aspect-Oriented software. 9
    • Thesis Outline• For my thesis, I have pursed three directions: 1. Mechanically alleviate burden of fragile pointcuts in Aspect-Oriented software. 2.Automatically refactor legacy Java software to language enumerated (enum) types. 9
    • Thesis Outline• For my thesis, I have pursed three directions: 1. Mechanically alleviate burden of fragile pointcuts in Aspect-Oriented software. 2.Automatically refactor legacy Java software to language enumerated (enum) types. 3.Robustly specify evolving Aspect-Oriented software components. 9
    • Crosscutting Concerns/* public void invalidate() { ; * Remove the object bound with the specified name from this session. If * ==================================================================== serverSession.removeApplicationSession(context); * the session does not have an object bound with this name, this method * * does nothing. * The Apache Software License, Version 1.1 // remove everything in the session /** * <p> * * Standard implementation of the <b>Session</b> interface. This object is * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. */ * notice, this list of conditions and the following disclaimer. * public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ Object object = attributes.get(name); * the documentation and/or other materials provided with the if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession return; * } implements HttpSession, Session { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { /** if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors * Update the accessed time information for this session. This method ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { * should be called by the context when a request comes in for a particular (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; * session, even if the application does not reference it. }itself, } /** */ } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. public void access() { * * } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated this.lastAccessedTime = this.thisAccessedTime; * Foundation" must not be used to endorse or promote products /** */ this.thisAccessedTime = System.currentTimeMillis(); * Bind an object to this session, using the specified name. If an objectderived * @deprecated public StandardSession(Manager manager) { this.isNew=false; * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ } * replaced. * permission, please contact apache@apache.org. super(); * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); /** * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } * Perform the internal processing required to invalidate this session, * <code>valueBound()</code> on the object. * permission of the Apache Group. * without triggering an exception if the session has already expired. * * public void setAttribute(String name, Object value) { */ * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS AND ANY EXPRESSED OR IMPLIED if (! valid) { /** public void expire() { * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ // Remove this session from our managers active sessions * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; if ((manager != null) && (manager instanceof ManagerBase)) * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } ((ManagerBase) manager).remove(this); * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** // Unbind any objects associated with this session */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. Vector results = new Vector(); public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ Enumeration attrs = getAttributeNames(); * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; while (attrs.hasMoreElements()) { if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } String attr = (String) attrs.nextElement(); !(value instanceof Serializable)) * SUCH DAMAGE. results.addElement(attr); throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** } (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before Enumeration names = results.elements(); * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time while (names.hasMoreElements()) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. String name = (String) names.nextElement(); removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ removeAttribute(name); attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } // Mark this session as invalid (new HttpSessionBindingEvent((HttpSession) this, name)); * /** setValid(false); } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } } private boolean isNew = true; /**package org.apache.tomcat.session; * @deprecated /** // -------------------------------------------- HttpSession Private Methods */ /**import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. }import org.apache.tomcat.util.StringManager; return getAttribute(name); */ /**import java.io.*; } private boolean isValid = false; * Read a serialized version of this session object from the specifiedimport java.net.*; /** * object input stream.import java.util.*; public Object getAttribute(String name) { * Set the <code>isNew</code> flag for this session. * <p>import javax.servlet.*; if (! valid) { /** * * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Managerimport javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * @param isNew The new value for the <code>isNew</code> flag * is not restored by this method, and must be set explicitly. */ */ */** throw new IllegalStateException(msg); private StringManager sm = void setNew(boolean isNew) { * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * this.isNew = isNew; * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * @exception IOException if an input/output error occurs * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** } */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; /**public class ApplicationSession implements HttpSession { * Set the <code>isValid</code> flag for this session. // Deserialize the scalar instance variables (except Manager) return values.get(name); * creationTime = ((Long) stream.readObject()).longValue(); private StringManager sm = } /** * @param isValid The new value for the <code>isValid</code> flag id = (String) stream.readObject(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. */ lastAccessedTime = ((Long) stream.readObject()).longValue(); private Hashtable values = new Hashtable(); /** */ void setValid(boolean isValid) { maxInactiveInterval = ((Integer) stream.readObject()).intValue(); private String id; * @deprecated private long thisAccessedTime = creationTime; isNew = ((Boolean) stream.readObject()).booleanValue(); private ServerSession serverSession; */ this.isValid = isValid; isValid = ((Boolean) stream.readObject()).booleanValue(); private Context context; public String[] getValueNames() { } private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); // Deserialize the attribute count and attribute values private long thisAccessTime = creationTime; Vector names = new Vector(); int n = ((Integer) stream.readObject()).intValue(); private long lastAccessed = creationTime; // ----------------------------------------------------- Session Properties // ------------------------------------------------- HttpSession Properties for (int i = 0; i < n; i++) { private int inactiveInterval = -1; while (e.hasMoreElements()) { String name = (String) stream.readObject(); private boolean valid = true; names.addElement(e.nextElement()); Object value = (Object) stream.readObject(); } /** /** attributes.put(name, value); ApplicationSession(String id, ServerSession serverSession, * Set the creation time for this session. This method is called by the * Return the time when this session was created, in milliseconds since } Context context) { String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * midnight, January 1, 1970 GMT. this.serverSession = serverSession; * * } this.context = context; names.copyInto(valueNames); * @param time The new creation time * @exception IllegalStateException if this method is called on an this.id = id; */ * invalidated session return valueNames; public void setCreationTime(long time) { */ /** this.inactiveInterval = context.getSessionTimeOut(); public long getCreationTime() { * Write a serialized version of this session object to the specified } this.creationTime = time; * object output stream. if (this.inactiveInterval != -1) { this.lastAccessedTime = time; return (this.creationTime); * <p> this.inactiveInterval *= 60; public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored } if (! valid) { } * in the serialized representation of this Session. After calling } String msg = sm.getString("applicationSession.session.ise"); * <code>readObject()</code>, you must set the associated Manager * explicitly. ServerSession getServerSession() { throw new IllegalStateException(msg); /** * <p> return serverSession; } * Return the session context with which this session is associated. * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable } * * will be silently ignored. If you do not want any such attributes, Hashtable valuesClone = (Hashtable)values.clone(); * @deprecated As of Version 2.1, this method is deprecated and has no * be sure the <code>distributable</code> property of our associated /** * replacement. It will be removed in a future version of the * Manager is set to <code>true</code>. * Called by context when request comes in so that accesses and return (Enumeration)valuesClone.keys(); * Java Servlet API. * * inactivities can be dealt with accordingly. } */ * @param stream The output stream to write to */ public HttpSessionContext getSessionContext() { * * @exception IOException if an input/output error occurs void accessed() { /** if (sessionContext == null) */ // set last accessed to thisAccessTime as it will be left over * @deprecated sessionContext = new StandardSessionContext(); private void writeObject(ObjectOutputStream stream) throws IOException { // from the previous access */ return (sessionContext); lastAccessed = thisAccessTime; // Write the scalar instance variables (except Manager) thisAccessTime = System.currentTimeMillis(); public void removeValue(String name) { } stream.writeObject(new Long(creationTime)); removeAttribute(name); stream.writeObject(id); validate(); } stream.writeObject(new Long(lastAccessedTime)); } // ----------------------------------------------HttpSession Public Methods stream.writeObject(new Integer(maxInactiveInterval)); public void removeAttribute(String name) { stream.writeObject(new Boolean(isNew)); void validate() { if (! valid) { } stream.writeObject(new Boolean(isValid)); // if we have an inactive interval, check to see if weve exceeded it String msg = sm.getString("applicationSession.session.ise"); /** if (inactiveInterval != -1) { * Return the object bound with the specified name in this session, or // Accumulate the names of serializable attributes int thisInterval = throw new IllegalStateException(msg); * <code>null</code> if no object is bound with that name. Vector results = new Vector(); (int)(System.currentTimeMillis() - lastAccessed) / 1000; } * Enumeration attrs = getAttributeNames(); * @param name Name of the attribute to be returned while (attrs.hasMoreElements()) { if (thisInterval > inactiveInterval) { if (name == null) { * String attr = (String) attrs.nextElement(); invalidate(); String msg = sm.getString("applicationSession.value.iae"); * @exception IllegalStateException if this method is called on an Object value = attributes.get(attr); } * invalidated session if (value instanceof Serializable) } throw new IllegalArgumentException(msg); */ results.addElement(attr); } } public Object getAttribute(String name) { } // HTTP SESSION IMPLEMENTATION METHODS Object o = values.get(name); return (attributes.get(name)); // Serialize the attribute count and the attribute values stream.writeObject(new Integer(results.size())); public String getId() { if (o instanceof HttpSessionBindingListener) { } Enumeration names = results.elements(); if (valid) { HttpSessionBindingEvent e = while (names.hasMoreElements()) { return id; new HttpSessionBindingEvent(this,name); String name = (String) names.nextElement(); } else { /** stream.writeObject(name); String msg = sm.getString("applicationSession.session.ise"); ((HttpSessionBindingListener)o).valueUnbound(e); * Return an <code>Enumeration</code> of <code>String</code> objects stream.writeObject(attributes.get(name)); } * containing the names of the objects bound to this session. } throw new IllegalStateException(msg); * } values.remove(name); * @exception IllegalStateException if this method is called on an } } * invalidated session } */ public long getCreationTime() { public void setMaxInactiveInterval(int interval) { public Enumeration getAttributeNames() { crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | if (valid) { if (! valid) { long getCreationTime() | return creationTime; String msg = sm.getString("applicationSession.session.ise"); return (attributes.keys()); Object getAttribute(String) | } else { Enumeration getAttributeNames() | String msg = sm.getString("applicationSession.session.ise"); throw new IllegalStateException(msg); } String[] getValueNames() | } void invalidate() | throw new IllegalStateException(msg); boolean isNew() | } /** void removeAttribute(String) | } * Return the object bound with the specified name in this session, or void setAttribute(String, Object)); * <code>null</code> if no object is bound with that name. /** * static advice(StandardSession s): invalidate(s) { * * @param name Name of the value to be returned before { * @deprecated * if (!s.isValid()) * @exception IllegalStateException if this method is called on an throw new IllegalStateException * invalidated session (s.sm.getString("standardSession." * + thisJoinPoint.methodName * @deprecated As of Version 2.2, this method is replaced by + ".ise")); * <code>getAttribute()</code> } */ } /** public Object getValue(String name) { * Return the session identifier for this session. */ return (getAttribute(name)); public String getId() { } } /** // -------------------------------------------------------------- Private Class * Return the set of names of objects bound to this session. If there * are no such objects, a zero-length array is returned. * /** * @exception IllegalStateException if this method is called on an * This class is a dummy implementation of the <code>HttpSessionContext</code> * invalidated session * interface, to conform to the requirement that such an object be returned * * when <code>HttpSession.getSessionContext()</code> is called. * @deprecated As of Version 2.2, this method is replaced by * * <code>getAttributeNames()</code> * @author Craig R. McClanahan */ * public String[] getValueNames() { * @deprecated As of Java Servlet API 2.1 with no replacement. The * interface will be removed in a future version of this API. Vector results = new Vector(); */ Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { final class StandardSessionContext implements HttpSessionContext { String attr = (String) attrs.nextElement(); results.addElement(attr); } private Vector dummy = new Vector(); return (this.id); String names[] = new String[results.size()]; for (int i = 0; i < names.length; i++) /** names[i] = (String) results.elementAt(i); * Return the session identifiers of all sessions defined return (names); * within this context. * } * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> * and will be removed in a future version of the API. /** */ * Invalidates this session and unbinds any objects bound to it. public Enumeration getIds() { * * @exception IllegalStateException if this method is called on return (dummy.elements()); * an invalidated session */ public void invalidate() { // Cause this session to expire expire(); } } /** * Return <code>true</code> if the client does not yet know about the * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client * has disabled the use of cookies, then a session would be new on each * request. * * @exception IllegalStateException if this method is called on an * invalidated session */ public boolean isNew() { return (this.isNew); }package org.apache.tomcat.session; void validate() { // if we have an inactive interval, check to see ifimport org.apache.tomcat.core.*; // weve exceeded itimport org.apache.tomcat.util.StringManager;import java.io.*; if (inactiveInterval != -1) {import java.net.*; int thisInterval =import java.util.*; (int)(System.currentTimeMillis() - lastAccessed) / 1000;import javax.servlet.*;import javax.servlet.http.*; if (thisInterval > inactiveInterval) { invalidate();/** * Core implementation of a server session ServerSessionManager ssm = * ServerSessionManager.getManager(); * @author James Duncan Davidson [duncan@eng.sun.com] * @author James Todd [gonzo@eng.sun.com] ssm.removeSession(this); */ } }public class ServerSession { } private StringManager sm = synchronized void invalidate() { StringManager.getManager("org.apache.tomcat.session"); Enumeration enum = appSessions.keys(); /** private Hashtable values = new Hashtable(); * Set the session identifier for this session. private Hashtable appSessions = new Hashtable(); while (enum.hasMoreElements()) { * private String id; Object key = enum.nextElement(); * @param id The new session identifier private long creationTime = System.currentTimeMillis();; ApplicationSession appSession = */ private long thisAccessTime = creationTime; (ApplicationSession)appSessions.get(key); public void setId(String id) { private long lastAccessed = creationTime; private int inactiveInterval = -1; appSession.invalidate(); } ServerSession(String id) { } this.id = id; } public void putValue(String name, Object value) { if (name == null) { public String getId() { String msg = sm.getString("serverSession.value.iae"); return id; } throw new IllegalArgumentException(msg); } public long getCreationTime() { return creationTime; removeValue(name); // remove any existing binding } values.put(name, value); } public long getLastAccessedTime() { return lastAccessed; public Object getValue(String name) { } if (name == null) { String msg = sm.getString("serverSession.value.iae"); public ApplicationSession getApplicationSession(Context context, boolean create) { throw new IllegalArgumentException(msg); ApplicationSession appSession = } if ((this.id != null) && (manager != null) && (ApplicationSession)appSessions.get(context); (manager instanceof ManagerBase)) return values.get(name); ((ManagerBase) manager).remove(this); if (appSession == null && create) { } // XXX public Enumeration getValueNames() { // sync to ensure valid? return values.keys(); } appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); public void removeValue(String name) { } values.remove(name); } // XXX // make sure that we havent gone over the end of our public void setMaxInactiveInterval(int interval) { // inactive interval -- if so, invalidate and create inactiveInterval = interval; // a new appSession } return appSession; public int getMaxInactiveInterval() { } return inactiveInterval; } void removeApplicationSession(Context context) { appSessions.remove(context); // XXX } // syncd for safty -- no other thread should be getting something // from this while we are reaping. This isnt the most optimal /** // solution for this, but well determine something else later. this.id = id; * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. synchronized void reap() { */ Enumeration enum = appSessions.keys(); void accessed() { while (enum.hasMoreElements()) { // set last accessed to thisAccessTime as it will be left over if ((manager != null) && (manager instanceof ManagerBase)) ((ManagerBase) manager).add(this); } /** * Return descriptive information about this Session implementation and * the corresponding version number, in the format * <code>&lt;description&gt;/&lt;version&gt;</code>. */ public String getInfo() { return (this.info); } /** * Return the last time the client sent a request associated with this * session, as the number of milliseconds since midnight, January 1, 1970 * GMT. Actions that your application takes, such as getting or setting * a value associated with the session, do not affect the access time. */ public long getLastAccessedTime() { return (this.lastAccessedTime); } /** * Return the Manager within which this Session is valid. */ public Manager getManager() { return (this.manager); } /** * Set the Manager within which this Session is valid. * * @param manager The new Manager */ public void setManager(Manager manager) { 10
    • Crosscutting Concerns /* public void invalidate() { ; * Remove the object bound with the specified name from this session. If * ==================================================================== serverSession.removeApplicationSession(context); * the session does not have an object bound with this name, this method * * does nothing. * The Apache Software License, Version 1.1 // remove everything in the session /** * <p> * * Standard implementation of the <b>Session</b> interface. This object is * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. */ * notice, this list of conditions and the following disclaimer. * public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ Object object = attributes.get(name); * the documentation and/or other materials provided with the if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession return; * } implements HttpSession, Session { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { /** if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors * Update the accessed time information for this session. This method ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { * should be called by the context when a request comes in for a particular (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; * session, even if the application does not reference it. } itself, } /** */ } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. public void access() { * * } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated this.lastAccessedTime = this.thisAccessedTime;• Crosscutting concerns * Foundation" must not be used to endorse or promote products /** */ this.thisAccessedTime = System.currentTimeMillis(); * Bind an object to this session, using the specified name. If an object derived * @deprecated public StandardSession(Manager manager) { this.isNew=false; * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ } * replaced. * permission, please contact apache@apache.org. super(); * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); /** * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } * Perform the internal processing required to invalidate this session, * <code>valueBound()</code> on the object. * permission of the Apache Group. * without triggering an exception if the session has already expired. * * public void setAttribute(String name, Object value) { */ * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS AND ANY EXPRESSED OR IMPLIED if (! valid) { /** public void expire() { * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ // Remove this session from our managers active sessions * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; if ((manager != null) && (manager instanceof ManagerBase)) * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } ((ManagerBase) manager).remove(this); * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** // Unbind any objects associated with this session */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. Vector results = new Vector(); public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ Enumeration attrs = getAttributeNames(); * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; while (attrs.hasMoreElements()) { if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } String attr = (String) attrs.nextElement(); !(value instanceof Serializable)) * SUCH DAMAGE. results.addElement(attr); throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** } (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before Enumeration names = results.elements(); * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time while (names.hasMoreElements()) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. String name = (String) names.nextElement(); removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ removeAttribute(name); attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } // Mark this session as invalid (new HttpSessionBindingEvent((HttpSession) this, name)); * /** setValid(false); } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } } private boolean isNew = true; /** package org.apache.tomcat.session; * @deprecated /** // -------------------------------------------- HttpSession Private Methods */ /** import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. } import org.apache.tomcat.util.StringManager; return getAttribute(name); */ /** import java.io.*; } private boolean isValid = false; * Read a serialized version of this session object from the specified import java.net.*; /** * object input stream. import java.util.*; public Object getAttribute(String name) { * Set the <code>isNew</code> flag for this session. * <p> import javax.servlet.*; if (! valid) { /** * * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager import javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * @param isNew The new value for the <code>isNew</code> flag * is not restored by this method, and must be set explicitly. */ */ * /** throw new IllegalStateException(msg); private StringManager sm = void setNew(boolean isNew) { * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * this.isNew = isNew; * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * @exception IOException if an input/output error occurs (CCCs) affect many * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** } */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; /** public class ApplicationSession implements HttpSession { * Set the <code>isValid</code> flag for this session. // Deserialize the scalar instance variables (except Manager) return values.get(name); * creationTime = ((Long) stream.readObject()).longValue(); private StringManager sm = } /** * @param isValid The new value for the <code>isValid</code> flag id = (String) stream.readObject(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. */ lastAccessedTime = ((Long) stream.readObject()).longValue(); private Hashtable values = new Hashtable(); /** */ void setValid(boolean isValid) { maxInactiveInterval = ((Integer) stream.readObject()).intValue(); private String id; * @deprecated private long thisAccessedTime = creationTime; isNew = ((Boolean) stream.readObject()).booleanValue(); private ServerSession serverSession; */ this.isValid = isValid; isValid = ((Boolean) stream.readObject()).booleanValue(); private Context context; public String[] getValueNames() { } private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); // Deserialize the attribute count and attribute values private long thisAccessTime = creationTime; Vector names = new Vector(); int n = ((Integer) stream.readObject()).intValue(); private long lastAccessed = creationTime; // ----------------------------------------------------- Session Properties // ------------------------------------------------- HttpSession Properties for (int i = 0; i < n; i++) { private int inactiveInterval = -1; while (e.hasMoreElements()) { String name = (String) stream.readObject(); private boolean valid = true; names.addElement(e.nextElement()); Object value = (Object) stream.readObject(); } /** /** attributes.put(name, value); ApplicationSession(String id, ServerSession serverSession, * Set the creation time for this session. This method is called by the * Return the time when this session was created, in milliseconds since } Context context) { String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * midnight, January 1, 1970 GMT. this.serverSession = serverSession; * * } this.context = context; names.copyInto(valueNames); * @param time The new creation time * @exception IllegalStateException if this method is called on an this.id = id; */ * invalidated session return valueNames; public void setCreationTime(long time) { */ /** this.inactiveInterval = context.getSessionTimeOut(); public long getCreationTime() { * Write a serialized version of this session object to the specified } this.creationTime = time; * object output stream. if (this.inactiveInterval != -1) { this.lastAccessedTime = time; return (this.creationTime); * <p> this.inactiveInterval *= 60; public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored } if (! valid) { } * in the serialized representation of this Session. After calling } String msg = sm.getString("applicationSession.session.ise"); * <code>readObject()</code>, you must set the associated Manager * explicitly. ServerSession getServerSession() { throw new IllegalStateException(msg); /** * <p> return serverSession; } * Return the session context with which this session is associated. * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable } * * will be silently ignored. If you do not want any such attributes, Hashtable valuesClone = (Hashtable)values.clone(); * @deprecated As of Version 2.1, this method is deprecated and has no * be sure the <code>distributable</code> property of our associated heterogeneous software /** * replacement. It will be removed in a future version of the * Manager is set to <code>true</code>. * Called by context when request comes in so that accesses and return (Enumeration)valuesClone.keys(); * Java Servlet API. * * inactivities can be dealt with accordingly. } */ * @param stream The output stream to write to */ public HttpSessionContext getSessionContext() { * * @exception IOException if an input/output error occurs void accessed() { /** if (sessionContext == null) */ // set last accessed to thisAccessTime as it will be left over * @deprecated sessionContext = new StandardSessionContext(); private void writeObject(ObjectOutputStream stream) throws IOException { // from the previous access */ return (sessionContext); lastAccessed = thisAccessTime; // Write the scalar instance variables (except Manager) thisAccessTime = System.currentTimeMillis(); public void removeValue(String name) { } stream.writeObject(new Long(creationTime)); removeAttribute(name); stream.writeObject(id); validate(); } stream.writeObject(new Long(lastAccessedTime)); } // ----------------------------------------------HttpSession Public Methods stream.writeObject(new Integer(maxInactiveInterval)); public void removeAttribute(String name) { stream.writeObject(new Boolean(isNew)); void validate() { if (! valid) { } stream.writeObject(new Boolean(isValid)); // if we have an inactive interval, check to see if weve exceeded it String msg = sm.getString("applicationSession.session.ise"); /** if (inactiveInterval != -1) { * Return the object bound with the specified name in this session, or // Accumulate the names of serializable attributes int thisInterval = throw new IllegalStateException(msg); * <code>null</code> if no object is bound with that name. Vector results = new Vector(); (int)(System.currentTimeMillis() - lastAccessed) / 1000; } * Enumeration attrs = getAttributeNames(); * @param name Name of the attribute to be returned while (attrs.hasMoreElements()) { if (thisInterval > inactiveInterval) { if (name == null) { * String attr = (String) attrs.nextElement(); invalidate(); String msg = sm.getString("applicationSession.value.iae"); * @exception IllegalStateException if this method is called on an Object value = attributes.get(attr); } * invalidated session if (value instanceof Serializable) } throw new IllegalArgumentException(msg); */ results.addElement(attr); } } public Object getAttribute(String name) { } // HTTP SESSION IMPLEMENTATION METHODS Object o = values.get(name); return (attributes.get(name)); // Serialize the attribute count and the attribute values stream.writeObject(new Integer(results.size())); public String getId() { if (o instanceof HttpSessionBindingListener) { } Enumeration names = results.elements(); if (valid) { HttpSessionBindingEvent e = while (names.hasMoreElements()) { return id; new HttpSessionBindingEvent(this,name); String name = (String) names.nextElement(); } else { /** stream.writeObject(name); String msg = sm.getString("applicationSession.session.ise"); ((HttpSessionBindingListener)o).valueUnbound(e); * Return an <code>Enumeration</code> of <code>String</code> objects stream.writeObject(attributes.get(name)); } * containing the names of the objects bound to this session. } throw new IllegalStateException(msg); * modules. } values.remove(name); * @exception IllegalStateException if this method is called on an } } * invalidated session } */ public long getCreationTime() { public void setMaxInactiveInterval(int interval) { public Enumeration getAttributeNames() { crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | if (valid) { if (! valid) { long getCreationTime() | return creationTime; String msg = sm.getString("applicationSession.session.ise"); return (attributes.keys()); Object getAttribute(String) | } else { Enumeration getAttributeNames() | String msg = sm.getString("applicationSession.session.ise"); throw new IllegalStateException(msg); } String[] getValueNames() | } void invalidate() | throw new IllegalStateException(msg); boolean isNew() | } /** void removeAttribute(String) | } * Return the object bound with the specified name in this session, or void setAttribute(String, Object)); * <code>null</code> if no object is bound with that name. /** * static advice(StandardSession s): invalidate(s) { * * @param name Name of the value to be returned before { * @deprecated * if (!s.isValid()) * @exception IllegalStateException if this method is called on an throw new IllegalStateException * invalidated session (s.sm.getString("standardSession." * + thisJoinPoint.methodName * @deprecated As of Version 2.2, this method is replaced by + ".ise")); * <code>getAttribute()</code> } */ } /** public Object getValue(String name) { * Return the session identifier for this session. */ return (getAttribute(name)); public String getId() { } } /** // -------------------------------------------------------------- Private Class * Return the set of names of objects bound to this session. If there * are no such objects, a zero-length array is returned. * /** * @exception IllegalStateException if this method is called on an * This class is a dummy implementation of the <code>HttpSessionContext</code> * invalidated session * interface, to conform to the requirement that such an object be returned * * when <code>HttpSession.getSessionContext()</code> is called. * @deprecated As of Version 2.2, this method is replaced by * * <code>getAttributeNames()</code> * @author Craig R. McClanahan */ * public String[] getValueNames() { * @deprecated As of Java Servlet API 2.1 with no replacement. The * interface will be removed in a future version of this API. Vector results = new Vector(); */ Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { final class StandardSessionContext implements HttpSessionContext { String attr = (String) attrs.nextElement(); results.addElement(attr); } private Vector dummy = new Vector(); return (this.id); String names[] = new String[results.size()]; for (int i = 0; i < names.length; i++) /** names[i] = (String) results.elementAt(i); * Return the session identifiers of all sessions defined return (names); * within this context. * } * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> * and will be removed in a future version of the API. /** */ * Invalidates this session and unbinds any objects bound to it. public Enumeration getIds() { * * @exception IllegalStateException if this method is called on return (dummy.elements()); * an invalidated session */ public void invalidate() { // Cause this session to expire expire(); } } /** * Return <code>true</code> if the client does not yet know about the * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client * has disabled the use of cookies, then a session would be new on each * request. * * @exception IllegalStateException if this method is called on an * invalidated session */ public boolean isNew() { return (this.isNew); } package org.apache.tomcat.session; void validate() { // if we have an inactive interval, check to see if import org.apache.tomcat.core.*; // weve exceeded it import org.apache.tomcat.util.StringManager; import java.io.*; if (inactiveInterval != -1) { import java.net.*; int thisInterval = import java.util.*; (int)(System.currentTimeMillis() - lastAccessed) / 1000; import javax.servlet.*; import javax.servlet.http.*; if (thisInterval > inactiveInterval) { invalidate(); /** * Core implementation of a server session ServerSessionManager ssm = * ServerSessionManager.getManager(); * @author James Duncan Davidson [duncan@eng.sun.com] * @author James Todd [gonzo@eng.sun.com] ssm.removeSession(this); */ } } public class ServerSession { } private StringManager sm = synchronized void invalidate() { StringManager.getManager("org.apache.tomcat.session"); Enumeration enum = appSessions.keys(); /** private Hashtable values = new Hashtable(); * Set the session identifier for this session. private Hashtable appSessions = new Hashtable(); while (enum.hasMoreElements()) { * private String id; Object key = enum.nextElement(); * @param id The new session identifier private long creationTime = System.currentTimeMillis();; ApplicationSession appSession = */ private long thisAccessTime = creationTime; (ApplicationSession)appSessions.get(key); public void setId(String id) { private long lastAccessed = creationTime; private int inactiveInterval = -1; appSession.invalidate(); } ServerSession(String id) { } this.id = id; } public void putValue(String name, Object value) { if (name == null) { public String getId() { String msg = sm.getString("serverSession.value.iae"); return id; } throw new IllegalArgumentException(msg); } public long getCreationTime() { return creationTime; removeValue(name); // remove any existing binding } values.put(name, value); } public long getLastAccessedTime() { return lastAccessed; public Object getValue(String name) { } if (name == null) { String msg = sm.getString("serverSession.value.iae"); public ApplicationSession getApplicationSession(Context context, boolean create) { throw new IllegalArgumentException(msg); ApplicationSession appSession = } if ((this.id != null) && (manager != null) && (ApplicationSession)appSessions.get(context); (manager instanceof ManagerBase)) return values.get(name); ((ManagerBase) manager).remove(this); if (appSession == null && create) { } // XXX public Enumeration getValueNames() { // sync to ensure valid? return values.keys(); } appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); public void removeValue(String name) { } values.remove(name); } // XXX // make sure that we havent gone over the end of our public void setMaxInactiveInterval(int interval) { // inactive interval -- if so, invalidate and create inactiveInterval = interval; // a new appSession } return appSession; public int getMaxInactiveInterval() { } return inactiveInterval; } void removeApplicationSession(Context context) { appSessions.remove(context); // XXX } // syncd for safty -- no other thread should be getting something // from this while we are reaping. This isnt the most optimal /** // solution for this, but well determine something else later. this.id = id; * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. synchronized void reap() { */ Enumeration enum = appSessions.keys(); void accessed() { while (enum.hasMoreElements()) { // set last accessed to thisAccessTime as it will be left over if ((manager != null) && (manager instanceof ManagerBase)) ((ManagerBase) manager).add(this); } /** * Return descriptive information about this Session implementation and * the corresponding version number, in the format * <code>&lt;description&gt;/&lt;version&gt;</code>. */ public String getInfo() { return (this.info); } /** * Return the last time the client sent a request associated with this * session, as the number of milliseconds since midnight, January 1, 1970 * GMT. Actions that your application takes, such as getting or setting * a value associated with the session, do not affect the access time. */ public long getLastAccessedTime() { return (this.lastAccessedTime); } /** * Return the Manager within which this Session is valid. */ public Manager getManager() { return (this.manager); } /** * Set the Manager within which this Session is valid. * * @param manager The new Manager */ public void setManager(Manager manager) { 10
    • Crosscutting Concerns /* public void invalidate() { ; * Remove the object bound with the specified name from this session. If * ==================================================================== serverSession.removeApplicationSession(context); * the session does not have an object bound with this name, this method * * does nothing. * The Apache Software License, Version 1.1 // remove everything in the session /** * <p> * * Standard implementation of the <b>Session</b> interface. This object is * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. */ * notice, this list of conditions and the following disclaimer. * public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ Object object = attributes.get(name); * the documentation and/or other materials provided with the if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession return; * } implements HttpSession, Session { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { /** if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors * Update the accessed time information for this session. This method ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { * should be called by the context when a request comes in for a particular (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; * session, even if the application does not reference it. } itself, } /** */ } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. public void access() { * * } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated this.lastAccessedTime = this.thisAccessedTime;• Crosscutting concerns * Foundation" must not be used to endorse or promote products /** */ this.thisAccessedTime = System.currentTimeMillis(); * Bind an object to this session, using the specified name. If an object derived * @deprecated public StandardSession(Manager manager) { this.isNew=false; * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ } * replaced. * permission, please contact apache@apache.org. super(); * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); /** * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } * Perform the internal processing required to invalidate this session, * <code>valueBound()</code> on the object. * permission of the Apache Group. * without triggering an exception if the session has already expired. * * public void setAttribute(String name, Object value) { */ * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS AND ANY EXPRESSED OR IMPLIED if (! valid) { /** public void expire() { * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ // Remove this session from our managers active sessions * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; if ((manager != null) && (manager instanceof ManagerBase)) * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } ((ManagerBase) manager).remove(this); * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** // Unbind any objects associated with this session */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. Vector results = new Vector(); public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ Enumeration attrs = getAttributeNames(); * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; while (attrs.hasMoreElements()) { if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } String attr = (String) attrs.nextElement(); !(value instanceof Serializable)) * SUCH DAMAGE. results.addElement(attr); throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** } (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before Enumeration names = results.elements(); * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time while (names.hasMoreElements()) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. String name = (String) names.nextElement(); removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ removeAttribute(name); attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } // Mark this session as invalid (new HttpSessionBindingEvent((HttpSession) this, name)); * /** setValid(false); } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } } private boolean isNew = true; /** package org.apache.tomcat.session; * @deprecated /** // -------------------------------------------- HttpSession Private Methods */ /** import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. } import org.apache.tomcat.util.StringManager; return getAttribute(name); */ /** import java.io.*; } private boolean isValid = false; * Read a serialized version of this session object from the specified import java.net.*; /** * object input stream. import java.util.*; public Object getAttribute(String name) { * Set the <code>isNew</code> flag for this session. * <p> import javax.servlet.*; if (! valid) { /** * * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager import javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * @param isNew The new value for the <code>isNew</code> flag * is not restored by this method, and must be set explicitly. */ */ * /** throw new IllegalStateException(msg); private StringManager sm = void setNew(boolean isNew) { * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * this.isNew = isNew; * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * @exception IOException if an input/output error occurs (CCCs) affect many * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** } */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; /** public class ApplicationSession implements HttpSession { * Set the <code>isValid</code> flag for this session. // Deserialize the scalar instance variables (except Manager) return values.get(name); * creationTime = ((Long) stream.readObject()).longValue(); private StringManager sm = } /** * @param isValid The new value for the <code>isValid</code> flag id = (String) stream.readObject(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. */ lastAccessedTime = ((Long) stream.readObject()).longValue(); private Hashtable values = new Hashtable(); /** */ void setValid(boolean isValid) { maxInactiveInterval = ((Integer) stream.readObject()).intValue(); private String id; * @deprecated private long thisAccessedTime = creationTime; isNew = ((Boolean) stream.readObject()).booleanValue(); private ServerSession serverSession; */ this.isValid = isValid; isValid = ((Boolean) stream.readObject()).booleanValue(); private Context context; public String[] getValueNames() { } private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); // Deserialize the attribute count and attribute values private long thisAccessTime = creationTime; Vector names = new Vector(); int n = ((Integer) stream.readObject()).intValue(); private long lastAccessed = creationTime; // ----------------------------------------------------- Session Properties // ------------------------------------------------- HttpSession Properties for (int i = 0; i < n; i++) { private int inactiveInterval = -1; while (e.hasMoreElements()) { String name = (String) stream.readObject(); private boolean valid = true; names.addElement(e.nextElement()); Object value = (Object) stream.readObject(); } /** /** attributes.put(name, value); ApplicationSession(String id, ServerSession serverSession, * Set the creation time for this session. This method is called by the * Return the time when this session was created, in milliseconds since } Context context) { String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * midnight, January 1, 1970 GMT. this.serverSession = serverSession; * * } this.context = context; names.copyInto(valueNames); * @param time The new creation time * @exception IllegalStateException if this method is called on an this.id = id; */ * invalidated session return valueNames; public void setCreationTime(long time) { */ /** this.inactiveInterval = context.getSessionTimeOut(); public long getCreationTime() { * Write a serialized version of this session object to the specified } this.creationTime = time; * object output stream. if (this.inactiveInterval != -1) { this.lastAccessedTime = time; return (this.creationTime); * <p> this.inactiveInterval *= 60; public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored } if (! valid) { } * in the serialized representation of this Session. After calling } String msg = sm.getString("applicationSession.session.ise"); * <code>readObject()</code>, you must set the associated Manager * explicitly. ServerSession getServerSession() { throw new IllegalStateException(msg); /** * <p> return serverSession; } * Return the session context with which this session is associated. * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable } * * will be silently ignored. If you do not want any such attributes, Hashtable valuesClone = (Hashtable)values.clone(); * @deprecated As of Version 2.1, this method is deprecated and has no * be sure the <code>distributable</code> property of our associated heterogeneous software /** * replacement. It will be removed in a future version of the * Manager is set to <code>true</code>. * Called by context when request comes in so that accesses and return (Enumeration)valuesClone.keys(); * Java Servlet API. * * inactivities can be dealt with accordingly. } */ * @param stream The output stream to write to */ public HttpSessionContext getSessionContext() { * * @exception IOException if an input/output error occurs void accessed() { /** if (sessionContext == null) */ // set last accessed to thisAccessTime as it will be left over * @deprecated sessionContext = new StandardSessionContext(); private void writeObject(ObjectOutputStream stream) throws IOException { // from the previous access */ return (sessionContext); lastAccessed = thisAccessTime; // Write the scalar instance variables (except Manager) thisAccessTime = System.currentTimeMillis(); public void removeValue(String name) { } stream.writeObject(new Long(creationTime)); removeAttribute(name); stream.writeObject(id); validate(); } stream.writeObject(new Long(lastAccessedTime)); } // ----------------------------------------------HttpSession Public Methods stream.writeObject(new Integer(maxInactiveInterval)); public void removeAttribute(String name) { stream.writeObject(new Boolean(isNew)); void validate() { if (! valid) { } stream.writeObject(new Boolean(isValid)); // if we have an inactive interval, check to see if weve exceeded it String msg = sm.getString("applicationSession.session.ise"); /** if (inactiveInterval != -1) { * Return the object bound with the specified name in this session, or // Accumulate the names of serializable attributes int thisInterval = throw new IllegalStateException(msg); * <code>null</code> if no object is bound with that name. Vector results = new Vector(); (int)(System.currentTimeMillis() - lastAccessed) / 1000; } * Enumeration attrs = getAttributeNames(); * @param name Name of the attribute to be returned while (attrs.hasMoreElements()) { if (thisInterval > inactiveInterval) { if (name == null) { * String attr = (String) attrs.nextElement(); invalidate(); String msg = sm.getString("applicationSession.value.iae"); * @exception IllegalStateException if this method is called on an Object value = attributes.get(attr); } * invalidated session if (value instanceof Serializable) } throw new IllegalArgumentException(msg); */ results.addElement(attr); } } public Object getAttribute(String name) { } // HTTP SESSION IMPLEMENTATION METHODS Object o = values.get(name); return (attributes.get(name)); // Serialize the attribute count and the attribute values stream.writeObject(new Integer(results.size())); public String getId() { if (o instanceof HttpSessionBindingListener) { } Enumeration names = results.elements(); if (valid) { HttpSessionBindingEvent e = while (names.hasMoreElements()) { return id; new HttpSessionBindingEvent(this,name); String name = (String) names.nextElement(); } else { /** stream.writeObject(name); String msg = sm.getString("applicationSession.session.ise"); ((HttpSessionBindingListener)o).valueUnbound(e); * Return an <code>Enumeration</code> of <code>String</code> objects stream.writeObject(attributes.get(name)); } * containing the names of the objects bound to this session. } throw new IllegalStateException(msg); * modules. } values.remove(name); * @exception IllegalStateException if this method is called on an } } * invalidated session } */ public long getCreationTime() { public void setMaxInactiveInterval(int interval) { public Enumeration getAttributeNames() { crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | if (valid) { if (! valid) { long getCreationTime() | return creationTime; String msg = sm.getString("applicationSession.session.ise"); return (attributes.keys()); Object getAttribute(String) | } else { Enumeration getAttributeNames() | String msg = sm.getString("applicationSession.session.ise"); throw new IllegalStateException(msg); } String[] getValueNames() | } void invalidate() | throw new IllegalStateException(msg); boolean isNew() | } /** void removeAttribute(String) | } * Return the object bound with the specified name in this session, or void setAttribute(String, Object)); * <code>null</code> if no object is bound with that name. /** * static advice(StandardSession s): invalidate(s) { * * @param name Name of the value to be returned before { * @deprecated * if (!s.isValid()) * @exception IllegalStateException if this method is called on an throw new IllegalStateException * invalidated session (s.sm.getString("standardSession." * + thisJoinPoint.methodName * @deprecated As of Version 2.2, this method is replaced by + ".ise")); * <code>getAttribute()</code> } */ } /** public Object getValue(String name) { * Return the session identifier for this session. */ return (getAttribute(name)); public String getId() { } } /** // -------------------------------------------------------------- Private Class * Return the set of names of objects bound to this session. If there * are no such objects, a zero-length array is returned. * /** * @exception IllegalStateException if this method is called on an * This class is a dummy implementation of the <code>HttpSessionContext</code> * invalidated session * interface, to conform to the requirement that such an object be returned * * when <code>HttpSession.getSessionContext()</code> is called. * @deprecated As of Version 2.2, this method is replaced by * * <code>getAttributeNames()</code> * @author Craig R. McClanahan */ * public String[] getValueNames() { * @deprecated As of Java Servlet API 2.1 with no replacement. The * interface will be removed in a future version of this API. Vector results = new Vector(); */ Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { final class StandardSessionContext implements HttpSessionContext { String attr = (String) attrs.nextElement(); results.addElement(attr); } private Vector dummy = new Vector(); return (this.id); String names[] = new String[results.size()]; for (int i = 0; i < names.length; i++) /** names[i] = (String) results.elementAt(i); * Return the session identifiers of all sessions defined return (names); * within this context. * } * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> * and will be removed in a future version of the API. /** */ * Invalidates this session and unbinds any objects bound to it. public Enumeration getIds() { * * @exception IllegalStateException if this method is called on return (dummy.elements()); * an invalidated session• Code is: */ public void invalidate() { // Cause this session to expire expire(); } } /** * Return <code>true</code> if the client does not yet know about the * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client * has disabled the use of cookies, then a session would be new on each * request. * * @exception IllegalStateException if this method is called on an * invalidated session */ public boolean isNew() { return (this.isNew); } package org.apache.tomcat.session; void validate() { // if we have an inactive interval, check to see if import org.apache.tomcat.core.*; // weve exceeded it import org.apache.tomcat.util.StringManager; import java.io.*; if (inactiveInterval != -1) { import java.net.*; int thisInterval = import java.util.*; (int)(System.currentTimeMillis() - lastAccessed) / 1000; import javax.servlet.*; import javax.servlet.http.*; if (thisInterval > inactiveInterval) { invalidate(); /** * Core implementation of a server session ServerSessionManager ssm = * ServerSessionManager.getManager(); * @author James Duncan Davidson [duncan@eng.sun.com] * @author James Todd [gonzo@eng.sun.com] ssm.removeSession(this); */ } } public class ServerSession { } private StringManager sm = synchronized void invalidate() { StringManager.getManager("org.apache.tomcat.session"); Enumeration enum = appSessions.keys(); /** private Hashtable values = new Hashtable(); * Set the session identifier for this session. private Hashtable appSessions = new Hashtable(); while (enum.hasMoreElements()) { * private String id; Object key = enum.nextElement(); * @param id The new session identifier private long creationTime = System.currentTimeMillis();; ApplicationSession appSession = */ private long thisAccessTime = creationTime; (ApplicationSession)appSessions.get(key); public void setId(String id) { private long lastAccessed = creationTime; private int inactiveInterval = -1; appSession.invalidate(); } ServerSession(String id) { } this.id = id; } public void putValue(String name, Object value) { if (name == null) { public String getId() { String msg = sm.getString("serverSession.value.iae"); return id; } throw new IllegalArgumentException(msg); } public long getCreationTime() { return creationTime; removeValue(name); // remove any existing binding } values.put(name, value); } public long getLastAccessedTime() { return lastAccessed; public Object getValue(String name) { } if (name == null) { String msg = sm.getString("serverSession.value.iae"); public ApplicationSession getApplicationSession(Context context, boolean create) { throw new IllegalArgumentException(msg); ApplicationSession appSession = } if ((this.id != null) && (manager != null) && (ApplicationSession)appSessions.get(context); (manager instanceof ManagerBase)) return values.get(name); ((ManagerBase) manager).remove(this); if (appSession == null && create) { } // XXX public Enumeration getValueNames() { // sync to ensure valid? return values.keys(); } appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); public void removeValue(String name) { } values.remove(name); } // XXX // make sure that we havent gone over the end of our public void setMaxInactiveInterval(int interval) { // inactive interval -- if so, invalidate and create inactiveInterval = interval; // a new appSession } return appSession; public int getMaxInactiveInterval() { } return inactiveInterval; } void removeApplicationSession(Context context) { appSessions.remove(context); // XXX } // syncd for safty -- no other thread should be getting something // from this while we are reaping. This isnt the most optimal /** // solution for this, but well determine something else later. this.id = id; * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. synchronized void reap() { */ Enumeration enum = appSessions.keys(); void accessed() { while (enum.hasMoreElements()) { // set last accessed to thisAccessTime as it will be left over if ((manager != null) && (manager instanceof ManagerBase)) ((ManagerBase) manager).add(this); } /** * Return descriptive information about this Session implementation and * the corresponding version number, in the format * <code>&lt;description&gt;/&lt;version&gt;</code>. */ public String getInfo() { return (this.info); } /** * Return the last time the client sent a request associated with this * session, as the number of milliseconds since midnight, January 1, 1970 * GMT. Actions that your application takes, such as getting or setting * a value associated with the session, do not affect the access time. */ public long getLastAccessedTime() { return (this.lastAccessedTime); } /** * Return the Manager within which this Session is valid. */ public Manager getManager() { return (this.manager); } /** * Set the Manager within which this Session is valid. * * @param manager The new Manager */ public void setManager(Manager manager) { 10
    • Crosscutting Concerns /* public void invalidate() { ; * Remove the object bound with the specified name from this session. If * ==================================================================== serverSession.removeApplicationSession(context); * the session does not have an object bound with this name, this method * * does nothing. * The Apache Software License, Version 1.1 // remove everything in the session /** * <p> * * Standard implementation of the <b>Session</b> interface. This object is * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. */ * notice, this list of conditions and the following disclaimer. * public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ Object object = attributes.get(name); * the documentation and/or other materials provided with the if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession return; * } implements HttpSession, Session { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { /** if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors * Update the accessed time information for this session. This method ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { * should be called by the context when a request comes in for a particular (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; * session, even if the application does not reference it. } itself, } /** */ } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. public void access() { * * } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated this.lastAccessedTime = this.thisAccessedTime;• Crosscutting concerns * Foundation" must not be used to endorse or promote products /** */ this.thisAccessedTime = System.currentTimeMillis(); * Bind an object to this session, using the specified name. If an object derived * @deprecated public StandardSession(Manager manager) { this.isNew=false; * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ } * replaced. * permission, please contact apache@apache.org. super(); * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); /** * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } * Perform the internal processing required to invalidate this session, * <code>valueBound()</code> on the object. * permission of the Apache Group. * without triggering an exception if the session has already expired. * * public void setAttribute(String name, Object value) { */ * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS AND ANY EXPRESSED OR IMPLIED if (! valid) { /** public void expire() { * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ // Remove this session from our managers active sessions * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; if ((manager != null) && (manager instanceof ManagerBase)) * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } ((ManagerBase) manager).remove(this); * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** // Unbind any objects associated with this session */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. Vector results = new Vector(); public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ Enumeration attrs = getAttributeNames(); * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; while (attrs.hasMoreElements()) { if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } String attr = (String) attrs.nextElement(); !(value instanceof Serializable)) * SUCH DAMAGE. results.addElement(attr); throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** } (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before Enumeration names = results.elements(); * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time while (names.hasMoreElements()) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. String name = (String) names.nextElement(); removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ removeAttribute(name); attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } // Mark this session as invalid (new HttpSessionBindingEvent((HttpSession) this, name)); * /** setValid(false); } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } } private boolean isNew = true; /** package org.apache.tomcat.session; * @deprecated /** // -------------------------------------------- HttpSession Private Methods */ /** import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. } import org.apache.tomcat.util.StringManager; return getAttribute(name); */ /** import java.io.*; } private boolean isValid = false; * Read a serialized version of this session object from the specified import java.net.*; /** * object input stream. import java.util.*; public Object getAttribute(String name) { * Set the <code>isNew</code> flag for this session. * <p> import javax.servlet.*; if (! valid) { /** * * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager import javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * @param isNew The new value for the <code>isNew</code> flag * is not restored by this method, and must be set explicitly. */ */ * /** throw new IllegalStateException(msg); private StringManager sm = void setNew(boolean isNew) { * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * this.isNew = isNew; * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * @exception IOException if an input/output error occurs (CCCs) affect many * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** } */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; /** public class ApplicationSession implements HttpSession { * Set the <code>isValid</code> flag for this session. // Deserialize the scalar instance variables (except Manager) return values.get(name); * creationTime = ((Long) stream.readObject()).longValue(); private StringManager sm = } /** * @param isValid The new value for the <code>isValid</code> flag id = (String) stream.readObject(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. */ lastAccessedTime = ((Long) stream.readObject()).longValue(); private Hashtable values = new Hashtable(); /** */ void setValid(boolean isValid) { maxInactiveInterval = ((Integer) stream.readObject()).intValue(); private String id; * @deprecated private long thisAccessedTime = creationTime; isNew = ((Boolean) stream.readObject()).booleanValue(); private ServerSession serverSession; */ this.isValid = isValid; isValid = ((Boolean) stream.readObject()).booleanValue(); private Context context; public String[] getValueNames() { } private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); // Deserialize the attribute count and attribute values private long thisAccessTime = creationTime; Vector names = new Vector(); int n = ((Integer) stream.readObject()).intValue(); private long lastAccessed = creationTime; // ----------------------------------------------------- Session Properties // ------------------------------------------------- HttpSession Properties for (int i = 0; i < n; i++) { private int inactiveInterval = -1; while (e.hasMoreElements()) { String name = (String) stream.readObject(); private boolean valid = true; names.addElement(e.nextElement()); Object value = (Object) stream.readObject(); } /** /** attributes.put(name, value); ApplicationSession(String id, ServerSession serverSession, * Set the creation time for this session. This method is called by the * Return the time when this session was created, in milliseconds since } Context context) { String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * midnight, January 1, 1970 GMT. this.serverSession = serverSession; * * } this.context = context; names.copyInto(valueNames); * @param time The new creation time * @exception IllegalStateException if this method is called on an this.id = id; */ * invalidated session return valueNames; public void setCreationTime(long time) { */ /** this.inactiveInterval = context.getSessionTimeOut(); public long getCreationTime() { * Write a serialized version of this session object to the specified } this.creationTime = time; * object output stream. if (this.inactiveInterval != -1) { this.lastAccessedTime = time; return (this.creationTime); * <p> this.inactiveInterval *= 60; public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored } if (! valid) { } * in the serialized representation of this Session. After calling } String msg = sm.getString("applicationSession.session.ise"); * <code>readObject()</code>, you must set the associated Manager * explicitly. ServerSession getServerSession() { throw new IllegalStateException(msg); /** * <p> return serverSession; } * Return the session context with which this session is associated. * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable } * * will be silently ignored. If you do not want any such attributes, Hashtable valuesClone = (Hashtable)values.clone(); * @deprecated As of Version 2.1, this method is deprecated and has no * be sure the <code>distributable</code> property of our associated heterogeneous software /** * replacement. It will be removed in a future version of the * Manager is set to <code>true</code>. * Called by context when request comes in so that accesses and return (Enumeration)valuesClone.keys(); * Java Servlet API. * * inactivities can be dealt with accordingly. } */ * @param stream The output stream to write to */ public HttpSessionContext getSessionContext() { * * @exception IOException if an input/output error occurs void accessed() { /** if (sessionContext == null) */ // set last accessed to thisAccessTime as it will be left over * @deprecated sessionContext = new StandardSessionContext(); private void writeObject(ObjectOutputStream stream) throws IOException { // from the previous access */ return (sessionContext); lastAccessed = thisAccessTime; // Write the scalar instance variables (except Manager) thisAccessTime = System.currentTimeMillis(); public void removeValue(String name) { } stream.writeObject(new Long(creationTime)); removeAttribute(name); stream.writeObject(id); validate(); } stream.writeObject(new Long(lastAccessedTime)); } // ----------------------------------------------HttpSession Public Methods stream.writeObject(new Integer(maxInactiveInterval)); public void removeAttribute(String name) { stream.writeObject(new Boolean(isNew)); void validate() { if (! valid) { } stream.writeObject(new Boolean(isValid)); // if we have an inactive interval, check to see if weve exceeded it String msg = sm.getString("applicationSession.session.ise"); /** if (inactiveInterval != -1) { * Return the object bound with the specified name in this session, or // Accumulate the names of serializable attributes int thisInterval = throw new IllegalStateException(msg); * <code>null</code> if no object is bound with that name. Vector results = new Vector(); (int)(System.currentTimeMillis() - lastAccessed) / 1000; } * Enumeration attrs = getAttributeNames(); * @param name Name of the attribute to be returned while (attrs.hasMoreElements()) { if (thisInterval > inactiveInterval) { if (name == null) { * String attr = (String) attrs.nextElement(); invalidate(); String msg = sm.getString("applicationSession.value.iae"); * @exception IllegalStateException if this method is called on an Object value = attributes.get(attr); } * invalidated session if (value instanceof Serializable) } throw new IllegalArgumentException(msg); */ results.addElement(attr); } } public Object getAttribute(String name) { } // HTTP SESSION IMPLEMENTATION METHODS Object o = values.get(name); return (attributes.get(name)); // Serialize the attribute count and the attribute values stream.writeObject(new Integer(results.size())); public String getId() { if (o instanceof HttpSessionBindingListener) { } Enumeration names = results.elements(); if (valid) { HttpSessionBindingEvent e = while (names.hasMoreElements()) { return id; new HttpSessionBindingEvent(this,name); String name = (String) names.nextElement(); } else { /** stream.writeObject(name); String msg = sm.getString("applicationSession.session.ise"); ((HttpSessionBindingListener)o).valueUnbound(e); * Return an <code>Enumeration</code> of <code>String</code> objects stream.writeObject(attributes.get(name)); } * containing the names of the objects bound to this session. } throw new IllegalStateException(msg); * modules. } values.remove(name); * @exception IllegalStateException if this method is called on an } } * invalidated session } */ public long getCreationTime() { public void setMaxInactiveInterval(int interval) { public Enumeration getAttributeNames() { crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | if (valid) { if (! valid) { long getCreationTime() | return creationTime; String msg = sm.getString("applicationSession.session.ise"); return (attributes.keys()); Object getAttribute(String) | } else { Enumeration getAttributeNames() | String msg = sm.getString("applicationSession.session.ise"); throw new IllegalStateException(msg); } String[] getValueNames() | } void invalidate() | throw new IllegalStateException(msg); boolean isNew() | } /** void removeAttribute(String) | } * Return the object bound with the specified name in this session, or void setAttribute(String, Object)); * <code>null</code> if no object is bound with that name. /** * static advice(StandardSession s): invalidate(s) { * * @param name Name of the value to be returned before { * @deprecated * if (!s.isValid()) * @exception IllegalStateException if this method is called on an throw new IllegalStateException * invalidated session (s.sm.getString("standardSession." * + thisJoinPoint.methodName * @deprecated As of Version 2.2, this method is replaced by + ".ise")); * <code>getAttribute()</code> } */ } /** public Object getValue(String name) { * Return the session identifier for this session. */ return (getAttribute(name)); public String getId() { } } /** // -------------------------------------------------------------- Private Class * Return the set of names of objects bound to this session. If there * are no such objects, a zero-length array is returned. * /** * @exception IllegalStateException if this method is called on an * This class is a dummy implementation of the <code>HttpSessionContext</code> * invalidated session * interface, to conform to the requirement that such an object be returned * * when <code>HttpSession.getSessionContext()</code> is called. * @deprecated As of Version 2.2, this method is replaced by * * <code>getAttributeNames()</code> * @author Craig R. McClanahan */ * public String[] getValueNames() { * @deprecated As of Java Servlet API 2.1 with no replacement. The * interface will be removed in a future version of this API. Vector results = new Vector(); */ Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { final class StandardSessionContext implements HttpSessionContext { String attr = (String) attrs.nextElement(); results.addElement(attr); } private Vector dummy = new Vector(); return (this.id); String names[] = new String[results.size()]; for (int i = 0; i < names.length; i++) /** names[i] = (String) results.elementAt(i); * Return the session identifiers of all sessions defined return (names); * within this context. * } * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> * and will be removed in a future version of the API. /** */ * Invalidates this session and unbinds any objects bound to it. public Enumeration getIds() { * * @exception IllegalStateException if this method is called on return (dummy.elements()); * an invalidated session• Code is: */ public void invalidate() { // Cause this session to expire expire(); } } /** * Return <code>true</code> if the client does not yet know about the * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client * has disabled the use of cookies, then a session would be new on each * request. * * @exception IllegalStateException if this method is called on an * invalidated session */ public boolean isNew() { return (this.isNew); } package org.apache.tomcat.session; void validate() { // if we have an inactive interval, check to see if import org.apache.tomcat.core.*; // weve exceeded it import org.apache.tomcat.util.StringManager; import java.io.*; if (inactiveInterval != -1) { import java.net.*; int thisInterval = import java.util.*; (int)(System.currentTimeMillis() - lastAccessed) / 1000; import javax.servlet.*; import javax.servlet.http.*; if (thisInterval > inactiveInterval) { invalidate(); /** * Core implementation of a server session ServerSessionManager ssm = * ServerSessionManager.getManager(); * @author James Duncan Davidson [duncan@eng.sun.com] * @author James Todd [gonzo@eng.sun.com] ssm.removeSession(this); */ } } public class ServerSession { } private StringManager sm = synchronized void invalidate() { StringManager.getManager("org.apache.tomcat.session"); Enumeration enum = appSessions.keys(); /** private Hashtable values = new Hashtable(); * Set the session identifier for this session. private Hashtable appSessions = new Hashtable(); while (enum.hasMoreElements()) { * private String id; Object key = enum.nextElement(); * @param id The new session identifier private long creationTime = System.currentTimeMillis();; ApplicationSession appSession = */ private long thisAccessTime = creationTime; (ApplicationSession)appSessions.get(key); public void setId(String id) { private long lastAccessed = creationTime; private int inactiveInterval = -1; appSession.invalidate(); } ServerSession(String id) { } this.id = id; } public void putValue(String name, Object value) { if (name == null) { public String getId() { String msg = sm.getString("serverSession.value.iae"); return id; } throw new IllegalArgumentException(msg); } public long getCreationTime() { return creationTime; removeValue(name); // remove any existing binding } values.put(name, value); } • Scattered throughout public long getLastAccessedTime() { return lastAccessed; public Object getValue(String name) { } if (name == null) { String msg = sm.getString("serverSession.value.iae"); public ApplicationSession getApplicationSession(Context context, boolean create) { throw new IllegalArgumentException(msg); ApplicationSession appSession = } if ((this.id != null) && (manager != null) && (ApplicationSession)appSessions.get(context); (manager instanceof ManagerBase)) return values.get(name); ((ManagerBase) manager).remove(this); if (appSession == null && create) { } // XXX public Enumeration getValueNames() { // sync to ensure valid? return values.keys(); } appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); public void removeValue(String name) { } values.remove(name); } // XXX // make sure that we havent gone over the end of our public void setMaxInactiveInterval(int interval) { // inactive interval -- if so, invalidate and create inactiveInterval = interval; // a new appSession } return appSession; public int getMaxInactiveInterval() { } return inactiveInterval; } void removeApplicationSession(Context context) { appSessions.remove(context); // XXX } // syncd for safty -- no other thread should be getting something // from this while we are reaping. This isnt the most optimal /** // solution for this, but well determine something else later. this.id = id; * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. synchronized void reap() { */ Enumeration enum = appSessions.keys(); void accessed() { while (enum.hasMoreElements()) { // set last accessed to thisAccessTime as it will be left over many modules. if ((manager != null) && (manager instanceof ManagerBase)) ((ManagerBase) manager).add(this); } /** * Return descriptive information about this Session implementation and * the corresponding version number, in the format * <code>&lt;description&gt;/&lt;version&gt;</code>. */ public String getInfo() { return (this.info); } /** * Return the last time the client sent a request associated with this * session, as the number of milliseconds since midnight, January 1, 1970 * GMT. Actions that your application takes, such as getting or setting * a value associated with the session, do not affect the access time. */ public long getLastAccessedTime() { return (this.lastAccessedTime); } /** * Return the Manager within which this Session is valid. */ public Manager getManager() { return (this.manager); } /** * Set the Manager within which this Session is valid. * * @param manager The new Manager */ public void setManager(Manager manager) { 10
    • Crosscutting Concerns /* public void invalidate() { ; * Remove the object bound with the specified name from this session. If * ==================================================================== serverSession.removeApplicationSession(context); * the session does not have an object bound with this name, this method * * does nothing. * The Apache Software License, Version 1.1 // remove everything in the session /** * <p> * * Standard implementation of the <b>Session</b> interface. This object is * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. */ * notice, this list of conditions and the following disclaimer. * public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ Object object = attributes.get(name); * the documentation and/or other materials provided with the if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession return; * } implements HttpSession, Session { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { /** if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors * Update the accessed time information for this session. This method ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { * should be called by the context when a request comes in for a particular (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; * session, even if the application does not reference it. } itself, } /** */ } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. public void access() { * * } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated this.lastAccessedTime = this.thisAccessedTime;• Crosscutting concerns * Foundation" must not be used to endorse or promote products /** */ this.thisAccessedTime = System.currentTimeMillis(); * Bind an object to this session, using the specified name. If an object derived * @deprecated public StandardSession(Manager manager) { this.isNew=false; * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ } * replaced. * permission, please contact apache@apache.org. super(); * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); /** * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } * Perform the internal processing required to invalidate this session, * <code>valueBound()</code> on the object. * permission of the Apache Group. * without triggering an exception if the session has already expired. * * public void setAttribute(String name, Object value) { */ * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS AND ANY EXPRESSED OR IMPLIED if (! valid) { /** public void expire() { * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ // Remove this session from our managers active sessions * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; if ((manager != null) && (manager instanceof ManagerBase)) * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } ((ManagerBase) manager).remove(this); * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** // Unbind any objects associated with this session */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. Vector results = new Vector(); public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ Enumeration attrs = getAttributeNames(); * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; while (attrs.hasMoreElements()) { if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } String attr = (String) attrs.nextElement(); !(value instanceof Serializable)) * SUCH DAMAGE. results.addElement(attr); throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** } (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before Enumeration names = results.elements(); * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time while (names.hasMoreElements()) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. String name = (String) names.nextElement(); removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ removeAttribute(name); attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } // Mark this session as invalid (new HttpSessionBindingEvent((HttpSession) this, name)); * /** setValid(false); } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } } private boolean isNew = true; /** package org.apache.tomcat.session; * @deprecated /** // -------------------------------------------- HttpSession Private Methods */ /** import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. } import org.apache.tomcat.util.StringManager; return getAttribute(name); */ /** import java.io.*; } private boolean isValid = false; * Read a serialized version of this session object from the specified import java.net.*; /** * object input stream. import java.util.*; public Object getAttribute(String name) { * Set the <code>isNew</code> flag for this session. * <p> import javax.servlet.*; if (! valid) { /** * * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager import javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * @param isNew The new value for the <code>isNew</code> flag * is not restored by this method, and must be set explicitly. */ */ * /** throw new IllegalStateException(msg); private StringManager sm = void setNew(boolean isNew) { * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * this.isNew = isNew; * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * @exception IOException if an input/output error occurs (CCCs) affect many * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** } */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; /** public class ApplicationSession implements HttpSession { * Set the <code>isValid</code> flag for this session. // Deserialize the scalar instance variables (except Manager) return values.get(name); * creationTime = ((Long) stream.readObject()).longValue(); private StringManager sm = } /** * @param isValid The new value for the <code>isValid</code> flag id = (String) stream.readObject(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. */ lastAccessedTime = ((Long) stream.readObject()).longValue(); private Hashtable values = new Hashtable(); /** */ void setValid(boolean isValid) { maxInactiveInterval = ((Integer) stream.readObject()).intValue(); private String id; * @deprecated private long thisAccessedTime = creationTime; isNew = ((Boolean) stream.readObject()).booleanValue(); private ServerSession serverSession; */ this.isValid = isValid; isValid = ((Boolean) stream.readObject()).booleanValue(); private Context context; public String[] getValueNames() { } private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); // Deserialize the attribute count and attribute values private long thisAccessTime = creationTime; Vector names = new Vector(); int n = ((Integer) stream.readObject()).intValue(); private long lastAccessed = creationTime; // ----------------------------------------------------- Session Properties // ------------------------------------------------- HttpSession Properties for (int i = 0; i < n; i++) { private int inactiveInterval = -1; while (e.hasMoreElements()) { String name = (String) stream.readObject(); private boolean valid = true; names.addElement(e.nextElement()); Object value = (Object) stream.readObject(); } /** /** attributes.put(name, value); ApplicationSession(String id, ServerSession serverSession, * Set the creation time for this session. This method is called by the * Return the time when this session was created, in milliseconds since } Context context) { String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * midnight, January 1, 1970 GMT. this.serverSession = serverSession; * * } this.context = context; names.copyInto(valueNames); * @param time The new creation time * @exception IllegalStateException if this method is called on an this.id = id; */ * invalidated session return valueNames; public void setCreationTime(long time) { */ /** this.inactiveInterval = context.getSessionTimeOut(); public long getCreationTime() { * Write a serialized version of this session object to the specified } this.creationTime = time; * object output stream. if (this.inactiveInterval != -1) { this.lastAccessedTime = time; return (this.creationTime); * <p> this.inactiveInterval *= 60; public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored } if (! valid) { } * in the serialized representation of this Session. After calling } String msg = sm.getString("applicationSession.session.ise"); * <code>readObject()</code>, you must set the associated Manager * explicitly. ServerSession getServerSession() { throw new IllegalStateException(msg); /** * <p> return serverSession; } * Return the session context with which this session is associated. * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable } * * will be silently ignored. If you do not want any such attributes, Hashtable valuesClone = (Hashtable)values.clone(); * @deprecated As of Version 2.1, this method is deprecated and has no * be sure the <code>distributable</code> property of our associated heterogeneous software /** * replacement. It will be removed in a future version of the * Manager is set to <code>true</code>. * Called by context when request comes in so that accesses and return (Enumeration)valuesClone.keys(); * Java Servlet API. * * inactivities can be dealt with accordingly. } */ * @param stream The output stream to write to */ public HttpSessionContext getSessionContext() { * * @exception IOException if an input/output error occurs void accessed() { /** if (sessionContext == null) */ // set last accessed to thisAccessTime as it will be left over * @deprecated sessionContext = new StandardSessionContext(); private void writeObject(ObjectOutputStream stream) throws IOException { // from the previous access */ return (sessionContext); lastAccessed = thisAccessTime; // Write the scalar instance variables (except Manager) thisAccessTime = System.currentTimeMillis(); public void removeValue(String name) { } stream.writeObject(new Long(creationTime)); removeAttribute(name); stream.writeObject(id); validate(); } stream.writeObject(new Long(lastAccessedTime)); } // ----------------------------------------------HttpSession Public Methods stream.writeObject(new Integer(maxInactiveInterval)); public void removeAttribute(String name) { stream.writeObject(new Boolean(isNew)); void validate() { if (! valid) { } stream.writeObject(new Boolean(isValid)); // if we have an inactive interval, check to see if weve exceeded it String msg = sm.getString("applicationSession.session.ise"); /** if (inactiveInterval != -1) { * Return the object bound with the specified name in this session, or // Accumulate the names of serializable attributes int thisInterval = throw new IllegalStateException(msg); * <code>null</code> if no object is bound with that name. Vector results = new Vector(); (int)(System.currentTimeMillis() - lastAccessed) / 1000; } * Enumeration attrs = getAttributeNames(); * @param name Name of the attribute to be returned while (attrs.hasMoreElements()) { if (thisInterval > inactiveInterval) { if (name == null) { * String attr = (String) attrs.nextElement(); invalidate(); String msg = sm.getString("applicationSession.value.iae"); * @exception IllegalStateException if this method is called on an Object value = attributes.get(attr); } * invalidated session if (value instanceof Serializable) } throw new IllegalArgumentException(msg); */ results.addElement(attr); } } public Object getAttribute(String name) { } // HTTP SESSION IMPLEMENTATION METHODS Object o = values.get(name); return (attributes.get(name)); // Serialize the attribute count and the attribute values stream.writeObject(new Integer(results.size())); public String getId() { if (o instanceof HttpSessionBindingListener) { } Enumeration names = results.elements(); if (valid) { HttpSessionBindingEvent e = while (names.hasMoreElements()) { return id; new HttpSessionBindingEvent(this,name); String name = (String) names.nextElement(); } else { /** stream.writeObject(name); String msg = sm.getString("applicationSession.session.ise"); ((HttpSessionBindingListener)o).valueUnbound(e); * Return an <code>Enumeration</code> of <code>String</code> objects stream.writeObject(attributes.get(name)); } * containing the names of the objects bound to this session. } throw new IllegalStateException(msg); * modules. } values.remove(name); * @exception IllegalStateException if this method is called on an } } * invalidated session } */ public long getCreationTime() { public void setMaxInactiveInterval(int interval) { public Enumeration getAttributeNames() { crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | if (valid) { if (! valid) { long getCreationTime() | return creationTime; String msg = sm.getString("applicationSession.session.ise"); return (attributes.keys()); Object getAttribute(String) | } else { Enumeration getAttributeNames() | String msg = sm.getString("applicationSession.session.ise"); throw new IllegalStateException(msg); } String[] getValueNames() | } void invalidate() | throw new IllegalStateException(msg); boolean isNew() | } /** void removeAttribute(String) | } * Return the object bound with the specified name in this session, or void setAttribute(String, Object)); * <code>null</code> if no object is bound with that name. /** * static advice(StandardSession s): invalidate(s) { * * @param name Name of the value to be returned before { * @deprecated * if (!s.isValid()) * @exception IllegalStateException if this method is called on an throw new IllegalStateException * invalidated session (s.sm.getString("standardSession." * + thisJoinPoint.methodName * @deprecated As of Version 2.2, this method is replaced by + ".ise")); * <code>getAttribute()</code> } */ } /** public Object getValue(String name) { * Return the session identifier for this session. */ return (getAttribute(name)); public String getId() { } } /** // -------------------------------------------------------------- Private Class * Return the set of names of objects bound to this session. If there * are no such objects, a zero-length array is returned. * /** * @exception IllegalStateException if this method is called on an * This class is a dummy implementation of the <code>HttpSessionContext</code> * invalidated session * interface, to conform to the requirement that such an object be returned * * when <code>HttpSession.getSessionContext()</code> is called. * @deprecated As of Version 2.2, this method is replaced by * * <code>getAttributeNames()</code> * @author Craig R. McClanahan */ * public String[] getValueNames() { * @deprecated As of Java Servlet API 2.1 with no replacement. The * interface will be removed in a future version of this API. Vector results = new Vector(); */ Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { final class StandardSessionContext implements HttpSessionContext { String attr = (String) attrs.nextElement(); results.addElement(attr); } private Vector dummy = new Vector(); return (this.id); String names[] = new String[results.size()]; for (int i = 0; i < names.length; i++) /** names[i] = (String) results.elementAt(i); * Return the session identifiers of all sessions defined return (names); * within this context. * } * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> * and will be removed in a future version of the API. /** */ * Invalidates this session and unbinds any objects bound to it. public Enumeration getIds() { * * @exception IllegalStateException if this method is called on return (dummy.elements()); * an invalidated session• Code is: */ public void invalidate() { // Cause this session to expire expire(); } } /** * Return <code>true</code> if the client does not yet know about the * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client * has disabled the use of cookies, then a session would be new on each * request. * * @exception IllegalStateException if this method is called on an * invalidated session */ public boolean isNew() { return (this.isNew); } package org.apache.tomcat.session; void validate() { // if we have an inactive interval, check to see if import org.apache.tomcat.core.*; // weve exceeded it import org.apache.tomcat.util.StringManager; import java.io.*; if (inactiveInterval != -1) { import java.net.*; int thisInterval = import java.util.*; (int)(System.currentTimeMillis() - lastAccessed) / 1000; import javax.servlet.*; import javax.servlet.http.*; if (thisInterval > inactiveInterval) { invalidate(); /** * Core implementation of a server session ServerSessionManager ssm = * ServerSessionManager.getManager(); * @author James Duncan Davidson [duncan@eng.sun.com] * @author James Todd [gonzo@eng.sun.com] ssm.removeSession(this); */ } } public class ServerSession { } private StringManager sm = synchronized void invalidate() { StringManager.getManager("org.apache.tomcat.session"); Enumeration enum = appSessions.keys(); /** private Hashtable values = new Hashtable(); * Set the session identifier for this session. private Hashtable appSessions = new Hashtable(); while (enum.hasMoreElements()) { * private String id; Object key = enum.nextElement(); * @param id The new session identifier private long creationTime = System.currentTimeMillis();; ApplicationSession appSession = */ private long thisAccessTime = creationTime; (ApplicationSession)appSessions.get(key); public void setId(String id) { private long lastAccessed = creationTime; private int inactiveInterval = -1; appSession.invalidate(); } ServerSession(String id) { } this.id = id; } public void putValue(String name, Object value) { if (name == null) { public String getId() { String msg = sm.getString("serverSession.value.iae"); return id; } throw new IllegalArgumentException(msg); } public long getCreationTime() { return creationTime; removeValue(name); // remove any existing binding } values.put(name, value); } • Scattered throughout public long getLastAccessedTime() { return lastAccessed; public Object getValue(String name) { } if (name == null) { String msg = sm.getString("serverSession.value.iae"); public ApplicationSession getApplicationSession(Context context, boolean create) { throw new IllegalArgumentException(msg); ApplicationSession appSession = } if ((this.id != null) && (manager != null) && (ApplicationSession)appSessions.get(context); (manager instanceof ManagerBase)) return values.get(name); ((ManagerBase) manager).remove(this); if (appSession == null && create) { } // XXX public Enumeration getValueNames() { // sync to ensure valid? return values.keys(); } appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); public void removeValue(String name) { } values.remove(name); } // XXX // make sure that we havent gone over the end of our public void setMaxInactiveInterval(int interval) { // inactive interval -- if so, invalidate and create inactiveInterval = interval; // a new appSession } return appSession; public int getMaxInactiveInterval() { } return inactiveInterval; } void removeApplicationSession(Context context) { appSessions.remove(context); // XXX } // syncd for safty -- no other thread should be getting something // from this while we are reaping. This isnt the most optimal /** // solution for this, but well determine something else later. this.id = id; * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. synchronized void reap() { */ Enumeration enum = appSessions.keys(); void accessed() { while (enum.hasMoreElements()) { // set last accessed to thisAccessTime as it will be left over many modules. if ((manager != null) && (manager instanceof ManagerBase)) ((ManagerBase) manager).add(this); } • Tangled with unrelated /** * Return descriptive information about this Session implementation and * the corresponding version number, in the format * <code>&lt;description&gt;/&lt;version&gt;</code>. */ public String getInfo() { return (this.info); modules. } /** * Return the last time the client sent a request associated with this * session, as the number of milliseconds since midnight, January 1, 1970 * GMT. Actions that your application takes, such as getting or setting * a value associated with the session, do not affect the access time. */ public long getLastAccessedTime() { return (this.lastAccessedTime); } /** * Return the Manager within which this Session is valid. */ public Manager getManager() { return (this.manager); } /** * Set the Manager within which this Session is valid. * * @param manager The new Manager */ public void setManager(Manager manager) { 10
    • Crosscutting Concerns /* public void invalidate() { ; * Remove the object bound with the specified name from this session. If * ==================================================================== serverSession.removeApplicationSession(context); * the session does not have an object bound with this name, this method * * does nothing. * The Apache Software License, Version 1.1 // remove everything in the session /** * <p> * * Standard implementation of the <b>Session</b> interface. This object is * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. */ * notice, this list of conditions and the following disclaimer. * public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ Object object = attributes.get(name); * the documentation and/or other materials provided with the if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession return; * } implements HttpSession, Session { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { /** if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors * Update the accessed time information for this session. This method ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { * should be called by the context when a request comes in for a particular (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; * session, even if the application does not reference it. } itself, } /** */ } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. public void access() { * * } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated this.lastAccessedTime = this.thisAccessedTime;• Crosscutting concerns * Foundation" must not be used to endorse or promote products /** */ this.thisAccessedTime = System.currentTimeMillis(); * Bind an object to this session, using the specified name. If an object derived * @deprecated public StandardSession(Manager manager) { this.isNew=false; * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ } * replaced. * permission, please contact apache@apache.org. super(); * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); /** * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } * Perform the internal processing required to invalidate this session, * <code>valueBound()</code> on the object. * permission of the Apache Group. * without triggering an exception if the session has already expired. * * public void setAttribute(String name, Object value) { */ * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS AND ANY EXPRESSED OR IMPLIED if (! valid) { /** public void expire() { * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ // Remove this session from our managers active sessions * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; if ((manager != null) && (manager instanceof ManagerBase)) * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } ((ManagerBase) manager).remove(this); * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** // Unbind any objects associated with this session */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. Vector results = new Vector(); public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ Enumeration attrs = getAttributeNames(); * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; while (attrs.hasMoreElements()) { if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } String attr = (String) attrs.nextElement(); !(value instanceof Serializable)) * SUCH DAMAGE. results.addElement(attr); throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** } (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before Enumeration names = results.elements(); * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time while (names.hasMoreElements()) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. String name = (String) names.nextElement(); removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ removeAttribute(name); attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } // Mark this session as invalid (new HttpSessionBindingEvent((HttpSession) this, name)); * /** setValid(false); } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } } private boolean isNew = true; /** package org.apache.tomcat.session; * @deprecated /** // -------------------------------------------- HttpSession Private Methods */ /** import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. } import org.apache.tomcat.util.StringManager; return getAttribute(name); */ /** import java.io.*; } private boolean isValid = false; * Read a serialized version of this session object from the specified import java.net.*; /** * object input stream. import java.util.*; public Object getAttribute(String name) { * Set the <code>isNew</code> flag for this session. * <p> import javax.servlet.*; if (! valid) { /** * * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager import javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * @param isNew The new value for the <code>isNew</code> flag * is not restored by this method, and must be set explicitly. */ */ * /** throw new IllegalStateException(msg); private StringManager sm = void setNew(boolean isNew) { * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * this.isNew = isNew; * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * @exception IOException if an input/output error occurs (CCCs) affect many * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** } */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; /** public class ApplicationSession implements HttpSession { * Set the <code>isValid</code> flag for this session. // Deserialize the scalar instance variables (except Manager) return values.get(name); * creationTime = ((Long) stream.readObject()).longValue(); private StringManager sm = } /** * @param isValid The new value for the <code>isValid</code> flag id = (String) stream.readObject(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. */ lastAccessedTime = ((Long) stream.readObject()).longValue(); private Hashtable values = new Hashtable(); /** */ void setValid(boolean isValid) { maxInactiveInterval = ((Integer) stream.readObject()).intValue(); private String id; * @deprecated private long thisAccessedTime = creationTime; isNew = ((Boolean) stream.readObject()).booleanValue(); private ServerSession serverSession; */ this.isValid = isValid; isValid = ((Boolean) stream.readObject()).booleanValue(); private Context context; public String[] getValueNames() { } private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); // Deserialize the attribute count and attribute values private long thisAccessTime = creationTime; Vector names = new Vector(); int n = ((Integer) stream.readObject()).intValue(); private long lastAccessed = creationTime; // ----------------------------------------------------- Session Properties // ------------------------------------------------- HttpSession Properties for (int i = 0; i < n; i++) { private int inactiveInterval = -1; while (e.hasMoreElements()) { String name = (String) stream.readObject(); private boolean valid = true; names.addElement(e.nextElement()); Object value = (Object) stream.readObject(); } /** /** attributes.put(name, value); ApplicationSession(String id, ServerSession serverSession, * Set the creation time for this session. This method is called by the * Return the time when this session was created, in milliseconds since } Context context) { String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * midnight, January 1, 1970 GMT. this.serverSession = serverSession; * * } this.context = context; names.copyInto(valueNames); * @param time The new creation time * @exception IllegalStateException if this method is called on an this.id = id; */ * invalidated session return valueNames; public void setCreationTime(long time) { */ /** this.inactiveInterval = context.getSessionTimeOut(); public long getCreationTime() { * Write a serialized version of this session object to the specified } this.creationTime = time; * object output stream. if (this.inactiveInterval != -1) { this.lastAccessedTime = time; return (this.creationTime); * <p> this.inactiveInterval *= 60; public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored } if (! valid) { } * in the serialized representation of this Session. After calling } String msg = sm.getString("applicationSession.session.ise"); * <code>readObject()</code>, you must set the associated Manager * explicitly. ServerSession getServerSession() { throw new IllegalStateException(msg); /** * <p> return serverSession; } * Return the session context with which this session is associated. * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable } * * will be silently ignored. If you do not want any such attributes, Hashtable valuesClone = (Hashtable)values.clone(); * @deprecated As of Version 2.1, this method is deprecated and has no * be sure the <code>distributable</code> property of our associated heterogeneous software /** * replacement. It will be removed in a future version of the * Manager is set to <code>true</code>. * Called by context when request comes in so that accesses and return (Enumeration)valuesClone.keys(); * Java Servlet API. * * inactivities can be dealt with accordingly. } */ * @param stream The output stream to write to Message */ public HttpSessionContext getSessionContext() { * * @exception IOException if an input/output error occurs void accessed() { /** if (sessionContext == null) */ // set last accessed to thisAccessTime as it will be left over * @deprecated sessionContext = new StandardSessionContext(); private void writeObject(ObjectOutputStream stream) throws IOException { // from the previous access */ return (sessionContext); lastAccessed = thisAccessTime; // Write the scalar instance variables (except Manager) thisAccessTime = System.currentTimeMillis(); public void removeValue(String name) { } stream.writeObject(new Long(creationTime)); removeAttribute(name); stream.writeObject(id); validate(); } stream.writeObject(new Long(lastAccessedTime)); } // ----------------------------------------------HttpSession Public Methods stream.writeObject(new Integer(maxInactiveInterval)); public void removeAttribute(String name) { stream.writeObject(new Boolean(isNew)); void validate() { if (! valid) { } stream.writeObject(new Boolean(isValid)); // if we have an inactive interval, check to see if weve exceeded it String msg = sm.getString("applicationSession.session.ise"); /** if (inactiveInterval != -1) { * Return the object bound with the specified name in this session, or // Accumulate the names of serializable attributes int thisInterval = throw new IllegalStateException(msg); * <code>null</code> if no object is bound with that name. Vector results = new Vector(); (int)(System.currentTimeMillis() - lastAccessed) / 1000; } * Enumeration attrs = getAttributeNames(); * @param name Name of the attribute to be returned while (attrs.hasMoreElements()) { if (thisInterval > inactiveInterval) { if (name == null) { * String attr = (String) attrs.nextElement(); invalidate(); String msg = sm.getString("applicationSession.value.iae"); * @exception IllegalStateException if this method is called on an Object value = attributes.get(attr); } * invalidated session if (value instanceof Serializable) } throw new IllegalArgumentException(msg); */ results.addElement(attr); } } public Object getAttribute(String name) { } // HTTP SESSION IMPLEMENTATION METHODS Object o = values.get(name); return (attributes.get(name)); // Serialize the attribute count and the attribute values stream.writeObject(new Integer(results.size())); public String getId() { if (o instanceof HttpSessionBindingListener) { } Enumeration names = results.elements(); if (valid) { HttpSessionBindingEvent e = while (names.hasMoreElements()) { return id; new HttpSessionBindingEvent(this,name); String name = (String) names.nextElement(); } else { /** stream.writeObject(name); String msg = sm.getString("applicationSession.session.ise"); ((HttpSessionBindingListener)o).valueUnbound(e); * Return an <code>Enumeration</code> of <code>String</code> objects stream.writeObject(attributes.get(name)); } * containing the names of the objects bound to this session. } throw new IllegalStateException(msg); * modules. } values.remove(name); * @exception IllegalStateException if this method is called on an } } * invalidated session } */ public long getCreationTime() { public void setMaxInactiveInterval(int interval) { public Enumeration getAttributeNames() { crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | if (valid) { if (! valid) { long getCreationTime() | return creationTime; String msg = sm.getString("applicationSession.session.ise"); return (attributes.keys()); Object getAttribute(String) | } else { Enumeration getAttributeNames() | String msg = sm.getString("applicationSession.session.ise"); throw new IllegalStateException(msg); } String[] getValueNames() | } void invalidate() | throw new IllegalStateException(msg); boolean isNew() | } /** void removeAttribute(String) | } * Return the object bound with the specified name in this session, or void setAttribute(String, Object)); encryption is an * <code>null</code> if no object is bound with that name. /** * static advice(StandardSession s): invalidate(s) { * * @param name Name of the value to be returned before { * @deprecated * if (!s.isValid()) * @exception IllegalStateException if this method is called on an throw new IllegalStateException * invalidated session (s.sm.getString("standardSession." * + thisJoinPoint.methodName * @deprecated As of Version 2.2, this method is replaced by + ".ise")); * <code>getAttribute()</code> } */ } /** public Object getValue(String name) { * Return the session identifier for this session. */ return (getAttribute(name)); public String getId() { } } /** // -------------------------------------------------------------- Private Class * Return the set of names of objects bound to this session. If there * are no such objects, a zero-length array is returned. * /** * @exception IllegalStateException if this method is called on an * This class is a dummy implementation of the <code>HttpSessionContext</code> * invalidated session * interface, to conform to the requirement that such an object be returned * * when <code>HttpSession.getSessionContext()</code> is called. * @deprecated As of Version 2.2, this method is replaced by * * <code>getAttributeNames()</code> * @author Craig R. McClanahan */ * public String[] getValueNames() { * @deprecated As of Java Servlet API 2.1 with no replacement. The * interface will be removed in a future version of this API. Vector results = new Vector(); */ Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { final class StandardSessionContext implements HttpSessionContext { String attr = (String) attrs.nextElement(); results.addElement(attr); } private Vector dummy = new Vector(); return (this.id); String names[] = new String[results.size()]; for (int i = 0; i < names.length; i++) /** names[i] = (String) results.elementAt(i); * Return the session identifiers of all sessions defined return (names); * within this context. * } * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> * and will be removed in a future version of the API. /** */ example since many * Invalidates this session and unbinds any objects bound to it. public Enumeration getIds() { * * @exception IllegalStateException if this method is called on return (dummy.elements()); * an invalidated session• Code is: */ public void invalidate() { // Cause this session to expire expire(); } } /** * Return <code>true</code> if the client does not yet know about the * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client * has disabled the use of cookies, then a session would be new on each * request. * * @exception IllegalStateException if this method is called on an * invalidated session */ public boolean isNew() { return (this.isNew); } package org.apache.tomcat.session; void validate() { // if we have an inactive interval, check to see if import org.apache.tomcat.core.*; // weve exceeded it import org.apache.tomcat.util.StringManager; import java.io.*; if (inactiveInterval != -1) { import java.net.*; int thisInterval = import java.util.*; (int)(System.currentTimeMillis() - lastAccessed) / 1000; import javax.servlet.*; parts of a program import javax.servlet.http.*; if (thisInterval > inactiveInterval) { invalidate(); /** * Core implementation of a server session ServerSessionManager ssm = * ServerSessionManager.getManager(); * @author James Duncan Davidson [duncan@eng.sun.com] * @author James Todd [gonzo@eng.sun.com] ssm.removeSession(this); */ } } public class ServerSession { } private StringManager sm = synchronized void invalidate() { StringManager.getManager("org.apache.tomcat.session"); Enumeration enum = appSessions.keys(); /** private Hashtable values = new Hashtable(); * Set the session identifier for this session. private Hashtable appSessions = new Hashtable(); while (enum.hasMoreElements()) { * private String id; Object key = enum.nextElement(); * @param id The new session identifier private long creationTime = System.currentTimeMillis();; ApplicationSession appSession = */ private long thisAccessTime = creationTime; (ApplicationSession)appSessions.get(key); public void setId(String id) { private long lastAccessed = creationTime; private int inactiveInterval = -1; appSession.invalidate(); } ServerSession(String id) { } this.id = id; } public void putValue(String name, Object value) { if (name == null) { public String getId() { String msg = sm.getString("serverSession.value.iae"); return id; } throw new IllegalArgumentException(msg); } public long getCreationTime() { return creationTime; removeValue(name); // remove any existing binding } values.put(name, value); } • Scattered throughout public long getLastAccessedTime() { return lastAccessed; public Object getValue(String name) { } if (name == null) { String msg = sm.getString("serverSession.value.iae"); public ApplicationSession getApplicationSession(Context context, boolean create) { throw new IllegalArgumentException(msg); ApplicationSession appSession = } if ((this.id != null) && (manager != null) && (ApplicationSession)appSessions.get(context); (manager instanceof ManagerBase)) return values.get(name); ((ManagerBase) manager).remove(this); if (appSession == null && create) { } involve security // XXX public Enumeration getValueNames() { // sync to ensure valid? return values.keys(); } appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); public void removeValue(String name) { } values.remove(name); } // XXX // make sure that we havent gone over the end of our public void setMaxInactiveInterval(int interval) { // inactive interval -- if so, invalidate and create inactiveInterval = interval; // a new appSession } return appSession; public int getMaxInactiveInterval() { } return inactiveInterval; } void removeApplicationSession(Context context) { appSessions.remove(context); // XXX } // syncd for safty -- no other thread should be getting something // from this while we are reaping. This isnt the most optimal /** // solution for this, but well determine something else later. this.id = id; * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. synchronized void reap() { */ Enumeration enum = appSessions.keys(); void accessed() { while (enum.hasMoreElements()) { // set last accessed to thisAccessTime as it will be left over many modules. if ((manager != null) && (manager instanceof ManagerBase)) ((ManagerBase) manager).add(this); } • Tangled with unrelated /** * Return descriptive information about this Session implementation and * the corresponding version number, in the format * <code>&lt;description&gt;/&lt;version&gt;</code>. */ public String getInfo() { return (this.info); modules. } /** * Return the last time the client sent a request associated with this * session, as the number of milliseconds since midnight, January 1, 1970 * GMT. Actions that your application takes, such as getting or setting * a value associated with the session, do not affect the access time. */ public long getLastAccessedTime() { return (this.lastAccessedTime); } /** * Return the Manager within which this Session is valid. */ public Manager getManager() { return (this.manager); } /** * Set the Manager within which this Session is valid. * * @param manager The new Manager */ public void setManager(Manager manager) { 10
    • Aspect-Oriented Programming /* public void invalidate() { ; * Remove the object bound with the specified name from this session. If * ==================================================================== serverSession.removeApplicationSession(context); /** * the session does not have an object bound with this name, this method * * Perform the internal processing required to invalidate this session, * does nothing. * The Apache Software License, Version 1.1 // remove everything in the session /** * without triggering an exception if the session has already expired. * <p> * * Standard implementation of the <b>Session</b> interface. This object is */ * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred public void expire() { * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> // Remove this session from our managers active sessions * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the if ((manager != null) && (manager instanceof ManagerBase)) * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. ((ManagerBase) manager).remove(this); * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an // Unbind any objects associated with this session * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. Vector results = new Vector(); */ * notice, this list of conditions and the following disclaimer. * Enumeration attrs = getAttributeNames(); public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan while (attrs.hasMoreElements()) { * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ String attr = (String) attrs.nextElement(); synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ results.addElement(attr); Object object = attributes.get(name); * the documentation and/or other materials provided with the } if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession Enumeration names = results.elements(); return; * } implements HttpSession, Session { while (names.hasMoreElements()) { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if String name = (String) names.nextElement(); // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { removeAttribute(name); if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors } ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; // Mark this session as invalid } itself, } /** setValid(false); } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. * * } } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated * Foundation" must not be used to endorse or promote products /** */ * Bind an object to this session, using the specified name. If an object derived * @deprecated public StandardSession(Manager manager) { /** * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ * replaced. * permission, please contact apache@apache.org. super(); } * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } /** * <code>valueBound()</code> on the object. * permission of the Apache Group. * Set the <code>isNew</code> flag for this session. * * public void setAttribute(String name, Object value) { * * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS AND ANY EXPRESSED OR IMPLIED if (! valid) { /** * @param isNew The new value for the <code>isNew</code> flag * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. */ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ void setNew(boolean isNew) { * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } this.isNew = isNew; * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** } */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; /** if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } * Set the <code>isValid</code> flag for this session. !(value instanceof Serializable)) * SUCH DAMAGE. * throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** * @param isValid The new value for the <code>isValid</code> flag (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before */ * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time void setValid(boolean isValid) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ this.isValid = isValid; attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } (new HttpSessionBindingEvent((HttpSession) this, name)); * /** // ------------------------------------------------- HttpSession Properties } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } private boolean isNew = true; /** /** * Return the time when this session was created, in milliseconds since package org.apache.tomcat.session; * @deprecated * midnight, January 1, 1970 GMT. // -------------------------------------------- HttpSession Private Methods */ /** * import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. * @exception IllegalStateException if this method is called on an import org.apache.tomcat.util.StringManager; return getAttribute(name); */ * invalidated session /** import java.io.*; } private boolean isValid = false; */ * Read a serialized version of this session object from the specified import java.net.*; public long getCreationTime() { * object input stream. import java.util.*; public Object getAttribute(String name) { * <p> import javax.servlet.*; if (! valid) { /** return (this.creationTime); * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager import javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * is not restored by this method, and must be set explicitly. */ } * /** throw new IllegalStateException(msg); private StringManager sm = * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * /** * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * Return the session context with which this session is associated. * @exception IOException if an input/output error occurs * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** * */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. * @deprecated As of Version 2.1, this method is deprecated and has no private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ * replacement. It will be removed in a future version of the throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; * Java Servlet API. public class ApplicationSession implements HttpSession { */ // Deserialize the scalar instance variables (except Manager) return values.get(name); public HttpSessionContext getSessionContext() { creationTime = ((Long) stream.readObject()). private StringManager sm = } /** isValid = ((Boolean) stream.readObject()).booleanValue(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. if (sessionContext == null) private Hashtable values = new Hashtable(); /** */ sessionContext = new StandardSessionContext(); // Deserialize the attribute count and attribute values private String id; * @deprecated private long thisAccessedTime = creationTime; return (sessionContext); int n = ((Integer) stream.readObject()).intValue(); private ServerSession serverSession; */ for (int i = 0; i < n; i++) { private Context context; public String[] getValueNames() { } String name = (String) stream.readObject(); private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); Object value = (Object) stream.readObject(); private long thisAccessTime = creationTime; Vector names = new Vector(); attributes.put(name, value); private boolean valid = true; // ----------------------------------------------------- Session Properties // ----------------------------------------------HttpSession Public Methods } while (e.hasMoreElements()) { ApplicationSession(String id, ServerSession serverSession, names.addElement(e.nextElement()); } Context context) { } /** /** this.serverSession = serverSession; * Set the creation time for this session. This method is called by the * Return the object bound with the specified name in this session, or this.context = context; String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * <code>null</code> if no object is bound with that name. /** this.id = id; * * * Write a serialized version of this session object to the specified names.copyInto(valueNames); * @param time The new creation time * @param name Name of the attribute to be returned * object output stream. this.inactiveInterval = context.getSessionTimeOut(); */ * * <p> return valueNames; public void setCreationTime(long time) { * @exception IllegalStateException if this method is called on an * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored if (this.inactiveInterval != -1) { * invalidated session * in the serialized representation of this Session. After calling this.inactiveInterval *= 60; } this.creationTime = time; */ * <code>readObject()</code>, you must set the associated Manager } this.lastAccessedTime = time; public Object getAttribute(String name) { * explicitly. } public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <p> if (! valid) { return (attributes.get(name)); * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable ServerSession getServerSession() { String msg = sm.getString("applicationSession.session.ise"); } * will be silently ignored. If you do not want any such attributes, return serverSession; } * be sure the <code>distributable</code> property of our associated } throw new IllegalStateException(msg); * Manager is set to <code>true</code>. } /** * /** * Return the session identifier for this session. /** * @param stream The output stream to write to * Called by context when request comes in so that accesses and Hashtable valuesClone = (Hashtable)values.clone(); */ * Return an <code>Enumeration</code> of <code>String</code> objects * * inactivities can be dealt with accordingly. public String getId() { * containing the names of the objects bound to this session. * @exception IOException if an input/output error occurs */ return (Enumeration)valuesClone.keys(); * */ } return (this.id); * @exception IllegalStateException if this method is called on an private void writeObject(ObjectOutputStream stream) throws IOException { * invalidated session // HTTP SESSION IMPLEMENTATION METHODS } */ // Write the scalar instance variables (except Manager) /** public Enumeration getAttributeNames() { stream.writeObject(new Long(creationTime)); public String getId() { * @deprecated stream.writeObject(id); if (valid) { */ /** return (attributes.keys()); stream.writeObject(new Long(lastAccessedTime)); return id; * Set the session identifier for this session. stream.writeObject(new Integer(maxInactiveInterval)); } else { public void removeValue(String name) { * } stream.writeObject(new Boolean(isNew)); String msg = sm.getString("applicationSession.session.ise");