Techniques for Automated Software Evolution

449
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

description

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

Transcript of Techniques for Automated Software Evolution

  • 1. Techniques for Automated SoftwareEvolutionPhD Dissertation by Raffi Khatchadourian Computer Science & Engineering Ohio State UniversityAdvisor: Neelam Soundarajan Committee: Atanas Rountev, Paul Sivilotti, Paul Evans 1

2. 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 ComputerScience. Worked as: A Software Engineer at State of New Jersey Office of InformationTechnology in Trenton, NJ. A UNIX Systems Administrator for pharmaceutical website in TomsRiver, 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 iPhonedevelopment team at Apple Inc. in Cupertino, CA on Monday (4/4/2011). 2 3. Publication Highlights Raffi Khatchadourian, Phil Greenwood, Awais Rashid, and Guoqing Xu.Pointcut rejuvenation: Recovering pointcut expressions in evolvingaspect-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 evolvingaspect-oriented software. In Proceedings of the 24th International Conferenceon Automated Software Engineering (ASE 09), pages 575579, Auckland, NewZealand, November 2009. IEEE/ACM. Raffi Khatchadourian, Johan Dovland, and Neelam Soundarajan. Enforcingbehavioral constraints in evolving aspect-oriented programs. InProceedings 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 1928, Brussels, Belgium, April2008. ACM. Raffi Khatchadourian, Jason Sawin, and Atanas Rountev. Automatedrefactoring of legacy Java software to enumerated types. In Proceedingsof the 23rd International Conference on Software Maintenance (ICSM 07),pages 224233, Paris, France, October 2007. IEEE. Peer-reviewed totals (2005-): 1 paper to appear in a journal, 5 papers appearing inconference proceedings, and 5 papers appearing in workshop proceedings. 3 4. Activity Highlights Helped develop new Applied Software Engineering course ECE/CSE 668based on Challenge-X hybrid SUV automobile simulation at OSU CARin 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 SoftwareEngineering (AOSE) Group at the Computing Department of LancasterUniversity, 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 theUniversity of Tokyo under Hidehiko Masuhara in 2010. Proposed project mentor for Google Summer of Code (GSoC) in 2009and 2010. Project based on refactoring to enumerated types in Java. Organizing committee member (Web Chair) for the EuropeanConference on Object-Oriented Programming (ECOOP).4 5. 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 6. Motivation6 7. Motivation Software changes overtime:6 8. Motivation Software changes overtime: Requirements evolve6 9. Motivation Software changes overtime: Requirements evolve New platforms emerge(e.g., mobile devices) 6 10. Motivation Software changes overtime: Requirements evolve New platforms emerge(e.g., mobile devices) Frameworks change(e.g., XML vs.annotation-based) 6 11. Motivation7 12. MotivationChanging and/or maintaining large, complex softwaresystems can be non-trivial:Tedious: May require changing many lines of code. Error-prone: Changes may be implementedincorrectly.Omission- May opportunities to produce betterprone: code.7 13. MotivationChanging and/or maintaining large, complex softwaresystems can be non-trivial:Tedious: May require changing many lines of code. Error-prone: Changes may be implementedincorrectly.Omission- May opportunities to produce betterprone: code.7 14. Motivation Adding aparameter to aChanging and/or maintaining large, complex softwaresystems can be non-trivial:methodTedious: May require changing many lines of code. Error-prone: Changes may be implementedincorrectly.Omission- May opportunities to produce betterprone: code.7 15. MotivationChanging and/or maintaining large, complex softwaresystems can be non-trivial:Tedious: May require changing many lines of code. Error-prone: Changes may be implementedincorrectly.Omission- May opportunities to produce betterprone: code.7 16. MotivationRemoving aChanging and/or maintaining large, complex softwaresystemsparameter maymethod can be non-trivial:alter overloading toTedious: May require changing many lines ofoverriding code. Error-prone: Changes may be implementedincorrectly.Omission- May opportunities to produce betterprone: code.7 17. MotivationChanging and/or maintaining large, complex softwaresystems can be non-trivial:Tedious: May require changing many lines of code. Error-prone: Changes may be implementedincorrectly.Omission- May opportunities to produce betterprone: code.7 18. MotivationChanging and/or maintaining large, complex softwaresystems can be non-trivial: Tedious: May require changing many lines ofcode.HashTable vs. Error-prone: Changes may be implementedincorrectly.HashMapOmission- May opportunities to produce betterprone: code.7 19. MotivationChanging and/or maintaining large, complex softwaresystems can be non-trivial:Tedious: May require changing many lines of code. Error-prone: Changes may be implementedincorrectly.Omission- May opportunities to produce betterprone: code.7 20. Approach8 21. Approach Approaches made toprovide mechanicalassistance in evolutiontasks.8 22. Approach Approaches made toprovide mechanicalassistance in evolutiontasks. Typically in the form ofplug-ins to IDEs. 8 23. Approach Approaches made toprovide mechanicalassistance in evolutiontasks. Typically in the form ofplug-ins to IDEs. Ease the burden ofsoftware maintenanceand evolution. 8 24. ApproachRestrict workspace to only Approaches made to displays elementsprovide mechanicalrelevant to theassistance in evolution tasktasks. Typically in the form ofplug-ins to IDEs. Ease the burden ofsoftware maintenanceand evolution. 8 25. ApproachRestrict workspace to only Approaches made to displays elementsprovide mechanicalrelevant to theassistance in evolution tasktasks. Typically in the form ofplug-ins to IDEs. Restructurecode the burden ofEase while preservingsemantics (i.e.,software maintenanceand evolution.refactoring) 8 26. Thesis Outline9 27. Thesis Outline For my thesis, I have pursed three directions:9 28. Thesis Outline For my thesis, I have pursed three directions: 1. Mechanically alleviate burden of fragile pointcuts inAspect-Oriented software. 9 29. Thesis Outline For my thesis, I have pursed three directions: 1. Mechanically alleviate burden of fragile pointcuts inAspect-Oriented software. 2.Automatically refactor legacy Java software to language enumerated (enum) types. 9 30. Thesis Outline For my thesis, I have pursed three directions: 1. Mechanically alleviate burden of fragile pointcuts inAspect-Oriented software. 2.Automatically refactor legacy Java software to language enumerated (enum) types. 3.Robustly specify evolving Aspect-Oriented software components. 9 31. 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 /***

* * Standard implementation of the Session interface. This object is * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rightsEnumeration enum = values.keys();* serializable, so that it can be stored in persistent storage or transferred * HttpSessionBindingListener, the container calls * reserved.while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * valueUnbound() on the object. *String name = (String)enum.nextElement();*

* * Redistribution and use in source and binary forms, with or without removeValue(name); * IMPLEMENTATION NOTE: 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 org.apache.tomcat.session 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 copyrightif (! valid) {* @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ synchronized (attributes) { *notice, this list of conditions and the following disclaimer inString msg = sm.getString("applicationSession.session.ise");*/ Object object = attributes.get(name); *the documentation and/or other materials provided with theif (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* @deprecatedpublic 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 [email protected]. super(); *

* 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); /*** HttpSessionBindingListener, the container calls *nor may "Apache" appear in their names without prior written }}* Perform the internal processing required to invalidate this session,* valueBound() 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 IMPLIEDif (! 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 ORthrow 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 ANDString 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 beforeEnumeration 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 moreHttpSessionBindingEvent e =* indicates that the session should never time out.String name = (String) names.nextElement(); removeAttribute(name); * information on the Apache Software Foundation, please seenew HttpSessionBindingEvent(this, name); */ removeAttribute(name);attributes.put(name, value); * .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 isNew flag for this session. *

import javax.servlet.*;if (! valid) { /*** * IMPLEMENTATION NOTE: 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 isNew 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 [[email protected]] if (name == null) {* @exception IOException if an input/output error occurs * @author Jason Hunter [[email protected]] String msg = sm.getString("applicationSession.value.iae");/** }*/ * @author James Todd [[email protected]]* 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 isValid 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 isValid 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 valuesprivate 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 anthis.id = id;*/* invalidated sessionreturn 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);*

this.inactiveInterval *= 60; public Enumeration getAttributeNames() { this.thisAccessedTime = time;* IMPLEMENTATION NOTE: 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");* readObject(), you must set the associated Manager * explicitly.ServerSession getServerSession() {throw new IllegalStateException(msg); /***

return serverSession; }* Return the session context with which this session is associated. * IMPLEMENTATION NOTE: 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 distributable property of our associated/*** replacement. It will be removed in a future version of the* Manager is set to true. * 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 occursvoid accessed() {/**if (sessionContext == null)*/// set last accessed to thisAccessTime as it will be left over * @deprecatedsessionContext = 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 itString 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 attributesint thisInterval =throw new IllegalStateException(msg);* null 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 anObject value = attributes.get(attr);}* invalidated sessionif (value instanceof Serializable)} throw new IllegalArgumentException(msg); */ results.addElement(attr);} } public Object getAttribute(String name) { }// HTTP SESSION IMPLEMENTATION METHODSObject o = values.get(name);return (attributes.get(name));// Serialize the attribute count and the attribute valuesstream.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 Enumeration of String objectsstream.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)); * null 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")); * getAttribute()} */ }/** 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 HttpSessionContext * invalidated session * interface, to conform to the requirement that such an object be returned * * when HttpSession.getSessionContext() is called. * @deprecated As of Version 2.2, this method is replaced by * * getAttributeNames()* @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 definedreturn (names);* within this context. *}* @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty Enumeration * 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 expireexpire();}} /** * Return true 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 [[email protected]] * @author James Todd [[email protected]]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 identifierprivate 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) { }// XXXpublic 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 createinactiveInterval = 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 overif ((manager != null) && (manager instanceof ManagerBase))((ManagerBase) manager).add(this);}/** * Return descriptive information about this Session implementation and * the corresponding version number, in the format * /. */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 32. 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 /***

* * Standard implementation of the Session interface. This object is * After this method executes, and if the object implements* Copyright (c) 1999 The Apache Software Foundation. All rightsEnumeration enum = values.keys();* serializable, so that it can be stored in persistent storage or transferred * HttpSessionBindingListener, the container calls* reserved.while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * valueUnbound() on the object.*String name = (String)enum.nextElement();*

** Redistribution and use in source and binary forms, with or without removeValue(name); * IMPLEMENTATION NOTE: 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 org.apache.tomcat.session 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 copyrightif (! valid) {* @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ synchronized (attributes) {*notice, this list of conditions and the following disclaimer inString msg = sm.getString("applicationSession.session.ise");*/ Object object = attributes.get(name);*the documentation and/or other materials provided with theif (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* @deprecatedpublic 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 [email protected]. super(); *

* 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); /*** HttpSessionBindingListener, the container calls*nor may "Apache" appear in their names without prior written }}* Perform the internal processing required to invalidate this session,* valueBound() 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 IMPLIEDif (! 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 ORthrow 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 ANDString 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 beforeEnumeration 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 moreHttpSessionBindingEvent e =* indicates that the session should never time out.String name = (String) names.nextElement(); removeAttribute(name);* information on the Apache Software Foundation, please seenew HttpSessionBindingEvent(this, name); */ removeAttribute(name);attributes.put(name, value);* .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 isNew flag for this session. *

import javax.servlet.*;if (! valid) { /*** * IMPLEMENTATION NOTE: 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 isNew 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 [[email protected]] if (name == null) {* @exception IOException if an input/output error occurs(CCCs) affect many* @author Jason Hunter [[email protected]] String msg = sm.getString("applicationSession.value.iae");/** }*/* @author James Todd [[email protected]]* 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 isValid 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 isValid 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);*

this.inactiveInterval *= 60; public Enumeration getAttributeNames() { this.thisAccessedTime = time;* IMPLEMENTATION NOTE: 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");* readObject(), you must set the associated Manager* explicitly. ServerSession getServerSession() {throw new IllegalStateException(msg); /***

return serverSession; }* Return the session context with which this session is associated. * IMPLEMENTATION NOTE: 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 distributable property of our associatedheterogeneous software /*** replacement. It will be removed in a future version of the* Manager is set to true.* 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 * @deprecatedsessionContext = 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 itString 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);* null 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 anObject value = attributes.get(attr); }* invalidated sessionif (value instanceof Serializable) } throw new IllegalArgumentException(msg); */ results.addElement(attr); } } public Object getAttribute(String name) { } // HTTP SESSION IMPLEMENTATION METHODSObject 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 Enumeration of String objectsstream.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));* null 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"));* getAttribute()}*/ } /** 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 HttpSessionContext* invalidated session * interface, to conform to the requirement that such an object be returned* * when HttpSession.getSessionContext() is called.* @deprecated As of Version 2.2, this method is replaced by ** getAttributeNames()* @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 Enumeration* 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 true 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 [[email protected]]* @author James Todd [[email protected]]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) { } // XXXpublic 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 createinactiveInterval = 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* /.*/ 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 33. 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 /***

* * Standard implementation of the Session interface. This object is * After this method executes, and if the object implements* Copyright (c) 1999 The Apache Software Foundation. All rightsEnumeration enum = values.keys();* serializable, so that it can be stored in persistent storage or transferred * HttpSessionBindingListener, the container calls* reserved.while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * valueUnbound() on the object.*String name = (String)enum.nextElement();*

** Redistribution and use in source and binary forms, with or without removeValue(name); * IMPLEMENTATION NOTE: 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 org.apache.tomcat.session 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 copyrightif (! valid) {* @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ synchronized (attributes) {*notice, this list of conditions and the following disclaimer inString msg = sm.getString("applicationSession.session.ise");*/ Object object = attributes.get(name);*the documentation and/or other materials provided with theif (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* @deprecatedpublic 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 [email protected]. super(); *

* 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); /*** HttpSessionBindingListener, the container calls*nor may "Apache" appear in their names without prior written }}* Perform the internal processing required to invalidate this session,* valueBound() 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 IMPLIEDif (! 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 ORthrow 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 ANDString 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 beforeEnumeration 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 moreHttpSessionBindingEvent e =* indicates that the session should never time out.String name = (String) names.nextElement(); removeAttribute(name);* information on the Apache Software Foundation, please seenew HttpSessionBindingEvent(this, name); */ removeAttribute(name);attributes.put(name, value);* .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 isNew flag for this session. *

import javax.servlet.*;if (! valid) { /*** * IMPLEMENTATION NOTE: 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 isNew 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 [[email protected]] if (name == null) {* @exception IOException if an input/output error occurs(CCCs) affect many* @author Jason Hunter [[email protected]] String msg = sm.getString("applicationSession.value.iae");/** }*/* @author James Todd [[email protected]]* 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 isValid 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 isValid 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);*

this.inactiveInterval *= 60; public Enumeration getAttributeNames() { this.thisAccessedTime = time;* IMPLEMENTATION NOTE: 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");* readObject(), you must set the associated Manager* explicitly. ServerSession getServerSession() {throw new IllegalStateException(msg); /***

return serverSession; }* Return the session context with which this session is associated. * IMPLEMENTATION NOTE: 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 distributable property of our associatedheterogeneous software /*** replacement. It will be removed in a future version of the* Manager is set to true.* 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 * @deprecatedsessionContext = 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 itString 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);* null 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 anObject value = attributes.get(attr); }* invalidated sessionif (value instanceof Serializable) } throw new IllegalArgumentException(msg); */ results.addElement(attr); } } public Object getAttribute(String name) { } // HTTP SESSION IMPLEMENTATION METHODSObject 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 Enumeration of String objectsstream.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));* null 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"));* getAttribute()}*/ } /** 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 HttpSessionContext* invalidated session * interface, to conform to the requirement that such an object be returned* * when HttpSession.getSessionContext() is called.* @deprecated As of Version 2.2, this method is replaced by ** getAttributeNames()* @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 Enumeration* 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 true 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 [[email protected]]* @author James Todd [[email protected]]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) { } // XXXpublic 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 createinactiveInterval = 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* /.*/ 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 34. 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 /***

* * Standard implementation of the Session interface. This object is * After this method executes, and if the object implements* Copyright (c) 1999 The Apache Software Foundation. All rightsEnumeration enum = values.keys();* serializable, so that it can be stored in persistent storage or transferred * HttpSessionBindingListener, the container calls* reserved.while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * valueUnbound() on the object.*String name = (String)enum.nextElement();*

** Redistribution and use in source and binary forms, with or without removeValue(name); * IMPLEMENTATION NOTE: 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 org.apache.tomcat.session 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 copyrightif (! valid) {* @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ synchronized (attributes) {*notice, this list of conditions and the following disclaimer inString msg = sm.getString("applicationSession.session.ise");*/ Object object = attributes.get(name);*the documentation and/or other materials provided with theif (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* @deprecatedpublic 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 [email protected]. super(); *

* 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); /*** HttpSessionBindingListener, the container calls*nor may "Apache" appear in their names without prior written }}* Perform the internal processing required to invalidate this session,* valueBound() 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 IMPLIEDif (! 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 ORthrow 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 ANDString 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 beforeEnumeration names = results.elements();* This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingLis