SlideShare a Scribd company logo
Techniques for Automated Software
            Evolution
      PhD Dissertation by Raffi Khatchadourian
         Computer Science & Engineering
               Ohio State University

            Advisor: Neelam Soundarajan
 Committee: Atanas Rountev, Paul Sivilotti, Paul Evans




                           1
Biography

• Born in New York, NY and raised in Edison, NJ.
• First generation American.
 • Family immigrated from Sofia, Bulgaria.
• Graduated from Monmouth University in 2004 with a B.S. in Computer
  Science.
• Worked as:
 • A Software Engineer at State of New Jersey Office of Information
    Technology in Trenton, NJ.
  • A UNIX Systems Administrator for pharmaceutical website in Toms
    River, NJ.
• Entered PhD program at OSU in September, 2005.
• M.S. in Computer Science from OSU in March, 2010.
• Start as an RF (wireless) Systems Integration Engineer on the iPhone
  development team at Apple Inc. in Cupertino, CA on Monday (4/4/2011).
                                                                         2
Publication Highlights
•   Raffi Khatchadourian, Phil Greenwood, Awais Rashid, and Guoqing Xu.
    Pointcut rejuvenation: Recovering pointcut expressions in evolving
    aspect-oriented software. IEEE Transactions on Software Engineering,
    99(PrePrints), 2011. ISSN 0098-5589.
•   Raffi Khatchadourian, Phil Greenwood, Awais Rashid, and Guoqing Xu.
    Pointcut rejuvenation: Recovering pointcut expressions in evolving
    aspect-oriented software. In Proceedings of the 24th International Conference
    on Automated Software Engineering (ASE ’09), pages 575–579, Auckland, New
    Zealand, November 2009. IEEE/ACM.
•   Raffi Khatchadourian, Johan Dovland, and Neelam Soundarajan. Enforcing
    behavioral constraints in evolving aspect-oriented programs. In
    Proceedings of the 7th International Workshop on Foundations of Aspect-
    Oriented Languages (FOAL ’08) at the 7th International Conference on Aspect-
    Oriented Software Development (AOSD ’08), pages 19–28, Brussels, Belgium, April
    2008. ACM.
•   Raffi Khatchadourian, Jason Sawin, and Atanas Rountev. Automated
    refactoring of legacy Java software to enumerated types. In Proceedings
    of the 23rd International Conference on Software Maintenance (ICSM ’07),
    pages 224–233, Paris, France, October 2007. IEEE.
•   Peer-reviewed totals (2005-): 1 paper to appear in a journal, 5 papers appearing in
    conference proceedings, and 5 papers appearing in workshop proceedings.           3
Activity Highlights

• Helped develop new Applied Software Engineering course ECE/CSE 668
  based on Challenge-X hybrid SUV automobile simulation at OSU CAR
  in 2006.
• Summer intern at Bell Labs under Rick Hull and Kedar Namjoshi
  (program language design for shared-experience, multimedia, multi-
  protocol, event-driven applications) in 2007.
• Visiting Graduate Research Associate with the Aspect-Oriented Software
  Engineering (AOSE) Group at the Computing Department of Lancaster
  University, UK under Awais Rashid in 2008.
• Visiting Researcher with the Programming Principles and Practices
  (PPP) Group at the Department of Graphics and Computer Science of the
  University of Tokyo under Hidehiko Masuhara in 2010.
• Proposed project mentor for Google Summer of Code (GSoC) in 2009
  and 2010. Project based on refactoring to enumerated types in Java.
• Organizing committee member (Web Chair) for the European
  Conference on Object-Oriented Programming (ECOOP).
                                                                        4
Award Highlights



• Japan Society for the Promotion of Science
 (JSPS) Summer Program Fellowship Recipient in
 2010.
• National Science Foundation (NSF) East Asia
 and Pacific Summer Institutes (EAPSI) Award
 Recipient in 2010.
• Ohio State University Department of Computer
 Science & Engineering Graduate Teaching Award
 Recipient in 2010.

                                                 5
Motivation




        6
Motivation




• Software changes over
  time:




                                  6
Motivation




• Software changes over
  time:

 • Requirements evolve




                                  6
Motivation




• Software changes over
  time:

 • Requirements evolve
 • New platforms emerge
    (e.g., mobile devices)




                                     6
Motivation




• Software changes over
  time:

 • Requirements evolve
 • New platforms emerge
    (e.g., mobile devices)

 • Frameworks change
    (e.g., XML vs.
    annotation-based)


                                     6
Motivation




        7
Motivation



Changing and/or maintaining large, complex software
systems can be non-trivial:
      Tedious: May require changing many lines of
               code.
 Error-prone: Changes may be implemented
              incorrectly.
    Omission- May opportunities to produce better
      prone: code.


                                                      7
Motivation



Changing and/or maintaining large, complex software
systems can be non-trivial:
      Tedious: May require changing many lines of
               code.
 Error-prone: Changes may be implemented
              incorrectly.
    Omission- May opportunities to produce better
      prone: code.


                                                      7
Motivation


                                       Adding a
                                    parameter to a
Changing and/or maintaining large, complex software
systems can be non-trivial:            method
      Tedious: May require changing many lines of
               code.
 Error-prone: Changes may be implemented
              incorrectly.
    Omission- May opportunities to produce better
      prone: code.


                                                      7
Motivation



Changing and/or maintaining large, complex software
systems can be non-trivial:
      Tedious: May require changing many lines of
               code.
 Error-prone: Changes may be implemented
              incorrectly.
    Omission- May opportunities to produce better
      prone: code.


                                                      7
Motivation



      Removing a
Changing and/or maintaining large, complex software
systemsparameter may
method can be non-trivial:
  alter overloading to
        Tedious: May require changing many lines of
        overriding
                   code.
 Error-prone: Changes may be implemented
              incorrectly.
    Omission- May opportunities to produce better
      prone: code.


                                                      7
Motivation



Changing and/or maintaining large, complex software
systems can be non-trivial:
      Tedious: May require changing many lines of
               code.
 Error-prone: Changes may be implemented
              incorrectly.
    Omission- May opportunities to produce better
      prone: code.


                                                      7
Motivation



Changing and/or maintaining large, complex software
systems can be non-trivial:
     Tedious: May require changing many lines of
              code.
                                  HashTable vs.
 Error-prone: Changes may be implemented
              incorrectly.          HashMap

    Omission- May opportunities to produce better
      prone: code.


                                                      7
Motivation



Changing and/or maintaining large, complex software
systems can be non-trivial:
      Tedious: May require changing many lines of
               code.
 Error-prone: Changes may be implemented
              incorrectly.
    Omission- May opportunities to produce better
      prone: code.


                                                      7
Approach




      8
Approach




• Approaches made to
  provide mechanical
  assistance in evolution
  tasks.




                                  8
Approach




• Approaches made to
  provide mechanical
  assistance in evolution
  tasks.

• Typically in the form of
  plug-ins to IDEs.




                                   8
Approach




• Approaches made to
  provide mechanical
  assistance in evolution
  tasks.

• Typically in the form of
  plug-ins to IDEs.

• Ease the burden of
  software maintenance
  and evolution.



                                   8
Approach


                                  Restrict
                             workspace to only
• Approaches made to         displays elements
  provide mechanical          relevant to the
  assistance in evolution           task
  tasks.

• Typically in the form of
  plug-ins to IDEs.

• Ease the burden of
  software maintenance
  and evolution.



                                                 8
Approach


                                  Restrict
                             workspace to only
• Approaches made to         displays elements
  provide mechanical          relevant to the
  assistance in evolution           task
  tasks.

• Typically in the form of
  plug-ins to IDEs.
       Restructure
•code the burden of
  Ease while preserving
      semantics (i.e.,
  software maintenance
  and evolution.
        refactoring)

                                                 8
Thesis Outline




            9
Thesis Outline




• For my thesis, I have pursed three directions:




                                                      9
Thesis Outline




• For my thesis, I have pursed three directions:
 1. Mechanically alleviate burden of fragile pointcuts in
    Aspect-Oriented software.




                                                       9
Thesis Outline




• For my thesis, I have pursed three directions:
 1. Mechanically alleviate burden of fragile pointcuts in
    Aspect-Oriented software.
 2.Automatically refactor legacy Java software to
   language enumerated (enum) types.




                                                       9
Thesis Outline




• For my thesis, I have pursed three directions:
 1. Mechanically alleviate burden of fragile pointcuts in
    Aspect-Oriented software.
 2.Automatically refactor legacy Java software to
   language enumerated (enum) types.
 3.Robustly specify evolving Aspect-Oriented software
   components.


                                                       9
Crosscutting Concerns


/*                                                                                              public void invalidate() {                                                          ;                                                                                                                                                                 * Remove the object bound with the specified name from this session. If
 * ====================================================================                                 serverSession.removeApplicationSession(context);                                                                                                                                                                                                   * the session does not have an object bound with this name, this method
 *                                                                                                                                                                                                                                                                                                                                                         * does nothing.
 * The Apache Software License, Version 1.1                                                                   // remove everything in the session                                   /**                                                                                                                                                                    * <p>
 *                                                                                                                                                                                   * Standard implementation of the <b>Session</b> interface. This object is                                                                                             * After this method executes, and if the object implements
 * Copyright (c) 1999 The Apache Software Foundation. All rights                                              Enumeration enum = values.keys();                                      * serializable, so that it can be stored in persistent storage or transferred                                                                                         * <code>HttpSessionBindingListener</code>, the container calls
 * reserved.                                                                                                  while (enum.hasMoreElements()) {                                       * to a different JVM for distributable session support.                                                                                                               * <code>valueUnbound()</code> on the object.
 *                                                                                                                String name = (String)enum.nextElement();                          * <p>                                                                                                                                                                 *
 * Redistribution and use in source and binary forms, with or without                                             removeValue(name);                                                 * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the                                                                                           * @param name Name of the object to remove from this session.
 * modification, are permitted provided that the following conditions                                         }                                                                      * internal (Session) and application level (HttpSession) view of the session.                                                                                         *
 * are met:                                                                                                                                                                          * However, because the class itself is not declared public, Java logic outside                                                                                        * @exception IllegalStateException if this method is called on an
 *                                                                                                            valid = false;                                                         * of the <code>org.apache.tomcat.session</code> package cannot cast an                                                                                                * invalidated session
 * 1. Redistributions of source code must retain the above copyright                                   }                                                                             * HttpSession view of this instance back to a Session view.                                                                                                           */
 *    notice, this list of conditions and the following disclaimer.                                                                                                                  *                                                                                                                                                                    public void removeAttribute(String name) {
 *                                                                                                     public boolean isNew() {                                                      * @author Craig R. McClanahan
 * 2. Redistributions in binary form must reproduce the above copyright                                    if (! valid) {                                                            * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $                                                                                                                 synchronized (attributes) {
 *    notice, this list of conditions and the following disclaimer in                                          String msg = sm.getString("applicationSession.session.ise");          */                                                                                                                                                                           Object object = attributes.get(name);
 *    the documentation and/or other materials provided with the                                                                                                                                                                                                                                                                                                  if (object == null)
 *    distribution.                                                                                               throw new IllegalStateException(msg);                             final class StandardSession                                                                                                                                                       return;
 *                                                                                                            }                                                                         implements HttpSession, Session {                                                                                                                                         attributes.remove(name);
 * 3. The end-user documentation included with the redistribution, if                                                                                                                                                                                                                                                                                             //      System.out.println( "Removing attribute " + name );
 *    any, must include the following acknowledgment:                                                         if (thisAccessTime == creationTime) {                                                                                                                     /**                                                                                       if (object instanceof HttpSessionBindingListener) {
 *       "This product includes software developed by the                                                         return true;                                                            // ----------------------------------------------------------- Constructors    * Update the accessed time information for this session. This method                         ((HttpSessionBindingListener) object).valueUnbound
 *        Apache Software Foundation (http://www.apache.org/)."                                               } else {                                                                                                                                                   * should be called by the context when a request comes in for a particular                       (new HttpSessionBindingEvent((HttpSession) this, name));
 *    Alternately, this acknowledgment may appear in the software                                                 return false;                                                                                                                                          * session, even if the application does not reference it.                                }
itself,                                                                                                       }                                                                           /**                                                                            */                                                                                   }
 *    if and wherever such third-party acknowledgments normally appear.                                }                                                                                   * Construct a new Session associated with the specified Manager.             public void access() {
 *                                                                                                                                                                                         *                                                                                                                                                              }
 * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software                                                                                                                      * @param manager The manager with which this Session is associated                 this.lastAccessedTime = this.thisAccessedTime;
 *    Foundation" must not be used to endorse or promote products                               /**                                                                                        */                                                                                 this.thisAccessedTime = System.currentTimeMillis();                     * Bind an object to this session, using the specified name. If an object
derived                                                                                                    * @deprecated                                                                  public StandardSession(Manager manager) {                                           this.isNew=false;                                                            * of the same name is already bound to this session, the object is
 *    from this software without prior written permission. For written                                     */                                                                                                                                                           }                                                                                  * replaced.
 *    permission, please contact apache@apache.org.                                                                                                                                           super();                                                                                                                                                     * <p>
 *                                                                                                     public void putValue(String name, Object value) {                                      this.manager = manager;                                                                                                                                      * After this method executes, and if the object implements
 * 5. Products derived from this software may not be called "Apache"                                       setAttribute(name, value);                                                                                                                                   /**                                                                                * <code>HttpSessionBindingListener</code>, the container calls
 *    nor may "Apache" appear in their names without prior written                                     }                                                                                  }                                                                              * Perform the internal processing required to invalidate this session,            * <code>valueBound()</code> on the object.
 *    permission of the Apache Group.                                                                                                                                                                                                                                    * without triggering an exception if the session has already expired.             *
 *                                                                                                     public void setAttribute(String name, Object value) {                                                                                                             */                                                                                * @param name Name to which the object is bound, cannot be null
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED                                        if (! valid) {                                                           /**                                                                                 public void expire() {                                                             * @param value Object to be bound, cannot be null
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES                                           String msg = sm.getString("applicationSession.session.ise");                * The last accessed time for this Session.                                                                                                                      *
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                                                                                                                             */                                                                                 // Remove this session from our manager's active sessions                    * @exception IllegalArgumentException if an attempt is made to add a
 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR                                                throw new IllegalStateException(msg);                                   private long lastAccessedTime = creationTime;                                       if ((manager != null) && (manager instanceof ManagerBase))                   * non-serializable object in an environment marked distributable.
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,                                           }                                                                                                                                                                   ((ManagerBase) manager).remove(this);                                    * @exception IllegalStateException if this method is called on an
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT                                                                                                                                                                                                                                                                                        * invalidated session
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF                                           if (name == null) {                                                         /**                                                                                 // Unbind any objects associated with this session                           */
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND                                            String msg = sm.getString("applicationSession.value.iae");               * The Manager with which this Session is associated.                               Vector results = new Vector();                                              public void setAttribute(String name, Object value) {
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,                                                                                                                      */                                                                                 Enumeration attrs = getAttributeNames();
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT                                             throw new IllegalArgumentException(msg);                                private Manager manager = null;                                                     while (attrs.hasMoreElements()) {                                               if ((manager != null) && manager.getDistributable() &&
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF                                         }                                                                                                                                                                   String attr = (String) attrs.nextElement();                                   !(value instanceof Serializable))
 * SUCH DAMAGE.                                                                                                                                                                                                                                                                   results.addElement(attr);                                                       throw new IllegalArgumentException
 * ====================================================================                                       removeValue(name);     // remove any existing binding                       /**                                                                                 }                                                                                       (sm.getString("standardSession.setAttribute.iae"));
 *                                                                                                                                                                                         * The maximum time interval, in seconds, between client requests before            Enumeration names = results.elements();
 * This software consists of voluntary contributions made by many                                             if (value != null && value instanceof HttpSessionBindingListener) {          * the servlet container may invalidate this session. A negative time               while (names.hasMoreElements()) {                                               synchronized (attributes) {
 * individuals on behalf of the Apache Software Foundation. For more                                              HttpSessionBindingEvent e =                                              * indicates that the session should never time out.                                    String name = (String) names.nextElement();                                     removeAttribute(name);
 * information on the Apache Software Foundation, please see                                                          new HttpSessionBindingEvent(this, name);                             */                                                                                     removeAttribute(name);                                                          attributes.put(name, value);
 * <http://www.apache.org/>.                                                                                                                                                              private int maxInactiveInterval = -1;                                               }                                                                                   if (value instanceof HttpSessionBindingListener)
 *                                                                                                                ((HttpSessionBindingListener)value).valueBound(e);                                                                                                                                                                                                  ((HttpSessionBindingListener) value).valueBound
 * [Additional notices, if required by prior licensing conditions]                                            }                                                                                                                                                               // Mark this session as invalid                                                             (new HttpSessionBindingEvent((HttpSession) this, name));
 *                                                                                                                                                                                        /**                                                                                 setValid(false);                                                                }
 */                                                                                                           values.put(name, value);                                                     * Flag indicating whether this session is new or not.
                                                                                                       }                                                                                   */                                                                           }                                                                                 }
                                                                                                                                                                                          private boolean isNew = true;
                                                                                                       /**
package org.apache.tomcat.session;                                                                       * @deprecated                                                                                                                                                  /**                                                                               // -------------------------------------------- HttpSession Private Methods
                                                                                                         */                                                                               /**
import org.apache.tomcat.core.*;                                                                       public Object getValue(String name) {                                               * Flag indicating whether this session is valid or not.                      }
import org.apache.tomcat.util.StringManager;                                                                return getAttribute(name);                                                     */                                                                                                                                                             /**
import java.io.*;                                                                                      }                                                                                  private boolean isValid = false;                                                                                                                                 * Read a serialized version of this session object from the specified
import java.net.*;                                                                                                                                                                                                                                                      /**                                                                                * object input stream.
import java.util.*;                                                                                    public Object getAttribute(String name) {                                                                                                                         * Set the <code>isNew</code> flag for this session.                               * <p>
import javax.servlet.*;                                                                                    if (! valid) {                                                                 /**                                                                            *                                                                                 * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager
import javax.servlet.http.*;                                                                                   String msg = sm.getString("applicationSession.session.ise");                * The string manager for this package.                                        * @param isNew The new value for the <code>isNew</code> flag                      * is not restored by this method, and must be set explicitly.
                                                                                                                                                                                           */                                                                            */                                                                                *
/**                                                                                                               throw new IllegalStateException(msg);                                   private StringManager sm =                                                    void setNew(boolean isNew) {                                                       * @param stream The input stream to read from
 * Core implementation of an application level session                                                        }                                                                               StringManager.getManager("org.apache.tomcat.session");                                                                                                       *
 *                                                                                                                                                                                                                                                                            this.isNew = isNew;                                                          * @exception ClassNotFoundException if an unknown class is specified
 * @author James Duncan Davidson [duncan@eng.sun.com]                                                         if (name == null) {                                                                                                                                                                                                                          * @exception IOException if an input/output error occurs
 * @author Jason Hunter [jch@eng.sun.com]                                                                         String msg = sm.getString("applicationSession.value.iae");              /**                                                                           }                                                                                  */
 * @author James Todd [gonzo@eng.sun.com]                                                                                                                                                  * The HTTP session context associated with this session.                                                                                                       private void readObject(ObjectInputStream stream)
 */                                                                                                               throw new IllegalArgumentException(msg);                                 */                                                                                                                                                                 throws ClassNotFoundException, IOException {
                                                                                                              }                                                                           private static HttpSessionContext sessionContext = null;                      /**
public class ApplicationSession implements HttpSession {                                                                                                                                                                                                                 * Set the <code>isValid</code> flag for this session.                                // Deserialize the scalar instance variables (except Manager)
                                                                                                              return values.get(name);                                                                                                                                   *                                                                                    creationTime = ((Long) stream.readObject()).longValue();
    private StringManager sm =                                                                         }                                                                                  /**                                                                            * @param isValid The new value for the <code>isValid</code> flag                     id = (String) stream.readObject();
        StringManager.getManager("org.apache.tomcat.session");                                                                                                                             * The current accessed time for this session.                                 */                                                                                   lastAccessedTime = ((Long) stream.readObject()).longValue();
    private Hashtable values = new Hashtable();                                                        /**                                                                                 */                                                                           void setValid(boolean isValid) {                                                      maxInactiveInterval = ((Integer) stream.readObject()).intValue();
    private String id;                                                                                  * @deprecated                                                                     private long thisAccessedTime = creationTime;                                                                                                                       isNew = ((Boolean) stream.readObject()).booleanValue();
    private ServerSession serverSession;                                                                */                                                                                                                                                                    this.isValid = isValid;                                                         isValid = ((Boolean) stream.readObject()).booleanValue();
    private Context context;                                                                           public String[] getValueNames() {                                                                                                                                }
    private long creationTime = System.currentTimeMillis();;                                               Enumeration e = getAttributeNames();                                                                                                                                                                                                               // Deserialize the attribute count and attribute values
    private long thisAccessTime = creationTime;                                                            Vector names = new Vector();                                                                                                                                                                                                                       int n = ((Integer) stream.readObject()).intValue();
    private long lastAccessed = creationTime;                                                                                                                                             // ----------------------------------------------------- Session Properties   // ------------------------------------------------- HttpSession Properties           for (int i = 0; i < n; i++) {
    private int inactiveInterval = -1;                                                                        while (e.hasMoreElements()) {                                                                                                                                                                                                                       String name = (String) stream.readObject();
    private boolean valid = true;                                                                                 names.addElement(e.nextElement());                                                                                                                                                                                                              Object value = (Object) stream.readObject();
                                                                                                              }                                                                           /**                                                                           /**                                                                                       attributes.put(name, value);
    ApplicationSession(String id, ServerSession serverSession,                                                                                                                             * Set the creation time for this session. This method is called by the        * Return the time when this session was created, in milliseconds since               }
        Context context) {                                                                                    String[] valueNames = new String[names.size()];                              * Manager when an existing Session instance is reused.                        * midnight, January 1, 1970 GMT.
        this.serverSession = serverSession;                                                                                                                                                *                                                                             *                                                                                }
        this.context = context;                                                                               names.copyInto(valueNames);                                                  * @param time The new creation time                                           * @exception IllegalStateException if this method is called on an
        this.id = id;                                                                                                                                                                      */                                                                            * invalidated session
                                                                                                              return valueNames;                                                          public void setCreationTime(long time) {                                       */                                                                               /**
        this.inactiveInterval = context.getSessionTimeOut();                                                                                                                                                                                                            public long getCreationTime() {                                                    * Write a serialized version of this session object to the specified
                                                                                                       }                                                                                      this.creationTime = time;                                                                                                                                    * object output stream.
        if (this.inactiveInterval != -1) {                                                                                                                                                    this.lastAccessedTime = time;                                                   return (this.creationTime);                                                  * <p>
            this.inactiveInterval *= 60;                                                               public Enumeration getAttributeNames() {                                               this.thisAccessedTime = time;                                                                                                                                * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored
        }                                                                                                  if (! valid) {                                                                                                                                               }                                                                                  * in the serialized representation of this Session. After calling
    }                                                                                                          String msg = sm.getString("applicationSession.session.ise");                                                                                                                                                                                * <code>readObject()</code>, you must set the associated Manager
                                                                                                                                                                                                                                                                                                                                                           * explicitly.
    ServerSession getServerSession() {                                                                            throw new IllegalStateException(msg);                                                                                                                 /**                                                                                * <p>
        return serverSession;                                                                                 }                                                                                                                                                          * Return the session context with which this session is associated.               * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable
    }                                                                                                                                                                                                                                                                    *                                                                                 * will be silently ignored. If you do not want any such attributes,
                                                                                                              Hashtable valuesClone = (Hashtable)values.clone();                                                                                                         * @deprecated As of Version 2.1, this method is deprecated and has no             * be sure the <code>distributable</code> property of our associated
    /**                                                                                                                                                                                                                                                                  * replacement. It will be removed in a future version of the                      * Manager is set to <code>true</code>.
     * Called by context when request comes in so that accesses and                                           return (Enumeration)valuesClone.keys();                                                                                                                    * Java Servlet API.                                                               *
     * inactivities can be dealt with accordingly.                                                     }                                                                                                                                                                 */                                                                                * @param stream The output stream to write to
     */                                                                                                                                                                                                                                                                 public HttpSessionContext getSessionContext() {                                    *
                                                                                                                                                                                                                                                                                                                                                           * @exception IOException if an input/output error occurs
    void accessed() {                                                                            /**                                                                                                                                                                          if (sessionContext == null)                                                  */
        // set last accessed to thisAccessTime as it will be left over                                     * @deprecated                                                                                                                                                          sessionContext = new StandardSessionContext();                          private void writeObject(ObjectOutputStream stream) throws IOException {
        // from the previous access                                                                        */                                                                                                                                                                 return (sessionContext);
        lastAccessed = thisAccessTime;                                                                                                                                                                                                                                                                                                                        // Write the scalar instance variables (except Manager)
        thisAccessTime = System.currentTimeMillis();                                                   public void removeValue(String name) {                                                                                                                           }                                                                                     stream.writeObject(new Long(creationTime));
                                                                                                           removeAttribute(name);                                                                                                                                                                                                                             stream.writeObject(id);
        validate();                                                                                    }                                                                                                                                                                                                                                                      stream.writeObject(new Long(lastAccessedTime));
    }                                                                                                                                                                                                                                                                   // ----------------------------------------------HttpSession Public Methods           stream.writeObject(new Integer(maxInactiveInterval));
                                                                                                       public void removeAttribute(String name) {                                                                                                                                                                                                             stream.writeObject(new Boolean(isNew));
    void validate() {                                                                                      if (! valid) {                                                                 }                                                                                                                                                                   stream.writeObject(new Boolean(isValid));
        // if we have an inactive interval, check to see if we've exceeded it                                  String msg = sm.getString("applicationSession.session.ise");                                                                                             /**
        if (inactiveInterval != -1) {                                                                                                                                                                                                                                    * Return the object bound with the specified name in this session, or                // Accumulate the names of serializable attributes
            int thisInterval =                                                                                    throw new IllegalStateException(msg);                                                                                                                  * <code>null</code> if no object is bound with that name.                            Vector results = new Vector();
                (int)(System.currentTimeMillis() - lastAccessed) / 1000;                                      }                                                                                                                                                          *                                                                                    Enumeration attrs = getAttributeNames();
                                                                                                                                                                                                                                                                         * @param name Name of the attribute to be returned                                   while (attrs.hasMoreElements()) {
            if (thisInterval > inactiveInterval) {                                                            if (name == null) {                                                                                                                                        *                                                                                        String attr = (String) attrs.nextElement();
                invalidate();                                                                                     String msg = sm.getString("applicationSession.value.iae");                                                                                             * @exception IllegalStateException if this method is called on an                        Object value = attributes.get(attr);
            }                                                                                                                                                                                                                                                            * invalidated session                                                                    if (value instanceof Serializable)
        }                                                                                                         throw new IllegalArgumentException(msg);                                                                                                               */                                                                                           results.addElement(attr);
    }                                                                                                         }                                                                                                                                                         public Object getAttribute(String name) {                                             }

    // HTTP SESSION IMPLEMENTATION METHODS                                                                    Object o = values.get(name);                                                                                                                                    return (attributes.get(name));                                                  // Serialize the attribute count and the attribute values
                                                                                                                                                                                                                                                                                                                                                              stream.writeObject(new Integer(results.size()));
    public String getId() {                                                                                   if (o instanceof HttpSessionBindingListener) {                                                                                                            }                                                                                     Enumeration names = results.elements();
        if (valid) {                                                                                              HttpSessionBindingEvent e =                                                                                                                                                                                                                 while (names.hasMoreElements()) {
            return id;                                                                                                new HttpSessionBindingEvent(this,name);                                                                                                                                                                                                     String name = (String) names.nextElement();
        } else {                                                                                                                                                                                                                                                        /**                                                                                       stream.writeObject(name);
            String msg = sm.getString("applicationSession.session.ise");                                          ((HttpSessionBindingListener)o).valueUnbound(e);                                                                                                       * Return an <code>Enumeration</code> of <code>String</code> objects                      stream.writeObject(attributes.get(name));
                                                                                                              }                                                                                                                                                          * containing the names of the objects bound to this session.                         }
            throw new IllegalStateException(msg);                                                                                                                                                                                                                        *
        }                                                                                                     values.remove(name);                                                                                                                                       * @exception IllegalStateException if this method is called on an
    }                                                                                                  }                                                                                                                                                                 * invalidated session                                                            }
                                                                                                                                                                                                                                                                         */
    public long getCreationTime() {                                                                    public void setMaxInactiveInterval(int interval) {                                                                                                               public Enumeration getAttributeNames() {                                          crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() |
        if (valid) {                                                                                       if (! valid) {                                                                                                                                                                                                                                                                              long getCreationTime() |
            return creationTime;                                                                               String msg = sm.getString("applicationSession.session.ise");                                                                                                   return (attributes.keys());                                                                                              Object getAttribute(String) |
        } else {                                                                                                                                                                                                                                                                                                                                                                                       Enumeration getAttributeNames() |
            String msg = sm.getString("applicationSession.session.ise");                                          throw new IllegalStateException(msg);                                                                                                                 }                                                                                                                              String[] getValueNames() |
                                                                                                              }                                                                                                                                                                                                                                                                                        void invalidate() |
            throw new IllegalStateException(msg);                                                                                                                                                                                                                                                                                                                                                      boolean isNew() |
        }                                                                                                                                                                                                                                                               /**                                                                                                                            void removeAttribute(String) |
    }                                                                                                                                                                                                                                                                    * Return the object bound with the specified name in this session, or                                                         void setAttribute(String, Object));
                                                                                                                                                                                                                                                                         * <code>null</code> if no object is bound with that name.
    /**                                                                                                                                                                                                                                                                  *                                                                                static advice(StandardSession s): invalidate(s) {
     *                                                                                                                                                                                                                                                                   * @param name Name of the value to be returned                                       before {
     * @deprecated                                                                                                                                                                                                                                                       *                                                                                        if (!s.isValid())
                                                                                                                                                                                                                                                                         * @exception IllegalStateException if this method is called on an                             throw new IllegalStateException
                                                                                                                                                                                                                                                                         * invalidated session                                                                             (s.sm.getString("standardSession."
                                                                                                                                                                                                                                                                         *                                                                                                                 + thisJoinPoint.methodName
                                                                                                                                                                                                                                                                         * @deprecated As of Version 2.2, this method is replaced by                                                       + ".ise"));
                                                                                                                                                                                                                                                                         * <code>getAttribute()</code>                                                        }
                                                                                                                                                                                                                                                                         */                                                                               }
                                                                                                                                                                                          /**                                                                           public Object getValue(String name) {
                                                                                                                                                                                           * Return the session identifier for this session.
                                                                                                                                                                                           */                                                                                 return (getAttribute(name));
                                                                                                                                                                                          public String getId() {
                                                                                                                                                                                                                                                                        }                                                                             }


                                                                                                                                                                                                                                                                        /**                                                                           // -------------------------------------------------------------- Private Class
                                                                                                                                                                                                                                                                         * Return the set of names of objects bound to this session. If there
                                                                                                                                                                                                                                                                         * are no such objects, a zero-length array is returned.
                                                                                                                                                                                                                                                                         *                                                                            /**
                                                                                                                                                                                                                                                                         * @exception IllegalStateException if this method is called on an             * This class is a dummy implementation of the <code>HttpSessionContext</code>
                                                                                                                                                                                                                                                                         * invalidated session                                                         * interface, to conform to the requirement that such an object be returned
                                                                                                                                                                                                                                                                         *                                                                             * when <code>HttpSession.getSessionContext()</code> is called.
                                                                                                                                                                                                                                                                         * @deprecated As of Version 2.2, this method is replaced by                   *
                                                                                                                                                                                                                                                                         * <code>getAttributeNames()</code>                                            * @author Craig R. McClanahan
                                                                                                                                                                                                                                                                         */                                                                            *
                                                                                                                                                                                                                                                                        public String[] getValueNames() {                                              * @deprecated As of Java Servlet API 2.1 with no replacement. The
                                                                                                                                                                                                                                                                                                                                                       * interface will be removed in a future version of this API.
                                                                                                                                                                                                                                                                              Vector results = new Vector();                                           */
                                                                                                                                                                                                                                                                              Enumeration attrs = getAttributeNames();
                                                                                                                                                                                                                                                                              while (attrs.hasMoreElements()) {                                       final class StandardSessionContext implements HttpSessionContext {
                                                                                                                                                                                                                                                                                  String attr = (String) attrs.nextElement();
                                                                                                                                                                                                                                                                                  results.addElement(attr);
                                                                                                                                                                                                                                                                              }                                                                           private Vector dummy = new Vector();
                                                                                                                                                                                              return (this.id);                                                               String names[] = new String[results.size()];
                                                                                                                                                                                                                                                                              for (int i = 0; i < names.length; i++)                                      /**
                                                                                                                                                                                                                                                                                  names[i] = (String) results.elementAt(i);                                * Return the session identifiers of all sessions defined
                                                                                                                                                                                                                                                                              return (names);                                                              * within this context.
                                                                                                                                                                                                                                                                                                                                                           *
                                                                                                                                                                                                                                                                        }                                                                                  * @deprecated As of Java Servlet API 2.1 with no replacement.
                                                                                                                                                                                                                                                                                                                                                           * This method must return an empty <code>Enumeration</code>
                                                                                                                                                                                                                                                                                                                                                           * and will be removed in a future version of the API.
                                                                                                                                                                                                                                                                        /**                                                                                */
                                                                                                                                                                                                                                                                         * Invalidates this session and unbinds any objects bound to it.                  public Enumeration getIds() {
                                                                                                                                                                                                                                                                         *
                                                                                                                                                                                                                                                                         * @exception IllegalStateException if this method is called on                       return (dummy.elements());
                                                                                                                                                                                                                                                                         * an invalidated session
                                                                                                                                                                                                                                                                         */
                                                                                                                                                                                                                                                                        public void invalidate() {

                                                                                                                                                                                                                                                                              // Cause this session to expire
                                                                                                                                                                                                                                                                              expire();

                                                                                                                                                                                                                                                                        }


                                                                                                                                                                                          }                                                                             /**
                                                                                                                                                                                                                                                                         * Return <code>true</code> if the client does not yet know about the
                                                                                                                                                                                                                                                                         * session, or if the client chooses not to join the session. For
                                                                                                                                                                                                                                                                         * example, if the server used only cookie-based sessions, and the client
                                                                                                                                                                                                                                                                         * has disabled the use of cookies, then a session would be new on each
                                                                                                                                                                                                                                                                         * request.
                                                                                                                                                                                                                                                                         *
                                                                                                                                                                                                                                                                         * @exception IllegalStateException if this method is called on an
                                                                                                                                                                                                                                                                         * invalidated session
                                                                                                                                                                                                                                                                         */
                                                                                                                                                                                                                                                                        public boolean isNew() {

                                                                                                                                                                                                                                                                              return (this.isNew);

                                                                                                                                                                                                                                                                        }




package org.apache.tomcat.session;                                              void validate() {
                                                                                        // if we have an inactive interval, check to see if
import org.apache.tomcat.core.*;                                                        // we've exceeded it
import org.apache.tomcat.util.StringManager;
import java.io.*;                                                                       if (inactiveInterval != -1) {
import java.net.*;                                                                          int thisInterval =
import java.util.*;                                                                             (int)(System.currentTimeMillis() - lastAccessed) / 1000;
import javax.servlet.*;
import javax.servlet.http.*;                                                                if (thisInterval > inactiveInterval) {
                                                                                                invalidate();
/**
 * Core implementation of a server session                                                       ServerSessionManager ssm =
 *                                                                                                   ServerSessionManager.getManager();
 * @author James Duncan Davidson [duncan@eng.sun.com]
 * @author James Todd [gonzo@eng.sun.com]                                                        ssm.removeSession(this);
 */                                                                                         }
                                                                                        }
public class ServerSession {                                                        }

    private StringManager sm =                                                      synchronized void invalidate() {
        StringManager.getManager("org.apache.tomcat.session");                          Enumeration enum = appSessions.keys();                                                            /**
    private Hashtable values = new Hashtable();                                                                                                                                            * Set the session identifier for this session.
    private Hashtable appSessions = new Hashtable();                                    while (enum.hasMoreElements()) {                                                                   *
    private String id;                                                                      Object key = enum.nextElement();                                                               * @param id The new session identifier
    private long creationTime = System.currentTimeMillis();;                                ApplicationSession appSession =                                                                */
    private long thisAccessTime = creationTime;                                                 (ApplicationSession)appSessions.get(key);                                                 public void setId(String id) {
    private long lastAccessed = creationTime;
    private int inactiveInterval = -1;                                                      appSession.invalidate();
                                                                                        }
    ServerSession(String id) {                                                      }
        this.id = id;
    }                                                                               public void putValue(String name, Object value) {
                                                                                        if (name == null) {
    public String getId() {                                                                 String msg = sm.getString("serverSession.value.iae");
        return id;
    }                                                                                       throw new IllegalArgumentException(msg);
                                                                                        }
    public long getCreationTime() {
        return creationTime;                                                            removeValue(name); // remove any existing binding
    }                                                                                   values.put(name, value);
                                                                                    }
    public long getLastAccessedTime() {
        return lastAccessed;                                                        public Object getValue(String name) {
    }                                                                                   if (name == null) {
                                                                                            String msg = sm.getString("serverSession.value.iae");
    public ApplicationSession getApplicationSession(Context context,
        boolean create) {                                                                   throw new IllegalArgumentException(msg);
        ApplicationSession appSession =                                                 }                                                                                                     if ((this.id != null) && (manager != null) &&
            (ApplicationSession)appSessions.get(context);                                                                                                                                       (manager instanceof ManagerBase))
                                                                                        return values.get(name);                                                                                  ((ManagerBase) manager).remove(this);
        if (appSession == null && create) {                                         }

            // XXX                                                                  public Enumeration getValueNames() {
            // sync to ensure valid?                                                    return values.keys();
                                                                                    }
            appSession = new ApplicationSession(id, this, context);
            appSessions.put(context, appSession);                                   public void removeValue(String name) {
        }                                                                               values.remove(name);
                                                                                    }
        // XXX
        // make sure that we haven't gone over the end of our                       public void setMaxInactiveInterval(int interval) {
        // inactive interval -- if so, invalidate and create                            inactiveInterval = interval;
        // a new appSession                                                         }

        return appSession;                                                          public int getMaxInactiveInterval() {
    }                                                                                   return inactiveInterval;
                                                                                    }
    void removeApplicationSession(Context context) {
        appSessions.remove(context);                                                // XXX
    }                                                                               // sync'd for safty -- no other thread should be getting something
                                                                                    // from this while we are reaping. This isn't the most optimal
    /**                                                                             // solution for this, but we'll determine something else later.                                           this.id = id;
     * Called by context when request comes in so that accesses and
     * inactivities can be dealt with accordingly.                                  synchronized void reap() {
     */                                                                                 Enumeration enum = appSessions.keys();

    void accessed() {                                                                   while (enum.hasMoreElements()) {
        // set last accessed to thisAccessTime as it will be left over




                                                                                                                                                                                              if ((manager != null) && (manager instanceof ManagerBase))
                                                                                                                                                                                                  ((ManagerBase) manager).add(this);




                                                                                                                                                                                          }




                                                                                                                                                                                          /**
                                                                                                                                                                                           * Return descriptive information about this Session implementation and
                                                                                                                                                                                           * the corresponding version number, in the format
                                                                                                                                                                                           * <code>&lt;description&gt;/&lt;version&gt;</code>.
                                                                                                                                                                                           */
                                                                                                                                                                                          public String getInfo() {




                                                                                                                                                                                              return (this.info);




                                                                                                                                                                                          }




                                                                                                                                                                                          /**
                                                                                                                                                                                           * Return the last time the client sent a request associated with this
                                                                                                                                                                                           * session, as the number of milliseconds since midnight, January 1, 1970
                                                                                                                                                                                           * GMT. Actions that your application takes, such as getting or setting
                                                                                                                                                                                           * a value associated with the session, do not affect the access time.
                                                                                                                                                                                           */
                                                                                                                                                                                          public long getLastAccessedTime() {

                                                                                                                                                                                              return (this.lastAccessedTime);

                                                                                                                                                                                          }


                                                                                                                                                                                          /**
                                                                                                                                                                                           * Return the Manager within which this Session is valid.
                                                                                                                                                                                           */
                                                                                                                                                                                          public Manager getManager() {

                                                                                                                                                                                              return (this.manager);

                                                                                                                                                                                          }


                                                                                                                                                                                          /**
                                                                                                                                                                                           * Set the Manager within which this Session is valid.
                                                                                                                                                                                           *
                                                                                                                                                                                           * @param manager The new Manager
                                                                                                                                                                                           */
                                                                                                                                                                                          public void setManager(Manager manager) {




                                                                                                                                                                                                                                                                                                                                                                                                                                             10
Crosscutting Concerns


                           /*                                                                                              public void invalidate() {                                                          ;                                                                                                                                                                 * Remove the object bound with the specified name from this session. If
                            * ====================================================================                                 serverSession.removeApplicationSession(context);                                                                                                                                                                                                   * the session does not have an object bound with this name, this method
                            *                                                                                                                                                                                                                                                                                                                                                         * does nothing.
                            * The Apache Software License, Version 1.1                                                                   // remove everything in the session                                   /**                                                                                                                                                                    * <p>
                            *                                                                                                                                                                                   * Standard implementation of the <b>Session</b> interface. This object is                                                                                             * After this method executes, and if the object implements
                            * Copyright (c) 1999 The Apache Software Foundation. All rights                                              Enumeration enum = values.keys();                                      * serializable, so that it can be stored in persistent storage or transferred                                                                                         * <code>HttpSessionBindingListener</code>, the container calls
                            * reserved.                                                                                                  while (enum.hasMoreElements()) {                                       * to a different JVM for distributable session support.                                                                                                               * <code>valueUnbound()</code> on the object.
                            *                                                                                                                String name = (String)enum.nextElement();                          * <p>                                                                                                                                                                 *
                            * Redistribution and use in source and binary forms, with or without                                             removeValue(name);                                                 * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the                                                                                           * @param name Name of the object to remove from this session.
                            * modification, are permitted provided that the following conditions                                         }                                                                      * internal (Session) and application level (HttpSession) view of the session.                                                                                         *
                            * are met:                                                                                                                                                                          * However, because the class itself is not declared public, Java logic outside                                                                                        * @exception IllegalStateException if this method is called on an
                            *                                                                                                            valid = false;                                                         * of the <code>org.apache.tomcat.session</code> package cannot cast an                                                                                                * invalidated session
                            * 1. Redistributions of source code must retain the above copyright                                   }                                                                             * HttpSession view of this instance back to a Session view.                                                                                                           */
                            *    notice, this list of conditions and the following disclaimer.                                                                                                                  *                                                                                                                                                                    public void removeAttribute(String name) {
                            *                                                                                                     public boolean isNew() {                                                      * @author Craig R. McClanahan
                            * 2. Redistributions in binary form must reproduce the above copyright                                    if (! valid) {                                                            * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $                                                                                                                 synchronized (attributes) {
                            *    notice, this list of conditions and the following disclaimer in                                          String msg = sm.getString("applicationSession.session.ise");          */                                                                                                                                                                           Object object = attributes.get(name);
                            *    the documentation and/or other materials provided with the                                                                                                                                                                                                                                                                                                  if (object == null)
                            *    distribution.                                                                                               throw new IllegalStateException(msg);                             final class StandardSession                                                                                                                                                       return;
                            *                                                                                                            }                                                                         implements HttpSession, Session {                                                                                                                                         attributes.remove(name);
                            * 3. The end-user documentation included with the redistribution, if                                                                                                                                                                                                                                                                                             //      System.out.println( "Removing attribute " + name );
                            *    any, must include the following acknowledgment:                                                         if (thisAccessTime == creationTime) {                                                                                                                     /**                                                                                       if (object instanceof HttpSessionBindingListener) {
                            *       "This product includes software developed by the                                                         return true;                                                            // ----------------------------------------------------------- Constructors    * Update the accessed time information for this session. This method                         ((HttpSessionBindingListener) object).valueUnbound
                            *        Apache Software Foundation (http://www.apache.org/)."                                               } else {                                                                                                                                                   * should be called by the context when a request comes in for a particular                       (new HttpSessionBindingEvent((HttpSession) this, name));
                            *    Alternately, this acknowledgment may appear in the software                                                 return false;                                                                                                                                          * session, even if the application does not reference it.                                }
                           itself,                                                                                                       }                                                                           /**                                                                            */                                                                                   }
                            *    if and wherever such third-party acknowledgments normally appear.                                }                                                                                   * Construct a new Session associated with the specified Manager.             public void access() {
                            *                                                                                                                                                                                         *                                                                                                                                                              }
                            * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software                                                                                                                      * @param manager The manager with which this Session is associated                 this.lastAccessedTime = this.thisAccessedTime;




• Crosscutting concerns
                            *    Foundation" must not be used to endorse or promote products                               /**                                                                                        */                                                                                 this.thisAccessedTime = System.currentTimeMillis();                     * Bind an object to this session, using the specified name. If an object
                           derived                                                                                                    * @deprecated                                                                  public StandardSession(Manager manager) {                                           this.isNew=false;                                                            * of the same name is already bound to this session, the object is
                            *    from this software without prior written permission. For written                                     */                                                                                                                                                           }                                                                                  * replaced.
                            *    permission, please contact apache@apache.org.                                                                                                                                           super();                                                                                                                                                     * <p>
                            *                                                                                                     public void putValue(String name, Object value) {                                      this.manager = manager;                                                                                                                                      * After this method executes, and if the object implements
                            * 5. Products derived from this software may not be called "Apache"                                       setAttribute(name, value);                                                                                                                                   /**                                                                                * <code>HttpSessionBindingListener</code>, the container calls
                            *    nor may "Apache" appear in their names without prior written                                     }                                                                                  }                                                                              * Perform the internal processing required to invalidate this session,            * <code>valueBound()</code> on the object.
                            *    permission of the Apache Group.                                                                                                                                                                                                                                    * without triggering an exception if the session has already expired.             *
                            *                                                                                                     public void setAttribute(String name, Object value) {                                                                                                             */                                                                                * @param name Name to which the object is bound, cannot be null
                            * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED                                        if (! valid) {                                                           /**                                                                                 public void expire() {                                                             * @param value Object to be bound, cannot be null
                            * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES                                           String msg = sm.getString("applicationSession.session.ise");                * The last accessed time for this Session.                                                                                                                      *
                            * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                                                                                                                             */                                                                                 // Remove this session from our manager's active sessions                    * @exception IllegalArgumentException if an attempt is made to add a
                            * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR                                                throw new IllegalStateException(msg);                                   private long lastAccessedTime = creationTime;                                       if ((manager != null) && (manager instanceof ManagerBase))                   * non-serializable object in an environment marked distributable.
                            * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,                                           }                                                                                                                                                                   ((ManagerBase) manager).remove(this);                                    * @exception IllegalStateException if this method is called on an
                            * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT                                                                                                                                                                                                                                                                                        * invalidated session
                            * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF                                           if (name == null) {                                                         /**                                                                                 // Unbind any objects associated with this session                           */
                            * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND                                            String msg = sm.getString("applicationSession.value.iae");               * The Manager with which this Session is associated.                               Vector results = new Vector();                                              public void setAttribute(String name, Object value) {
                            * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,                                                                                                                      */                                                                                 Enumeration attrs = getAttributeNames();
                            * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT                                             throw new IllegalArgumentException(msg);                                private Manager manager = null;                                                     while (attrs.hasMoreElements()) {                                               if ((manager != null) && manager.getDistributable() &&
                            * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF                                         }                                                                                                                                                                   String attr = (String) attrs.nextElement();                                   !(value instanceof Serializable))
                            * SUCH DAMAGE.                                                                                                                                                                                                                                                                   results.addElement(attr);                                                       throw new IllegalArgumentException
                            * ====================================================================                                       removeValue(name);     // remove any existing binding                       /**                                                                                 }                                                                                       (sm.getString("standardSession.setAttribute.iae"));
                            *                                                                                                                                                                                         * The maximum time interval, in seconds, between client requests before            Enumeration names = results.elements();
                            * This software consists of voluntary contributions made by many                                             if (value != null && value instanceof HttpSessionBindingListener) {          * the servlet container may invalidate this session. A negative time               while (names.hasMoreElements()) {                                               synchronized (attributes) {
                            * individuals on behalf of the Apache Software Foundation. For more                                              HttpSessionBindingEvent e =                                              * indicates that the session should never time out.                                    String name = (String) names.nextElement();                                     removeAttribute(name);
                            * information on the Apache Software Foundation, please see                                                          new HttpSessionBindingEvent(this, name);                             */                                                                                     removeAttribute(name);                                                          attributes.put(name, value);
                            * <http://www.apache.org/>.                                                                                                                                                              private int maxInactiveInterval = -1;                                               }                                                                                   if (value instanceof HttpSessionBindingListener)
                            *                                                                                                                ((HttpSessionBindingListener)value).valueBound(e);                                                                                                                                                                                                  ((HttpSessionBindingListener) value).valueBound
                            * [Additional notices, if required by prior licensing conditions]                                            }                                                                                                                                                               // Mark this session as invalid                                                             (new HttpSessionBindingEvent((HttpSession) this, name));
                            *                                                                                                                                                                                        /**                                                                                 setValid(false);                                                                }
                            */                                                                                                           values.put(name, value);                                                     * Flag indicating whether this session is new or not.
                                                                                                                                  }                                                                                   */                                                                           }                                                                                 }
                                                                                                                                                                                                                     private boolean isNew = true;
                                                                                                                                  /**
                           package org.apache.tomcat.session;                                                                       * @deprecated                                                                                                                                                  /**                                                                               // -------------------------------------------- HttpSession Private Methods
                                                                                                                                    */                                                                               /**
                           import org.apache.tomcat.core.*;                                                                       public Object getValue(String name) {                                               * Flag indicating whether this session is valid or not.                      }
                           import org.apache.tomcat.util.StringManager;                                                                return getAttribute(name);                                                     */                                                                                                                                                             /**
                           import java.io.*;                                                                                      }                                                                                  private boolean isValid = false;                                                                                                                                 * Read a serialized version of this session object from the specified
                           import java.net.*;                                                                                                                                                                                                                                                      /**                                                                                * object input stream.
                           import java.util.*;                                                                                    public Object getAttribute(String name) {                                                                                                                         * Set the <code>isNew</code> flag for this session.                               * <p>
                           import javax.servlet.*;                                                                                    if (! valid) {                                                                 /**                                                                            *                                                                                 * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager
                           import javax.servlet.http.*;                                                                                   String msg = sm.getString("applicationSession.session.ise");                * The string manager for this package.                                        * @param isNew The new value for the <code>isNew</code> flag                      * is not restored by this method, and must be set explicitly.
                                                                                                                                                                                                                      */                                                                            */                                                                                *
                           /**                                                                                                               throw new IllegalStateException(msg);                                   private StringManager sm =                                                    void setNew(boolean isNew) {                                                       * @param stream The input stream to read from
                            * Core implementation of an application level session                                                        }                                                                               StringManager.getManager("org.apache.tomcat.session");                                                                                                       *
                            *                                                                                                                                                                                                                                                                            this.isNew = isNew;                                                          * @exception ClassNotFoundException if an unknown class is specified
                            * @author James Duncan Davidson [duncan@eng.sun.com]                                                         if (name == null) {                                                                                                                                                                                                                          * @exception IOException if an input/output error occurs




  (CCCs) affect many
                            * @author Jason Hunter [jch@eng.sun.com]                                                                         String msg = sm.getString("applicationSession.value.iae");              /**                                                                           }                                                                                  */
                            * @author James Todd [gonzo@eng.sun.com]                                                                                                                                                  * The HTTP session context associated with this session.                                                                                                       private void readObject(ObjectInputStream stream)
                            */                                                                                                               throw new IllegalArgumentException(msg);                                 */                                                                                                                                                                 throws ClassNotFoundException, IOException {
                                                                                                                                         }                                                                           private static HttpSessionContext sessionContext = null;                      /**
                           public class ApplicationSession implements HttpSession {                                                                                                                                                                                                                 * Set the <code>isValid</code> flag for this session.                                // Deserialize the scalar instance variables (except Manager)
                                                                                                                                         return values.get(name);                                                                                                                                   *                                                                                    creationTime = ((Long) stream.readObject()).longValue();
                               private StringManager sm =                                                                         }                                                                                  /**                                                                            * @param isValid The new value for the <code>isValid</code> flag                     id = (String) stream.readObject();
                                   StringManager.getManager("org.apache.tomcat.session");                                                                                                                             * The current accessed time for this session.                                 */                                                                                   lastAccessedTime = ((Long) stream.readObject()).longValue();
                               private Hashtable values = new Hashtable();                                                        /**                                                                                 */                                                                           void setValid(boolean isValid) {                                                      maxInactiveInterval = ((Integer) stream.readObject()).intValue();
                               private String id;                                                                                  * @deprecated                                                                     private long thisAccessedTime = creationTime;                                                                                                                       isNew = ((Boolean) stream.readObject()).booleanValue();
                               private ServerSession serverSession;                                                                */                                                                                                                                                                    this.isValid = isValid;                                                         isValid = ((Boolean) stream.readObject()).booleanValue();
                               private Context context;                                                                           public String[] getValueNames() {                                                                                                                                }
                               private long creationTime = System.currentTimeMillis();;                                               Enumeration e = getAttributeNames();                                                                                                                                                                                                               // Deserialize the attribute count and attribute values
                               private long thisAccessTime = creationTime;                                                            Vector names = new Vector();                                                                                                                                                                                                                       int n = ((Integer) stream.readObject()).intValue();
                               private long lastAccessed = creationTime;                                                                                                                                             // ----------------------------------------------------- Session Properties   // ------------------------------------------------- HttpSession Properties           for (int i = 0; i < n; i++) {
                               private int inactiveInterval = -1;                                                                        while (e.hasMoreElements()) {                                                                                                                                                                                                                       String name = (String) stream.readObject();
                               private boolean valid = true;                                                                                 names.addElement(e.nextElement());                                                                                                                                                                                                              Object value = (Object) stream.readObject();
                                                                                                                                         }                                                                           /**                                                                           /**                                                                                       attributes.put(name, value);
                               ApplicationSession(String id, ServerSession serverSession,                                                                                                                             * Set the creation time for this session. This method is called by the        * Return the time when this session was created, in milliseconds since               }
                                   Context context) {                                                                                    String[] valueNames = new String[names.size()];                              * Manager when an existing Session instance is reused.                        * midnight, January 1, 1970 GMT.
                                   this.serverSession = serverSession;                                                                                                                                                *                                                                             *                                                                                }
                                   this.context = context;                                                                               names.copyInto(valueNames);                                                  * @param time The new creation time                                           * @exception IllegalStateException if this method is called on an
                                   this.id = id;                                                                                                                                                                      */                                                                            * invalidated session
                                                                                                                                         return valueNames;                                                          public void setCreationTime(long time) {                                       */                                                                               /**
                                   this.inactiveInterval = context.getSessionTimeOut();                                                                                                                                                                                                            public long getCreationTime() {                                                    * Write a serialized version of this session object to the specified
                                                                                                                                  }                                                                                      this.creationTime = time;                                                                                                                                    * object output stream.
                                   if (this.inactiveInterval != -1) {                                                                                                                                                    this.lastAccessedTime = time;                                                   return (this.creationTime);                                                  * <p>
                                       this.inactiveInterval *= 60;                                                               public Enumeration getAttributeNames() {                                               this.thisAccessedTime = time;                                                                                                                                * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored
                                   }                                                                                                  if (! valid) {                                                                                                                                               }                                                                                  * in the serialized representation of this Session. After calling
                               }                                                                                                          String msg = sm.getString("applicationSession.session.ise");                                                                                                                                                                                * <code>readObject()</code>, you must set the associated Manager
                                                                                                                                                                                                                                                                                                                                                                                      * explicitly.
                               ServerSession getServerSession() {                                                                            throw new IllegalStateException(msg);                                                                                                                 /**                                                                                * <p>
                                   return serverSession;                                                                                 }                                                                                                                                                          * Return the session context with which this session is associated.               * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable
                               }                                                                                                                                                                                                                                                                    *                                                                                 * will be silently ignored. If you do not want any such attributes,
                                                                                                                                         Hashtable valuesClone = (Hashtable)values.clone();                                                                                                         * @deprecated As of Version 2.1, this method is deprecated and has no             * be sure the <code>distributable</code> property of our associated




  heterogeneous software
                               /**                                                                                                                                                                                                                                                                  * replacement. It will be removed in a future version of the                      * Manager is set to <code>true</code>.
                                * Called by context when request comes in so that accesses and                                           return (Enumeration)valuesClone.keys();                                                                                                                    * Java Servlet API.                                                               *
                                * inactivities can be dealt with accordingly.                                                     }                                                                                                                                                                 */                                                                                * @param stream The output stream to write to
                                */                                                                                                                                                                                                                                                                 public HttpSessionContext getSessionContext() {                                    *
                                                                                                                                                                                                                                                                                                                                                                                      * @exception IOException if an input/output error occurs
                               void accessed() {                                                                            /**                                                                                                                                                                          if (sessionContext == null)                                                  */
                                   // set last accessed to thisAccessTime as it will be left over                                     * @deprecated                                                                                                                                                          sessionContext = new StandardSessionContext();                          private void writeObject(ObjectOutputStream stream) throws IOException {
                                   // from the previous access                                                                        */                                                                                                                                                                 return (sessionContext);
                                   lastAccessed = thisAccessTime;                                                                                                                                                                                                                                                                                                                        // Write the scalar instance variables (except Manager)
                                   thisAccessTime = System.currentTimeMillis();                                                   public void removeValue(String name) {                                                                                                                           }                                                                                     stream.writeObject(new Long(creationTime));
                                                                                                                                      removeAttribute(name);                                                                                                                                                                                                                             stream.writeObject(id);
                                   validate();                                                                                    }                                                                                                                                                                                                                                                      stream.writeObject(new Long(lastAccessedTime));
                               }                                                                                                                                                                                                                                                                   // ----------------------------------------------HttpSession Public Methods           stream.writeObject(new Integer(maxInactiveInterval));
                                                                                                                                  public void removeAttribute(String name) {                                                                                                                                                                                                             stream.writeObject(new Boolean(isNew));
                               void validate() {                                                                                      if (! valid) {                                                                 }                                                                                                                                                                   stream.writeObject(new Boolean(isValid));
                                   // if we have an inactive interval, check to see if we've exceeded it                                  String msg = sm.getString("applicationSession.session.ise");                                                                                             /**
                                   if (inactiveInterval != -1) {                                                                                                                                                                                                                                    * Return the object bound with the specified name in this session, or                // Accumulate the names of serializable attributes
                                       int thisInterval =                                                                                    throw new IllegalStateException(msg);                                                                                                                  * <code>null</code> if no object is bound with that name.                            Vector results = new Vector();
                                           (int)(System.currentTimeMillis() - lastAccessed) / 1000;                                      }                                                                                                                                                          *                                                                                    Enumeration attrs = getAttributeNames();
                                                                                                                                                                                                                                                                                                    * @param name Name of the attribute to be returned                                   while (attrs.hasMoreElements()) {
                                       if (thisInterval > inactiveInterval) {                                                            if (name == null) {                                                                                                                                        *                                                                                        String attr = (String) attrs.nextElement();
                                           invalidate();                                                                                     String msg = sm.getString("applicationSession.value.iae");                                                                                             * @exception IllegalStateException if this method is called on an                        Object value = attributes.get(attr);
                                       }                                                                                                                                                                                                                                                            * invalidated session                                                                    if (value instanceof Serializable)
                                   }                                                                                                         throw new IllegalArgumentException(msg);                                                                                                               */                                                                                           results.addElement(attr);
                               }                                                                                                         }                                                                                                                                                         public Object getAttribute(String name) {                                             }

                               // HTTP SESSION IMPLEMENTATION METHODS                                                                    Object o = values.get(name);                                                                                                                                    return (attributes.get(name));                                                  // Serialize the attribute count and the attribute values
                                                                                                                                                                                                                                                                                                                                                                                         stream.writeObject(new Integer(results.size()));
                               public String getId() {                                                                                   if (o instanceof HttpSessionBindingListener) {                                                                                                            }                                                                                     Enumeration names = results.elements();
                                   if (valid) {                                                                                              HttpSessionBindingEvent e =                                                                                                                                                                                                                 while (names.hasMoreElements()) {
                                       return id;                                                                                                new HttpSessionBindingEvent(this,name);                                                                                                                                                                                                     String name = (String) names.nextElement();
                                   } else {                                                                                                                                                                                                                                                        /**                                                                                       stream.writeObject(name);
                                       String msg = sm.getString("applicationSession.session.ise");                                          ((HttpSessionBindingListener)o).valueUnbound(e);                                                                                                       * Return an <code>Enumeration</code> of <code>String</code> objects                      stream.writeObject(attributes.get(name));
                                                                                                                                         }                                                                                                                                                          * containing the names of the objects bound to this session.                         }
                                       throw new IllegalStateException(msg);                                                                                                                                                                                                                        *




  modules.
                                   }                                                                                                     values.remove(name);                                                                                                                                       * @exception IllegalStateException if this method is called on an
                               }                                                                                                  }                                                                                                                                                                 * invalidated session                                                            }
                                                                                                                                                                                                                                                                                                    */
                               public long getCreationTime() {                                                                    public void setMaxInactiveInterval(int interval) {                                                                                                               public Enumeration getAttributeNames() {                                          crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() |
                                   if (valid) {                                                                                       if (! valid) {                                                                                                                                                                                                                                                                              long getCreationTime() |
                                       return creationTime;                                                                               String msg = sm.getString("applicationSession.session.ise");                                                                                                   return (attributes.keys());                                                                                              Object getAttribute(String) |
                                   } else {                                                                                                                                                                                                                                                                                                                                                                                       Enumeration getAttributeNames() |
                                       String msg = sm.getString("applicationSession.session.ise");                                          throw new IllegalStateException(msg);                                                                                                                 }                                                                                                                              String[] getValueNames() |
                                                                                                                                         }                                                                                                                                                                                                                                                                                        void invalidate() |
                                       throw new IllegalStateException(msg);                                                                                                                                                                                                                                                                                                                                                      boolean isNew() |
                                   }                                                                                                                                                                                                                                                               /**                                                                                                                            void removeAttribute(String) |
                               }                                                                                                                                                                                                                                                                    * Return the object bound with the specified name in this session, or                                                         void setAttribute(String, Object));
                                                                                                                                                                                                                                                                                                    * <code>null</code> if no object is bound with that name.
                               /**                                                                                                                                                                                                                                                                  *                                                                                static advice(StandardSession s): invalidate(s) {
                                *                                                                                                                                                                                                                                                                   * @param name Name of the value to be returned                                       before {
                                * @deprecated                                                                                                                                                                                                                                                       *                                                                                        if (!s.isValid())
                                                                                                                                                                                                                                                                                                    * @exception IllegalStateException if this method is called on an                             throw new IllegalStateException
                                                                                                                                                                                                                                                                                                    * invalidated session                                                                             (s.sm.getString("standardSession."
                                                                                                                                                                                                                                                                                                    *                                                                                                                 + thisJoinPoint.methodName
                                                                                                                                                                                                                                                                                                    * @deprecated As of Version 2.2, this method is replaced by                                                       + ".ise"));
                                                                                                                                                                                                                                                                                                    * <code>getAttribute()</code>                                                        }
                                                                                                                                                                                                                                                                                                    */                                                                               }
                                                                                                                                                                                                                     /**                                                                           public Object getValue(String name) {
                                                                                                                                                                                                                      * Return the session identifier for this session.
                                                                                                                                                                                                                      */                                                                                 return (getAttribute(name));
                                                                                                                                                                                                                     public String getId() {
                                                                                                                                                                                                                                                                                                   }                                                                             }


                                                                                                                                                                                                                                                                                                   /**                                                                           // -------------------------------------------------------------- Private Class
                                                                                                                                                                                                                                                                                                    * Return the set of names of objects bound to this session. If there
                                                                                                                                                                                                                                                                                                    * are no such objects, a zero-length array is returned.
                                                                                                                                                                                                                                                                                                    *                                                                            /**
                                                                                                                                                                                                                                                                                                    * @exception IllegalStateException if this method is called on an             * This class is a dummy implementation of the <code>HttpSessionContext</code>
                                                                                                                                                                                                                                                                                                    * invalidated session                                                         * interface, to conform to the requirement that such an object be returned
                                                                                                                                                                                                                                                                                                    *                                                                             * when <code>HttpSession.getSessionContext()</code> is called.
                                                                                                                                                                                                                                                                                                    * @deprecated As of Version 2.2, this method is replaced by                   *
                                                                                                                                                                                                                                                                                                    * <code>getAttributeNames()</code>                                            * @author Craig R. McClanahan
                                                                                                                                                                                                                                                                                                    */                                                                            *
                                                                                                                                                                                                                                                                                                   public String[] getValueNames() {                                              * @deprecated As of Java Servlet API 2.1 with no replacement. The
                                                                                                                                                                                                                                                                                                                                                                                  * interface will be removed in a future version of this API.
                                                                                                                                                                                                                                                                                                         Vector results = new Vector();                                           */
                                                                                                                                                                                                                                                                                                         Enumeration attrs = getAttributeNames();
                                                                                                                                                                                                                                                                                                         while (attrs.hasMoreElements()) {                                       final class StandardSessionContext implements HttpSessionContext {
                                                                                                                                                                                                                                                                                                             String attr = (String) attrs.nextElement();
                                                                                                                                                                                                                                                                                                             results.addElement(attr);
                                                                                                                                                                                                                                                                                                         }                                                                           private Vector dummy = new Vector();
                                                                                                                                                                                                                         return (this.id);                                                               String names[] = new String[results.size()];
                                                                                                                                                                                                                                                                                                         for (int i = 0; i < names.length; i++)                                      /**
                                                                                                                                                                                                                                                                                                             names[i] = (String) results.elementAt(i);                                * Return the session identifiers of all sessions defined
                                                                                                                                                                                                                                                                                                         return (names);                                                              * within this context.
                                                                                                                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                                   }                                                                                  * @deprecated As of Java Servlet API 2.1 with no replacement.
                                                                                                                                                                                                                                                                                                                                                                                      * This method must return an empty <code>Enumeration</code>
                                                                                                                                                                                                                                                                                                                                                                                      * and will be removed in a future version of the API.
                                                                                                                                                                                                                                                                                                   /**                                                                                */
                                                                                                                                                                                                                                                                                                    * Invalidates this session and unbinds any objects bound to it.                  public Enumeration getIds() {
                                                                                                                                                                                                                                                                                                    *
                                                                                                                                                                                                                                                                                                    * @exception IllegalStateException if this method is called on                       return (dummy.elements());
                                                                                                                                                                                                                                                                                                    * an invalidated session
                                                                                                                                                                                                                                                                                                    */
                                                                                                                                                                                                                                                                                                   public void invalidate() {

                                                                                                                                                                                                                                                                                                         // Cause this session to expire
                                                                                                                                                                                                                                                                                                         expire();

                                                                                                                                                                                                                                                                                                   }


                                                                                                                                                                                                                     }                                                                             /**
                                                                                                                                                                                                                                                                                                    * Return <code>true</code> if the client does not yet know about the
                                                                                                                                                                                                                                                                                                    * session, or if the client chooses not to join the session. For
                                                                                                                                                                                                                                                                                                    * example, if the server used only cookie-based sessions, and the client
                                                                                                                                                                                                                                                                                                    * has disabled the use of cookies, then a session would be new on each
                                                                                                                                                                                                                                                                                                    * request.
                                                                                                                                                                                                                                                                                                    *
                                                                                                                                                                                                                                                                                                    * @exception IllegalStateException if this method is called on an
                                                                                                                                                                                                                                                                                                    * invalidated session
                                                                                                                                                                                                                                                                                                    */
                                                                                                                                                                                                                                                                                                   public boolean isNew() {

                                                                                                                                                                                                                                                                                                         return (this.isNew);

                                                                                                                                                                                                                                                                                                   }




                           package org.apache.tomcat.session;                                              void validate() {
                                                                                                                   // if we have an inactive interval, check to see if
                           import org.apache.tomcat.core.*;                                                        // we've exceeded it
                           import org.apache.tomcat.util.StringManager;
                           import java.io.*;                                                                       if (inactiveInterval != -1) {
                           import java.net.*;                                                                          int thisInterval =
                           import java.util.*;                                                                             (int)(System.currentTimeMillis() - lastAccessed) / 1000;
                           import javax.servlet.*;
                           import javax.servlet.http.*;                                                                if (thisInterval > inactiveInterval) {
                                                                                                                           invalidate();
                           /**
                            * Core implementation of a server session                                                       ServerSessionManager ssm =
                            *                                                                                                   ServerSessionManager.getManager();
                            * @author James Duncan Davidson [duncan@eng.sun.com]
                            * @author James Todd [gonzo@eng.sun.com]                                                        ssm.removeSession(this);
                            */                                                                                         }
                                                                                                                   }
                           public class ServerSession {                                                        }

                               private StringManager sm =                                                      synchronized void invalidate() {
                                   StringManager.getManager("org.apache.tomcat.session");                          Enumeration enum = appSessions.keys();                                                            /**
                               private Hashtable values = new Hashtable();                                                                                                                                            * Set the session identifier for this session.
                               private Hashtable appSessions = new Hashtable();                                    while (enum.hasMoreElements()) {                                                                   *
                               private String id;                                                                      Object key = enum.nextElement();                                                               * @param id The new session identifier
                               private long creationTime = System.currentTimeMillis();;                                ApplicationSession appSession =                                                                */
                               private long thisAccessTime = creationTime;                                                 (ApplicationSession)appSessions.get(key);                                                 public void setId(String id) {
                               private long lastAccessed = creationTime;
                               private int inactiveInterval = -1;                                                      appSession.invalidate();
                                                                                                                   }
                               ServerSession(String id) {                                                      }
                                   this.id = id;
                               }                                                                               public void putValue(String name, Object value) {
                                                                                                                   if (name == null) {
                               public String getId() {                                                                 String msg = sm.getString("serverSession.value.iae");
                                   return id;
                               }                                                                                       throw new IllegalArgumentException(msg);
                                                                                                                   }
                               public long getCreationTime() {
                                   return creationTime;                                                            removeValue(name); // remove any existing binding
                               }                                                                                   values.put(name, value);
                                                                                                               }
                               public long getLastAccessedTime() {
                                   return lastAccessed;                                                        public Object getValue(String name) {
                               }                                                                                   if (name == null) {
                                                                                                                       String msg = sm.getString("serverSession.value.iae");
                               public ApplicationSession getApplicationSession(Context context,
                                   boolean create) {                                                                   throw new IllegalArgumentException(msg);
                                   ApplicationSession appSession =                                                 }                                                                                                     if ((this.id != null) && (manager != null) &&
                                       (ApplicationSession)appSessions.get(context);                                                                                                                                       (manager instanceof ManagerBase))
                                                                                                                   return values.get(name);                                                                                  ((ManagerBase) manager).remove(this);
                                   if (appSession == null && create) {                                         }

                                       // XXX                                                                  public Enumeration getValueNames() {
                                       // sync to ensure valid?                                                    return values.keys();
                                                                                                               }
                                       appSession = new ApplicationSession(id, this, context);
                                       appSessions.put(context, appSession);                                   public void removeValue(String name) {
                                   }                                                                               values.remove(name);
                                                                                                               }
                                   // XXX
                                   // make sure that we haven't gone over the end of our                       public void setMaxInactiveInterval(int interval) {
                                   // inactive interval -- if so, invalidate and create                            inactiveInterval = interval;
                                   // a new appSession                                                         }

                                   return appSession;                                                          public int getMaxInactiveInterval() {
                               }                                                                                   return inactiveInterval;
                                                                                                               }
                               void removeApplicationSession(Context context) {
                                   appSessions.remove(context);                                                // XXX
                               }                                                                               // sync'd for safty -- no other thread should be getting something
                                                                                                               // from this while we are reaping. This isn't the most optimal
                               /**                                                                             // solution for this, but we'll determine something else later.                                           this.id = id;
                                * Called by context when request comes in so that accesses and
                                * inactivities can be dealt with accordingly.                                  synchronized void reap() {
                                */                                                                                 Enumeration enum = appSessions.keys();

                               void accessed() {                                                                   while (enum.hasMoreElements()) {
                                   // set last accessed to thisAccessTime as it will be left over




                                                                                                                                                                                                                         if ((manager != null) && (manager instanceof ManagerBase))
                                                                                                                                                                                                                             ((ManagerBase) manager).add(this);




                                                                                                                                                                                                                     }




                                                                                                                                                                                                                     /**
                                                                                                                                                                                                                      * Return descriptive information about this Session implementation and
                                                                                                                                                                                                                      * the corresponding version number, in the format
                                                                                                                                                                                                                      * <code>&lt;description&gt;/&lt;version&gt;</code>.
                                                                                                                                                                                                                      */
                                                                                                                                                                                                                     public String getInfo() {




                                                                                                                                                                                                                         return (this.info);




                                                                                                                                                                                                                     }




                                                                                                                                                                                                                     /**
                                                                                                                                                                                                                      * Return the last time the client sent a request associated with this
                                                                                                                                                                                                                      * session, as the number of milliseconds since midnight, January 1, 1970
                                                                                                                                                                                                                      * GMT. Actions that your application takes, such as getting or setting
                                                                                                                                                                                                                      * a value associated with the session, do not affect the access time.
                                                                                                                                                                                                                      */
                                                                                                                                                                                                                     public long getLastAccessedTime() {

                                                                                                                                                                                                                         return (this.lastAccessedTime);

                                                                                                                                                                                                                     }


                                                                                                                                                                                                                     /**
                                                                                                                                                                                                                      * Return the Manager within which this Session is valid.
                                                                                                                                                                                                                      */
                                                                                                                                                                                                                     public Manager getManager() {

                                                                                                                                                                                                                         return (this.manager);

                                                                                                                                                                                                                     }


                                                                                                                                                                                                                     /**
                                                                                                                                                                                                                      * Set the Manager within which this Session is valid.
                                                                                                                                                                                                                      *
                                                                                                                                                                                                                      * @param manager The new Manager
                                                                                                                                                                                                                      */
                                                                                                                                                                                                                     public void setManager(Manager manager) {




                                                                                                                                                                                                                                                                                                                                                                                                                                                                        10
Crosscutting Concerns


                           /*                                                                                              public void invalidate() {                                                          ;                                                                                                                                                                 * Remove the object bound with the specified name from this session. If
                            * ====================================================================                                 serverSession.removeApplicationSession(context);                                                                                                                                                                                                   * the session does not have an object bound with this name, this method
                            *                                                                                                                                                                                                                                                                                                                                                         * does nothing.
                            * The Apache Software License, Version 1.1                                                                   // remove everything in the session                                   /**                                                                                                                                                                    * <p>
                            *                                                                                                                                                                                   * Standard implementation of the <b>Session</b> interface. This object is                                                                                             * After this method executes, and if the object implements
                            * Copyright (c) 1999 The Apache Software Foundation. All rights                                              Enumeration enum = values.keys();                                      * serializable, so that it can be stored in persistent storage or transferred                                                                                         * <code>HttpSessionBindingListener</code>, the container calls
                            * reserved.                                                                                                  while (enum.hasMoreElements()) {                                       * to a different JVM for distributable session support.                                                                                                               * <code>valueUnbound()</code> on the object.
                            *                                                                                                                String name = (String)enum.nextElement();                          * <p>                                                                                                                                                                 *
                            * Redistribution and use in source and binary forms, with or without                                             removeValue(name);                                                 * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the                                                                                           * @param name Name of the object to remove from this session.
                            * modification, are permitted provided that the following conditions                                         }                                                                      * internal (Session) and application level (HttpSession) view of the session.                                                                                         *
                            * are met:                                                                                                                                                                          * However, because the class itself is not declared public, Java logic outside                                                                                        * @exception IllegalStateException if this method is called on an
                            *                                                                                                            valid = false;                                                         * of the <code>org.apache.tomcat.session</code> package cannot cast an                                                                                                * invalidated session
                            * 1. Redistributions of source code must retain the above copyright                                   }                                                                             * HttpSession view of this instance back to a Session view.                                                                                                           */
                            *    notice, this list of conditions and the following disclaimer.                                                                                                                  *                                                                                                                                                                    public void removeAttribute(String name) {
                            *                                                                                                     public boolean isNew() {                                                      * @author Craig R. McClanahan
                            * 2. Redistributions in binary form must reproduce the above copyright                                    if (! valid) {                                                            * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $                                                                                                                 synchronized (attributes) {
                            *    notice, this list of conditions and the following disclaimer in                                          String msg = sm.getString("applicationSession.session.ise");          */                                                                                                                                                                           Object object = attributes.get(name);
                            *    the documentation and/or other materials provided with the                                                                                                                                                                                                                                                                                                  if (object == null)
                            *    distribution.                                                                                               throw new IllegalStateException(msg);                             final class StandardSession                                                                                                                                                       return;
                            *                                                                                                            }                                                                         implements HttpSession, Session {                                                                                                                                         attributes.remove(name);
                            * 3. The end-user documentation included with the redistribution, if                                                                                                                                                                                                                                                                                             //      System.out.println( "Removing attribute " + name );
                            *    any, must include the following acknowledgment:                                                         if (thisAccessTime == creationTime) {                                                                                                                     /**                                                                                       if (object instanceof HttpSessionBindingListener) {
                            *       "This product includes software developed by the                                                         return true;                                                            // ----------------------------------------------------------- Constructors    * Update the accessed time information for this session. This method                         ((HttpSessionBindingListener) object).valueUnbound
                            *        Apache Software Foundation (http://www.apache.org/)."                                               } else {                                                                                                                                                   * should be called by the context when a request comes in for a particular                       (new HttpSessionBindingEvent((HttpSession) this, name));
                            *    Alternately, this acknowledgment may appear in the software                                                 return false;                                                                                                                                          * session, even if the application does not reference it.                                }
                           itself,                                                                                                       }                                                                           /**                                                                            */                                                                                   }
                            *    if and wherever such third-party acknowledgments normally appear.                                }                                                                                   * Construct a new Session associated with the specified Manager.             public void access() {
                            *                                                                                                                                                                                         *                                                                                                                                                              }
                            * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software                                                                                                                      * @param manager The manager with which this Session is associated                 this.lastAccessedTime = this.thisAccessedTime;




• Crosscutting concerns
                            *    Foundation" must not be used to endorse or promote products                               /**                                                                                        */                                                                                 this.thisAccessedTime = System.currentTimeMillis();                     * Bind an object to this session, using the specified name. If an object
                           derived                                                                                                    * @deprecated                                                                  public StandardSession(Manager manager) {                                           this.isNew=false;                                                            * of the same name is already bound to this session, the object is
                            *    from this software without prior written permission. For written                                     */                                                                                                                                                           }                                                                                  * replaced.
                            *    permission, please contact apache@apache.org.                                                                                                                                           super();                                                                                                                                                     * <p>
                            *                                                                                                     public void putValue(String name, Object value) {                                      this.manager = manager;                                                                                                                                      * After this method executes, and if the object implements
                            * 5. Products derived from this software may not be called "Apache"                                       setAttribute(name, value);                                                                                                                                   /**                                                                                * <code>HttpSessionBindingListener</code>, the container calls
                            *    nor may "Apache" appear in their names without prior written                                     }                                                                                  }                                                                              * Perform the internal processing required to invalidate this session,            * <code>valueBound()</code> on the object.
                            *    permission of the Apache Group.                                                                                                                                                                                                                                    * without triggering an exception if the session has already expired.             *
                            *                                                                                                     public void setAttribute(String name, Object value) {                                                                                                             */                                                                                * @param name Name to which the object is bound, cannot be null
                            * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED                                        if (! valid) {                                                           /**                                                                                 public void expire() {                                                             * @param value Object to be bound, cannot be null
                            * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES                                           String msg = sm.getString("applicationSession.session.ise");                * The last accessed time for this Session.                                                                                                                      *
                            * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                                                                                                                             */                                                                                 // Remove this session from our manager's active sessions                    * @exception IllegalArgumentException if an attempt is made to add a
                            * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR                                                throw new IllegalStateException(msg);                                   private long lastAccessedTime = creationTime;                                       if ((manager != null) && (manager instanceof ManagerBase))                   * non-serializable object in an environment marked distributable.
                            * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,                                           }                                                                                                                                                                   ((ManagerBase) manager).remove(this);                                    * @exception IllegalStateException if this method is called on an
                            * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT                                                                                                                                                                                                                                                                                        * invalidated session
                            * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF                                           if (name == null) {                                                         /**                                                                                 // Unbind any objects associated with this session                           */
                            * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND                                            String msg = sm.getString("applicationSession.value.iae");               * The Manager with which this Session is associated.                               Vector results = new Vector();                                              public void setAttribute(String name, Object value) {
                            * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,                                                                                                                      */                                                                                 Enumeration attrs = getAttributeNames();
                            * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT                                             throw new IllegalArgumentException(msg);                                private Manager manager = null;                                                     while (attrs.hasMoreElements()) {                                               if ((manager != null) && manager.getDistributable() &&
                            * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF                                         }                                                                                                                                                                   String attr = (String) attrs.nextElement();                                   !(value instanceof Serializable))
                            * SUCH DAMAGE.                                                                                                                                                                                                                                                                   results.addElement(attr);                                                       throw new IllegalArgumentException
                            * ====================================================================                                       removeValue(name);     // remove any existing binding                       /**                                                                                 }                                                                                       (sm.getString("standardSession.setAttribute.iae"));
                            *                                                                                                                                                                                         * The maximum time interval, in seconds, between client requests before            Enumeration names = results.elements();
                            * This software consists of voluntary contributions made by many                                             if (value != null && value instanceof HttpSessionBindingListener) {          * the servlet container may invalidate this session. A negative time               while (names.hasMoreElements()) {                                               synchronized (attributes) {
                            * individuals on behalf of the Apache Software Foundation. For more                                              HttpSessionBindingEvent e =                                              * indicates that the session should never time out.                                    String name = (String) names.nextElement();                                     removeAttribute(name);
                            * information on the Apache Software Foundation, please see                                                          new HttpSessionBindingEvent(this, name);                             */                                                                                     removeAttribute(name);                                                          attributes.put(name, value);
                            * <http://www.apache.org/>.                                                                                                                                                              private int maxInactiveInterval = -1;                                               }                                                                                   if (value instanceof HttpSessionBindingListener)
                            *                                                                                                                ((HttpSessionBindingListener)value).valueBound(e);                                                                                                                                                                                                  ((HttpSessionBindingListener) value).valueBound
                            * [Additional notices, if required by prior licensing conditions]                                            }                                                                                                                                                               // Mark this session as invalid                                                             (new HttpSessionBindingEvent((HttpSession) this, name));
                            *                                                                                                                                                                                        /**                                                                                 setValid(false);                                                                }
                            */                                                                                                           values.put(name, value);                                                     * Flag indicating whether this session is new or not.
                                                                                                                                  }                                                                                   */                                                                           }                                                                                 }
                                                                                                                                                                                                                     private boolean isNew = true;
                                                                                                                                  /**
                           package org.apache.tomcat.session;                                                                       * @deprecated                                                                                                                                                  /**                                                                               // -------------------------------------------- HttpSession Private Methods
                                                                                                                                    */                                                                               /**
                           import org.apache.tomcat.core.*;                                                                       public Object getValue(String name) {                                               * Flag indicating whether this session is valid or not.                      }
                           import org.apache.tomcat.util.StringManager;                                                                return getAttribute(name);                                                     */                                                                                                                                                             /**
                           import java.io.*;                                                                                      }                                                                                  private boolean isValid = false;                                                                                                                                 * Read a serialized version of this session object from the specified
                           import java.net.*;                                                                                                                                                                                                                                                      /**                                                                                * object input stream.
                           import java.util.*;                                                                                    public Object getAttribute(String name) {                                                                                                                         * Set the <code>isNew</code> flag for this session.                               * <p>
                           import javax.servlet.*;                                                                                    if (! valid) {                                                                 /**                                                                            *                                                                                 * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager
                           import javax.servlet.http.*;                                                                                   String msg = sm.getString("applicationSession.session.ise");                * The string manager for this package.                                        * @param isNew The new value for the <code>isNew</code> flag                      * is not restored by this method, and must be set explicitly.
                                                                                                                                                                                                                      */                                                                            */                                                                                *
                           /**                                                                                                               throw new IllegalStateException(msg);                                   private StringManager sm =                                                    void setNew(boolean isNew) {                                                       * @param stream The input stream to read from
                            * Core implementation of an application level session                                                        }                                                                               StringManager.getManager("org.apache.tomcat.session");                                                                                                       *
                            *                                                                                                                                                                                                                                                                            this.isNew = isNew;                                                          * @exception ClassNotFoundException if an unknown class is specified
                            * @author James Duncan Davidson [duncan@eng.sun.com]                                                         if (name == null) {                                                                                                                                                                                                                          * @exception IOException if an input/output error occurs




  (CCCs) affect many
                            * @author Jason Hunter [jch@eng.sun.com]                                                                         String msg = sm.getString("applicationSession.value.iae");              /**                                                                           }                                                                                  */
                            * @author James Todd [gonzo@eng.sun.com]                                                                                                                                                  * The HTTP session context associated with this session.                                                                                                       private void readObject(ObjectInputStream stream)
                            */                                                                                                               throw new IllegalArgumentException(msg);                                 */                                                                                                                                                                 throws ClassNotFoundException, IOException {
                                                                                                                                         }                                                                           private static HttpSessionContext sessionContext = null;                      /**
                           public class ApplicationSession implements HttpSession {                                                                                                                                                                                                                 * Set the <code>isValid</code> flag for this session.                                // Deserialize the scalar instance variables (except Manager)
                                                                                                                                         return values.get(name);                                                                                                                                   *                                                                                    creationTime = ((Long) stream.readObject()).longValue();
                               private StringManager sm =                                                                         }                                                                                  /**                                                                            * @param isValid The new value for the <code>isValid</code> flag                     id = (String) stream.readObject();
                                   StringManager.getManager("org.apache.tomcat.session");                                                                                                                             * The current accessed time for this session.                                 */                                                                                   lastAccessedTime = ((Long) stream.readObject()).longValue();
                               private Hashtable values = new Hashtable();                                                        /**                                                                                 */                                                                           void setValid(boolean isValid) {                                                      maxInactiveInterval = ((Integer) stream.readObject()).intValue();
                               private String id;                                                                                  * @deprecated                                                                     private long thisAccessedTime = creationTime;                                                                                                                       isNew = ((Boolean) stream.readObject()).booleanValue();
                               private ServerSession serverSession;                                                                */                                                                                                                                                                    this.isValid = isValid;                                                         isValid = ((Boolean) stream.readObject()).booleanValue();
                               private Context context;                                                                           public String[] getValueNames() {                                                                                                                                }
                               private long creationTime = System.currentTimeMillis();;                                               Enumeration e = getAttributeNames();                                                                                                                                                                                                               // Deserialize the attribute count and attribute values
                               private long thisAccessTime = creationTime;                                                            Vector names = new Vector();                                                                                                                                                                                                                       int n = ((Integer) stream.readObject()).intValue();
                               private long lastAccessed = creationTime;                                                                                                                                             // ----------------------------------------------------- Session Properties   // ------------------------------------------------- HttpSession Properties           for (int i = 0; i < n; i++) {
                               private int inactiveInterval = -1;                                                                        while (e.hasMoreElements()) {                                                                                                                                                                                                                       String name = (String) stream.readObject();
                               private boolean valid = true;                                                                                 names.addElement(e.nextElement());                                                                                                                                                                                                              Object value = (Object) stream.readObject();
                                                                                                                                         }                                                                           /**                                                                           /**                                                                                       attributes.put(name, value);
                               ApplicationSession(String id, ServerSession serverSession,                                                                                                                             * Set the creation time for this session. This method is called by the        * Return the time when this session was created, in milliseconds since               }
                                   Context context) {                                                                                    String[] valueNames = new String[names.size()];                              * Manager when an existing Session instance is reused.                        * midnight, January 1, 1970 GMT.
                                   this.serverSession = serverSession;                                                                                                                                                *                                                                             *                                                                                }
                                   this.context = context;                                                                               names.copyInto(valueNames);                                                  * @param time The new creation time                                           * @exception IllegalStateException if this method is called on an
                                   this.id = id;                                                                                                                                                                      */                                                                            * invalidated session
                                                                                                                                         return valueNames;                                                          public void setCreationTime(long time) {                                       */                                                                               /**
                                   this.inactiveInterval = context.getSessionTimeOut();                                                                                                                                                                                                            public long getCreationTime() {                                                    * Write a serialized version of this session object to the specified
                                                                                                                                  }                                                                                      this.creationTime = time;                                                                                                                                    * object output stream.
                                   if (this.inactiveInterval != -1) {                                                                                                                                                    this.lastAccessedTime = time;                                                   return (this.creationTime);                                                  * <p>
                                       this.inactiveInterval *= 60;                                                               public Enumeration getAttributeNames() {                                               this.thisAccessedTime = time;                                                                                                                                * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored
                                   }                                                                                                  if (! valid) {                                                                                                                                               }                                                                                  * in the serialized representation of this Session. After calling
                               }                                                                                                          String msg = sm.getString("applicationSession.session.ise");                                                                                                                                                                                * <code>readObject()</code>, you must set the associated Manager
                                                                                                                                                                                                                                                                                                                                                                                      * explicitly.
                               ServerSession getServerSession() {                                                                            throw new IllegalStateException(msg);                                                                                                                 /**                                                                                * <p>
                                   return serverSession;                                                                                 }                                                                                                                                                          * Return the session context with which this session is associated.               * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable
                               }                                                                                                                                                                                                                                                                    *                                                                                 * will be silently ignored. If you do not want any such attributes,
                                                                                                                                         Hashtable valuesClone = (Hashtable)values.clone();                                                                                                         * @deprecated As of Version 2.1, this method is deprecated and has no             * be sure the <code>distributable</code> property of our associated




  heterogeneous software
                               /**                                                                                                                                                                                                                                                                  * replacement. It will be removed in a future version of the                      * Manager is set to <code>true</code>.
                                * Called by context when request comes in so that accesses and                                           return (Enumeration)valuesClone.keys();                                                                                                                    * Java Servlet API.                                                               *
                                * inactivities can be dealt with accordingly.                                                     }                                                                                                                                                                 */                                                                                * @param stream The output stream to write to
                                */                                                                                                                                                                                                                                                                 public HttpSessionContext getSessionContext() {                                    *
                                                                                                                                                                                                                                                                                                                                                                                      * @exception IOException if an input/output error occurs
                               void accessed() {                                                                            /**                                                                                                                                                                          if (sessionContext == null)                                                  */
                                   // set last accessed to thisAccessTime as it will be left over                                     * @deprecated                                                                                                                                                          sessionContext = new StandardSessionContext();                          private void writeObject(ObjectOutputStream stream) throws IOException {
                                   // from the previous access                                                                        */                                                                                                                                                                 return (sessionContext);
                                   lastAccessed = thisAccessTime;                                                                                                                                                                                                                                                                                                                        // Write the scalar instance variables (except Manager)
                                   thisAccessTime = System.currentTimeMillis();                                                   public void removeValue(String name) {                                                                                                                           }                                                                                     stream.writeObject(new Long(creationTime));
                                                                                                                                      removeAttribute(name);                                                                                                                                                                                                                             stream.writeObject(id);
                                   validate();                                                                                    }                                                                                                                                                                                                                                                      stream.writeObject(new Long(lastAccessedTime));
                               }                                                                                                                                                                                                                                                                   // ----------------------------------------------HttpSession Public Methods           stream.writeObject(new Integer(maxInactiveInterval));
                                                                                                                                  public void removeAttribute(String name) {                                                                                                                                                                                                             stream.writeObject(new Boolean(isNew));
                               void validate() {                                                                                      if (! valid) {                                                                 }                                                                                                                                                                   stream.writeObject(new Boolean(isValid));
                                   // if we have an inactive interval, check to see if we've exceeded it                                  String msg = sm.getString("applicationSession.session.ise");                                                                                             /**
                                   if (inactiveInterval != -1) {                                                                                                                                                                                                                                    * Return the object bound with the specified name in this session, or                // Accumulate the names of serializable attributes
                                       int thisInterval =                                                                                    throw new IllegalStateException(msg);                                                                                                                  * <code>null</code> if no object is bound with that name.                            Vector results = new Vector();
                                           (int)(System.currentTimeMillis() - lastAccessed) / 1000;                                      }                                                                                                                                                          *                                                                                    Enumeration attrs = getAttributeNames();
                                                                                                                                                                                                                                                                                                    * @param name Name of the attribute to be returned                                   while (attrs.hasMoreElements()) {
                                       if (thisInterval > inactiveInterval) {                                                            if (name == null) {                                                                                                                                        *                                                                                        String attr = (String) attrs.nextElement();
                                           invalidate();                                                                                     String msg = sm.getString("applicationSession.value.iae");                                                                                             * @exception IllegalStateException if this method is called on an                        Object value = attributes.get(attr);
                                       }                                                                                                                                                                                                                                                            * invalidated session                                                                    if (value instanceof Serializable)
                                   }                                                                                                         throw new IllegalArgumentException(msg);                                                                                                               */                                                                                           results.addElement(attr);
                               }                                                                                                         }                                                                                                                                                         public Object getAttribute(String name) {                                             }

                               // HTTP SESSION IMPLEMENTATION METHODS                                                                    Object o = values.get(name);                                                                                                                                    return (attributes.get(name));                                                  // Serialize the attribute count and the attribute values
                                                                                                                                                                                                                                                                                                                                                                                         stream.writeObject(new Integer(results.size()));
                               public String getId() {                                                                                   if (o instanceof HttpSessionBindingListener) {                                                                                                            }                                                                                     Enumeration names = results.elements();
                                   if (valid) {                                                                                              HttpSessionBindingEvent e =                                                                                                                                                                                                                 while (names.hasMoreElements()) {
                                       return id;                                                                                                new HttpSessionBindingEvent(this,name);                                                                                                                                                                                                     String name = (String) names.nextElement();
                                   } else {                                                                                                                                                                                                                                                        /**                                                                                       stream.writeObject(name);
                                       String msg = sm.getString("applicationSession.session.ise");                                          ((HttpSessionBindingListener)o).valueUnbound(e);                                                                                                       * Return an <code>Enumeration</code> of <code>String</code> objects                      stream.writeObject(attributes.get(name));
                                                                                                                                         }                                                                                                                                                          * containing the names of the objects bound to this session.                         }
                                       throw new IllegalStateException(msg);                                                                                                                                                                                                                        *




  modules.
                                   }                                                                                                     values.remove(name);                                                                                                                                       * @exception IllegalStateException if this method is called on an
                               }                                                                                                  }                                                                                                                                                                 * invalidated session                                                            }
                                                                                                                                                                                                                                                                                                    */
                               public long getCreationTime() {                                                                    public void setMaxInactiveInterval(int interval) {                                                                                                               public Enumeration getAttributeNames() {                                          crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() |
                                   if (valid) {                                                                                       if (! valid) {                                                                                                                                                                                                                                                                              long getCreationTime() |
                                       return creationTime;                                                                               String msg = sm.getString("applicationSession.session.ise");                                                                                                   return (attributes.keys());                                                                                              Object getAttribute(String) |
                                   } else {                                                                                                                                                                                                                                                                                                                                                                                       Enumeration getAttributeNames() |
                                       String msg = sm.getString("applicationSession.session.ise");                                          throw new IllegalStateException(msg);                                                                                                                 }                                                                                                                              String[] getValueNames() |
                                                                                                                                         }                                                                                                                                                                                                                                                                                        void invalidate() |
                                       throw new IllegalStateException(msg);                                                                                                                                                                                                                                                                                                                                                      boolean isNew() |
                                   }                                                                                                                                                                                                                                                               /**                                                                                                                            void removeAttribute(String) |
                               }                                                                                                                                                                                                                                                                    * Return the object bound with the specified name in this session, or                                                         void setAttribute(String, Object));
                                                                                                                                                                                                                                                                                                    * <code>null</code> if no object is bound with that name.
                               /**                                                                                                                                                                                                                                                                  *                                                                                static advice(StandardSession s): invalidate(s) {
                                *                                                                                                                                                                                                                                                                   * @param name Name of the value to be returned                                       before {
                                * @deprecated                                                                                                                                                                                                                                                       *                                                                                        if (!s.isValid())
                                                                                                                                                                                                                                                                                                    * @exception IllegalStateException if this method is called on an                             throw new IllegalStateException
                                                                                                                                                                                                                                                                                                    * invalidated session                                                                             (s.sm.getString("standardSession."
                                                                                                                                                                                                                                                                                                    *                                                                                                                 + thisJoinPoint.methodName
                                                                                                                                                                                                                                                                                                    * @deprecated As of Version 2.2, this method is replaced by                                                       + ".ise"));
                                                                                                                                                                                                                                                                                                    * <code>getAttribute()</code>                                                        }
                                                                                                                                                                                                                                                                                                    */                                                                               }
                                                                                                                                                                                                                     /**                                                                           public Object getValue(String name) {
                                                                                                                                                                                                                      * Return the session identifier for this session.
                                                                                                                                                                                                                      */                                                                                 return (getAttribute(name));
                                                                                                                                                                                                                     public String getId() {
                                                                                                                                                                                                                                                                                                   }                                                                             }


                                                                                                                                                                                                                                                                                                   /**                                                                           // -------------------------------------------------------------- Private Class
                                                                                                                                                                                                                                                                                                    * Return the set of names of objects bound to this session. If there
                                                                                                                                                                                                                                                                                                    * are no such objects, a zero-length array is returned.
                                                                                                                                                                                                                                                                                                    *                                                                            /**
                                                                                                                                                                                                                                                                                                    * @exception IllegalStateException if this method is called on an             * This class is a dummy implementation of the <code>HttpSessionContext</code>
                                                                                                                                                                                                                                                                                                    * invalidated session                                                         * interface, to conform to the requirement that such an object be returned
                                                                                                                                                                                                                                                                                                    *                                                                             * when <code>HttpSession.getSessionContext()</code> is called.
                                                                                                                                                                                                                                                                                                    * @deprecated As of Version 2.2, this method is replaced by                   *
                                                                                                                                                                                                                                                                                                    * <code>getAttributeNames()</code>                                            * @author Craig R. McClanahan
                                                                                                                                                                                                                                                                                                    */                                                                            *
                                                                                                                                                                                                                                                                                                   public String[] getValueNames() {                                              * @deprecated As of Java Servlet API 2.1 with no replacement. The
                                                                                                                                                                                                                                                                                                                                                                                  * interface will be removed in a future version of this API.
                                                                                                                                                                                                                                                                                                         Vector results = new Vector();                                           */
                                                                                                                                                                                                                                                                                                         Enumeration attrs = getAttributeNames();
                                                                                                                                                                                                                                                                                                         while (attrs.hasMoreElements()) {                                       final class StandardSessionContext implements HttpSessionContext {
                                                                                                                                                                                                                                                                                                             String attr = (String) attrs.nextElement();
                                                                                                                                                                                                                                                                                                             results.addElement(attr);
                                                                                                                                                                                                                                                                                                         }                                                                           private Vector dummy = new Vector();
                                                                                                                                                                                                                         return (this.id);                                                               String names[] = new String[results.size()];
                                                                                                                                                                                                                                                                                                         for (int i = 0; i < names.length; i++)                                      /**
                                                                                                                                                                                                                                                                                                             names[i] = (String) results.elementAt(i);                                * Return the session identifiers of all sessions defined
                                                                                                                                                                                                                                                                                                         return (names);                                                              * within this context.
                                                                                                                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                                   }                                                                                  * @deprecated As of Java Servlet API 2.1 with no replacement.
                                                                                                                                                                                                                                                                                                                                                                                      * This method must return an empty <code>Enumeration</code>
                                                                                                                                                                                                                                                                                                                                                                                      * and will be removed in a future version of the API.
                                                                                                                                                                                                                                                                                                   /**                                                                                */
                                                                                                                                                                                                                                                                                                    * Invalidates this session and unbinds any objects bound to it.                  public Enumeration getIds() {
                                                                                                                                                                                                                                                                                                    *
                                                                                                                                                                                                                                                                                                    * @exception IllegalStateException if this method is called on                       return (dummy.elements());
                                                                                                                                                                                                                                                                                                    * an invalidated session




• Code is:
                                                                                                                                                                                                                                                                                                    */
                                                                                                                                                                                                                                                                                                   public void invalidate() {

                                                                                                                                                                                                                                                                                                         // Cause this session to expire
                                                                                                                                                                                                                                                                                                         expire();

                                                                                                                                                                                                                                                                                                   }


                                                                                                                                                                                                                     }                                                                             /**
                                                                                                                                                                                                                                                                                                    * Return <code>true</code> if the client does not yet know about the
                                                                                                                                                                                                                                                                                                    * session, or if the client chooses not to join the session. For
                                                                                                                                                                                                                                                                                                    * example, if the server used only cookie-based sessions, and the client
                                                                                                                                                                                                                                                                                                    * has disabled the use of cookies, then a session would be new on each
                                                                                                                                                                                                                                                                                                    * request.
                                                                                                                                                                                                                                                                                                    *
                                                                                                                                                                                                                                                                                                    * @exception IllegalStateException if this method is called on an
                                                                                                                                                                                                                                                                                                    * invalidated session
                                                                                                                                                                                                                                                                                                    */
                                                                                                                                                                                                                                                                                                   public boolean isNew() {

                                                                                                                                                                                                                                                                                                         return (this.isNew);

                                                                                                                                                                                                                                                                                                   }




                           package org.apache.tomcat.session;                                              void validate() {
                                                                                                                   // if we have an inactive interval, check to see if
                           import org.apache.tomcat.core.*;                                                        // we've exceeded it
                           import org.apache.tomcat.util.StringManager;
                           import java.io.*;                                                                       if (inactiveInterval != -1) {
                           import java.net.*;                                                                          int thisInterval =
                           import java.util.*;                                                                             (int)(System.currentTimeMillis() - lastAccessed) / 1000;
                           import javax.servlet.*;
                           import javax.servlet.http.*;                                                                if (thisInterval > inactiveInterval) {
                                                                                                                           invalidate();
                           /**
                            * Core implementation of a server session                                                       ServerSessionManager ssm =
                            *                                                                                                   ServerSessionManager.getManager();
                            * @author James Duncan Davidson [duncan@eng.sun.com]
                            * @author James Todd [gonzo@eng.sun.com]                                                        ssm.removeSession(this);
                            */                                                                                         }
                                                                                                                   }
                           public class ServerSession {                                                        }

                               private StringManager sm =                                                      synchronized void invalidate() {
                                   StringManager.getManager("org.apache.tomcat.session");                          Enumeration enum = appSessions.keys();                                                            /**
                               private Hashtable values = new Hashtable();                                                                                                                                            * Set the session identifier for this session.
                               private Hashtable appSessions = new Hashtable();                                    while (enum.hasMoreElements()) {                                                                   *
                               private String id;                                                                      Object key = enum.nextElement();                                                               * @param id The new session identifier
                               private long creationTime = System.currentTimeMillis();;                                ApplicationSession appSession =                                                                */
                               private long thisAccessTime = creationTime;                                                 (ApplicationSession)appSessions.get(key);                                                 public void setId(String id) {
                               private long lastAccessed = creationTime;
                               private int inactiveInterval = -1;                                                      appSession.invalidate();
                                                                                                                   }
                               ServerSession(String id) {                                                      }
                                   this.id = id;
                               }                                                                               public void putValue(String name, Object value) {
                                                                                                                   if (name == null) {
                               public String getId() {                                                                 String msg = sm.getString("serverSession.value.iae");
                                   return id;
                               }                                                                                       throw new IllegalArgumentException(msg);
                                                                                                                   }
                               public long getCreationTime() {
                                   return creationTime;                                                            removeValue(name); // remove any existing binding
                               }                                                                                   values.put(name, value);
                                                                                                               }
                               public long getLastAccessedTime() {
                                   return lastAccessed;                                                        public Object getValue(String name) {
                               }                                                                                   if (name == null) {
                                                                                                                       String msg = sm.getString("serverSession.value.iae");
                               public ApplicationSession getApplicationSession(Context context,
                                   boolean create) {                                                                   throw new IllegalArgumentException(msg);
                                   ApplicationSession appSession =                                                 }                                                                                                     if ((this.id != null) && (manager != null) &&
                                       (ApplicationSession)appSessions.get(context);                                                                                                                                       (manager instanceof ManagerBase))
                                                                                                                   return values.get(name);                                                                                  ((ManagerBase) manager).remove(this);
                                   if (appSession == null && create) {                                         }

                                       // XXX                                                                  public Enumeration getValueNames() {
                                       // sync to ensure valid?                                                    return values.keys();
                                                                                                               }
                                       appSession = new ApplicationSession(id, this, context);
                                       appSessions.put(context, appSession);                                   public void removeValue(String name) {
                                   }                                                                               values.remove(name);
                                                                                                               }
                                   // XXX
                                   // make sure that we haven't gone over the end of our                       public void setMaxInactiveInterval(int interval) {
                                   // inactive interval -- if so, invalidate and create                            inactiveInterval = interval;
                                   // a new appSession                                                         }

                                   return appSession;                                                          public int getMaxInactiveInterval() {
                               }                                                                                   return inactiveInterval;
                                                                                                               }
                               void removeApplicationSession(Context context) {
                                   appSessions.remove(context);                                                // XXX
                               }                                                                               // sync'd for safty -- no other thread should be getting something
                                                                                                               // from this while we are reaping. This isn't the most optimal
                               /**                                                                             // solution for this, but we'll determine something else later.                                           this.id = id;
                                * Called by context when request comes in so that accesses and
                                * inactivities can be dealt with accordingly.                                  synchronized void reap() {
                                */                                                                                 Enumeration enum = appSessions.keys();

                               void accessed() {                                                                   while (enum.hasMoreElements()) {
                                   // set last accessed to thisAccessTime as it will be left over




                                                                                                                                                                                                                         if ((manager != null) && (manager instanceof ManagerBase))
                                                                                                                                                                                                                             ((ManagerBase) manager).add(this);




                                                                                                                                                                                                                     }




                                                                                                                                                                                                                     /**
                                                                                                                                                                                                                      * Return descriptive information about this Session implementation and
                                                                                                                                                                                                                      * the corresponding version number, in the format
                                                                                                                                                                                                                      * <code>&lt;description&gt;/&lt;version&gt;</code>.
                                                                                                                                                                                                                      */
                                                                                                                                                                                                                     public String getInfo() {




                                                                                                                                                                                                                         return (this.info);




                                                                                                                                                                                                                     }




                                                                                                                                                                                                                     /**
                                                                                                                                                                                                                      * Return the last time the client sent a request associated with this
                                                                                                                                                                                                                      * session, as the number of milliseconds since midnight, January 1, 1970
                                                                                                                                                                                                                      * GMT. Actions that your application takes, such as getting or setting
                                                                                                                                                                                                                      * a value associated with the session, do not affect the access time.
                                                                                                                                                                                                                      */
                                                                                                                                                                                                                     public long getLastAccessedTime() {

                                                                                                                                                                                                                         return (this.lastAccessedTime);

                                                                                                                                                                                                                     }


                                                                                                                                                                                                                     /**
                                                                                                                                                                                                                      * Return the Manager within which this Session is valid.
                                                                                                                                                                                                                      */
                                                                                                                                                                                                                     public Manager getManager() {

                                                                                                                                                                                                                         return (this.manager);

                                                                                                                                                                                                                     }


                                                                                                                                                                                                                     /**
                                                                                                                                                                                                                      * Set the Manager within which this Session is valid.
                                                                                                                                                                                                                      *
                                                                                                                                                                                                                      * @param manager The new Manager
                                                                                                                                                                                                                      */
                                                                                                                                                                                                                     public void setManager(Manager manager) {




                                                                                                                                                                                                                                                                                                                                                                                                                                                                        10
Crosscutting Concerns


                           /*                                                                                              public void invalidate() {                                                          ;                                                                                                                                                                 * Remove the object bound with the specified name from this session. If
                            * ====================================================================                                 serverSession.removeApplicationSession(context);                                                                                                                                                                                                   * the session does not have an object bound with this name, this method
                            *                                                                                                                                                                                                                                                                                                                                                         * does nothing.
                            * The Apache Software License, Version 1.1                                                                   // remove everything in the session                                   /**                                                                                                                                                                    * <p>
                            *                                                                                                                                                                                   * Standard implementation of the <b>Session</b> interface. This object is                                                                                             * After this method executes, and if the object implements
                            * Copyright (c) 1999 The Apache Software Foundation. All rights                                              Enumeration enum = values.keys();                                      * serializable, so that it can be stored in persistent storage or transferred                                                                                         * <code>HttpSessionBindingListener</code>, the container calls
                            * reserved.                                                                                                  while (enum.hasMoreElements()) {                                       * to a different JVM for distributable session support.                                                                                                               * <code>valueUnbound()</code> on the object.
                            *                                                                                                                String name = (String)enum.nextElement();                          * <p>                                                                                                                                                                 *
                            * Redistribution and use in source and binary forms, with or without                                             removeValue(name);                                                 * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the                                                                                           * @param name Name of the object to remove from this session.
                            * modification, are permitted provided that the following conditions                                         }                                                                      * internal (Session) and application level (HttpSession) view of the session.                                                                                         *
                            * are met:                                                                                                                                                                          * However, because the class itself is not declared public, Java logic outside                                                                                        * @exception IllegalStateException if this method is called on an
                            *                                                                                                            valid = false;                                                         * of the <code>org.apache.tomcat.session</code> package cannot cast an                                                                                                * invalidated session
                            * 1. Redistributions of source code must retain the above copyright                                   }                                                                             * HttpSession view of this instance back to a Session view.                                                                                                           */
                            *    notice, this list of conditions and the following disclaimer.                                                                                                                  *                                                                                                                                                                    public void removeAttribute(String name) {
                            *                                                                                                     public boolean isNew() {                                                      * @author Craig R. McClanahan
                            * 2. Redistributions in binary form must reproduce the above copyright                                    if (! valid) {                                                            * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $                                                                                                                 synchronized (attributes) {
                            *    notice, this list of conditions and the following disclaimer in                                          String msg = sm.getString("applicationSession.session.ise");          */                                                                                                                                                                           Object object = attributes.get(name);
                            *    the documentation and/or other materials provided with the                                                                                                                                                                                                                                                                                                  if (object == null)
                            *    distribution.                                                                                               throw new IllegalStateException(msg);                             final class StandardSession                                                                                                                                                       return;
                            *                                                                                                            }                                                                         implements HttpSession, Session {                                                                                                                                         attributes.remove(name);
                            * 3. The end-user documentation included with the redistribution, if                                                                                                                                                                                                                                                                                             //      System.out.println( "Removing attribute " + name );
                            *    any, must include the following acknowledgment:                                                         if (thisAccessTime == creationTime) {                                                                                                                     /**                                                                                       if (object instanceof HttpSessionBindingListener) {
                            *       "This product includes software developed by the                                                         return true;                                                            // ----------------------------------------------------------- Constructors    * Update the accessed time information for this session. This method                         ((HttpSessionBindingListener) object).valueUnbound
                            *        Apache Software Foundation (http://www.apache.org/)."                                               } else {                                                                                                                                                   * should be called by the context when a request comes in for a particular                       (new HttpSessionBindingEvent((HttpSession) this, name));
                            *    Alternately, this acknowledgment may appear in the software                                                 return false;                                                                                                                                          * session, even if the application does not reference it.                                }
                           itself,                                                                                                       }                                                                           /**                                                                            */                                                                                   }
                            *    if and wherever such third-party acknowledgments normally appear.                                }                                                                                   * Construct a new Session associated with the specified Manager.             public void access() {
                            *                                                                                                                                                                                         *                                                                                                                                                              }
                            * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software                                                                                                                      * @param manager The manager with which this Session is associated                 this.lastAccessedTime = this.thisAccessedTime;




• Crosscutting concerns
                            *    Foundation" must not be used to endorse or promote products                               /**                                                                                        */                                                                                 this.thisAccessedTime = System.currentTimeMillis();                     * Bind an object to this session, using the specified name. If an object
                           derived                                                                                                    * @deprecated                                                                  public StandardSession(Manager manager) {                                           this.isNew=false;                                                            * of the same name is already bound to this session, the object is
                            *    from this software without prior written permission. For written                                     */                                                                                                                                                           }                                                                                  * replaced.
                            *    permission, please contact apache@apache.org.                                                                                                                                           super();                                                                                                                                                     * <p>
                            *                                                                                                     public void putValue(String name, Object value) {                                      this.manager = manager;                                                                                                                                      * After this method executes, and if the object implements
                            * 5. Products derived from this software may not be called "Apache"                                       setAttribute(name, value);                                                                                                                                   /**                                                                                * <code>HttpSessionBindingListener</code>, the container calls
                            *    nor may "Apache" appear in their names without prior written                                     }                                                                                  }                                                                              * Perform the internal processing required to invalidate this session,            * <code>valueBound()</code> on the object.
                            *    permission of the Apache Group.                                                                                                                                                                                                                                    * without triggering an exception if the session has already expired.             *
                            *                                                                                                     public void setAttribute(String name, Object value) {                                                                                                             */                                                                                * @param name Name to which the object is bound, cannot be null
                            * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED                                        if (! valid) {                                                           /**                                                                                 public void expire() {                                                             * @param value Object to be bound, cannot be null
                            * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES                                           String msg = sm.getString("applicationSession.session.ise");                * The last accessed time for this Session.                                                                                                                      *
                            * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                                                                                                                             */                                                                                 // Remove this session from our manager's active sessions                    * @exception IllegalArgumentException if an attempt is made to add a
                            * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR                                                throw new IllegalStateException(msg);                                   private long lastAccessedTime = creationTime;                                       if ((manager != null) && (manager instanceof ManagerBase))                   * non-serializable object in an environment marked distributable.
                            * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,                                           }                                                                                                                                                                   ((ManagerBase) manager).remove(this);                                    * @exception IllegalStateException if this method is called on an
                            * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT                                                                                                                                                                                                                                                                                        * invalidated session
                            * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF                                           if (name == null) {                                                         /**                                                                                 // Unbind any objects associated with this session                           */
                            * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND                                            String msg = sm.getString("applicationSession.value.iae");               * The Manager with which this Session is associated.                               Vector results = new Vector();                                              public void setAttribute(String name, Object value) {
                            * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,                                                                                                                      */                                                                                 Enumeration attrs = getAttributeNames();
                            * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT                                             throw new IllegalArgumentException(msg);                                private Manager manager = null;                                                     while (attrs.hasMoreElements()) {                                               if ((manager != null) && manager.getDistributable() &&
                            * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF                                         }                                                                                                                                                                   String attr = (String) attrs.nextElement();                                   !(value instanceof Serializable))
                            * SUCH DAMAGE.                                                                                                                                                                                                                                                                   results.addElement(attr);                                                       throw new IllegalArgumentException
                            * ====================================================================                                       removeValue(name);     // remove any existing binding                       /**                                                                                 }                                                                                       (sm.getString("standardSession.setAttribute.iae"));
                            *                                                                                                                                                                                         * The maximum time interval, in seconds, between client requests before            Enumeration names = results.elements();
                            * This software consists of voluntary contributions made by many                                             if (value != null && value instanceof HttpSessionBindingListener) {          * the servlet container may invalidate this session. A negative time               while (names.hasMoreElements()) {                                               synchronized (attributes) {
                            * individuals on behalf of the Apache Software Foundation. For more                                              HttpSessionBindingEvent e =                                              * indicates that the session should never time out.                                    String name = (String) names.nextElement();                                     removeAttribute(name);
                            * information on the Apache Software Foundation, please see                                                          new HttpSessionBindingEvent(this, name);                             */                                                                                     removeAttribute(name);                                                          attributes.put(name, value);
                            * <http://www.apache.org/>.                                                                                                                                                              private int maxInactiveInterval = -1;                                               }                                                                                   if (value instanceof HttpSessionBindingListener)
                            *                                                                                                                ((HttpSessionBindingListener)value).valueBound(e);                                                                                                                                                                                                  ((HttpSessionBindingListener) value).valueBound
                            * [Additional notices, if required by prior licensing conditions]                                            }                                                                                                                                                               // Mark this session as invalid                                                             (new HttpSessionBindingEvent((HttpSession) this, name));
                            *                                                                                                                                                                                        /**                                                                                 setValid(false);                                                                }
                            */                                                                                                           values.put(name, value);                                                     * Flag indicating whether this session is new or not.
                                                                                                                                  }                                                                                   */                                                                           }                                                                                 }
                                                                                                                                                                                                                     private boolean isNew = true;
                                                                                                                                  /**
                           package org.apache.tomcat.session;                                                                       * @deprecated                                                                                                                                                  /**                                                                               // -------------------------------------------- HttpSession Private Methods
                                                                                                                                    */                                                                               /**
                           import org.apache.tomcat.core.*;                                                                       public Object getValue(String name) {                                               * Flag indicating whether this session is valid or not.                      }
                           import org.apache.tomcat.util.StringManager;                                                                return getAttribute(name);                                                     */                                                                                                                                                             /**
                           import java.io.*;                                                                                      }                                                                                  private boolean isValid = false;                                                                                                                                 * Read a serialized version of this session object from the specified
                           import java.net.*;                                                                                                                                                                                                                                                      /**                                                                                * object input stream.
                           import java.util.*;                                                                                    public Object getAttribute(String name) {                                                                                                                         * Set the <code>isNew</code> flag for this session.                               * <p>
                           import javax.servlet.*;                                                                                    if (! valid) {                                                                 /**                                                                            *                                                                                 * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager
                           import javax.servlet.http.*;                                                                                   String msg = sm.getString("applicationSession.session.ise");                * The string manager for this package.                                        * @param isNew The new value for the <code>isNew</code> flag                      * is not restored by this method, and must be set explicitly.
                                                                                                                                                                                                                      */                                                                            */                                                                                *
                           /**                                                                                                               throw new IllegalStateException(msg);                                   private StringManager sm =                                                    void setNew(boolean isNew) {                                                       * @param stream The input stream to read from
                            * Core implementation of an application level session                                                        }                                                                               StringManager.getManager("org.apache.tomcat.session");                                                                                                       *
                            *                                                                                                                                                                                                                                                                            this.isNew = isNew;                                                          * @exception ClassNotFoundException if an unknown class is specified
                            * @author James Duncan Davidson [duncan@eng.sun.com]                                                         if (name == null) {                                                                                                                                                                                                                          * @exception IOException if an input/output error occurs




  (CCCs) affect many
                            * @author Jason Hunter [jch@eng.sun.com]                                                                         String msg = sm.getString("applicationSession.value.iae");              /**                                                                           }                                                                                  */
                            * @author James Todd [gonzo@eng.sun.com]                                                                                                                                                  * The HTTP session context associated with this session.                                                                                                       private void readObject(ObjectInputStream stream)
                            */                                                                                                               throw new IllegalArgumentException(msg);                                 */                                                                                                                                                                 throws ClassNotFoundException, IOException {
                                                                                                                                         }                                                                           private static HttpSessionContext sessionContext = null;                      /**
                           public class ApplicationSession implements HttpSession {                                                                                                                                                                                                                 * Set the <code>isValid</code> flag for this session.                                // Deserialize the scalar instance variables (except Manager)
                                                                                                                                         return values.get(name);                                                                                                                                   *                                                                                    creationTime = ((Long) stream.readObject()).longValue();
                               private StringManager sm =                                                                         }                                                                                  /**                                                                            * @param isValid The new value for the <code>isValid</code> flag                     id = (String) stream.readObject();
                                   StringManager.getManager("org.apache.tomcat.session");                                                                                                                             * The current accessed time for this session.                                 */                                                                                   lastAccessedTime = ((Long) stream.readObject()).longValue();
                               private Hashtable values = new Hashtable();                                                        /**                                                                                 */                                                                           void setValid(boolean isValid) {                                                      maxInactiveInterval = ((Integer) stream.readObject()).intValue();
                               private String id;                                                                                  * @deprecated                                                                     private long thisAccessedTime = creationTime;                                                                                                                       isNew = ((Boolean) stream.readObject()).booleanValue();
                               private ServerSession serverSession;                                                                */                                                                                                                                                                    this.isValid = isValid;                                                         isValid = ((Boolean) stream.readObject()).booleanValue();
                               private Context context;                                                                           public String[] getValueNames() {                                                                                                                                }
                               private long creationTime = System.currentTimeMillis();;                                               Enumeration e = getAttributeNames();                                                                                                                                                                                                               // Deserialize the attribute count and attribute values
                               private long thisAccessTime = creationTime;                                                            Vector names = new Vector();                                                                                                                                                                                                                       int n = ((Integer) stream.readObject()).intValue();
                               private long lastAccessed = creationTime;                                                                                                                                             // ----------------------------------------------------- Session Properties   // ------------------------------------------------- HttpSession Properties           for (int i = 0; i < n; i++) {
                               private int inactiveInterval = -1;                                                                        while (e.hasMoreElements()) {                                                                                                                                                                                                                       String name = (String) stream.readObject();
                               private boolean valid = true;                                                                                 names.addElement(e.nextElement());                                                                                                                                                                                                              Object value = (Object) stream.readObject();
                                                                                                                                         }                                                                           /**                                                                           /**                                                                                       attributes.put(name, value);
                               ApplicationSession(String id, ServerSession serverSession,                                                                                                                             * Set the creation time for this session. This method is called by the        * Return the time when this session was created, in milliseconds since               }
                                   Context context) {                                                                                    String[] valueNames = new String[names.size()];                              * Manager when an existing Session instance is reused.                        * midnight, January 1, 1970 GMT.
                                   this.serverSession = serverSession;                                                                                                                                                *                                                                             *                                                                                }
                                   this.context = context;                                                                               names.copyInto(valueNames);                                                  * @param time The new creation time                                           * @exception IllegalStateException if this method is called on an
                                   this.id = id;                                                                                                                                                                      */                                                                            * invalidated session
                                                                                                                                         return valueNames;                                                          public void setCreationTime(long time) {                                       */                                                                               /**
                                   this.inactiveInterval = context.getSessionTimeOut();                                                                                                                                                                                                            public long getCreationTime() {                                                    * Write a serialized version of this session object to the specified
                                                                                                                                  }                                                                                      this.creationTime = time;                                                                                                                                    * object output stream.
                                   if (this.inactiveInterval != -1) {                                                                                                                                                    this.lastAccessedTime = time;                                                   return (this.creationTime);                                                  * <p>
                                       this.inactiveInterval *= 60;                                                               public Enumeration getAttributeNames() {                                               this.thisAccessedTime = time;                                                                                                                                * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored
                                   }                                                                                                  if (! valid) {                                                                                                                                               }                                                                                  * in the serialized representation of this Session. After calling
                               }                                                                                                          String msg = sm.getString("applicationSession.session.ise");                                                                                                                                                                                * <code>readObject()</code>, you must set the associated Manager
                                                                                                                                                                                                                                                                                                                                                                                      * explicitly.
                               ServerSession getServerSession() {                                                                            throw new IllegalStateException(msg);                                                                                                                 /**                                                                                * <p>
                                   return serverSession;                                                                                 }                                                                                                                                                          * Return the session context with which this session is associated.               * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable
                               }                                                                                                                                                                                                                                                                    *                                                                                 * will be silently ignored. If you do not want any such attributes,
                                                                                                                                         Hashtable valuesClone = (Hashtable)values.clone();                                                                                                         * @deprecated As of Version 2.1, this method is deprecated and has no             * be sure the <code>distributable</code> property of our associated




  heterogeneous software
                               /**                                                                                                                                                                                                                                                                  * replacement. It will be removed in a future version of the                      * Manager is set to <code>true</code>.
                                * Called by context when request comes in so that accesses and                                           return (Enumeration)valuesClone.keys();                                                                                                                    * Java Servlet API.                                                               *
                                * inactivities can be dealt with accordingly.                                                     }                                                                                                                                                                 */                                                                                * @param stream The output stream to write to
                                */                                                                                                                                                                                                                                                                 public HttpSessionContext getSessionContext() {                                    *
                                                                                                                                                                                                                                                                                                                                                                                      * @exception IOException if an input/output error occurs
                               void accessed() {                                                                            /**                                                                                                                                                                          if (sessionContext == null)                                                  */
                                   // set last accessed to thisAccessTime as it will be left over                                     * @deprecated                                                                                                                                                          sessionContext = new StandardSessionContext();                          private void writeObject(ObjectOutputStream stream) throws IOException {
                                   // from the previous access                                                                        */                                                                                                                                                                 return (sessionContext);
                                   lastAccessed = thisAccessTime;                                                                                                                                                                                                                                                                                                                        // Write the scalar instance variables (except Manager)
                                   thisAccessTime = System.currentTimeMillis();                                                   public void removeValue(String name) {                                                                                                                           }                                                                                     stream.writeObject(new Long(creationTime));
                                                                                                                                      removeAttribute(name);                                                                                                                                                                                                                             stream.writeObject(id);
                                   validate();                                                                                    }                                                                                                                                                                                                                                                      stream.writeObject(new Long(lastAccessedTime));
                               }                                                                                                                                                                                                                                                                   // ----------------------------------------------HttpSession Public Methods           stream.writeObject(new Integer(maxInactiveInterval));
                                                                                                                                  public void removeAttribute(String name) {                                                                                                                                                                                                             stream.writeObject(new Boolean(isNew));
                               void validate() {                                                                                      if (! valid) {                                                                 }                                                                                                                                                                   stream.writeObject(new Boolean(isValid));
                                   // if we have an inactive interval, check to see if we've exceeded it                                  String msg = sm.getString("applicationSession.session.ise");                                                                                             /**
                                   if (inactiveInterval != -1) {                                                                                                                                                                                                                                    * Return the object bound with the specified name in this session, or                // Accumulate the names of serializable attributes
                                       int thisInterval =                                                                                    throw new IllegalStateException(msg);                                                                                                                  * <code>null</code> if no object is bound with that name.                            Vector results = new Vector();
                                           (int)(System.currentTimeMillis() - lastAccessed) / 1000;                                      }                                                                                                                                                          *                                                                                    Enumeration attrs = getAttributeNames();
                                                                                                                                                                                                                                                                                                    * @param name Name of the attribute to be returned                                   while (attrs.hasMoreElements()) {
                                       if (thisInterval > inactiveInterval) {                                                            if (name == null) {                                                                                                                                        *                                                                                        String attr = (String) attrs.nextElement();
                                           invalidate();                                                                                     String msg = sm.getString("applicationSession.value.iae");                                                                                             * @exception IllegalStateException if this method is called on an                        Object value = attributes.get(attr);
                                       }                                                                                                                                                                                                                                                            * invalidated session                                                                    if (value instanceof Serializable)
                                   }                                                                                                         throw new IllegalArgumentException(msg);                                                                                                               */                                                                                           results.addElement(attr);
                               }                                                                                                         }                                                                                                                                                         public Object getAttribute(String name) {                                             }

                               // HTTP SESSION IMPLEMENTATION METHODS                                                                    Object o = values.get(name);                                                                                                                                    return (attributes.get(name));                                                  // Serialize the attribute count and the attribute values
                                                                                                                                                                                                                                                                                                                                                                                         stream.writeObject(new Integer(results.size()));
                               public String getId() {                                                                                   if (o instanceof HttpSessionBindingListener) {                                                                                                            }                                                                                     Enumeration names = results.elements();
                                   if (valid) {                                                                                              HttpSessionBindingEvent e =                                                                                                                                                                                                                 while (names.hasMoreElements()) {
                                       return id;                                                                                                new HttpSessionBindingEvent(this,name);                                                                                                                                                                                                     String name = (String) names.nextElement();
                                   } else {                                                                                                                                                                                                                                                        /**                                                                                       stream.writeObject(name);
                                       String msg = sm.getString("applicationSession.session.ise");                                          ((HttpSessionBindingListener)o).valueUnbound(e);                                                                                                       * Return an <code>Enumeration</code> of <code>String</code> objects                      stream.writeObject(attributes.get(name));
                                                                                                                                         }                                                                                                                                                          * containing the names of the objects bound to this session.                         }
                                       throw new IllegalStateException(msg);                                                                                                                                                                                                                        *




  modules.
                                   }                                                                                                     values.remove(name);                                                                                                                                       * @exception IllegalStateException if this method is called on an
                               }                                                                                                  }                                                                                                                                                                 * invalidated session                                                            }
                                                                                                                                                                                                                                                                                                    */
                               public long getCreationTime() {                                                                    public void setMaxInactiveInterval(int interval) {                                                                                                               public Enumeration getAttributeNames() {                                          crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() |
                                   if (valid) {                                                                                       if (! valid) {                                                                                                                                                                                                                                                                              long getCreationTime() |
                                       return creationTime;                                                                               String msg = sm.getString("applicationSession.session.ise");                                                                                                   return (attributes.keys());                                                                                              Object getAttribute(String) |
                                   } else {                                                                                                                                                                                                                                                                                                                                                                                       Enumeration getAttributeNames() |
                                       String msg = sm.getString("applicationSession.session.ise");                                          throw new IllegalStateException(msg);                                                                                                                 }                                                                                                                              String[] getValueNames() |
                                                                                                                                         }                                                                                                                                                                                                                                                                                        void invalidate() |
                                       throw new IllegalStateException(msg);                                                                                                                                                                                                                                                                                                                                                      boolean isNew() |
                                   }                                                                                                                                                                                                                                                               /**                                                                                                                            void removeAttribute(String) |
                               }                                                                                                                                                                                                                                                                    * Return the object bound with the specified name in this session, or                                                         void setAttribute(String, Object));
                                                                                                                                                                                                                                                                                                    * <code>null</code> if no object is bound with that name.
                               /**                                                                                                                                                                                                                                                                  *                                                                                static advice(StandardSession s): invalidate(s) {
                                *                                                                                                                                                                                                                                                                   * @param name Name of the value to be returned                                       before {
                                * @deprecated                                                                                                                                                                                                                                                       *                                                                                        if (!s.isValid())
                                                                                                                                                                                                                                                                                                    * @exception IllegalStateException if this method is called on an                             throw new IllegalStateException
                                                                                                                                                                                                                                                                                                    * invalidated session                                                                             (s.sm.getString("standardSession."
                                                                                                                                                                                                                                                                                                    *                                                                                                                 + thisJoinPoint.methodName
                                                                                                                                                                                                                                                                                                    * @deprecated As of Version 2.2, this method is replaced by                                                       + ".ise"));
                                                                                                                                                                                                                                                                                                    * <code>getAttribute()</code>                                                        }
                                                                                                                                                                                                                                                                                                    */                                                                               }
                                                                                                                                                                                                                     /**                                                                           public Object getValue(String name) {
                                                                                                                                                                                                                      * Return the session identifier for this session.
                                                                                                                                                                                                                      */                                                                                 return (getAttribute(name));
                                                                                                                                                                                                                     public String getId() {
                                                                                                                                                                                                                                                                                                   }                                                                             }


                                                                                                                                                                                                                                                                                                   /**                                                                           // -------------------------------------------------------------- Private Class
                                                                                                                                                                                                                                                                                                    * Return the set of names of objects bound to this session. If there
                                                                                                                                                                                                                                                                                                    * are no such objects, a zero-length array is returned.
                                                                                                                                                                                                                                                                                                    *                                                                            /**
                                                                                                                                                                                                                                                                                                    * @exception IllegalStateException if this method is called on an             * This class is a dummy implementation of the <code>HttpSessionContext</code>
                                                                                                                                                                                                                                                                                                    * invalidated session                                                         * interface, to conform to the requirement that such an object be returned
                                                                                                                                                                                                                                                                                                    *                                                                             * when <code>HttpSession.getSessionContext()</code> is called.
                                                                                                                                                                                                                                                                                                    * @deprecated As of Version 2.2, this method is replaced by                   *
                                                                                                                                                                                                                                                                                                    * <code>getAttributeNames()</code>                                            * @author Craig R. McClanahan
                                                                                                                                                                                                                                                                                                    */                                                                            *
                                                                                                                                                                                                                                                                                                   public String[] getValueNames() {                                              * @deprecated As of Java Servlet API 2.1 with no replacement. The
                                                                                                                                                                                                                                                                                                                                                                                  * interface will be removed in a future version of this API.
                                                                                                                                                                                                                                                                                                         Vector results = new Vector();                                           */
                                                                                                                                                                                                                                                                                                         Enumeration attrs = getAttributeNames();
                                                                                                                                                                                                                                                                                                         while (attrs.hasMoreElements()) {                                       final class StandardSessionContext implements HttpSessionContext {
                                                                                                                                                                                                                                                                                                             String attr = (String) attrs.nextElement();
                                                                                                                                                                                                                                                                                                             results.addElement(attr);
                                                                                                                                                                                                                                                                                                         }                                                                           private Vector dummy = new Vector();
                                                                                                                                                                                                                         return (this.id);                                                               String names[] = new String[results.size()];
                                                                                                                                                                                                                                                                                                         for (int i = 0; i < names.length; i++)                                      /**
                                                                                                                                                                                                                                                                                                             names[i] = (String) results.elementAt(i);                                * Return the session identifiers of all sessions defined
                                                                                                                                                                                                                                                                                                         return (names);                                                              * within this context.
                                                                                                                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                                   }                                                                                  * @deprecated As of Java Servlet API 2.1 with no replacement.
                                                                                                                                                                                                                                                                                                                                                                                      * This method must return an empty <code>Enumeration</code>
                                                                                                                                                                                                                                                                                                                                                                                      * and will be removed in a future version of the API.
                                                                                                                                                                                                                                                                                                   /**                                                                                */
                                                                                                                                                                                                                                                                                                    * Invalidates this session and unbinds any objects bound to it.                  public Enumeration getIds() {
                                                                                                                                                                                                                                                                                                    *
                                                                                                                                                                                                                                                                                                    * @exception IllegalStateException if this method is called on                       return (dummy.elements());
                                                                                                                                                                                                                                                                                                    * an invalidated session




• Code is:
                                                                                                                                                                                                                                                                                                    */
                                                                                                                                                                                                                                                                                                   public void invalidate() {

                                                                                                                                                                                                                                                                                                         // Cause this session to expire
                                                                                                                                                                                                                                                                                                         expire();

                                                                                                                                                                                                                                                                                                   }


                                                                                                                                                                                                                     }                                                                             /**
                                                                                                                                                                                                                                                                                                    * Return <code>true</code> if the client does not yet know about the
                                                                                                                                                                                                                                                                                                    * session, or if the client chooses not to join the session. For
                                                                                                                                                                                                                                                                                                    * example, if the server used only cookie-based sessions, and the client
                                                                                                                                                                                                                                                                                                    * has disabled the use of cookies, then a session would be new on each
                                                                                                                                                                                                                                                                                                    * request.
                                                                                                                                                                                                                                                                                                    *
                                                                                                                                                                                                                                                                                                    * @exception IllegalStateException if this method is called on an
                                                                                                                                                                                                                                                                                                    * invalidated session
                                                                                                                                                                                                                                                                                                    */
                                                                                                                                                                                                                                                                                                   public boolean isNew() {

                                                                                                                                                                                                                                                                                                         return (this.isNew);

                                                                                                                                                                                                                                                                                                   }




                           package org.apache.tomcat.session;                                              void validate() {
                                                                                                                   // if we have an inactive interval, check to see if
                           import org.apache.tomcat.core.*;                                                        // we've exceeded it
                           import org.apache.tomcat.util.StringManager;
                           import java.io.*;                                                                       if (inactiveInterval != -1) {
                           import java.net.*;                                                                          int thisInterval =
                           import java.util.*;                                                                             (int)(System.currentTimeMillis() - lastAccessed) / 1000;
                           import javax.servlet.*;
                           import javax.servlet.http.*;                                                                if (thisInterval > inactiveInterval) {
                                                                                                                           invalidate();
                           /**
                            * Core implementation of a server session                                                       ServerSessionManager ssm =
                            *                                                                                                   ServerSessionManager.getManager();
                            * @author James Duncan Davidson [duncan@eng.sun.com]
                            * @author James Todd [gonzo@eng.sun.com]                                                        ssm.removeSession(this);
                            */                                                                                         }
                                                                                                                   }
                           public class ServerSession {                                                        }

                               private StringManager sm =                                                      synchronized void invalidate() {
                                   StringManager.getManager("org.apache.tomcat.session");                          Enumeration enum = appSessions.keys();                                                            /**
                               private Hashtable values = new Hashtable();                                                                                                                                            * Set the session identifier for this session.
                               private Hashtable appSessions = new Hashtable();                                    while (enum.hasMoreElements()) {                                                                   *
                               private String id;                                                                      Object key = enum.nextElement();                                                               * @param id The new session identifier
                               private long creationTime = System.currentTimeMillis();;                                ApplicationSession appSession =                                                                */
                               private long thisAccessTime = creationTime;                                                 (ApplicationSession)appSessions.get(key);                                                 public void setId(String id) {
                               private long lastAccessed = creationTime;
                               private int inactiveInterval = -1;                                                      appSession.invalidate();
                                                                                                                   }
                               ServerSession(String id) {                                                      }
                                   this.id = id;
                               }                                                                               public void putValue(String name, Object value) {
                                                                                                                   if (name == null) {
                               public String getId() {                                                                 String msg = sm.getString("serverSession.value.iae");
                                   return id;
                               }                                                                                       throw new IllegalArgumentException(msg);
                                                                                                                   }
                               public long getCreationTime() {
                                   return creationTime;                                                            removeValue(name); // remove any existing binding
                               }                                                                                   values.put(name, value);
                                                                                                               }




 • Scattered throughout
                               public long getLastAccessedTime() {
                                   return lastAccessed;                                                        public Object getValue(String name) {
                               }                                                                                   if (name == null) {
                                                                                                                       String msg = sm.getString("serverSession.value.iae");
                               public ApplicationSession getApplicationSession(Context context,
                                   boolean create) {                                                                   throw new IllegalArgumentException(msg);
                                   ApplicationSession appSession =                                                 }                                                                                                     if ((this.id != null) && (manager != null) &&
                                       (ApplicationSession)appSessions.get(context);                                                                                                                                       (manager instanceof ManagerBase))
                                                                                                                   return values.get(name);                                                                                  ((ManagerBase) manager).remove(this);
                                   if (appSession == null && create) {                                         }

                                       // XXX                                                                  public Enumeration getValueNames() {
                                       // sync to ensure valid?                                                    return values.keys();
                                                                                                               }
                                       appSession = new ApplicationSession(id, this, context);
                                       appSessions.put(context, appSession);                                   public void removeValue(String name) {
                                   }                                                                               values.remove(name);
                                                                                                               }
                                   // XXX
                                   // make sure that we haven't gone over the end of our                       public void setMaxInactiveInterval(int interval) {
                                   // inactive interval -- if so, invalidate and create                            inactiveInterval = interval;
                                   // a new appSession                                                         }

                                   return appSession;                                                          public int getMaxInactiveInterval() {
                               }                                                                                   return inactiveInterval;
                                                                                                               }
                               void removeApplicationSession(Context context) {
                                   appSessions.remove(context);                                                // XXX
                               }                                                                               // sync'd for safty -- no other thread should be getting something
                                                                                                               // from this while we are reaping. This isn't the most optimal
                               /**                                                                             // solution for this, but we'll determine something else later.                                           this.id = id;
                                * Called by context when request comes in so that accesses and
                                * inactivities can be dealt with accordingly.                                  synchronized void reap() {
                                */                                                                                 Enumeration enum = appSessions.keys();

                               void accessed() {                                                                   while (enum.hasMoreElements()) {
                                   // set last accessed to thisAccessTime as it will be left over




   many modules.
                                                                                                                                                                                                                         if ((manager != null) && (manager instanceof ManagerBase))
                                                                                                                                                                                                                             ((ManagerBase) manager).add(this);




                                                                                                                                                                                                                     }




                                                                                                                                                                                                                     /**
                                                                                                                                                                                                                      * Return descriptive information about this Session implementation and
                                                                                                                                                                                                                      * the corresponding version number, in the format
                                                                                                                                                                                                                      * <code>&lt;description&gt;/&lt;version&gt;</code>.
                                                                                                                                                                                                                      */
                                                                                                                                                                                                                     public String getInfo() {




                                                                                                                                                                                                                         return (this.info);




                                                                                                                                                                                                                     }




                                                                                                                                                                                                                     /**
                                                                                                                                                                                                                      * Return the last time the client sent a request associated with this
                                                                                                                                                                                                                      * session, as the number of milliseconds since midnight, January 1, 1970
                                                                                                                                                                                                                      * GMT. Actions that your application takes, such as getting or setting
                                                                                                                                                                                                                      * a value associated with the session, do not affect the access time.
                                                                                                                                                                                                                      */
                                                                                                                                                                                                                     public long getLastAccessedTime() {

                                                                                                                                                                                                                         return (this.lastAccessedTime);

                                                                                                                                                                                                                     }


                                                                                                                                                                                                                     /**
                                                                                                                                                                                                                      * Return the Manager within which this Session is valid.
                                                                                                                                                                                                                      */
                                                                                                                                                                                                                     public Manager getManager() {

                                                                                                                                                                                                                         return (this.manager);

                                                                                                                                                                                                                     }


                                                                                                                                                                                                                     /**
                                                                                                                                                                                                                      * Set the Manager within which this Session is valid.
                                                                                                                                                                                                                      *
                                                                                                                                                                                                                      * @param manager The new Manager
                                                                                                                                                                                                                      */
                                                                                                                                                                                                                     public void setManager(Manager manager) {




                                                                                                                                                                                                                                                                                                                                                                                                                                                                        10
Crosscutting Concerns


                            /*                                                                                              public void invalidate() {                                                          ;                                                                                                                                                                 * Remove the object bound with the specified name from this session. If
                             * ====================================================================                                 serverSession.removeApplicationSession(context);                                                                                                                                                                                                   * the session does not have an object bound with this name, this method
                             *                                                                                                                                                                                                                                                                                                                                                         * does nothing.
                             * The Apache Software License, Version 1.1                                                                   // remove everything in the session                                   /**                                                                                                                                                                    * <p>
                             *                                                                                                                                                                                   * Standard implementation of the <b>Session</b> interface. This object is                                                                                             * After this method executes, and if the object implements
                             * Copyright (c) 1999 The Apache Software Foundation. All rights                                              Enumeration enum = values.keys();                                      * serializable, so that it can be stored in persistent storage or transferred                                                                                         * <code>HttpSessionBindingListener</code>, the container calls
                             * reserved.                                                                                                  while (enum.hasMoreElements()) {                                       * to a different JVM for distributable session support.                                                                                                               * <code>valueUnbound()</code> on the object.
                             *                                                                                                                String name = (String)enum.nextElement();                          * <p>                                                                                                                                                                 *
                             * Redistribution and use in source and binary forms, with or without                                             removeValue(name);                                                 * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the                                                                                           * @param name Name of the object to remove from this session.
                             * modification, are permitted provided that the following conditions                                         }                                                                      * internal (Session) and application level (HttpSession) view of the session.                                                                                         *
                             * are met:                                                                                                                                                                          * However, because the class itself is not declared public, Java logic outside                                                                                        * @exception IllegalStateException if this method is called on an
                             *                                                                                                            valid = false;                                                         * of the <code>org.apache.tomcat.session</code> package cannot cast an                                                                                                * invalidated session
                             * 1. Redistributions of source code must retain the above copyright                                   }                                                                             * HttpSession view of this instance back to a Session view.                                                                                                           */
                             *    notice, this list of conditions and the following disclaimer.                                                                                                                  *                                                                                                                                                                    public void removeAttribute(String name) {
                             *                                                                                                     public boolean isNew() {                                                      * @author Craig R. McClanahan
                             * 2. Redistributions in binary form must reproduce the above copyright                                    if (! valid) {                                                            * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $                                                                                                                 synchronized (attributes) {
                             *    notice, this list of conditions and the following disclaimer in                                          String msg = sm.getString("applicationSession.session.ise");          */                                                                                                                                                                           Object object = attributes.get(name);
                             *    the documentation and/or other materials provided with the                                                                                                                                                                                                                                                                                                  if (object == null)
                             *    distribution.                                                                                               throw new IllegalStateException(msg);                             final class StandardSession                                                                                                                                                       return;
                             *                                                                                                            }                                                                         implements HttpSession, Session {                                                                                                                                         attributes.remove(name);
                             * 3. The end-user documentation included with the redistribution, if                                                                                                                                                                                                                                                                                             //      System.out.println( "Removing attribute " + name );
                             *    any, must include the following acknowledgment:                                                         if (thisAccessTime == creationTime) {                                                                                                                     /**                                                                                       if (object instanceof HttpSessionBindingListener) {
                             *       "This product includes software developed by the                                                         return true;                                                            // ----------------------------------------------------------- Constructors    * Update the accessed time information for this session. This method                         ((HttpSessionBindingListener) object).valueUnbound
                             *        Apache Software Foundation (http://www.apache.org/)."                                               } else {                                                                                                                                                   * should be called by the context when a request comes in for a particular                       (new HttpSessionBindingEvent((HttpSession) this, name));
                             *    Alternately, this acknowledgment may appear in the software                                                 return false;                                                                                                                                          * session, even if the application does not reference it.                                }
                            itself,                                                                                                       }                                                                           /**                                                                            */                                                                                   }
                             *    if and wherever such third-party acknowledgments normally appear.                                }                                                                                   * Construct a new Session associated with the specified Manager.             public void access() {
                             *                                                                                                                                                                                         *                                                                                                                                                              }
                             * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software                                                                                                                      * @param manager The manager with which this Session is associated                 this.lastAccessedTime = this.thisAccessedTime;




• Crosscutting concerns
                             *    Foundation" must not be used to endorse or promote products                               /**                                                                                        */                                                                                 this.thisAccessedTime = System.currentTimeMillis();                     * Bind an object to this session, using the specified name. If an object
                            derived                                                                                                    * @deprecated                                                                  public StandardSession(Manager manager) {                                           this.isNew=false;                                                            * of the same name is already bound to this session, the object is
                             *    from this software without prior written permission. For written                                     */                                                                                                                                                           }                                                                                  * replaced.
                             *    permission, please contact apache@apache.org.                                                                                                                                           super();                                                                                                                                                     * <p>
                             *                                                                                                     public void putValue(String name, Object value) {                                      this.manager = manager;                                                                                                                                      * After this method executes, and if the object implements
                             * 5. Products derived from this software may not be called "Apache"                                       setAttribute(name, value);                                                                                                                                   /**                                                                                * <code>HttpSessionBindingListener</code>, the container calls
                             *    nor may "Apache" appear in their names without prior written                                     }                                                                                  }                                                                              * Perform the internal processing required to invalidate this session,            * <code>valueBound()</code> on the object.
                             *    permission of the Apache Group.                                                                                                                                                                                                                                    * without triggering an exception if the session has already expired.             *
                             *                                                                                                     public void setAttribute(String name, Object value) {                                                                                                             */                                                                                * @param name Name to which the object is bound, cannot be null
                             * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED                                        if (! valid) {                                                           /**                                                                                 public void expire() {                                                             * @param value Object to be bound, cannot be null
                             * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES                                           String msg = sm.getString("applicationSession.session.ise");                * The last accessed time for this Session.                                                                                                                      *
                             * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                                                                                                                             */                                                                                 // Remove this session from our manager's active sessions                    * @exception IllegalArgumentException if an attempt is made to add a
                             * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR                                                throw new IllegalStateException(msg);                                   private long lastAccessedTime = creationTime;                                       if ((manager != null) && (manager instanceof ManagerBase))                   * non-serializable object in an environment marked distributable.
                             * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,                                           }                                                                                                                                                                   ((ManagerBase) manager).remove(this);                                    * @exception IllegalStateException if this method is called on an
                             * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT                                                                                                                                                                                                                                                                                        * invalidated session
                             * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF                                           if (name == null) {                                                         /**                                                                                 // Unbind any objects associated with this session                           */
                             * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND                                            String msg = sm.getString("applicationSession.value.iae");               * The Manager with which this Session is associated.                               Vector results = new Vector();                                              public void setAttribute(String name, Object value) {
                             * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,                                                                                                                      */                                                                                 Enumeration attrs = getAttributeNames();
                             * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT                                             throw new IllegalArgumentException(msg);                                private Manager manager = null;                                                     while (attrs.hasMoreElements()) {                                               if ((manager != null) && manager.getDistributable() &&
                             * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF                                         }                                                                                                                                                                   String attr = (String) attrs.nextElement();                                   !(value instanceof Serializable))
                             * SUCH DAMAGE.                                                                                                                                                                                                                                                                   results.addElement(attr);                                                       throw new IllegalArgumentException
                             * ====================================================================                                       removeValue(name);     // remove any existing binding                       /**                                                                                 }                                                                                       (sm.getString("standardSession.setAttribute.iae"));
                             *                                                                                                                                                                                         * The maximum time interval, in seconds, between client requests before            Enumeration names = results.elements();
                             * This software consists of voluntary contributions made by many                                             if (value != null && value instanceof HttpSessionBindingListener) {          * the servlet container may invalidate this session. A negative time               while (names.hasMoreElements()) {                                               synchronized (attributes) {
                             * individuals on behalf of the Apache Software Foundation. For more                                              HttpSessionBindingEvent e =                                              * indicates that the session should never time out.                                    String name = (String) names.nextElement();                                     removeAttribute(name);
                             * information on the Apache Software Foundation, please see                                                          new HttpSessionBindingEvent(this, name);                             */                                                                                     removeAttribute(name);                                                          attributes.put(name, value);
                             * <http://www.apache.org/>.                                                                                                                                                              private int maxInactiveInterval = -1;                                               }                                                                                   if (value instanceof HttpSessionBindingListener)
                             *                                                                                                                ((HttpSessionBindingListener)value).valueBound(e);                                                                                                                                                                                                  ((HttpSessionBindingListener) value).valueBound
                             * [Additional notices, if required by prior licensing conditions]                                            }                                                                                                                                                               // Mark this session as invalid                                                             (new HttpSessionBindingEvent((HttpSession) this, name));
                             *                                                                                                                                                                                        /**                                                                                 setValid(false);                                                                }
                             */                                                                                                           values.put(name, value);                                                     * Flag indicating whether this session is new or not.
                                                                                                                                   }                                                                                   */                                                                           }                                                                                 }
                                                                                                                                                                                                                      private boolean isNew = true;
                                                                                                                                   /**
                            package org.apache.tomcat.session;                                                                       * @deprecated                                                                                                                                                  /**                                                                               // -------------------------------------------- HttpSession Private Methods
                                                                                                                                     */                                                                               /**
                            import org.apache.tomcat.core.*;                                                                       public Object getValue(String name) {                                               * Flag indicating whether this session is valid or not.                      }
                            import org.apache.tomcat.util.StringManager;                                                                return getAttribute(name);                                                     */                                                                                                                                                             /**
                            import java.io.*;                                                                                      }                                                                                  private boolean isValid = false;                                                                                                                                 * Read a serialized version of this session object from the specified
                            import java.net.*;                                                                                                                                                                                                                                                      /**                                                                                * object input stream.
                            import java.util.*;                                                                                    public Object getAttribute(String name) {                                                                                                                         * Set the <code>isNew</code> flag for this session.                               * <p>
                            import javax.servlet.*;                                                                                    if (! valid) {                                                                 /**                                                                            *                                                                                 * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager
                            import javax.servlet.http.*;                                                                                   String msg = sm.getString("applicationSession.session.ise");                * The string manager for this package.                                        * @param isNew The new value for the <code>isNew</code> flag                      * is not restored by this method, and must be set explicitly.
                                                                                                                                                                                                                       */                                                                            */                                                                                *
                            /**                                                                                                               throw new IllegalStateException(msg);                                   private StringManager sm =                                                    void setNew(boolean isNew) {                                                       * @param stream The input stream to read from
                             * Core implementation of an application level session                                                        }                                                                               StringManager.getManager("org.apache.tomcat.session");                                                                                                       *
                             *                                                                                                                                                                                                                                                                            this.isNew = isNew;                                                          * @exception ClassNotFoundException if an unknown class is specified
                             * @author James Duncan Davidson [duncan@eng.sun.com]                                                         if (name == null) {                                                                                                                                                                                                                          * @exception IOException if an input/output error occurs




  (CCCs) affect many
                             * @author Jason Hunter [jch@eng.sun.com]                                                                         String msg = sm.getString("applicationSession.value.iae");              /**                                                                           }                                                                                  */
                             * @author James Todd [gonzo@eng.sun.com]                                                                                                                                                  * The HTTP session context associated with this session.                                                                                                       private void readObject(ObjectInputStream stream)
                             */                                                                                                               throw new IllegalArgumentException(msg);                                 */                                                                                                                                                                 throws ClassNotFoundException, IOException {
                                                                                                                                          }                                                                           private static HttpSessionContext sessionContext = null;                      /**
                            public class ApplicationSession implements HttpSession {                                                                                                                                                                                                                 * Set the <code>isValid</code> flag for this session.                                // Deserialize the scalar instance variables (except Manager)
                                                                                                                                          return values.get(name);                                                                                                                                   *                                                                                    creationTime = ((Long) stream.readObject()).longValue();
                                private StringManager sm =                                                                         }                                                                                  /**                                                                            * @param isValid The new value for the <code>isValid</code> flag                     id = (String) stream.readObject();
                                    StringManager.getManager("org.apache.tomcat.session");                                                                                                                             * The current accessed time for this session.                                 */                                                                                   lastAccessedTime = ((Long) stream.readObject()).longValue();
                                private Hashtable values = new Hashtable();                                                        /**                                                                                 */                                                                           void setValid(boolean isValid) {                                                      maxInactiveInterval = ((Integer) stream.readObject()).intValue();
                                private String id;                                                                                  * @deprecated                                                                     private long thisAccessedTime = creationTime;                                                                                                                       isNew = ((Boolean) stream.readObject()).booleanValue();
                                private ServerSession serverSession;                                                                */                                                                                                                                                                    this.isValid = isValid;                                                         isValid = ((Boolean) stream.readObject()).booleanValue();
                                private Context context;                                                                           public String[] getValueNames() {                                                                                                                                }
                                private long creationTime = System.currentTimeMillis();;                                               Enumeration e = getAttributeNames();                                                                                                                                                                                                               // Deserialize the attribute count and attribute values
                                private long thisAccessTime = creationTime;                                                            Vector names = new Vector();                                                                                                                                                                                                                       int n = ((Integer) stream.readObject()).intValue();
                                private long lastAccessed = creationTime;                                                                                                                                             // ----------------------------------------------------- Session Properties   // ------------------------------------------------- HttpSession Properties           for (int i = 0; i < n; i++) {
                                private int inactiveInterval = -1;                                                                        while (e.hasMoreElements()) {                                                                                                                                                                                                                       String name = (String) stream.readObject();
                                private boolean valid = true;                                                                                 names.addElement(e.nextElement());                                                                                                                                                                                                              Object value = (Object) stream.readObject();
                                                                                                                                          }                                                                           /**                                                                           /**                                                                                       attributes.put(name, value);
                                ApplicationSession(String id, ServerSession serverSession,                                                                                                                             * Set the creation time for this session. This method is called by the        * Return the time when this session was created, in milliseconds since               }
                                    Context context) {                                                                                    String[] valueNames = new String[names.size()];                              * Manager when an existing Session instance is reused.                        * midnight, January 1, 1970 GMT.
                                    this.serverSession = serverSession;                                                                                                                                                *                                                                             *                                                                                }
                                    this.context = context;                                                                               names.copyInto(valueNames);                                                  * @param time The new creation time                                           * @exception IllegalStateException if this method is called on an
                                    this.id = id;                                                                                                                                                                      */                                                                            * invalidated session
                                                                                                                                          return valueNames;                                                          public void setCreationTime(long time) {                                       */                                                                               /**
                                    this.inactiveInterval = context.getSessionTimeOut();                                                                                                                                                                                                            public long getCreationTime() {                                                    * Write a serialized version of this session object to the specified
                                                                                                                                   }                                                                                      this.creationTime = time;                                                                                                                                    * object output stream.
                                    if (this.inactiveInterval != -1) {                                                                                                                                                    this.lastAccessedTime = time;                                                   return (this.creationTime);                                                  * <p>
                                        this.inactiveInterval *= 60;                                                               public Enumeration getAttributeNames() {                                               this.thisAccessedTime = time;                                                                                                                                * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored
                                    }                                                                                                  if (! valid) {                                                                                                                                               }                                                                                  * in the serialized representation of this Session. After calling
                                }                                                                                                          String msg = sm.getString("applicationSession.session.ise");                                                                                                                                                                                * <code>readObject()</code>, you must set the associated Manager
                                                                                                                                                                                                                                                                                                                                                                                       * explicitly.
                                ServerSession getServerSession() {                                                                            throw new IllegalStateException(msg);                                                                                                                 /**                                                                                * <p>
                                    return serverSession;                                                                                 }                                                                                                                                                          * Return the session context with which this session is associated.               * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable
                                }                                                                                                                                                                                                                                                                    *                                                                                 * will be silently ignored. If you do not want any such attributes,
                                                                                                                                          Hashtable valuesClone = (Hashtable)values.clone();                                                                                                         * @deprecated As of Version 2.1, this method is deprecated and has no             * be sure the <code>distributable</code> property of our associated




  heterogeneous software
                                /**                                                                                                                                                                                                                                                                  * replacement. It will be removed in a future version of the                      * Manager is set to <code>true</code>.
                                 * Called by context when request comes in so that accesses and                                           return (Enumeration)valuesClone.keys();                                                                                                                    * Java Servlet API.                                                               *
                                 * inactivities can be dealt with accordingly.                                                     }                                                                                                                                                                 */                                                                                * @param stream The output stream to write to
                                 */                                                                                                                                                                                                                                                                 public HttpSessionContext getSessionContext() {                                    *
                                                                                                                                                                                                                                                                                                                                                                                       * @exception IOException if an input/output error occurs
                                void accessed() {                                                                            /**                                                                                                                                                                          if (sessionContext == null)                                                  */
                                    // set last accessed to thisAccessTime as it will be left over                                     * @deprecated                                                                                                                                                          sessionContext = new StandardSessionContext();                          private void writeObject(ObjectOutputStream stream) throws IOException {
                                    // from the previous access                                                                        */                                                                                                                                                                 return (sessionContext);
                                    lastAccessed = thisAccessTime;                                                                                                                                                                                                                                                                                                                        // Write the scalar instance variables (except Manager)
                                    thisAccessTime = System.currentTimeMillis();                                                   public void removeValue(String name) {                                                                                                                           }                                                                                     stream.writeObject(new Long(creationTime));
                                                                                                                                       removeAttribute(name);                                                                                                                                                                                                                             stream.writeObject(id);
                                    validate();                                                                                    }                                                                                                                                                                                                                                                      stream.writeObject(new Long(lastAccessedTime));
                                }                                                                                                                                                                                                                                                                   // ----------------------------------------------HttpSession Public Methods           stream.writeObject(new Integer(maxInactiveInterval));
                                                                                                                                   public void removeAttribute(String name) {                                                                                                                                                                                                             stream.writeObject(new Boolean(isNew));
                                void validate() {                                                                                      if (! valid) {                                                                 }                                                                                                                                                                   stream.writeObject(new Boolean(isValid));
                                    // if we have an inactive interval, check to see if we've exceeded it                                  String msg = sm.getString("applicationSession.session.ise");                                                                                             /**
                                    if (inactiveInterval != -1) {                                                                                                                                                                                                                                    * Return the object bound with the specified name in this session, or                // Accumulate the names of serializable attributes
                                        int thisInterval =                                                                                    throw new IllegalStateException(msg);                                                                                                                  * <code>null</code> if no object is bound with that name.                            Vector results = new Vector();
                                            (int)(System.currentTimeMillis() - lastAccessed) / 1000;                                      }                                                                                                                                                          *                                                                                    Enumeration attrs = getAttributeNames();
                                                                                                                                                                                                                                                                                                     * @param name Name of the attribute to be returned                                   while (attrs.hasMoreElements()) {
                                        if (thisInterval > inactiveInterval) {                                                            if (name == null) {                                                                                                                                        *                                                                                        String attr = (String) attrs.nextElement();
                                            invalidate();                                                                                     String msg = sm.getString("applicationSession.value.iae");                                                                                             * @exception IllegalStateException if this method is called on an                        Object value = attributes.get(attr);
                                        }                                                                                                                                                                                                                                                            * invalidated session                                                                    if (value instanceof Serializable)
                                    }                                                                                                         throw new IllegalArgumentException(msg);                                                                                                               */                                                                                           results.addElement(attr);
                                }                                                                                                         }                                                                                                                                                         public Object getAttribute(String name) {                                             }

                                // HTTP SESSION IMPLEMENTATION METHODS                                                                    Object o = values.get(name);                                                                                                                                    return (attributes.get(name));                                                  // Serialize the attribute count and the attribute values
                                                                                                                                                                                                                                                                                                                                                                                          stream.writeObject(new Integer(results.size()));
                                public String getId() {                                                                                   if (o instanceof HttpSessionBindingListener) {                                                                                                            }                                                                                     Enumeration names = results.elements();
                                    if (valid) {                                                                                              HttpSessionBindingEvent e =                                                                                                                                                                                                                 while (names.hasMoreElements()) {
                                        return id;                                                                                                new HttpSessionBindingEvent(this,name);                                                                                                                                                                                                     String name = (String) names.nextElement();
                                    } else {                                                                                                                                                                                                                                                        /**                                                                                       stream.writeObject(name);
                                        String msg = sm.getString("applicationSession.session.ise");                                          ((HttpSessionBindingListener)o).valueUnbound(e);                                                                                                       * Return an <code>Enumeration</code> of <code>String</code> objects                      stream.writeObject(attributes.get(name));
                                                                                                                                          }                                                                                                                                                          * containing the names of the objects bound to this session.                         }
                                        throw new IllegalStateException(msg);                                                                                                                                                                                                                        *




  modules.
                                    }                                                                                                     values.remove(name);                                                                                                                                       * @exception IllegalStateException if this method is called on an
                                }                                                                                                  }                                                                                                                                                                 * invalidated session                                                            }
                                                                                                                                                                                                                                                                                                     */
                                public long getCreationTime() {                                                                    public void setMaxInactiveInterval(int interval) {                                                                                                               public Enumeration getAttributeNames() {                                          crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() |
                                    if (valid) {                                                                                       if (! valid) {                                                                                                                                                                                                                                                                              long getCreationTime() |
                                        return creationTime;                                                                               String msg = sm.getString("applicationSession.session.ise");                                                                                                   return (attributes.keys());                                                                                              Object getAttribute(String) |
                                    } else {                                                                                                                                                                                                                                                                                                                                                                                       Enumeration getAttributeNames() |
                                        String msg = sm.getString("applicationSession.session.ise");                                          throw new IllegalStateException(msg);                                                                                                                 }                                                                                                                              String[] getValueNames() |
                                                                                                                                          }                                                                                                                                                                                                                                                                                        void invalidate() |
                                        throw new IllegalStateException(msg);                                                                                                                                                                                                                                                                                                                                                      boolean isNew() |
                                    }                                                                                                                                                                                                                                                               /**                                                                                                                            void removeAttribute(String) |
                                }                                                                                                                                                                                                                                                                    * Return the object bound with the specified name in this session, or                                                         void setAttribute(String, Object));
                                                                                                                                                                                                                                                                                                     * <code>null</code> if no object is bound with that name.
                                /**                                                                                                                                                                                                                                                                  *                                                                                static advice(StandardSession s): invalidate(s) {
                                 *                                                                                                                                                                                                                                                                   * @param name Name of the value to be returned                                       before {
                                 * @deprecated                                                                                                                                                                                                                                                       *                                                                                        if (!s.isValid())
                                                                                                                                                                                                                                                                                                     * @exception IllegalStateException if this method is called on an                             throw new IllegalStateException
                                                                                                                                                                                                                                                                                                     * invalidated session                                                                             (s.sm.getString("standardSession."
                                                                                                                                                                                                                                                                                                     *                                                                                                                 + thisJoinPoint.methodName
                                                                                                                                                                                                                                                                                                     * @deprecated As of Version 2.2, this method is replaced by                                                       + ".ise"));
                                                                                                                                                                                                                                                                                                     * <code>getAttribute()</code>                                                        }
                                                                                                                                                                                                                                                                                                     */                                                                               }
                                                                                                                                                                                                                      /**                                                                           public Object getValue(String name) {
                                                                                                                                                                                                                       * Return the session identifier for this session.
                                                                                                                                                                                                                       */                                                                                 return (getAttribute(name));
                                                                                                                                                                                                                      public String getId() {
                                                                                                                                                                                                                                                                                                    }                                                                             }


                                                                                                                                                                                                                                                                                                    /**                                                                           // -------------------------------------------------------------- Private Class
                                                                                                                                                                                                                                                                                                     * Return the set of names of objects bound to this session. If there
                                                                                                                                                                                                                                                                                                     * are no such objects, a zero-length array is returned.
                                                                                                                                                                                                                                                                                                     *                                                                            /**
                                                                                                                                                                                                                                                                                                     * @exception IllegalStateException if this method is called on an             * This class is a dummy implementation of the <code>HttpSessionContext</code>
                                                                                                                                                                                                                                                                                                     * invalidated session                                                         * interface, to conform to the requirement that such an object be returned
                                                                                                                                                                                                                                                                                                     *                                                                             * when <code>HttpSession.getSessionContext()</code> is called.
                                                                                                                                                                                                                                                                                                     * @deprecated As of Version 2.2, this method is replaced by                   *
                                                                                                                                                                                                                                                                                                     * <code>getAttributeNames()</code>                                            * @author Craig R. McClanahan
                                                                                                                                                                                                                                                                                                     */                                                                            *
                                                                                                                                                                                                                                                                                                    public String[] getValueNames() {                                              * @deprecated As of Java Servlet API 2.1 with no replacement. The
                                                                                                                                                                                                                                                                                                                                                                                   * interface will be removed in a future version of this API.
                                                                                                                                                                                                                                                                                                          Vector results = new Vector();                                           */
                                                                                                                                                                                                                                                                                                          Enumeration attrs = getAttributeNames();
                                                                                                                                                                                                                                                                                                          while (attrs.hasMoreElements()) {                                       final class StandardSessionContext implements HttpSessionContext {
                                                                                                                                                                                                                                                                                                              String attr = (String) attrs.nextElement();
                                                                                                                                                                                                                                                                                                              results.addElement(attr);
                                                                                                                                                                                                                                                                                                          }                                                                           private Vector dummy = new Vector();
                                                                                                                                                                                                                          return (this.id);                                                               String names[] = new String[results.size()];
                                                                                                                                                                                                                                                                                                          for (int i = 0; i < names.length; i++)                                      /**
                                                                                                                                                                                                                                                                                                              names[i] = (String) results.elementAt(i);                                * Return the session identifiers of all sessions defined
                                                                                                                                                                                                                                                                                                          return (names);                                                              * within this context.
                                                                                                                                                                                                                                                                                                                                                                                       *
                                                                                                                                                                                                                                                                                                    }                                                                                  * @deprecated As of Java Servlet API 2.1 with no replacement.
                                                                                                                                                                                                                                                                                                                                                                                       * This method must return an empty <code>Enumeration</code>
                                                                                                                                                                                                                                                                                                                                                                                       * and will be removed in a future version of the API.
                                                                                                                                                                                                                                                                                                    /**                                                                                */
                                                                                                                                                                                                                                                                                                     * Invalidates this session and unbinds any objects bound to it.                  public Enumeration getIds() {
                                                                                                                                                                                                                                                                                                     *
                                                                                                                                                                                                                                                                                                     * @exception IllegalStateException if this method is called on                       return (dummy.elements());
                                                                                                                                                                                                                                                                                                     * an invalidated session




• Code is:
                                                                                                                                                                                                                                                                                                     */
                                                                                                                                                                                                                                                                                                    public void invalidate() {

                                                                                                                                                                                                                                                                                                          // Cause this session to expire
                                                                                                                                                                                                                                                                                                          expire();

                                                                                                                                                                                                                                                                                                    }


                                                                                                                                                                                                                      }                                                                             /**
                                                                                                                                                                                                                                                                                                     * Return <code>true</code> if the client does not yet know about the
                                                                                                                                                                                                                                                                                                     * session, or if the client chooses not to join the session. For
                                                                                                                                                                                                                                                                                                     * example, if the server used only cookie-based sessions, and the client
                                                                                                                                                                                                                                                                                                     * has disabled the use of cookies, then a session would be new on each
                                                                                                                                                                                                                                                                                                     * request.
                                                                                                                                                                                                                                                                                                     *
                                                                                                                                                                                                                                                                                                     * @exception IllegalStateException if this method is called on an
                                                                                                                                                                                                                                                                                                     * invalidated session
                                                                                                                                                                                                                                                                                                     */
                                                                                                                                                                                                                                                                                                    public boolean isNew() {

                                                                                                                                                                                                                                                                                                          return (this.isNew);

                                                                                                                                                                                                                                                                                                    }




                            package org.apache.tomcat.session;                                              void validate() {
                                                                                                                    // if we have an inactive interval, check to see if
                            import org.apache.tomcat.core.*;                                                        // we've exceeded it
                            import org.apache.tomcat.util.StringManager;
                            import java.io.*;                                                                       if (inactiveInterval != -1) {
                            import java.net.*;                                                                          int thisInterval =
                            import java.util.*;                                                                             (int)(System.currentTimeMillis() - lastAccessed) / 1000;
                            import javax.servlet.*;
                            import javax.servlet.http.*;                                                                if (thisInterval > inactiveInterval) {
                                                                                                                            invalidate();
                            /**
                             * Core implementation of a server session                                                       ServerSessionManager ssm =
                             *                                                                                                   ServerSessionManager.getManager();
                             * @author James Duncan Davidson [duncan@eng.sun.com]
                             * @author James Todd [gonzo@eng.sun.com]                                                        ssm.removeSession(this);
                             */                                                                                         }
                                                                                                                    }
                            public class ServerSession {                                                        }

                                private StringManager sm =                                                      synchronized void invalidate() {
                                    StringManager.getManager("org.apache.tomcat.session");                          Enumeration enum = appSessions.keys();                                                            /**
                                private Hashtable values = new Hashtable();                                                                                                                                            * Set the session identifier for this session.
                                private Hashtable appSessions = new Hashtable();                                    while (enum.hasMoreElements()) {                                                                   *
                                private String id;                                                                      Object key = enum.nextElement();                                                               * @param id The new session identifier
                                private long creationTime = System.currentTimeMillis();;                                ApplicationSession appSession =                                                                */
                                private long thisAccessTime = creationTime;                                                 (ApplicationSession)appSessions.get(key);                                                 public void setId(String id) {
                                private long lastAccessed = creationTime;
                                private int inactiveInterval = -1;                                                      appSession.invalidate();
                                                                                                                    }
                                ServerSession(String id) {                                                      }
                                    this.id = id;
                                }                                                                               public void putValue(String name, Object value) {
                                                                                                                    if (name == null) {
                                public String getId() {                                                                 String msg = sm.getString("serverSession.value.iae");
                                    return id;
                                }                                                                                       throw new IllegalArgumentException(msg);
                                                                                                                    }
                                public long getCreationTime() {
                                    return creationTime;                                                            removeValue(name); // remove any existing binding
                                }                                                                                   values.put(name, value);
                                                                                                                }




 • Scattered throughout
                                public long getLastAccessedTime() {
                                    return lastAccessed;                                                        public Object getValue(String name) {
                                }                                                                                   if (name == null) {
                                                                                                                        String msg = sm.getString("serverSession.value.iae");
                                public ApplicationSession getApplicationSession(Context context,
                                    boolean create) {                                                                   throw new IllegalArgumentException(msg);
                                    ApplicationSession appSession =                                                 }                                                                                                     if ((this.id != null) && (manager != null) &&
                                        (ApplicationSession)appSessions.get(context);                                                                                                                                       (manager instanceof ManagerBase))
                                                                                                                    return values.get(name);                                                                                  ((ManagerBase) manager).remove(this);
                                    if (appSession == null && create) {                                         }

                                        // XXX                                                                  public Enumeration getValueNames() {
                                        // sync to ensure valid?                                                    return values.keys();
                                                                                                                }
                                        appSession = new ApplicationSession(id, this, context);
                                        appSessions.put(context, appSession);                                   public void removeValue(String name) {
                                    }                                                                               values.remove(name);
                                                                                                                }
                                    // XXX
                                    // make sure that we haven't gone over the end of our                       public void setMaxInactiveInterval(int interval) {
                                    // inactive interval -- if so, invalidate and create                            inactiveInterval = interval;
                                    // a new appSession                                                         }

                                    return appSession;                                                          public int getMaxInactiveInterval() {
                                }                                                                                   return inactiveInterval;
                                                                                                                }
                                void removeApplicationSession(Context context) {
                                    appSessions.remove(context);                                                // XXX
                                }                                                                               // sync'd for safty -- no other thread should be getting something
                                                                                                                // from this while we are reaping. This isn't the most optimal
                                /**                                                                             // solution for this, but we'll determine something else later.                                           this.id = id;
                                 * Called by context when request comes in so that accesses and
                                 * inactivities can be dealt with accordingly.                                  synchronized void reap() {
                                 */                                                                                 Enumeration enum = appSessions.keys();

                                void accessed() {                                                                   while (enum.hasMoreElements()) {
                                    // set last accessed to thisAccessTime as it will be left over




   many modules.
                                                                                                                                                                                                                          if ((manager != null) && (manager instanceof ManagerBase))
                                                                                                                                                                                                                              ((ManagerBase) manager).add(this);




                                                                                                                                                                                                                      }




 • Tangled with unrelated
                                                                                                                                                                                                                      /**
                                                                                                                                                                                                                       * Return descriptive information about this Session implementation and
                                                                                                                                                                                                                       * the corresponding version number, in the format
                                                                                                                                                                                                                       * <code>&lt;description&gt;/&lt;version&gt;</code>.
                                                                                                                                                                                                                       */
                                                                                                                                                                                                                      public String getInfo() {




                                                                                                                                                                                                                          return (this.info);




   modules.                                                                                                                                                                                                           }




                                                                                                                                                                                                                      /**
                                                                                                                                                                                                                       * Return the last time the client sent a request associated with this
                                                                                                                                                                                                                       * session, as the number of milliseconds since midnight, January 1, 1970
                                                                                                                                                                                                                       * GMT. Actions that your application takes, such as getting or setting
                                                                                                                                                                                                                       * a value associated with the session, do not affect the access time.
                                                                                                                                                                                                                       */
                                                                                                                                                                                                                      public long getLastAccessedTime() {

                                                                                                                                                                                                                          return (this.lastAccessedTime);

                                                                                                                                                                                                                      }


                                                                                                                                                                                                                      /**
                                                                                                                                                                                                                       * Return the Manager within which this Session is valid.
                                                                                                                                                                                                                       */
                                                                                                                                                                                                                      public Manager getManager() {

                                                                                                                                                                                                                          return (this.manager);

                                                                                                                                                                                                                      }


                                                                                                                                                                                                                      /**
                                                                                                                                                                                                                       * Set the Manager within which this Session is valid.
                                                                                                                                                                                                                       *
                                                                                                                                                                                                                       * @param manager The new Manager
                                                                                                                                                                                                                       */
                                                                                                                                                                                                                      public void setManager(Manager manager) {




                                                                                                                                                                                                                                                                                                                                                                                                                                                                         10
Crosscutting Concerns


                              /*                                                                                              public void invalidate() {                                                          ;                                                                                                                                                                 * Remove the object bound with the specified name from this session. If
                               * ====================================================================                                 serverSession.removeApplicationSession(context);                                                                                                                                                                                                   * the session does not have an object bound with this name, this method
                               *                                                                                                                                                                                                                                                                                                                                                         * does nothing.
                               * The Apache Software License, Version 1.1                                                                   // remove everything in the session                                   /**                                                                                                                                                                    * <p>
                               *                                                                                                                                                                                   * Standard implementation of the <b>Session</b> interface. This object is                                                                                             * After this method executes, and if the object implements
                               * Copyright (c) 1999 The Apache Software Foundation. All rights                                              Enumeration enum = values.keys();                                      * serializable, so that it can be stored in persistent storage or transferred                                                                                         * <code>HttpSessionBindingListener</code>, the container calls
                               * reserved.                                                                                                  while (enum.hasMoreElements()) {                                       * to a different JVM for distributable session support.                                                                                                               * <code>valueUnbound()</code> on the object.
                               *                                                                                                                String name = (String)enum.nextElement();                          * <p>                                                                                                                                                                 *
                               * Redistribution and use in source and binary forms, with or without                                             removeValue(name);                                                 * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the                                                                                           * @param name Name of the object to remove from this session.
                               * modification, are permitted provided that the following conditions                                         }                                                                      * internal (Session) and application level (HttpSession) view of the session.                                                                                         *
                               * are met:                                                                                                                                                                          * However, because the class itself is not declared public, Java logic outside                                                                                        * @exception IllegalStateException if this method is called on an
                               *                                                                                                            valid = false;                                                         * of the <code>org.apache.tomcat.session</code> package cannot cast an                                                                                                * invalidated session
                               * 1. Redistributions of source code must retain the above copyright                                   }                                                                             * HttpSession view of this instance back to a Session view.                                                                                                           */
                               *    notice, this list of conditions and the following disclaimer.                                                                                                                  *                                                                                                                                                                    public void removeAttribute(String name) {
                               *                                                                                                     public boolean isNew() {                                                      * @author Craig R. McClanahan
                               * 2. Redistributions in binary form must reproduce the above copyright                                    if (! valid) {                                                            * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $                                                                                                                 synchronized (attributes) {
                               *    notice, this list of conditions and the following disclaimer in                                          String msg = sm.getString("applicationSession.session.ise");          */                                                                                                                                                                           Object object = attributes.get(name);
                               *    the documentation and/or other materials provided with the                                                                                                                                                                                                                                                                                                  if (object == null)
                               *    distribution.                                                                                               throw new IllegalStateException(msg);                             final class StandardSession                                                                                                                                                       return;
                               *                                                                                                            }                                                                         implements HttpSession, Session {                                                                                                                                         attributes.remove(name);
                               * 3. The end-user documentation included with the redistribution, if                                                                                                                                                                                                                                                                                             //      System.out.println( "Removing attribute " + name );
                               *    any, must include the following acknowledgment:                                                         if (thisAccessTime == creationTime) {                                                                                                                     /**                                                                                       if (object instanceof HttpSessionBindingListener) {
                               *       "This product includes software developed by the                                                         return true;                                                            // ----------------------------------------------------------- Constructors    * Update the accessed time information for this session. This method                         ((HttpSessionBindingListener) object).valueUnbound
                               *        Apache Software Foundation (http://www.apache.org/)."                                               } else {                                                                                                                                                   * should be called by the context when a request comes in for a particular                       (new HttpSessionBindingEvent((HttpSession) this, name));
                               *    Alternately, this acknowledgment may appear in the software                                                 return false;                                                                                                                                          * session, even if the application does not reference it.                                }
                              itself,                                                                                                       }                                                                           /**                                                                            */                                                                                   }
                               *    if and wherever such third-party acknowledgments normally appear.                                }                                                                                   * Construct a new Session associated with the specified Manager.             public void access() {
                               *                                                                                                                                                                                         *                                                                                                                                                              }
                               * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software                                                                                                                      * @param manager The manager with which this Session is associated                 this.lastAccessedTime = this.thisAccessedTime;




• Crosscutting concerns
                               *    Foundation" must not be used to endorse or promote products                               /**                                                                                        */                                                                                 this.thisAccessedTime = System.currentTimeMillis();                     * Bind an object to this session, using the specified name. If an object
                              derived                                                                                                    * @deprecated                                                                  public StandardSession(Manager manager) {                                           this.isNew=false;                                                            * of the same name is already bound to this session, the object is
                               *    from this software without prior written permission. For written                                     */                                                                                                                                                           }                                                                                  * replaced.
                               *    permission, please contact apache@apache.org.                                                                                                                                           super();                                                                                                                                                     * <p>
                               *                                                                                                     public void putValue(String name, Object value) {                                      this.manager = manager;                                                                                                                                      * After this method executes, and if the object implements
                               * 5. Products derived from this software may not be called "Apache"                                       setAttribute(name, value);                                                                                                                                   /**                                                                                * <code>HttpSessionBindingListener</code>, the container calls
                               *    nor may "Apache" appear in their names without prior written                                     }                                                                                  }                                                                              * Perform the internal processing required to invalidate this session,            * <code>valueBound()</code> on the object.
                               *    permission of the Apache Group.                                                                                                                                                                                                                                    * without triggering an exception if the session has already expired.             *
                               *                                                                                                     public void setAttribute(String name, Object value) {                                                                                                             */                                                                                * @param name Name to which the object is bound, cannot be null
                               * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED                                        if (! valid) {                                                           /**                                                                                 public void expire() {                                                             * @param value Object to be bound, cannot be null
                               * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES                                           String msg = sm.getString("applicationSession.session.ise");                * The last accessed time for this Session.                                                                                                                      *
                               * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                                                                                                                             */                                                                                 // Remove this session from our manager's active sessions                    * @exception IllegalArgumentException if an attempt is made to add a
                               * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR                                                throw new IllegalStateException(msg);                                   private long lastAccessedTime = creationTime;                                       if ((manager != null) && (manager instanceof ManagerBase))                   * non-serializable object in an environment marked distributable.
                               * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,                                           }                                                                                                                                                                   ((ManagerBase) manager).remove(this);                                    * @exception IllegalStateException if this method is called on an
                               * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT                                                                                                                                                                                                                                                                                        * invalidated session
                               * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF                                           if (name == null) {                                                         /**                                                                                 // Unbind any objects associated with this session                           */
                               * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND                                            String msg = sm.getString("applicationSession.value.iae");               * The Manager with which this Session is associated.                               Vector results = new Vector();                                              public void setAttribute(String name, Object value) {
                               * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,                                                                                                                      */                                                                                 Enumeration attrs = getAttributeNames();
                               * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT                                             throw new IllegalArgumentException(msg);                                private Manager manager = null;                                                     while (attrs.hasMoreElements()) {                                               if ((manager != null) && manager.getDistributable() &&
                               * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF                                         }                                                                                                                                                                   String attr = (String) attrs.nextElement();                                   !(value instanceof Serializable))
                               * SUCH DAMAGE.                                                                                                                                                                                                                                                                   results.addElement(attr);                                                       throw new IllegalArgumentException
                               * ====================================================================                                       removeValue(name);     // remove any existing binding                       /**                                                                                 }                                                                                       (sm.getString("standardSession.setAttribute.iae"));
                               *                                                                                                                                                                                         * The maximum time interval, in seconds, between client requests before            Enumeration names = results.elements();
                               * This software consists of voluntary contributions made by many                                             if (value != null && value instanceof HttpSessionBindingListener) {          * the servlet container may invalidate this session. A negative time               while (names.hasMoreElements()) {                                               synchronized (attributes) {
                               * individuals on behalf of the Apache Software Foundation. For more                                              HttpSessionBindingEvent e =                                              * indicates that the session should never time out.                                    String name = (String) names.nextElement();                                     removeAttribute(name);
                               * information on the Apache Software Foundation, please see                                                          new HttpSessionBindingEvent(this, name);                             */                                                                                     removeAttribute(name);                                                          attributes.put(name, value);
                               * <http://www.apache.org/>.                                                                                                                                                              private int maxInactiveInterval = -1;                                               }                                                                                   if (value instanceof HttpSessionBindingListener)
                               *                                                                                                                ((HttpSessionBindingListener)value).valueBound(e);                                                                                                                                                                                                  ((HttpSessionBindingListener) value).valueBound
                               * [Additional notices, if required by prior licensing conditions]                                            }                                                                                                                                                               // Mark this session as invalid                                                             (new HttpSessionBindingEvent((HttpSession) this, name));
                               *                                                                                                                                                                                        /**                                                                                 setValid(false);                                                                }
                               */                                                                                                           values.put(name, value);                                                     * Flag indicating whether this session is new or not.
                                                                                                                                     }                                                                                   */                                                                           }                                                                                 }
                                                                                                                                                                                                                        private boolean isNew = true;
                                                                                                                                     /**
                              package org.apache.tomcat.session;                                                                       * @deprecated                                                                                                                                                  /**                                                                               // -------------------------------------------- HttpSession Private Methods
                                                                                                                                       */                                                                               /**
                              import org.apache.tomcat.core.*;                                                                       public Object getValue(String name) {                                               * Flag indicating whether this session is valid or not.                      }
                              import org.apache.tomcat.util.StringManager;                                                                return getAttribute(name);                                                     */                                                                                                                                                             /**
                              import java.io.*;                                                                                      }                                                                                  private boolean isValid = false;                                                                                                                                 * Read a serialized version of this session object from the specified
                              import java.net.*;                                                                                                                                                                                                                                                      /**                                                                                * object input stream.
                              import java.util.*;                                                                                    public Object getAttribute(String name) {                                                                                                                         * Set the <code>isNew</code> flag for this session.                               * <p>
                              import javax.servlet.*;                                                                                    if (! valid) {                                                                 /**                                                                            *                                                                                 * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager
                              import javax.servlet.http.*;                                                                                   String msg = sm.getString("applicationSession.session.ise");                * The string manager for this package.                                        * @param isNew The new value for the <code>isNew</code> flag                      * is not restored by this method, and must be set explicitly.
                                                                                                                                                                                                                         */                                                                            */                                                                                *
                              /**                                                                                                               throw new IllegalStateException(msg);                                   private StringManager sm =                                                    void setNew(boolean isNew) {                                                       * @param stream The input stream to read from
                               * Core implementation of an application level session                                                        }                                                                               StringManager.getManager("org.apache.tomcat.session");                                                                                                       *
                               *                                                                                                                                                                                                                                                                            this.isNew = isNew;                                                          * @exception ClassNotFoundException if an unknown class is specified
                               * @author James Duncan Davidson [duncan@eng.sun.com]                                                         if (name == null) {                                                                                                                                                                                                                          * @exception IOException if an input/output error occurs




  (CCCs) affect many
                               * @author Jason Hunter [jch@eng.sun.com]                                                                         String msg = sm.getString("applicationSession.value.iae");              /**                                                                           }                                                                                  */
                               * @author James Todd [gonzo@eng.sun.com]                                                                                                                                                  * The HTTP session context associated with this session.                                                                                                       private void readObject(ObjectInputStream stream)
                               */                                                                                                               throw new IllegalArgumentException(msg);                                 */                                                                                                                                                                 throws ClassNotFoundException, IOException {
                                                                                                                                            }                                                                           private static HttpSessionContext sessionContext = null;                      /**
                              public class ApplicationSession implements HttpSession {                                                                                                                                                                                                                 * Set the <code>isValid</code> flag for this session.                                // Deserialize the scalar instance variables (except Manager)
                                                                                                                                            return values.get(name);                                                                                                                                   *                                                                                    creationTime = ((Long) stream.readObject()).longValue();
                                  private StringManager sm =                                                                         }                                                                                  /**                                                                            * @param isValid The new value for the <code>isValid</code> flag                     id = (String) stream.readObject();
                                      StringManager.getManager("org.apache.tomcat.session");                                                                                                                             * The current accessed time for this session.                                 */                                                                                   lastAccessedTime = ((Long) stream.readObject()).longValue();
                                  private Hashtable values = new Hashtable();                                                        /**                                                                                 */                                                                           void setValid(boolean isValid) {                                                      maxInactiveInterval = ((Integer) stream.readObject()).intValue();
                                  private String id;                                                                                  * @deprecated                                                                     private long thisAccessedTime = creationTime;                                                                                                                       isNew = ((Boolean) stream.readObject()).booleanValue();
                                  private ServerSession serverSession;                                                                */                                                                                                                                                                    this.isValid = isValid;                                                         isValid = ((Boolean) stream.readObject()).booleanValue();
                                  private Context context;                                                                           public String[] getValueNames() {                                                                                                                                }
                                  private long creationTime = System.currentTimeMillis();;                                               Enumeration e = getAttributeNames();                                                                                                                                                                                                               // Deserialize the attribute count and attribute values
                                  private long thisAccessTime = creationTime;                                                            Vector names = new Vector();                                                                                                                                                                                                                       int n = ((Integer) stream.readObject()).intValue();
                                  private long lastAccessed = creationTime;                                                                                                                                             // ----------------------------------------------------- Session Properties   // ------------------------------------------------- HttpSession Properties           for (int i = 0; i < n; i++) {
                                  private int inactiveInterval = -1;                                                                        while (e.hasMoreElements()) {                                                                                                                                                                                                                       String name = (String) stream.readObject();
                                  private boolean valid = true;                                                                                 names.addElement(e.nextElement());                                                                                                                                                                                                              Object value = (Object) stream.readObject();
                                                                                                                                            }                                                                           /**                                                                           /**                                                                                       attributes.put(name, value);
                                  ApplicationSession(String id, ServerSession serverSession,                                                                                                                             * Set the creation time for this session. This method is called by the        * Return the time when this session was created, in milliseconds since               }
                                      Context context) {                                                                                    String[] valueNames = new String[names.size()];                              * Manager when an existing Session instance is reused.                        * midnight, January 1, 1970 GMT.
                                      this.serverSession = serverSession;                                                                                                                                                *                                                                             *                                                                                }
                                      this.context = context;                                                                               names.copyInto(valueNames);                                                  * @param time The new creation time                                           * @exception IllegalStateException if this method is called on an
                                      this.id = id;                                                                                                                                                                      */                                                                            * invalidated session
                                                                                                                                            return valueNames;                                                          public void setCreationTime(long time) {                                       */                                                                               /**
                                      this.inactiveInterval = context.getSessionTimeOut();                                                                                                                                                                                                            public long getCreationTime() {                                                    * Write a serialized version of this session object to the specified
                                                                                                                                     }                                                                                      this.creationTime = time;                                                                                                                                    * object output stream.
                                      if (this.inactiveInterval != -1) {                                                                                                                                                    this.lastAccessedTime = time;                                                   return (this.creationTime);                                                  * <p>
                                          this.inactiveInterval *= 60;                                                               public Enumeration getAttributeNames() {                                               this.thisAccessedTime = time;                                                                                                                                * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored
                                      }                                                                                                  if (! valid) {                                                                                                                                               }                                                                                  * in the serialized representation of this Session. After calling
                                  }                                                                                                          String msg = sm.getString("applicationSession.session.ise");                                                                                                                                                                                * <code>readObject()</code>, you must set the associated Manager
                                                                                                                                                                                                                                                                                                                                                                                         * explicitly.
                                  ServerSession getServerSession() {                                                                            throw new IllegalStateException(msg);                                                                                                                 /**                                                                                * <p>
                                      return serverSession;                                                                                 }                                                                                                                                                          * Return the session context with which this session is associated.               * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable
                                  }                                                                                                                                                                                                                                                                    *                                                                                 * will be silently ignored. If you do not want any such attributes,
                                                                                                                                            Hashtable valuesClone = (Hashtable)values.clone();                                                                                                         * @deprecated As of Version 2.1, this method is deprecated and has no             * be sure the <code>distributable</code> property of our associated




  heterogeneous software
                                  /**                                                                                                                                                                                                                                                                  * replacement. It will be removed in a future version of the                      * Manager is set to <code>true</code>.
                                   * Called by context when request comes in so that accesses and                                           return (Enumeration)valuesClone.keys();                                                                                                                    * Java Servlet API.                                                               *
                                   * inactivities can be dealt with accordingly.                                                     }                                                                                                                                                                 */                                                                                * @param stream The output stream to write to




                                  Message
                                   */                                                                                                                                                                                                                                                                 public HttpSessionContext getSessionContext() {                                    *
                                                                                                                                                                                                                                                                                                                                                                                         * @exception IOException if an input/output error occurs
                                  void accessed() {                                                                            /**                                                                                                                                                                          if (sessionContext == null)                                                  */
                                      // set last accessed to thisAccessTime as it will be left over                                     * @deprecated                                                                                                                                                          sessionContext = new StandardSessionContext();                          private void writeObject(ObjectOutputStream stream) throws IOException {
                                      // from the previous access                                                                        */                                                                                                                                                                 return (sessionContext);
                                      lastAccessed = thisAccessTime;                                                                                                                                                                                                                                                                                                                        // Write the scalar instance variables (except Manager)
                                      thisAccessTime = System.currentTimeMillis();                                                   public void removeValue(String name) {                                                                                                                           }                                                                                     stream.writeObject(new Long(creationTime));
                                                                                                                                         removeAttribute(name);                                                                                                                                                                                                                             stream.writeObject(id);
                                      validate();                                                                                    }                                                                                                                                                                                                                                                      stream.writeObject(new Long(lastAccessedTime));
                                  }                                                                                                                                                                                                                                                                   // ----------------------------------------------HttpSession Public Methods           stream.writeObject(new Integer(maxInactiveInterval));
                                                                                                                                     public void removeAttribute(String name) {                                                                                                                                                                                                             stream.writeObject(new Boolean(isNew));
                                  void validate() {                                                                                      if (! valid) {                                                                 }                                                                                                                                                                   stream.writeObject(new Boolean(isValid));
                                      // if we have an inactive interval, check to see if we've exceeded it                                  String msg = sm.getString("applicationSession.session.ise");                                                                                             /**
                                      if (inactiveInterval != -1) {                                                                                                                                                                                                                                    * Return the object bound with the specified name in this session, or                // Accumulate the names of serializable attributes
                                          int thisInterval =                                                                                    throw new IllegalStateException(msg);                                                                                                                  * <code>null</code> if no object is bound with that name.                            Vector results = new Vector();
                                              (int)(System.currentTimeMillis() - lastAccessed) / 1000;                                      }                                                                                                                                                          *                                                                                    Enumeration attrs = getAttributeNames();
                                                                                                                                                                                                                                                                                                       * @param name Name of the attribute to be returned                                   while (attrs.hasMoreElements()) {
                                          if (thisInterval > inactiveInterval) {                                                            if (name == null) {                                                                                                                                        *                                                                                        String attr = (String) attrs.nextElement();
                                              invalidate();                                                                                     String msg = sm.getString("applicationSession.value.iae");                                                                                             * @exception IllegalStateException if this method is called on an                        Object value = attributes.get(attr);
                                          }                                                                                                                                                                                                                                                            * invalidated session                                                                    if (value instanceof Serializable)
                                      }                                                                                                         throw new IllegalArgumentException(msg);                                                                                                               */                                                                                           results.addElement(attr);
                                  }                                                                                                         }                                                                                                                                                         public Object getAttribute(String name) {                                             }

                                  // HTTP SESSION IMPLEMENTATION METHODS                                                                    Object o = values.get(name);                                                                                                                                    return (attributes.get(name));                                                  // Serialize the attribute count and the attribute values
                                                                                                                                                                                                                                                                                                                                                                                            stream.writeObject(new Integer(results.size()));
                                  public String getId() {                                                                                   if (o instanceof HttpSessionBindingListener) {                                                                                                            }                                                                                     Enumeration names = results.elements();
                                      if (valid) {                                                                                              HttpSessionBindingEvent e =                                                                                                                                                                                                                 while (names.hasMoreElements()) {
                                          return id;                                                                                                new HttpSessionBindingEvent(this,name);                                                                                                                                                                                                     String name = (String) names.nextElement();
                                      } else {                                                                                                                                                                                                                                                        /**                                                                                       stream.writeObject(name);
                                          String msg = sm.getString("applicationSession.session.ise");                                          ((HttpSessionBindingListener)o).valueUnbound(e);                                                                                                       * Return an <code>Enumeration</code> of <code>String</code> objects                      stream.writeObject(attributes.get(name));
                                                                                                                                            }                                                                                                                                                          * containing the names of the objects bound to this session.                         }
                                          throw new IllegalStateException(msg);                                                                                                                                                                                                                        *




  modules.
                                      }                                                                                                     values.remove(name);                                                                                                                                       * @exception IllegalStateException if this method is called on an
                                  }                                                                                                  }                                                                                                                                                                 * invalidated session                                                            }
                                                                                                                                                                                                                                                                                                       */
                                  public long getCreationTime() {                                                                    public void setMaxInactiveInterval(int interval) {                                                                                                               public Enumeration getAttributeNames() {                                          crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() |
                                      if (valid) {                                                                                       if (! valid) {                                                                                                                                                                                                                                                                              long getCreationTime() |
                                          return creationTime;                                                                               String msg = sm.getString("applicationSession.session.ise");                                                                                                   return (attributes.keys());                                                                                              Object getAttribute(String) |
                                      } else {                                                                                                                                                                                                                                                                                                                                                                                       Enumeration getAttributeNames() |
                                          String msg = sm.getString("applicationSession.session.ise");                                          throw new IllegalStateException(msg);                                                                                                                 }                                                                                                                              String[] getValueNames() |
                                                                                                                                            }                                                                                                                                                                                                                                                                                        void invalidate() |
                                          throw new IllegalStateException(msg);                                                                                                                                                                                                                                                                                                                                                      boolean isNew() |
                                      }                                                                                                                                                                                                                                                               /**                                                                                                                            void removeAttribute(String) |
                                  }                                                                                                                                                                                                                                                                    * Return the object bound with the specified name in this session, or                                                         void setAttribute(String, Object));




                              encryption is an
                                                                                                                                                                                                                                                                                                       * <code>null</code> if no object is bound with that name.
                                  /**                                                                                                                                                                                                                                                                  *                                                                                static advice(StandardSession s): invalidate(s) {
                                   *                                                                                                                                                                                                                                                                   * @param name Name of the value to be returned                                       before {
                                   * @deprecated                                                                                                                                                                                                                                                       *                                                                                        if (!s.isValid())
                                                                                                                                                                                                                                                                                                       * @exception IllegalStateException if this method is called on an                             throw new IllegalStateException
                                                                                                                                                                                                                                                                                                       * invalidated session                                                                             (s.sm.getString("standardSession."
                                                                                                                                                                                                                                                                                                       *                                                                                                                 + thisJoinPoint.methodName
                                                                                                                                                                                                                                                                                                       * @deprecated As of Version 2.2, this method is replaced by                                                       + ".ise"));
                                                                                                                                                                                                                                                                                                       * <code>getAttribute()</code>                                                        }
                                                                                                                                                                                                                                                                                                       */                                                                               }
                                                                                                                                                                                                                        /**                                                                           public Object getValue(String name) {
                                                                                                                                                                                                                         * Return the session identifier for this session.
                                                                                                                                                                                                                         */                                                                                 return (getAttribute(name));
                                                                                                                                                                                                                        public String getId() {
                                                                                                                                                                                                                                                                                                      }                                                                             }


                                                                                                                                                                                                                                                                                                      /**                                                                           // -------------------------------------------------------------- Private Class
                                                                                                                                                                                                                                                                                                       * Return the set of names of objects bound to this session. If there
                                                                                                                                                                                                                                                                                                       * are no such objects, a zero-length array is returned.
                                                                                                                                                                                                                                                                                                       *                                                                            /**
                                                                                                                                                                                                                                                                                                       * @exception IllegalStateException if this method is called on an             * This class is a dummy implementation of the <code>HttpSessionContext</code>
                                                                                                                                                                                                                                                                                                       * invalidated session                                                         * interface, to conform to the requirement that such an object be returned
                                                                                                                                                                                                                                                                                                       *                                                                             * when <code>HttpSession.getSessionContext()</code> is called.
                                                                                                                                                                                                                                                                                                       * @deprecated As of Version 2.2, this method is replaced by                   *
                                                                                                                                                                                                                                                                                                       * <code>getAttributeNames()</code>                                            * @author Craig R. McClanahan
                                                                                                                                                                                                                                                                                                       */                                                                            *
                                                                                                                                                                                                                                                                                                      public String[] getValueNames() {                                              * @deprecated As of Java Servlet API 2.1 with no replacement. The
                                                                                                                                                                                                                                                                                                                                                                                     * interface will be removed in a future version of this API.
                                                                                                                                                                                                                                                                                                            Vector results = new Vector();                                           */
                                                                                                                                                                                                                                                                                                            Enumeration attrs = getAttributeNames();
                                                                                                                                                                                                                                                                                                            while (attrs.hasMoreElements()) {                                       final class StandardSessionContext implements HttpSessionContext {
                                                                                                                                                                                                                                                                                                                String attr = (String) attrs.nextElement();
                                                                                                                                                                                                                                                                                                                results.addElement(attr);
                                                                                                                                                                                                                                                                                                            }                                                                           private Vector dummy = new Vector();
                                                                                                                                                                                                                            return (this.id);                                                               String names[] = new String[results.size()];
                                                                                                                                                                                                                                                                                                            for (int i = 0; i < names.length; i++)                                      /**
                                                                                                                                                                                                                                                                                                                names[i] = (String) results.elementAt(i);                                * Return the session identifiers of all sessions defined
                                                                                                                                                                                                                                                                                                            return (names);                                                              * within this context.
                                                                                                                                                                                                                                                                                                                                                                                         *
                                                                                                                                                                                                                                                                                                      }                                                                                  * @deprecated As of Java Servlet API 2.1 with no replacement.
                                                                                                                                                                                                                                                                                                                                                                                         * This method must return an empty <code>Enumeration</code>
                                                                                                                                                                                                                                                                                                                                                                                         * and will be removed in a future version of the API.
                                                                                                                                                                                                                                                                                                      /**                                                                                */




                            example since many
                                                                                                                                                                                                                                                                                                       * Invalidates this session and unbinds any objects bound to it.                  public Enumeration getIds() {
                                                                                                                                                                                                                                                                                                       *
                                                                                                                                                                                                                                                                                                       * @exception IllegalStateException if this method is called on                       return (dummy.elements());
                                                                                                                                                                                                                                                                                                       * an invalidated session




• Code is:
                                                                                                                                                                                                                                                                                                       */
                                                                                                                                                                                                                                                                                                      public void invalidate() {

                                                                                                                                                                                                                                                                                                            // Cause this session to expire
                                                                                                                                                                                                                                                                                                            expire();

                                                                                                                                                                                                                                                                                                      }


                                                                                                                                                                                                                        }                                                                             /**
                                                                                                                                                                                                                                                                                                       * Return <code>true</code> if the client does not yet know about the
                                                                                                                                                                                                                                                                                                       * session, or if the client chooses not to join the session. For
                                                                                                                                                                                                                                                                                                       * example, if the server used only cookie-based sessions, and the client
                                                                                                                                                                                                                                                                                                       * has disabled the use of cookies, then a session would be new on each
                                                                                                                                                                                                                                                                                                       * request.
                                                                                                                                                                                                                                                                                                       *
                                                                                                                                                                                                                                                                                                       * @exception IllegalStateException if this method is called on an
                                                                                                                                                                                                                                                                                                       * invalidated session
                                                                                                                                                                                                                                                                                                       */
                                                                                                                                                                                                                                                                                                      public boolean isNew() {

                                                                                                                                                                                                                                                                                                            return (this.isNew);

                                                                                                                                                                                                                                                                                                      }




                              package org.apache.tomcat.session;                                              void validate() {
                                                                                                                      // if we have an inactive interval, check to see if
                              import org.apache.tomcat.core.*;                                                        // we've exceeded it
                              import org.apache.tomcat.util.StringManager;
                              import java.io.*;                                                                       if (inactiveInterval != -1) {
                              import java.net.*;                                                                          int thisInterval =
                              import java.util.*;                                                                             (int)(System.currentTimeMillis() - lastAccessed) / 1000;
                              import javax.servlet.*;




                             parts of a program
                              import javax.servlet.http.*;                                                                if (thisInterval > inactiveInterval) {
                                                                                                                              invalidate();
                              /**
                               * Core implementation of a server session                                                       ServerSessionManager ssm =
                               *                                                                                                   ServerSessionManager.getManager();
                               * @author James Duncan Davidson [duncan@eng.sun.com]
                               * @author James Todd [gonzo@eng.sun.com]                                                        ssm.removeSession(this);
                               */                                                                                         }
                                                                                                                      }
                              public class ServerSession {                                                        }

                                  private StringManager sm =                                                      synchronized void invalidate() {
                                      StringManager.getManager("org.apache.tomcat.session");                          Enumeration enum = appSessions.keys();                                                            /**
                                  private Hashtable values = new Hashtable();                                                                                                                                            * Set the session identifier for this session.
                                  private Hashtable appSessions = new Hashtable();                                    while (enum.hasMoreElements()) {                                                                   *
                                  private String id;                                                                      Object key = enum.nextElement();                                                               * @param id The new session identifier
                                  private long creationTime = System.currentTimeMillis();;                                ApplicationSession appSession =                                                                */
                                  private long thisAccessTime = creationTime;                                                 (ApplicationSession)appSessions.get(key);                                                 public void setId(String id) {
                                  private long lastAccessed = creationTime;
                                  private int inactiveInterval = -1;                                                      appSession.invalidate();
                                                                                                                      }
                                  ServerSession(String id) {                                                      }
                                      this.id = id;
                                  }                                                                               public void putValue(String name, Object value) {
                                                                                                                      if (name == null) {
                                  public String getId() {                                                                 String msg = sm.getString("serverSession.value.iae");
                                      return id;
                                  }                                                                                       throw new IllegalArgumentException(msg);
                                                                                                                      }
                                  public long getCreationTime() {
                                      return creationTime;                                                            removeValue(name); // remove any existing binding
                                  }                                                                                   values.put(name, value);
                                                                                                                  }




 • Scattered throughout
                                  public long getLastAccessedTime() {
                                      return lastAccessed;                                                        public Object getValue(String name) {
                                  }                                                                                   if (name == null) {
                                                                                                                          String msg = sm.getString("serverSession.value.iae");
                                  public ApplicationSession getApplicationSession(Context context,
                                      boolean create) {                                                                   throw new IllegalArgumentException(msg);
                                      ApplicationSession appSession =                                                 }                                                                                                     if ((this.id != null) && (manager != null) &&
                                          (ApplicationSession)appSessions.get(context);                                                                                                                                       (manager instanceof ManagerBase))
                                                                                                                      return values.get(name);                                                                                  ((ManagerBase) manager).remove(this);
                                      if (appSession == null && create) {                                         }




                              involve security
                                          // XXX                                                                  public Enumeration getValueNames() {
                                          // sync to ensure valid?                                                    return values.keys();
                                                                                                                  }
                                          appSession = new ApplicationSession(id, this, context);
                                          appSessions.put(context, appSession);                                   public void removeValue(String name) {
                                      }                                                                               values.remove(name);
                                                                                                                  }
                                      // XXX
                                      // make sure that we haven't gone over the end of our                       public void setMaxInactiveInterval(int interval) {
                                      // inactive interval -- if so, invalidate and create                            inactiveInterval = interval;
                                      // a new appSession                                                         }

                                      return appSession;                                                          public int getMaxInactiveInterval() {
                                  }                                                                                   return inactiveInterval;
                                                                                                                  }
                                  void removeApplicationSession(Context context) {
                                      appSessions.remove(context);                                                // XXX
                                  }                                                                               // sync'd for safty -- no other thread should be getting something
                                                                                                                  // from this while we are reaping. This isn't the most optimal
                                  /**                                                                             // solution for this, but we'll determine something else later.                                           this.id = id;
                                   * Called by context when request comes in so that accesses and
                                   * inactivities can be dealt with accordingly.                                  synchronized void reap() {
                                   */                                                                                 Enumeration enum = appSessions.keys();

                                  void accessed() {                                                                   while (enum.hasMoreElements()) {
                                      // set last accessed to thisAccessTime as it will be left over




   many modules.
                                                                                                                                                                                                                            if ((manager != null) && (manager instanceof ManagerBase))
                                                                                                                                                                                                                                ((ManagerBase) manager).add(this);




                                                                                                                                                                                                                        }




 • Tangled with unrelated
                                                                                                                                                                                                                        /**
                                                                                                                                                                                                                         * Return descriptive information about this Session implementation and
                                                                                                                                                                                                                         * the corresponding version number, in the format
                                                                                                                                                                                                                         * <code>&lt;description&gt;/&lt;version&gt;</code>.
                                                                                                                                                                                                                         */
                                                                                                                                                                                                                        public String getInfo() {




                                                                                                                                                                                                                            return (this.info);




   modules.                                                                                                                                                                                                             }




                                                                                                                                                                                                                        /**
                                                                                                                                                                                                                         * Return the last time the client sent a request associated with this
                                                                                                                                                                                                                         * session, as the number of milliseconds since midnight, January 1, 1970
                                                                                                                                                                                                                         * GMT. Actions that your application takes, such as getting or setting
                                                                                                                                                                                                                         * a value associated with the session, do not affect the access time.
                                                                                                                                                                                                                         */
                                                                                                                                                                                                                        public long getLastAccessedTime() {

                                                                                                                                                                                                                            return (this.lastAccessedTime);

                                                                                                                                                                                                                        }


                                                                                                                                                                                                                        /**
                                                                                                                                                                                                                         * Return the Manager within which this Session is valid.
                                                                                                                                                                                                                         */
                                                                                                                                                                                                                        public Manager getManager() {

                                                                                                                                                                                                                            return (this.manager);

                                                                                                                                                                                                                        }


                                                                                                                                                                                                                        /**
                                                                                                                                                                                                                         * Set the Manager within which this Session is valid.
                                                                                                                                                                                                                         *
                                                                                                                                                                                                                         * @param manager The new Manager
                                                                                                                                                                                                                         */
                                                                                                                                                                                                                        public void setManager(Manager manager) {




                                                                                                                                                                                                                                                                                                                                                                                                                                                                           10
Aspect-Oriented Programming


   /*                                                                                      public void invalidate() {                                                             ;                                                                                                                                                                                        * Remove the object bound with the specified name from this session. If
    * ====================================================================                         serverSession.removeApplicationSession(context);                                                                                                                         /**                                                                                                 * the session does not have an object bound with this name, this method
    *                                                                                                                                                                                                                                                                        * Perform the internal processing required to invalidate this session,                             * does nothing.
    * The Apache Software License, Version 1.1                                                              // remove everything in the session                                   /**                                                                                        * without triggering an exception if the session has already expired.                              * <p>
    *                                                                                                                                                                              * Standard implementation of the <b>Session</b> interface. This object is                 */                                                                                                 * After this method executes, and if the object implements
    * Copyright (c) 1999 The Apache Software Foundation. All rights                                         Enumeration enum = values.keys();                                      * serializable, so that it can be stored in persistent storage or transferred            public void expire() {                                                                              * <code>HttpSessionBindingListener</code>, the container calls
    * reserved.                                                                                             while (enum.hasMoreElements()) {                                       * to a different JVM for distributable session support.                                                                                                                                      * <code>valueUnbound()</code> on the object.
    *                                                                                                           String name = (String)enum.nextElement();                          * <p>                                                                                          // Remove this session from our manager's active sessions                                     *
    * Redistribution and use in source and binary forms, with or without                                        removeValue(name);                                                 * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the                    if ((manager != null) && (manager instanceof ManagerBase))                                    * @param name Name of the object to remove from this session.
    * modification, are permitted provided that the following conditions                                    }                                                                      * internal (Session) and application level (HttpSession) view of the session.                      ((ManagerBase) manager).remove(this);                                                     *
    * are met:                                                                                                                                                                     * However, because the class itself is not declared public, Java logic outside                                                                                                               * @exception IllegalStateException if this method is called on an
    *                                                                                                       valid = false;                                                         * of the <code>org.apache.tomcat.session</code> package cannot cast an                         // Unbind any objects associated with this session                                            * invalidated session
    * 1. Redistributions of source code must retain the above copyright                              }                                                                             * HttpSession view of this instance back to a Session view.                                    Vector results = new Vector();                                                                */
    *    notice, this list of conditions and the following disclaimer.                                                                                                             *                                                                                              Enumeration attrs = getAttributeNames();                                                     public void removeAttribute(String name) {
    *                                                                                                public boolean isNew() {                                                      * @author Craig R. McClanahan                                                                  while (attrs.hasMoreElements()) {
    * 2. Redistributions in binary form must reproduce the above copyright                               if (! valid) {                                                            * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $                                           String attr = (String) attrs.nextElement();                                                  synchronized (attributes) {
    *    notice, this list of conditions and the following disclaimer in                                     String msg = sm.getString("applicationSession.session.ise");          */                                                                                                 results.addElement(attr);                                                                        Object object = attributes.get(name);
    *    the documentation and/or other materials provided with the                                                                                                                                                                                                               }                                                                                                    if (object == null)
    *    distribution.                                                                                          throw new IllegalStateException(msg);                             final class StandardSession                                                                     Enumeration names = results.elements();                                                                  return;
    *                                                                                                       }                                                                         implements HttpSession, Session {                                                           while (names.hasMoreElements()) {                                                                    attributes.remove(name);
    * 3. The end-user documentation included with the redistribution, if                                                                                                                                                                                                              String name = (String) names.nextElement();                                                      //      System.out.println( "Removing attribute " + name );
    *    any, must include the following acknowledgment:                                                    if (thisAccessTime == creationTime) {                                                                                                                                     removeAttribute(name);                                                                           if (object instanceof HttpSessionBindingListener) {
    *       "This product includes software developed by the                                                    return true;                                                            // ----------------------------------------------------------- Constructors               }                                                                                                        ((HttpSessionBindingListener) object).valueUnbound
    *        Apache Software Foundation (http://www.apache.org/)."                                          } else {                                                                                                                                                                                                                                                                           (new HttpSessionBindingEvent((HttpSession) this, name));
    *    Alternately, this acknowledgment may appear in the software                                            return false;                                                                                                                                                     // Mark this session as invalid                                                                      }
   itself,                                                                                                  }                                                                           /**                                                                                       setValid(false);                                                                                 }
    *    if and wherever such third-party acknowledgments normally appear.                           }                                                                                   * Construct a new Session associated with the specified Manager.
    *                                                                                                                                                                                    *                                                                                  }                                                                                                  }
    * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software                                                                                                                 * @param manager The manager with which this Session is associated
    *    Foundation" must not be used to endorse or promote products                       /**                                                                                           */                                                                                                                                                                                * Bind an object to this session, using the specified name. If an object
   derived                                                                                               * @deprecated                                                                  public StandardSession(Manager manager) {                                           /**                                                                                                 * of the same name is already bound to this session, the object is
    *    from this software without prior written permission. For written                                */                                                                                                                                                                                                                                                                     * replaced.
    *    permission, please contact apache@apache.org.                                                                                                                                      super();                                                                        }                                                                                                   * <p>
    *                                                                                                public void putValue(String name, Object value) {                                      this.manager = manager;                                                                                                                                                             * After this method executes, and if the object implements
    * 5. Products derived from this software may not be called "Apache"                                  setAttribute(name, value);                                                                                                                                                                                                                                             * <code>HttpSessionBindingListener</code>, the container calls
    *    nor may "Apache" appear in their names without prior written                                }                                                                                  }                                                                                   /**                                                                                                 * <code>valueBound()</code> on the object.
    *    permission of the Apache Group.                                                                                                                                                                                                                                     * Set the <code>isNew</code> flag for this session.                                                *
    *                                                                                                public void setAttribute(String name, Object value) {                                                                                                                   *                                                                                                  * @param name Name to which the object is bound, cannot be null
    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED                                   if (! valid) {                                                           /**                                                                                        * @param isNew The new value for the <code>isNew</code> flag                                       * @param value Object to be bound, cannot be null
    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES                                      String msg = sm.getString("applicationSession.session.ise");                * The last accessed time for this Session.                                          */                                                                                                 *
    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                                                                                                                        */                                                                                 void setNew(boolean isNew) {                                                                        * @exception IllegalArgumentException if an attempt is made to add a
    * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR                                           throw new IllegalStateException(msg);                                   private long lastAccessedTime = creationTime;                                                                                                                                           * non-serializable object in an environment marked distributable.
    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,                                      }                                                                                                                                                                     this.isNew = isNew;                                                                           * @exception IllegalStateException if this method is called on an
    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT                                                                                                                                                                                                                                                                                                          * invalidated session
    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF                                      if (name == null) {                                                         /**                                                                                 }                                                                                                   */
    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND                                       String msg = sm.getString("applicationSession.value.iae");               * The Manager with which this Session is associated.                                                                                                                                  public void setAttribute(String name, Object value) {
    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,                                                                                                                 */
    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT                                        throw new IllegalArgumentException(msg);                                private Manager manager = null;                                                     /**                                                                                                    if ((manager != null) && manager.getDistributable() &&
    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF                                    }                                                                                                                                                                * Set the <code>isValid</code> flag for this session.                                                   !(value instanceof Serializable))
    * SUCH DAMAGE.                                                                                                                                                                                                                                                           *                                                                                                         throw new IllegalArgumentException
    * ====================================================================                                  removeValue(name);     // remove any existing binding                       /**                                                                                  * @param isValid The new value for the <code>isValid</code> flag                                              (sm.getString("standardSession.setAttribute.iae"));
    *                                                                                                                                                                                    * The maximum time interval, in seconds, between client requests before             */
    * This software consists of voluntary contributions made by many                                        if (value != null && value instanceof HttpSessionBindingListener) {          * the servlet container may invalidate this session. A negative time               void setValid(boolean isValid) {                                                                       synchronized (attributes) {
    * individuals on behalf of the Apache Software Foundation. For more                                         HttpSessionBindingEvent e =                                              * indicates that the session should never time out.                                                                                                                                           removeAttribute(name);
    * information on the Apache Software Foundation, please see                                                     new HttpSessionBindingEvent(this, name);                             */                                                                                       this.isValid = isValid;                                                                              attributes.put(name, value);
    * <http://www.apache.org/>.                                                                                                                                                         private int maxInactiveInterval = -1;                                               }                                                                                                          if (value instanceof HttpSessionBindingListener)
    *                                                                                                           ((HttpSessionBindingListener)value).valueBound(e);                                                                                                                                                                                                                         ((HttpSessionBindingListener) value).valueBound
    * [Additional notices, if required by prior licensing conditions]                                       }                                                                                                                                                                                                                                                                                  (new HttpSessionBindingEvent((HttpSession) this, name));
    *                                                                                                                                                                                   /**                                                                                 // ------------------------------------------------- HttpSession Properties                            }
    */                                                                                                      values.put(name, value);                                                     * Flag indicating whether this session is new or not.
                                                                                                     }                                                                                   */                                                                                                                                                                                    }
                                                                                                                                                                                        private boolean isNew = true;                                                       /**
                                                                                                     /**                                                                                                                                                                     * Return the time when this session was created, in milliseconds since
   package org.apache.tomcat.session;                                                                  * @deprecated                                                                                                                                                         * midnight, January 1, 1970 GMT.                                                                  // -------------------------------------------- HttpSession Private Methods
                                                                                                       */                                                                               /**                                                                                  *
   import org.apache.tomcat.core.*;                                                                  public Object getValue(String name) {                                               * Flag indicating whether this session is valid or not.                             * @exception IllegalStateException if this method is called on an
   import org.apache.tomcat.util.StringManager;                                                           return getAttribute(name);                                                     */                                                                                  * invalidated session                                                                             /**
   import java.io.*;                                                                                 }                                                                                  private boolean isValid = false;                                                     */                                                                                                 * Read a serialized version of this session object from the specified
   import java.net.*;                                                                                                                                                                                                                                                       public long getCreationTime() {                                                                     * object input stream.
   import java.util.*;                                                                               public Object getAttribute(String name) {                                                                                                                                                                                                                                  * <p>
   import javax.servlet.*;                                                                               if (! valid) {                                                                 /**                                                                                       return (this.creationTime);                                                                   * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager
   import javax.servlet.http.*;                                                                              String msg = sm.getString("applicationSession.session.ise");                * The string manager for this package.                                                                                                                                                 * is not restored by this method, and must be set explicitly.
                                                                                                                                                                                         */                                                                                 }                                                                                                   *
   /**                                                                                                          throw new IllegalStateException(msg);                                   private StringManager sm =                                                                                                                                                              * @param stream The input stream to read from
    * Core implementation of an application level session                                                   }                                                                               StringManager.getManager("org.apache.tomcat.session");                                                                                                                              *
    *                                                                                                                                                                                                                                                                       /**                                                                                                 * @exception ClassNotFoundException if an unknown class is specified
    * @author James Duncan Davidson [duncan@eng.sun.com]                                                    if (name == null) {                                                                                                                                              * Return the session context with which this session is associated.                                * @exception IOException if an input/output error occurs
    * @author Jason Hunter [jch@eng.sun.com]                                                                    String msg = sm.getString("applicationSession.value.iae");              /**                                                                                  *                                                                                                  */
    * @author James Todd [gonzo@eng.sun.com]                                                                                                                                             * The HTTP session context associated with this session.                            * @deprecated As of Version 2.1, this method is deprecated and has no                             private void readObject(ObjectInputStream stream)
    */                                                                                                          throw new IllegalArgumentException(msg);                                 */                                                                                  * replacement. It will be removed in a future version of the                                          throws ClassNotFoundException, IOException {
                                                                                                            }                                                                           private static HttpSessionContext sessionContext = null;                             * Java Servlet API.
   public class ApplicationSession implements HttpSession {                                                                                                                                                                                                                  */                                                                                                    // Deserialize the scalar instance variables (except Manager)
                                                                                                            return values.get(name);                                                                                                                                        public HttpSessionContext getSessionContext() {                                                        creationTime = ((Long) stream.readObject()).
       private StringManager sm =                                                                    }                                                                                  /**                                                                                                                                                                                        isValid = ((Boolean) stream.readObject()).booleanValue();
           StringManager.getManager("org.apache.tomcat.session");                                                                                                                        * The current accessed time for this session.                                            if (sessionContext == null)
       private Hashtable values = new Hashtable();                                                   /**                                                                                 */                                                                                           sessionContext = new StandardSessionContext();                                               // Deserialize the attribute count and attribute values
       private String id;                                                                             * @deprecated                                                                     private long thisAccessedTime = creationTime;                                             return (sessionContext);                                                                         int n = ((Integer) stream.readObject()).intValue();
       private ServerSession serverSession;                                                           */                                                                                                                                                                                                                                                                           for (int i = 0; i < n; i++) {
       private Context context;                                                                      public String[] getValueNames() {                                                                                                                                      }                                                                                                          String name = (String) stream.readObject();
       private long creationTime = System.currentTimeMillis();;                                          Enumeration e = getAttributeNames();                                                                                                                                                                                                                                          Object value = (Object) stream.readObject();
       private long thisAccessTime = creationTime;                                                       Vector names = new Vector();                                                                                                                                                                                                                                                  attributes.put(name, value);
   private boolean valid = true;                                                                                                                                                        // ----------------------------------------------------- Session Properties         // ----------------------------------------------HttpSession Public Methods                            }
                                                                                                            while (e.hasMoreElements()) {
       ApplicationSession(String id, ServerSession serverSession,                                               names.addElement(e.nextElement());                                                                                                                                                                                                                             }
           Context context) {                                                                               }                                                                           /**                                                                                 /**
           this.serverSession = serverSession;                                                                                                                                           * Set the creation time for this session. This method is called by the              * Return the object bound with the specified name in this session, or
           this.context = context;                                                                          String[] valueNames = new String[names.size()];                              * Manager when an existing Session instance is reused.                              * <code>null</code> if no object is bound with that name.                                         /**
           this.id = id;                                                                                                                                                                 *                                                                                   *                                                                                                  * Write a serialized version of this session object to the specified
                                                                                                            names.copyInto(valueNames);                                                  * @param time The new creation time                                                 * @param name Name of the attribute to be returned                                                 * object output stream.
           this.inactiveInterval = context.getSessionTimeOut();                                                                                                                          */                                                                                  *                                                                                                  * <p>
                                                                                                            return valueNames;                                                          public void setCreationTime(long time) {                                             * @exception IllegalStateException if this method is called on an                                  * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored
           if (this.inactiveInterval != -1) {                                                                                                                                                                                                                                * invalidated session                                                                              * in the serialized representation of this Session. After calling
               this.inactiveInterval *= 60;                                                          }                                                                                      this.creationTime = time;                                                        */                                                                                                 * <code>readObject()</code>, you must set the associated Manager
           }                                                                                                                                                                                this.lastAccessedTime = time;                                                   public Object getAttribute(String name) {                                                           * explicitly.
       }                                                                                             public Enumeration getAttributeNames() {                                               this.thisAccessedTime = time;                                                                                                                                                       * <p>
                                                                                                         if (! valid) {                                                                                                                                                           return (attributes.get(name));                                                                * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable
       ServerSession getServerSession() {                                                                    String msg = sm.getString("applicationSession.session.ise");               }                                                                                                                                                                                       * will be silently ignored. If you do not want any such attributes,
           return serverSession;                                                                                                                                                                                                                                            }                                                                                                   * be sure the <code>distributable</code> property of our associated
       }                                                                                                        throw new IllegalStateException(msg);                                                                                                                                                                                                                           * Manager is set to <code>true</code>.
                                                                                                            }                                                                           /**                                                                                                                                                                                     *
       /**                                                                                                                                                                               * Return the session identifier for this session.                                  /**                                                                                                 * @param stream The output stream to write to
        * Called by context when request comes in so that accesses and                                      Hashtable valuesClone = (Hashtable)values.clone();                           */                                                                                  * Return an <code>Enumeration</code> of <code>String</code> objects                                *
        * inactivities can be dealt with accordingly.                                                                                                                                   public String getId() {                                                              * containing the names of the objects bound to this session.                                       * @exception IOException if an input/output error occurs
        */                                                                                                  return (Enumeration)valuesClone.keys();                                                                                                                          *                                                                                                  */
                                                                                                     }                                                                                      return (this.id);                                                                * @exception IllegalStateException if this method is called on an                                 private void writeObject(ObjectOutputStream stream) throws IOException {
                                                                                                                                                                                                                                                                             * invalidated session
       // HTTP SESSION IMPLEMENTATION METHODS                                                                                                                                           }                                                                                    */                                                                                                    // Write the scalar instance variables (except Manager)
                                                                                               /**                                                                                                                                                                          public Enumeration getAttributeNames() {                                                               stream.writeObject(new Long(creationTime));
       public String getId() {                                                                           * @deprecated                                                                                                                                                                                                                                                             stream.writeObject(id);
           if (valid) {                                                                                  */                                                                             /**                                                                                       return (attributes.keys());                                                                      stream.writeObject(new Long(lastAccessedTime));
               return id;                                                                                                                                                                * Set the session identifier for this session.                                                                                                                                            stream.writeObject(new Integer(maxInactiveInterval));
           } else {                                                                                  public void removeValue(String name) {                                              *                                                                                  }                                                                                                      stream.writeObject(new Boolean(isNew));
               String msg = sm.getString("applicationSession.session.ise");                              removeAttribute(name);                                                          * @param id The new session identifier                                                                                                                                                    stream.writeObject(new Boolean(isValid));
                                                                                                     }                                                                                   */
               throw new IllegalStateException(msg);                                                                                                                                    public void setId(String id) {                                                      /**                                                                                                    // Accumulate the names of serializable attributes
           }                                                                                         public void removeAttribute(String name) {                                                                                                                              * Return the object bound with the specified name in this session, or                                 Vector results = new Vector();
       }                                                                                                 if (! valid) {                                                                     if ((this.id != null) && (manager != null) &&                                    * <code>null</code> if no object is bound with that name.                                             Enumeration attrs = getAttributeNames();
                                                                                                             String msg = sm.getString("applicationSession.session.ise");                     (manager instanceof ManagerBase))                                              *                                                                                                     while (attrs.hasMoreElements()) {
       public long getCreationTime() {                                                                                                                                                          ((ManagerBase) manager).remove(this);                                        * @param name Name of the value to be returned                                                            String attr = (String) attrs.nextElement();
           if (valid) {                                                                                         throw new IllegalStateException(msg);                                                                                                                        *                                                                                                         Object value = attributes.get(attr);
               return creationTime;                                                                         }                                                                               this.id = id;                                                                    * @exception IllegalStateException if this method is called on an                                         if (value instanceof Serializable)
           } else {                                                                                                                                                                                                                                                          * invalidated session                                                                                         results.addElement(attr);
               String msg = sm.getString("applicationSession.session.ise");                                 if (name == null) {                                                             if ((manager != null) && (manager instanceof ManagerBase))                       *                                                                                                     }
                                                                                                                String msg = sm.getString("applicationSession.value.iae");                      ((ManagerBase) manager).add(this);                                           * @deprecated As of Version 2.2, this method is replaced by
               throw new IllegalStateException(msg);                                                                                                                                                                                                                         * <code>getAttribute()</code>                                                                         // Serialize the attribute count and the attribute values
           }                                                                                                    throw new IllegalArgumentException(msg);                                }                                                                                    */                                                                                                    stream.writeObject(new Integer(results.size()));
       }                                                                                                    }                                                                                                                                                               public Object getValue(String name) {                                                                  Enumeration names = results.elements();
                                                                                                                                                                                                                                                                                                                                                                                   while (names.hasMoreElements()) {
       /**                                                                                                  Object o = values.get(name);                                                /**                                                                                       return (getAttribute(name));                                                                         String name = (String) names.nextElement();
        *                                                                                                                                                                                * Return descriptive information about this Session implementation and                                                                                                                        stream.writeObject(name);
        * @deprecated                                                                                       if (o instanceof HttpSessionBindingListener) {                               * the corresponding version number, in the format                                  }                                                                                                          stream.writeObject(attributes.get(name));
        */                                                                                                      HttpSessionBindingEvent e =                                              * <code>&lt;description&gt;/&lt;version&gt;</code>.                                                                                                                                       }
                                                                                                                    new HttpSessionBindingEvent(this,name);                              */
       public HttpSessionContext getSessionContext() {                                                                                                                                  public String getInfo() {                                                           /**
           return new SessionContextImpl();                                                                     ((HttpSessionBindingListener)o).valueUnbound(e);                                                                                                             * Return the set of names of objects bound to this session. If there                              }
       }                                                                                                    }                                                                               return (this.info);                                                              * are no such objects, a zero-length array is returned.
                                                                                                                                                                                                                                                                             *                                                                                                 crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() |
                                                                                                            values.remove(name);                                                        }                                                                                    * @exception IllegalStateException if this method is called on an                                                                              long getCreationTime() |
                                                                                                     }                                                                                                                                                                       * invalidated session                                                                                                                          Object getAttribute(String) |
                                                                                                                                                                                  /**                                                                                        *                                                                                                                                              Enumeration getAttributeNames() |
                                                                                                     public void setMaxInactiveInterval(int interval) {                                  * Return the Manager within which this Session is valid.                            * @deprecated As of Version 2.2, this method is replaced by                                                                                    String[] getValueNames() |
                                                                                                         if (! valid) {                                                                  */                                                                                  * <code>getAttributeNames()</code>                                                                                                             void invalidate() |
                                                                                                             String msg = sm.getString("applicationSession.session.ise");               public Manager getManager() {                                                        */                                                                                                                                             boolean isNew() |
                                                                                                                                                                                                                                                                            public String[] getValueNames() {                                                                                                               void removeAttribute(String) |
                                                                                                                throw new IllegalStateException(msg);                                       return (this.manager);                                                                                                                                                                                                          void setAttribute(String, Object));
                                                                                                            }                                                                                                                                                                     Vector results = new Vector();
                                                                                                                                                                                        }                                                                                         Enumeration attrs = getAttributeNames();                                                     static advice(StandardSession s): invalidate(s) {
                                                                                                            inactiveInterval = interval;                                                                                                                                          while (attrs.hasMoreElements()) {                                                                before {
                                                                                                     }                                                                                                                                                                                String attr = (String) attrs.nextElement();                                                      if (!s.isValid())
                                                                                                                                                                                        /**                                                                                           results.addElement(attr);                                                                             throw new IllegalStateException
                                                                                                     public int getMaxInactiveInterval() {                                               * Set the Manager within which this Session is valid.                                    }                                                                                                             (s.sm.getString("standardSession."
                                                                                                         if (! valid) {                                                                  *                                                                                        String names[] = new String[results.size()];                                                                                  + thisJoinPoint.methodName
                                                                                                             String msg = sm.getString("applicationSession.session.ise");                * @param manager The new Manager                                                         for (int i = 0; i < names.length; i++)                                                                                        + ".ise"));
                                                                                                                                                                                         */                                                                                           names[i] = (String) results.elementAt(i);                                                    }
                                                                                                                throw new IllegalStateException(msg);                                   public void setManager(Manager manager) {                                                 return (names);                                                                              }
                                                                                                            }
                                                                                                                                                                                            this.manager = manager;                                                         }
                                                                                                            return inactiveInterval;
                                                                                                     }                                                                                  }
                                                                                           }                                                                                                                                                                                /**                                                                                            }
                                                                                                                                                                                                                                                                             * Invalidates this session and unbinds any objects bound to it.
                                                                                                                                                                                        /**                                                                                  *
                                                                                           //-----------------------------------------------------------------------                     * Return the maximum time interval, in seconds, between client requests             * @exception IllegalStateException if this method is called on                                // -------------------------------------------------------------- Private Class
                                                                                                                                                                                         * before the servlet container will invalidate the session. A negative              * an invalidated session
                                                                                                                                                                                         * time indicates that the session should never time out.                            */
                                                                                                                                                                                         *                                                                                  public void invalidate() {                                                                     /**
                                                                                                                                                                                         * @exception IllegalStateException if this method is called on                                                                                                                     * This class is a dummy implementation of the <code>HttpSessionContext</code>
                                                                                                                                                                                         * an invalidated session                                                                 // Cause this session to expire                                                           * interface, to conform to the requirement that such an object be returned
                                                                                                                                                                                         */                                                                                       expire();                                                                                 * when <code>HttpSession.getSessionContext()</code> is called.
                                                                                                                                                                                        public int getMaxInactiveInterval() {                                                                                                                                               *
                                                                                                                                                                                                                                                                            }                                                                                               * @author Craig R. McClanahan
                                                                                                                                                                                            return (this.maxInactiveInterval);                                                                                                                                              *
                                                                                                                                                                                                                                                                                                                                                                            * @deprecated As of Java Servlet API 2.1 with no replacement. The
                                                                                                                                                                                                                                                                            /**                                                                                             * interface will be removed in a future version of this API.
                                                                                                                                                                                                                                                                             * Return <code>true</code> if the client does not yet know about the                           */
                                                                                                                                                                                                                                                                             * session, or if the client chooses not to join the session. For
                                                                                                                                                                                                                                                                             * example, if the server used only cookie-based sessions, and the client                      final class StandardSessionContext implements HttpSessionContext {
                                                                                                                                                                                                                                                                             * has disabled the use of cookies, then a session would be new on each
                                                                                                                                                                                                                                                                             * request.
                                                                                                                                                                                                                                                                             *                                                                                                 private Vector dummy = new Vector();
                                                                                                                                                                                                                                                                             * @exception IllegalStateException if this method is called on an
                                                                                                                                                                                                                                                                             * invalidated session                                                                             /**
                                                                                                                                                                                                                                                                             */                                                                                                 * Return the session identifiers of all sessions defined
                                                                                                                                                                                                                                                                            public boolean isNew() {                                                                            * within this context.
                                                                                                                                                                                                                                                                                                                                                                                *
                                                                                                                                                                                                                                                                                  return (this.isNew);                                                                          * @deprecated As of Java Servlet API 2.1 with no replacement.
                                                                                                                                                                                                                                                                                                                                                                                * This method must return an empty <code>Enumeration</code>
                                                                                                                                                                                                                                                                            }                                                                                                   * and will be removed in a future version of the API.
                                                                                                                                                                                                                                                                                                                                                                                */
                                                                                                                                                                                                                                                                                                                                                                               public Enumeration getIds() {

                                                                                                                                                                                                                                                                                                                                                                                   return (dummy.elements());

                                                                                                                                                                                                                                                                                                                                                                               }


                                                                                                                                                                                                                                                                                                                                                                               /**
                                                                                                                                                                                                                                                                                                                                                                                * Return the <code>HttpSession</code> associated with the
                                                                                                                                                                                                                                                                                                                                                                                * specified session identifier.
                                                                                                                                                                                                                                                                                                                                                                                *
                                                                                                                                                                                                                                                                                                                                                                                * @param id Session identifier for which to look up a session
                                                                                                                                                                                                                                                                                                                                                                                *
                                                                                                                                                                                                                                                                                                                                                                                * @deprecated As of Java Servlet API 2.1 with no replacement.
                                                                                                                                                                                                                                                                                                                                                                                * This method must return null and will be removed in a
                                                                                                                                                                                                                                                                                                                                                                                * future version of the API.
                                                                                                                                                                                                                                                                                                                                                                                */
                                                                                                                                                                                                                                                                                                                                                                               public HttpSession getSession(String id) {

                                                                                                                                                                                                                                                                                                                                                                                   return (null);

                                                                                                                                                                                                                                                                                                                                                                               }

                                                                                                                                                                                                                                                                                                                                                                           }




   package org.apache.tomcat.session;                                         ynchronized void invalidate() {
                                                                                      Enumeration enum = appSessions.keys();
   import org.apache.tomcat.core.*;
   import org.apache.tomcat.util.StringManager;                                       while (enum.hasMoreElements()) {
   import java.io.*;                                                                      Object key = enum.nextElement();
   import java.net.*;                                                                     ApplicationSession appSession =
   import java.util.*;                                                                        (ApplicationSession)appSessions.get(key);
   import javax.servlet.*;
   import javax.servlet.http.*;                                                           appSession.invalidate();
                                                                                      }
   /**                                                                            }
    * Core implementation of a server session
    *                                                                             public void putValue(String name, Object value) {
    * @author James Duncan Davidson [duncan@eng.sun.com]                              if (name == null) {
    * @author James Todd [gonzo@eng.sun.com]                                              String msg = sm.getString("serverSession.value.iae");
    */
                                                                                          throw new IllegalArgumentException(msg);
   public class ServerSession {                                                       }

       private StringManager sm =                                                     removeValue(name); // remove any existing binding
           StringManager.getManager("org.apache.tomcat.session");                     values.put(name, value);
       private Hashtable values = new Hashtable();                                }
       private Hashtable appSessions = new Hashtable();
       private String id;                                                         public Object getValue(String name) {
       private long creationTime = System.currentTimeMillis();;                       if (name == null) {
       private long thisAccessTime = creationTime;                                        String msg = sm.getString("serverSession.value.iae");
       private long lastAccessed = creationTime;
       private int inactiveInterval = -1;                                                 throw new IllegalArgumentException(msg);
                                                                                      }
       ServerSession(String id) {
           this.id = id;                                                              return values.get(name);
       }                                                                          }

       public String getId() {                                                    public Enumeration getValueNames() {
           return id;                                                                 return values.keys();
       }                                                                          }

       public long getCreationTime() {                                            public void removeValue(String name) {
           return creationTime;                                                       values.remove(name);
       }                                                                          }

       public long getLastAccessedTime() {                                        public void setMaxInactiveInterval(int interval) {
           return lastAccessed;                                                       inactiveInterval = interval;
       }                                                                          }

       public ApplicationSession getApplicationSession(Context context,           public int getMaxInactiveInterval() {
           boolean create) {                                                          return inactiveInterval;
           ApplicationSession appSession =                                        }
               (ApplicationSession)appSessions.get(context);
                                                                                  // XXX
           if (appSession == null && create) {                                    // sync'd for safty -- no other thread should be getting something
                                                                                  // from this while we are reaping. This isn't the most optimal
               // XXX                                                             // solution for this, but we'll determine something else later.
               // sync to ensure valid?
                                                                                  synchronized void reap() {
               appSession = new ApplicationSession(id, this, context);                Enumeration enum = appSessions.keys();
               appSessions.put(context, appSession);
           }                                                                          while (enum.hasMoreElements()) {
                                                                                          Object key = enum.nextElement();
           // XXX                                                                         ApplicationSession appSession =
           // make sure that we haven't gone over the end of our                              (ApplicationSession)appSessions.get(key);
           // inactive interval -- if so, invalidate and create
           // a new appSession                                                            appSession.validate();
                                                                                      }
           return appSession;                                                     }
       }                                                                      }

       void removeApplicationSession(Context context) {
           appSessions.remove(context);
       }

       /**
        * Called by context when request comes in so that accesses and
        * inactivities can be dealt with accordingly.
        */


       void validate()




                                                                                                                                                                                                  private long lastAccessed = creationTime;                                                                                                     if (inactiveInterval != -1) {
                                                                                                                                                                                                     private int inactiveInterval = -1;                                                                                                                     int thisInterval =
                                                                                                                                                                                                                                                                                                                                                                (int)(System.currentTimeMillis() - lastAccessed) / 1000;
                                                                                                                                                                                                  void accessed() {
                                                                                                                                                                                                         // set last accessed to thisAccessTime as it will be left over                                                                                       if (thisInterval > inactiveInterval) {
                                                                                                                                                                                                         // from the previous access                                                                                                                              invalidate();
                                                                                                                                                                                                         lastAccessed = thisAccessTime;
                                                                                                                                                                                                         thisAccessTime = System.currentTimeMillis();                                                                                                             ServerSessionManager ssm =
                                                                                                                                                                                                                                                                                                                                                                      ServerSessionManager.getManager();
                                                                                                                                                                                                            validate();
                                                                                                                                                                                                     }                                                                                                                                                            ssm.removeSession(this);
                                                                                                                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                     void validate() {                                                                                                                                    }
                                                                                                                                                                                                         // if we have an inactive interval, check to see if we've exceeded it                                                                        }
                                                                                                                                                                                                         if (inactiveInterval != -1) {
                                                                                                                                                                                                             int thisInterval =                                                                                                                    private long lastAccessedTime = creationTime;
                                                                                                                                                                                                                 (int)(System.currentTimeMillis() - lastAccessed) / 1000;

                                                                                                                                                                                                                if (thisInterval > inactiveInterval) {
                                                                                                                                                                                                                    invalidate();                                                                                                                     /**
                                                                                                                                                                                                                }                                                                                                                                      * 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() {                                                                                                                  */
                                                                                                                                                                                                         if (valid) {                                                                                                                                 public long getLastAccessedTime() {
                                                                                                                                                                                                             return lastAccessed;
                                                                                                                                                                                                         } else {                                                                                                                                         return (this.lastAccessedTime);
                                                                                                                                                                                                             String msg = sm.getString("applicationSession.session.ise");
                                                                                                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                throw new IllegalStateException(msg);
                                                                                                                                                                                                            }
                                                                                                                                                                                                     }                                                                                                                                                    this.lastAccessedTime = time;


                                                                                                                                                                                                  public long getLastAccessedTime() {
                                                                                                                                                                                                         return lastAccessed;
                                                                                                                                                                                                     }


                                                                                                                                                                                                  private long lastAccessed = creationTime;

                                                                                                                                                                                                  void accessed() {
                                                                                                                                                                                                         // set last accessed to thisAccessTime as it will be left over
                                                                                                                                                                                                         // from the previous access

                                                                                                                                                                                                            lastAccessed = thisAccessTime;
                                                                                                                                                                                                            thisAccessTime = System.currentTimeMillis();

                                                                                                                                                                                                     }




                                                                                                                                                                                                                                                                                                                                                                                                                                                                  11
Aspect-Oriented Programming


                                /*                                                                                      public void invalidate() {                                                             ;                                                                                                                                                                                        * Remove the object bound with the specified name from this session. If
                                 * ====================================================================                         serverSession.removeApplicationSession(context);                                                                                                                         /**                                                                                                 * the session does not have an object bound with this name, this method
                                 *                                                                                                                                                                                                                                                                        * Perform the internal processing required to invalidate this session,                             * does nothing.
                                 * The Apache Software License, Version 1.1                                                              // remove everything in the session                                   /**                                                                                        * without triggering an exception if the session has already expired.                              * <p>
                                 *                                                                                                                                                                              * Standard implementation of the <b>Session</b> interface. This object is                 */                                                                                                 * After this method executes, and if the object implements
                                 * Copyright (c) 1999 The Apache Software Foundation. All rights                                         Enumeration enum = values.keys();                                      * serializable, so that it can be stored in persistent storage or transferred            public void expire() {                                                                              * <code>HttpSessionBindingListener</code>, the container calls
                                 * reserved.                                                                                             while (enum.hasMoreElements()) {                                       * to a different JVM for distributable session support.                                                                                                                                      * <code>valueUnbound()</code> on the object.
                                 *                                                                                                           String name = (String)enum.nextElement();                          * <p>                                                                                          // Remove this session from our manager's active sessions                                     *
                                 * Redistribution and use in source and binary forms, with or without                                        removeValue(name);                                                 * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the                    if ((manager != null) && (manager instanceof ManagerBase))                                    * @param name Name of the object to remove from this session.
                                 * modification, are permitted provided that the following conditions                                    }                                                                      * internal (Session) and application level (HttpSession) view of the session.                      ((ManagerBase) manager).remove(this);                                                     *
                                 * are met:                                                                                                                                                                     * However, because the class itself is not declared public, Java logic outside                                                                                                               * @exception IllegalStateException if this method is called on an
                                 *                                                                                                       valid = false;                                                         * of the <code>org.apache.tomcat.session</code> package cannot cast an                         // Unbind any objects associated with this session                                            * invalidated session
                                 * 1. Redistributions of source code must retain the above copyright                              }                                                                             * HttpSession view of this instance back to a Session view.                                    Vector results = new Vector();                                                                */
                                 *    notice, this list of conditions and the following disclaimer.                                                                                                             *                                                                                              Enumeration attrs = getAttributeNames();                                                     public void removeAttribute(String name) {
                                 *                                                                                                public boolean isNew() {                                                      * @author Craig R. McClanahan                                                                  while (attrs.hasMoreElements()) {
                                 * 2. Redistributions in binary form must reproduce the above copyright                               if (! valid) {                                                            * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $                                           String attr = (String) attrs.nextElement();                                                  synchronized (attributes) {
                                 *    notice, this list of conditions and the following disclaimer in                                     String msg = sm.getString("applicationSession.session.ise");          */                                                                                                 results.addElement(attr);                                                                        Object object = attributes.get(name);
                                 *    the documentation and/or other materials provided with the                                                                                                                                                                                                               }                                                                                                    if (object == null)
                                 *    distribution.                                                                                          throw new IllegalStateException(msg);                             final class StandardSession                                                                     Enumeration names = results.elements();                                                                  return;
                                 *                                                                                                       }                                                                         implements HttpSession, Session {                                                           while (names.hasMoreElements()) {                                                                    attributes.remove(name);
                                 * 3. The end-user documentation included with the redistribution, if                                                                                                                                                                                                              String name = (String) names.nextElement();                                                      //      System.out.println( "Removing attribute " + name );
                                 *    any, must include the following acknowledgment:                                                    if (thisAccessTime == creationTime) {                                                                                                                                     removeAttribute(name);                                                                           if (object instanceof HttpSessionBindingListener) {
                                 *       "This product includes software developed by the                                                    return true;                                                            // ----------------------------------------------------------- Constructors               }                                                                                                        ((HttpSessionBindingListener) object).valueUnbound
                                 *        Apache Software Foundation (http://www.apache.org/)."                                          } else {                                                                                                                                                                                                                                                                           (new HttpSessionBindingEvent((HttpSession) this, name));
                                 *    Alternately, this acknowledgment may appear in the software                                            return false;                                                                                                                                                     // Mark this session as invalid                                                                      }
                                itself,                                                                                                  }                                                                           /**                                                                                       setValid(false);                                                                                 }
                                 *    if and wherever such third-party acknowledgments normally appear.                           }                                                                                   * Construct a new Session associated with the specified Manager.
                                 *                                                                                                                                                                                    *                                                                                  }                                                                                                  }
                                 * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software                                                                                                                 * @param manager The manager with which this Session is associated
                                 *    Foundation" must not be used to endorse or promote products                       /**                                                                                           */                                                                                                                                                                                * Bind an object to this session, using the specified name. If an object
                                derived                                                                                               * @deprecated                                                                  public StandardSession(Manager manager) {                                           /**                                                                                                 * of the same name is already bound to this session, the object is
                                 *    from this software without prior written permission. For written                                */                                                                                                                                                                                                                                                                     * replaced.
                                 *    permission, please contact apache@apache.org.                                                                                                                                      super();                                                                        }                                                                                                   * <p>
                                 *                                                                                                public void putValue(String name, Object value) {                                      this.manager = manager;                                                                                                                                                             * After this method executes, and if the object implements
                                 * 5. Products derived from this software may not be called "Apache"                                  setAttribute(name, value);                                                                                                                                                                                                                                             * <code>HttpSessionBindingListener</code>, the container calls
                                 *    nor may "Apache" appear in their names without prior written                                }                                                                                  }                                                                                   /**                                                                                                 * <code>valueBound()</code> on the object.
                                 *    permission of the Apache Group.                                                                                                                                                                                                                                     * Set the <code>isNew</code> flag for this session.                                                *
                                 *                                                                                                public void setAttribute(String name, Object value) {                                                                                                                   *                                                                                                  * @param name Name to which the object is bound, cannot be null
                                 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED                                   if (! valid) {                                                           /**                                                                                        * @param isNew The new value for the <code>isNew</code> flag                                       * @param value Object to be bound, cannot be null
                                 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES                                      String msg = sm.getString("applicationSession.session.ise");                * The last accessed time for this Session.                                          */                                                                                                 *
                                 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                                                                                                                        */                                                                                 void setNew(boolean isNew) {                                                                        * @exception IllegalArgumentException if an attempt is made to add a
                                 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR                                           throw new IllegalStateException(msg);                                   private long lastAccessedTime = creationTime;                                                                                                                                           * non-serializable object in an environment marked distributable.
                                 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,                                      }                                                                                                                                                                     this.isNew = isNew;                                                                           * @exception IllegalStateException if this method is called on an
                                 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT                                                                                                                                                                                                                                                                                                          * invalidated session
                                 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF                                      if (name == null) {                                                         /**                                                                                 }                                                                                                   */
                                 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND                                       String msg = sm.getString("applicationSession.value.iae");               * The Manager with which this Session is associated.                                                                                                                                  public void setAttribute(String name, Object value) {
                                 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,                                                                                                                 */
                                 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT                                        throw new IllegalArgumentException(msg);                                private Manager manager = null;                                                     /**                                                                                                    if ((manager != null) && manager.getDistributable() &&
                                 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF                                    }                                                                                                                                                                * Set the <code>isValid</code> flag for this session.                                                   !(value instanceof Serializable))




•
                                 * SUCH DAMAGE.                                                                                                                                                                                                                                                           *                                                                                                         throw new IllegalArgumentException
                                 * ====================================================================                                  removeValue(name);     // remove any existing binding                       /**                                                                                  * @param isValid The new value for the <code>isValid</code> flag                                              (sm.getString("standardSession.setAttribute.iae"));
                                 *                                                                                                                                                                                    * The maximum time interval, in seconds, between client requests before             */
                                 * This software consists of voluntary contributions made by many                                        if (value != null && value instanceof HttpSessionBindingListener) {          * the servlet container may invalidate this session. A negative time               void setValid(boolean isValid) {                                                                       synchronized (attributes) {
                                 * individuals on behalf of the Apache Software Foundation. For more                                         HttpSessionBindingEvent e =                                              * indicates that the session should never time out.                                                                                                                                           removeAttribute(name);
                                 * information on the Apache Software Foundation, please see                                                     new HttpSessionBindingEvent(this, name);                             */                                                                                       this.isValid = isValid;                                                                              attributes.put(name, value);
                                 * <http://www.apache.org/>.                                                                                                                                                         private int maxInactiveInterval = -1;                                               }                                                                                                          if (value instanceof HttpSessionBindingListener)
                                 *                                                                                                           ((HttpSessionBindingListener)value).valueBound(e);                                                                                                                                                                                                                         ((HttpSessionBindingListener) value).valueBound
                                 * [Additional notices, if required by prior licensing conditions]                                       }                                                                                                                                                                                                                                                                                  (new HttpSessionBindingEvent((HttpSession) this, name));
                                 *                                                                                                                                                                                   /**                                                                                 // ------------------------------------------------- HttpSession Properties                            }
                                 */                                                                                                      values.put(name, value);                                                     * Flag indicating whether this session is new or not.
                                                                                                                                  }                                                                                   */                                                                                                                                                                                    }
                                                                                                                                                                                                                     private boolean isNew = true;                                                       /**




    Aspect-Oriented
                                                                                                                                  /**                                                                                                                                                                     * Return the time when this session was created, in milliseconds since
                                package org.apache.tomcat.session;                                                                  * @deprecated                                                                                                                                                         * midnight, January 1, 1970 GMT.                                                                  // -------------------------------------------- HttpSession Private Methods
                                                                                                                                    */                                                                               /**                                                                                  *
                                import org.apache.tomcat.core.*;                                                                  public Object getValue(String name) {                                               * Flag indicating whether this session is valid or not.                             * @exception IllegalStateException if this method is called on an
                                import org.apache.tomcat.util.StringManager;                                                           return getAttribute(name);                                                     */                                                                                  * invalidated session                                                                             /**
                                import java.io.*;                                                                                 }                                                                                  private boolean isValid = false;                                                     */                                                                                                 * Read a serialized version of this session object from the specified
                                import java.net.*;                                                                                                                                                                                                                                                       public long getCreationTime() {                                                                     * object input stream.
                                import java.util.*;                                                                               public Object getAttribute(String name) {                                                                                                                                                                                                                                  * <p>
                                import javax.servlet.*;                                                                               if (! valid) {                                                                 /**                                                                                       return (this.creationTime);                                                                   * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager
                                import javax.servlet.http.*;                                                                              String msg = sm.getString("applicationSession.session.ise");                * The string manager for this package.                                                                                                                                                 * is not restored by this method, and must be set explicitly.
                                                                                                                                                                                                                      */                                                                                 }                                                                                                   *
                                /**                                                                                                          throw new IllegalStateException(msg);                                   private StringManager sm =                                                                                                                                                              * @param stream The input stream to read from
                                 * Core implementation of an application level session                                                   }                                                                               StringManager.getManager("org.apache.tomcat.session");                                                                                                                              *
                                 *                                                                                                                                                                                                                                                                       /**                                                                                                 * @exception ClassNotFoundException if an unknown class is specified
                                 * @author James Duncan Davidson [duncan@eng.sun.com]                                                    if (name == null) {                                                                                                                                              * Return the session context with which this session is associated.                                * @exception IOException if an input/output error occurs
                                 * @author Jason Hunter [jch@eng.sun.com]                                                                    String msg = sm.getString("applicationSession.value.iae");              /**                                                                                  *                                                                                                  */
                                 * @author James Todd [gonzo@eng.sun.com]                                                                                                                                             * The HTTP session context associated with this session.                            * @deprecated As of Version 2.1, this method is deprecated and has no                             private void readObject(ObjectInputStream stream)
                                 */                                                                                                          throw new IllegalArgumentException(msg);                                 */                                                                                  * replacement. It will be removed in a future version of the                                          throws ClassNotFoundException, IOException {
                                                                                                                                         }                                                                           private static HttpSessionContext sessionContext = null;                             * Java Servlet API.
                                public class ApplicationSession implements HttpSession {                                                                                                                                                                                                                  */                                                                                                    // Deserialize the scalar instance variables (except Manager)
                                                                                                                                         return values.get(name);                                                                                                                                        public HttpSessionContext getSessionContext() {                                                        creationTime = ((Long) stream.readObject()).
                                    private StringManager sm =                                                                    }                                                                                  /**                                                                                                                                                                                        isValid = ((Boolean) stream.readObject()).booleanValue();
                                        StringManager.getManager("org.apache.tomcat.session");                                                                                                                        * The current accessed time for this session.                                            if (sessionContext == null)
                                    private Hashtable values = new Hashtable();                                                   /**                                                                                 */                                                                                           sessionContext = new StandardSessionContext();                                               // Deserialize the attribute count and attribute values
                                    private String id;                                                                             * @deprecated                                                                     private long thisAccessedTime = creationTime;                                             return (sessionContext);                                                                         int n = ((Integer) stream.readObject()).intValue();
                                    private ServerSession serverSession;                                                           */                                                                                                                                                                                                                                                                           for (int i = 0; i < n; i++) {
                                    private Context context;                                                                      public String[] getValueNames() {                                                                                                                                      }                                                                                                          String name = (String) stream.readObject();
                                    private long creationTime = System.currentTimeMillis();;                                          Enumeration e = getAttributeNames();                                                                                                                                                                                                                                          Object value = (Object) stream.readObject();
                                    private long thisAccessTime = creationTime;                                                       Vector names = new Vector();                                                                                                                                                                                                                                                  attributes.put(name, value);
                                private boolean valid = true;                                                                                                                                                        // ----------------------------------------------------- Session Properties         // ----------------------------------------------HttpSession Public Methods                            }
                                                                                                                                         while (e.hasMoreElements()) {
                                    ApplicationSession(String id, ServerSession serverSession,                                               names.addElement(e.nextElement());                                                                                                                                                                                                                             }
                                        Context context) {                                                                               }                                                                           /**                                                                                 /**
                                        this.serverSession = serverSession;                                                                                                                                           * Set the creation time for this session. This method is called by the              * Return the object bound with the specified name in this session, or
                                        this.context = context;                                                                          String[] valueNames = new String[names.size()];                              * Manager when an existing Session instance is reused.                              * <code>null</code> if no object is bound with that name.                                         /**




    Programming enables
                                        this.id = id;                                                                                                                                                                 *                                                                                   *                                                                                                  * Write a serialized version of this session object to the specified
                                                                                                                                         names.copyInto(valueNames);                                                  * @param time The new creation time                                                 * @param name Name of the attribute to be returned                                                 * object output stream.
                                        this.inactiveInterval = context.getSessionTimeOut();                                                                                                                          */                                                                                  *                                                                                                  * <p>
                                                                                                                                         return valueNames;                                                          public void setCreationTime(long time) {                                             * @exception IllegalStateException if this method is called on an                                  * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored
                                        if (this.inactiveInterval != -1) {                                                                                                                                                                                                                                * invalidated session                                                                              * in the serialized representation of this Session. After calling
                                            this.inactiveInterval *= 60;                                                          }                                                                                      this.creationTime = time;                                                        */                                                                                                 * <code>readObject()</code>, you must set the associated Manager
                                        }                                                                                                                                                                                this.lastAccessedTime = time;                                                   public Object getAttribute(String name) {                                                           * explicitly.
                                    }                                                                                             public Enumeration getAttributeNames() {                                               this.thisAccessedTime = time;                                                                                                                                                       * <p>
                                                                                                                                      if (! valid) {                                                                                                                                                           return (attributes.get(name));                                                                * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable
                                    ServerSession getServerSession() {                                                                    String msg = sm.getString("applicationSession.session.ise");               }                                                                                                                                                                                       * will be silently ignored. If you do not want any such attributes,
                                        return serverSession;                                                                                                                                                                                                                                            }                                                                                                   * be sure the <code>distributable</code> property of our associated
                                    }                                                                                                        throw new IllegalStateException(msg);                                                                                                                                                                                                                           * Manager is set to <code>true</code>.
                                                                                                                                         }                                                                           /**                                                                                                                                                                                     *
                                    /**                                                                                                                                                                               * Return the session identifier for this session.                                  /**                                                                                                 * @param stream The output stream to write to
                                     * Called by context when request comes in so that accesses and                                      Hashtable valuesClone = (Hashtable)values.clone();                           */                                                                                  * Return an <code>Enumeration</code> of <code>String</code> objects                                *
                                     * inactivities can be dealt with accordingly.                                                                                                                                   public String getId() {                                                              * containing the names of the objects bound to this session.                                       * @exception IOException if an input/output error occurs
                                     */                                                                                                  return (Enumeration)valuesClone.keys();                                                                                                                          *                                                                                                  */
                                                                                                                                  }                                                                                      return (this.id);                                                                * @exception IllegalStateException if this method is called on an                                 private void writeObject(ObjectOutputStream stream) throws IOException {
                                                                                                                                                                                                                                                                                                          * invalidated session
                                    // HTTP SESSION IMPLEMENTATION METHODS                                                                                                                                           }                                                                                    */                                                                                                    // Write the scalar instance variables (except Manager)
                                                                                                                            /**                                                                                                                                                                          public Enumeration getAttributeNames() {                                                               stream.writeObject(new Long(creationTime));
                                    public String getId() {                                                                           * @deprecated                                                                                                                                                                                                                                                             stream.writeObject(id);
                                        if (valid) {                                                                                  */                                                                             /**                                                                                       return (attributes.keys());                                                                      stream.writeObject(new Long(lastAccessedTime));
                                            return id;                                                                                                                                                                * Set the session identifier for this session.                                                                                                                                            stream.writeObject(new Integer(maxInactiveInterval));
                                        } else {                                                                                  public void removeValue(String name) {                                              *                                                                                  }                                                                                                      stream.writeObject(new Boolean(isNew));
                                            String msg = sm.getString("applicationSession.session.ise");                              removeAttribute(name);                                                          * @param id The new session identifier                                                                                                                                                    stream.writeObject(new Boolean(isValid));
                                                                                                                                  }                                                                                   */
                                            throw new IllegalStateException(msg);                                                                                                                                    public void setId(String id) {                                                      /**                                                                                                    // Accumulate the names of serializable attributes
                                        }                                                                                         public void removeAttribute(String name) {                                                                                                                              * Return the object bound with the specified name in this session, or                                 Vector results = new Vector();
                                    }                                                                                                 if (! valid) {                                                                     if ((this.id != null) && (manager != null) &&                                    * <code>null</code> if no object is bound with that name.                                             Enumeration attrs = getAttributeNames();
                                                                                                                                          String msg = sm.getString("applicationSession.session.ise");                     (manager instanceof ManagerBase))                                              *                                                                                                     while (attrs.hasMoreElements()) {
                                    public long getCreationTime() {                                                                                                                                                          ((ManagerBase) manager).remove(this);                                        * @param name Name of the value to be returned                                                            String attr = (String) attrs.nextElement();
                                        if (valid) {                                                                                         throw new IllegalStateException(msg);                                                                                                                        *                                                                                                         Object value = attributes.get(attr);
                                            return creationTime;                                                                         }                                                                               this.id = id;                                                                    * @exception IllegalStateException if this method is called on an                                         if (value instanceof Serializable)
                                        } else {                                                                                                                                                                                                                                                          * invalidated session                                                                                         results.addElement(attr);




    localized implementations
                                            String msg = sm.getString("applicationSession.session.ise");                                 if (name == null) {                                                             if ((manager != null) && (manager instanceof ManagerBase))                       *                                                                                                     }
                                                                                                                                             String msg = sm.getString("applicationSession.value.iae");                      ((ManagerBase) manager).add(this);                                           * @deprecated As of Version 2.2, this method is replaced by
                                            throw new IllegalStateException(msg);                                                                                                                                                                                                                         * <code>getAttribute()</code>                                                                         // Serialize the attribute count and the attribute values
                                        }                                                                                                    throw new IllegalArgumentException(msg);                                }                                                                                    */                                                                                                    stream.writeObject(new Integer(results.size()));
                                    }                                                                                                    }                                                                                                                                                               public Object getValue(String name) {                                                                  Enumeration names = results.elements();
                                                                                                                                                                                                                                                                                                                                                                                                                while (names.hasMoreElements()) {
                                    /**                                                                                                  Object o = values.get(name);                                                /**                                                                                       return (getAttribute(name));                                                                         String name = (String) names.nextElement();
                                     *                                                                                                                                                                                * Return descriptive information about this Session implementation and                                                                                                                        stream.writeObject(name);
                                     * @deprecated                                                                                       if (o instanceof HttpSessionBindingListener) {                               * the corresponding version number, in the format                                  }                                                                                                          stream.writeObject(attributes.get(name));
                                     */                                                                                                      HttpSessionBindingEvent e =                                              * <code>&lt;description&gt;/&lt;version&gt;</code>.                                                                                                                                       }
                                                                                                                                                 new HttpSessionBindingEvent(this,name);                              */
                                    public HttpSessionContext getSessionContext() {                                                                                                                                  public String getInfo() {                                                           /**
                                        return new SessionContextImpl();                                                                     ((HttpSessionBindingListener)o).valueUnbound(e);                                                                                                             * Return the set of names of objects bound to this session. If there                              }
                                    }                                                                                                    }                                                                               return (this.info);                                                              * are no such objects, a zero-length array is returned.
                                                                                                                                                                                                                                                                                                          *                                                                                                 crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() |
                                                                                                                                         values.remove(name);                                                        }                                                                                    * @exception IllegalStateException if this method is called on an                                                                              long getCreationTime() |
                                                                                                                                  }                                                                                                                                                                       * invalidated session                                                                                                                          Object getAttribute(String) |
                                                                                                                                                                                                               /**                                                                                        *                                                                                                                                              Enumeration getAttributeNames() |
                                                                                                                                  public void setMaxInactiveInterval(int interval) {                                  * Return the Manager within which this Session is valid.                            * @deprecated As of Version 2.2, this method is replaced by                                                                                    String[] getValueNames() |
                                                                                                                                      if (! valid) {                                                                  */                                                                                  * <code>getAttributeNames()</code>                                                                                                             void invalidate() |
                                                                                                                                          String msg = sm.getString("applicationSession.session.ise");               public Manager getManager() {                                                        */                                                                                                                                             boolean isNew() |
                                                                                                                                                                                                                                                                                                         public String[] getValueNames() {                                                                                                               void removeAttribute(String) |
                                                                                                                                             throw new IllegalStateException(msg);                                       return (this.manager);                                                                                                                                                                                                          void setAttribute(String, Object));
                                                                                                                                         }                                                                                                                                                                     Vector results = new Vector();
                                                                                                                                                                                                                     }                                                                                         Enumeration attrs = getAttributeNames();                                                     static advice(StandardSession s): invalidate(s) {
                                                                                                                                         inactiveInterval = interval;                                                                                                                                          while (attrs.hasMoreElements()) {                                                                before {
                                                                                                                                  }                                                                                                                                                                                String attr = (String) attrs.nextElement();                                                      if (!s.isValid())
                                                                                                                                                                                                                     /**                                                                                           results.addElement(attr);                                                                             throw new IllegalStateException
                                                                                                                                  public int getMaxInactiveInterval() {                                               * Set the Manager within which this Session is valid.                                    }                                                                                                             (s.sm.getString("standardSession."
                                                                                                                                      if (! valid) {                                                                  *                                                                                        String names[] = new String[results.size()];                                                                                  + thisJoinPoint.methodName
                                                                                                                                          String msg = sm.getString("applicationSession.session.ise");                * @param manager The new Manager                                                         for (int i = 0; i < names.length; i++)                                                                                        + ".ise"));
                                                                                                                                                                                                                      */                                                                                           names[i] = (String) results.elementAt(i);                                                    }
                                                                                                                                             throw new IllegalStateException(msg);                                   public void setManager(Manager manager) {                                                 return (names);                                                                              }
                                                                                                                                         }
                                                                                                                                                                                                                         this.manager = manager;                                                         }




    of CCCs.
                                                                                                                                         return inactiveInterval;
                                                                                                                                  }                                                                                  }
                                                                                                                        }                                                                                                                                                                                /**                                                                                            }
                                                                                                                                                                                                                                                                                                          * Invalidates this session and unbinds any objects bound to it.
                                                                                                                                                                                                                     /**                                                                                  *
                                                                                                                        //-----------------------------------------------------------------------                     * Return the maximum time interval, in seconds, between client requests             * @exception IllegalStateException if this method is called on                                // -------------------------------------------------------------- Private Class
                                                                                                                                                                                                                      * before the servlet container will invalidate the session. A negative              * an invalidated session
                                                                                                                                                                                                                      * time indicates that the session should never time out.                            */
                                                                                                                                                                                                                      *                                                                                  public void invalidate() {                                                                     /**
                                                                                                                                                                                                                      * @exception IllegalStateException if this method is called on                                                                                                                     * This class is a dummy implementation of the <code>HttpSessionContext</code>
                                                                                                                                                                                                                      * an invalidated session                                                                 // Cause this session to expire                                                           * interface, to conform to the requirement that such an object be returned
                                                                                                                                                                                                                      */                                                                                       expire();                                                                                 * when <code>HttpSession.getSessionContext()</code> is called.
                                                                                                                                                                                                                     public int getMaxInactiveInterval() {                                                                                                                                               *
                                                                                                                                                                                                                                                                                                         }                                                                                               * @author Craig R. McClanahan
                                                                                                                                                                                                                         return (this.maxInactiveInterval);                                                                                                                                              *
                                                                                                                                                                                                                                                                                                                                                                                                         * @deprecated As of Java Servlet API 2.1 with no replacement. The
                                                                                                                                                                                                                                                                                                         /**                                                                                             * interface will be removed in a future version of this API.
                                                                                                                                                                                                                                                                                                          * Return <code>true</code> if the client does not yet know about the                           */
                                                                                                                                                                                                                                                                                                          * session, or if the client chooses not to join the session. For
                                                                                                                                                                                                                                                                                                          * example, if the server used only cookie-based sessions, and the client                      final class StandardSessionContext implements HttpSessionContext {
                                                                                                                                                                                                                                                                                                          * has disabled the use of cookies, then a session would be new on each
                                                                                                                                                                                                                                                                                                          * request.
                                                                                                                                                                                                                                                                                                          *                                                                                                 private Vector dummy = new Vector();
                                                                                                                                                                                                                                                                                                          * @exception IllegalStateException if this method is called on an
                                                                                                                                                                                                                                                                                                          * invalidated session                                                                             /**
                                                                                                                                                                                                                                                                                                          */                                                                                                 * Return the session identifiers of all sessions defined
                                                                                                                                                                                                                                                                                                         public boolean isNew() {                                                                            * within this context.
                                                                                                                                                                                                                                                                                                                                                                                                             *
                                                                                                                                                                                                                                                                                                               return (this.isNew);                                                                          * @deprecated As of Java Servlet API 2.1 with no replacement.
                                                                                                                                                                                                                                                                                                                                                                                                             * This method must return an empty <code>Enumeration</code>
                                                                                                                                                                                                                                                                                                         }                                                                                                   * and will be removed in a future version of the API.
                                                                                                                                                                                                                                                                                                                                                                                                             */
                                                                                                                                                                                                                                                                                                                                                                                                            public Enumeration getIds() {

                                                                                                                                                                                                                                                                                                                                                                                                                return (dummy.elements());

                                                                                                                                                                                                                                                                                                                                                                                                            }


                                                                                                                                                                                                                                                                                                                                                                                                            /**
                                                                                                                                                                                                                                                                                                                                                                                                             * Return the <code>HttpSession</code> associated with the
                                                                                                                                                                                                                                                                                                                                                                                                             * specified session identifier.
                                                                                                                                                                                                                                                                                                                                                                                                             *
                                                                                                                                                                                                                                                                                                                                                                                                             * @param id Session identifier for which to look up a session
                                                                                                                                                                                                                                                                                                                                                                                                             *
                                                                                                                                                                                                                                                                                                                                                                                                             * @deprecated As of Java Servlet API 2.1 with no replacement.
                                                                                                                                                                                                                                                                                                                                                                                                             * This method must return null and will be removed in a
                                                                                                                                                                                                                                                                                                                                                                                                             * future version of the API.
                                                                                                                                                                                                                                                                                                                                                                                                             */
                                                                                                                                                                                                                                                                                                                                                                                                            public HttpSession getSession(String id) {

                                                                                                                                                                                                                                                                                                                                                                                                                return (null);

                                                                                                                                                                                                                                                                                                                                                                                                            }

                                                                                                                                                                                                                                                                                                                                                                                                        }




                                package org.apache.tomcat.session;                                         ynchronized void invalidate() {
                                                                                                                   Enumeration enum = appSessions.keys();
                                import org.apache.tomcat.core.*;
                                import org.apache.tomcat.util.StringManager;                                       while (enum.hasMoreElements()) {
                                import java.io.*;                                                                      Object key = enum.nextElement();
                                import java.net.*;                                                                     ApplicationSession appSession =
                                import java.util.*;                                                                        (ApplicationSession)appSessions.get(key);
                                import javax.servlet.*;
                                import javax.servlet.http.*;                                                           appSession.invalidate();
                                                                                                                   }
                                /**                                                                            }
                                 * Core implementation of a server session
                                 *                                                                             public void putValue(String name, Object value) {
                                 * @author James Duncan Davidson [duncan@eng.sun.com]                              if (name == null) {
                                 * @author James Todd [gonzo@eng.sun.com]                                              String msg = sm.getString("serverSession.value.iae");
                                 */
                                                                                                                       throw new IllegalArgumentException(msg);
                                public class ServerSession {                                                       }

                                    private StringManager sm =                                                     removeValue(name); // remove any existing binding
                                        StringManager.getManager("org.apache.tomcat.session");                     values.put(name, value);
                                    private Hashtable values = new Hashtable();                                }
                                    private Hashtable appSessions = new Hashtable();
                                    private String id;                                                         public Object getValue(String name) {
                                    private long creationTime = System.currentTimeMillis();;                       if (name == null) {
                                    private long thisAccessTime = creationTime;                                        String msg = sm.getString("serverSession.value.iae");
                                    private long lastAccessed = creationTime;
                                    private int inactiveInterval = -1;                                                 throw new IllegalArgumentException(msg);
                                                                                                                   }
                                    ServerSession(String id) {
                                        this.id = id;                                                              return values.get(name);
                                    }                                                                          }

                                    public String getId() {                                                    public Enumeration getValueNames() {
                                        return id;                                                                 return values.keys();
                                    }                                                                          }

                                    public long getCreationTime() {                                            public void removeValue(String name) {
                                        return creationTime;                                                       values.remove(name);
                                    }                                                                          }

                                    public long getLastAccessedTime() {                                        public void setMaxInactiveInterval(int interval) {
                                        return lastAccessed;                                                       inactiveInterval = interval;
                                    }                                                                          }

                                    public ApplicationSession getApplicationSession(Context context,           public int getMaxInactiveInterval() {
                                        boolean create) {                                                          return inactiveInterval;
                                        ApplicationSession appSession =                                        }
                                            (ApplicationSession)appSessions.get(context);
                                                                                                               // XXX
                                        if (appSession == null && create) {                                    // sync'd for safty -- no other thread should be getting something
                                                                                                               // from this while we are reaping. This isn't the most optimal
                                            // XXX                                                             // solution for this, but we'll determine something else later.
                                            // sync to ensure valid?
                                                                                                               synchronized void reap() {
                                            appSession = new ApplicationSession(id, this, context);                Enumeration enum = appSessions.keys();
                                            appSessions.put(context, appSession);
                                        }                                                                          while (enum.hasMoreElements()) {
                                                                                                                       Object key = enum.nextElement();
                                        // XXX                                                                         ApplicationSession appSession =
                                        // make sure that we haven't gone over the end of our                              (ApplicationSession)appSessions.get(key);
                                        // inactive interval -- if so, invalidate and create
                                        // a new appSession                                                            appSession.validate();
                                                                                                                   }
                                        return appSession;                                                     }
                                    }                                                                      }

                                    void removeApplicationSession(Context context) {
                                        appSessions.remove(context);
                                    }

                                    /**
                                     * Called by context when request comes in so that accesses and
                                     * inactivities can be dealt with accordingly.
                                     */


                                    void validate()




                                                                                                                                                                                                                               private long lastAccessed = creationTime;                                                                                                     if (inactiveInterval != -1) {
                                                                                                                                                                                                                                  private int inactiveInterval = -1;                                                                                                                     int thisInterval =
                                                                                                                                                                                                                                                                                                                                                                                             (int)(System.currentTimeMillis() - lastAccessed) / 1000;
                                                                                                                                                                                                                               void accessed() {
                                                                                                                                                                                                                                      // set last accessed to thisAccessTime as it will be left over                                                                                       if (thisInterval > inactiveInterval) {
                                                                                                                                                                                                                                      // from the previous access                                                                                                                              invalidate();
                                                                                                                                                                                                                                      lastAccessed = thisAccessTime;
                                                                                                                                                                                                                                      thisAccessTime = System.currentTimeMillis();                                                                                                             ServerSessionManager ssm =
                                                                                                                                                                                                                                                                                                                                                                                                   ServerSessionManager.getManager();
                                                                                                                                                                                                                                         validate();
                                                                                                                                                                                                                                  }                                                                                                                                                            ssm.removeSession(this);
                                                                                                                                                                                                                                                                                                                                                                                           }
                                                                                                                                                                                                                                  void validate() {                                                                                                                                    }
                                                                                                                                                                                                                                      // if we have an inactive interval, check to see if we've exceeded it                                                                        }
                                                                                                                                                                                                                                      if (inactiveInterval != -1) {
                                                                                                                                                                                                                                          int thisInterval =                                                                                                                    private long lastAccessedTime = creationTime;
                                                                                                                                                                                                                                              (int)(System.currentTimeMillis() - lastAccessed) / 1000;

                                                                                                                                                                                                                                             if (thisInterval > inactiveInterval) {
                                                                                                                                                                                                                                                 invalidate();                                                                                                                     /**
                                                                                                                                                                                                                                             }                                                                                                                                      * 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() {                                                                                                                  */
                                                                                                                                                                                                                                      if (valid) {                                                                                                                                 public long getLastAccessedTime() {
                                                                                                                                                                                                                                          return lastAccessed;
                                                                                                                                                                                                                                      } else {                                                                                                                                         return (this.lastAccessedTime);
                                                                                                                                                                                                                                          String msg = sm.getString("applicationSession.session.ise");
                                                                                                                                                                                                                                                                                                                                                                                   }
                                                                                                                                                                                                                                             throw new IllegalStateException(msg);
                                                                                                                                                                                                                                         }
                                                                                                                                                                                                                                  }                                                                                                                                                    this.lastAccessedTime = time;


                                                                                                                                                                                                                               public long getLastAccessedTime() {
                                                                                                                                                                                                                                      return lastAccessed;
                                                                                                                                                                                                                                  }


                                                                                                                                                                                                                               private long lastAccessed = creationTime;

                                                                                                                                                                                                                               void accessed() {
                                                                                                                                                                                                                                      // set last accessed to thisAccessTime as it will be left over
                                                                                                                                                                                                                                      // from the previous access

                                                                                                                                                                                                                                         lastAccessed = thisAccessTime;
                                                                                                                                                                                                                                         thisAccessTime = System.currentTimeMillis();

                                                                                                                                                                                                                                  }




                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               11
Aspect-Oriented Programming


                                /*                                                                                      public void invalidate() {                                                             ;                                                                                                                                                                                        * Remove the object bound with the specified name from this session. If
                                 * ====================================================================                         serverSession.removeApplicationSession(context);                                                                                                                         /**                                                                                                 * the session does not have an object bound with this name, this method
                                 *                                                                                                                                                                                                                                                                        * Perform the internal processing required to invalidate this session,                             * does nothing.
                                 * The Apache Software License, Version 1.1                                                              // remove everything in the session                                   /**                                                                                        * without triggering an exception if the session has already expired.                              * <p>
                                 *                                                                                                                                                                              * Standard implementation of the <b>Session</b> interface. This object is                 */                                                                                                 * After this method executes, and if the object implements
                                 * Copyright (c) 1999 The Apache Software Foundation. All rights                                         Enumeration enum = values.keys();                                      * serializable, so that it can be stored in persistent storage or transferred            public void expire() {                                                                              * <code>HttpSessionBindingListener</code>, the container calls
                                 * reserved.                                                                                             while (enum.hasMoreElements()) {                                       * to a different JVM for distributable session support.                                                                                                                                      * <code>valueUnbound()</code> on the object.
                                 *                                                                                                           String name = (String)enum.nextElement();                          * <p>                                                                                          // Remove this session from our manager's active sessions                                     *
                                 * Redistribution and use in source and binary forms, with or without                                        removeValue(name);                                                 * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the                    if ((manager != null) && (manager instanceof ManagerBase))                                    * @param name Name of the object to remove from this session.
                                 * modification, are permitted provided that the following conditions                                    }                                                                      * internal (Session) and application level (HttpSession) view of the session.                      ((ManagerBase) manager).remove(this);                                                     *
                                 * are met:                                                                                                                                                                     * However, because the class itself is not declared public, Java logic outside                                                                                                               * @exception IllegalStateException if this method is called on an
                                 *                                                                                                       valid = false;                                                         * of the <code>org.apache.tomcat.session</code> package cannot cast an                         // Unbind any objects associated with this session                                            * invalidated session
                                 * 1. Redistributions of source code must retain the above copyright                              }                                                                             * HttpSession view of this instance back to a Session view.                                    Vector results = new Vector();                                                                */
                                 *    notice, this list of conditions and the following disclaimer.                                                                                                             *                                                                                              Enumeration attrs = getAttributeNames();                                                     public void removeAttribute(String name) {
                                 *                                                                                                public boolean isNew() {                                                      * @author Craig R. McClanahan                                                                  while (attrs.hasMoreElements()) {
                                 * 2. Redistributions in binary form must reproduce the above copyright                               if (! valid) {                                                            * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $                                           String attr = (String) attrs.nextElement();                                                  synchronized (attributes) {
                                 *    notice, this list of conditions and the following disclaimer in                                     String msg = sm.getString("applicationSession.session.ise");          */                                                                                                 results.addElement(attr);                                                                        Object object = attributes.get(name);
                                 *    the documentation and/or other materials provided with the                                                                                                                                                                                                               }                                                                                                    if (object == null)
                                 *    distribution.                                                                                          throw new IllegalStateException(msg);                             final class StandardSession                                                                     Enumeration names = results.elements();                                                                  return;
                                 *                                                                                                       }                                                                         implements HttpSession, Session {                                                           while (names.hasMoreElements()) {                                                                    attributes.remove(name);
                                 * 3. The end-user documentation included with the redistribution, if                                                                                                                                                                                                              String name = (String) names.nextElement();                                                      //      System.out.println( "Removing attribute " + name );
                                 *    any, must include the following acknowledgment:                                                    if (thisAccessTime == creationTime) {                                                                                                                                     removeAttribute(name);                                                                           if (object instanceof HttpSessionBindingListener) {
                                 *       "This product includes software developed by the                                                    return true;                                                            // ----------------------------------------------------------- Constructors               }                                                                                                        ((HttpSessionBindingListener) object).valueUnbound
                                 *        Apache Software Foundation (http://www.apache.org/)."                                          } else {                                                                                                                                                                                                                                                                           (new HttpSessionBindingEvent((HttpSession) this, name));
                                 *    Alternately, this acknowledgment may appear in the software                                            return false;                                                                                                                                                     // Mark this session as invalid                                                                      }
                                itself,                                                                                                  }                                                                           /**                                                                                       setValid(false);                                                                                 }
                                 *    if and wherever such third-party acknowledgments normally appear.                           }                                                                                   * Construct a new Session associated with the specified Manager.
                                 *                                                                                                                                                                                    *                                                                                  }                                                                                                  }
                                 * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software                                                                                                                 * @param manager The manager with which this Session is associated
                                 *    Foundation" must not be used to endorse or promote products                       /**                                                                                           */                                                                                                                                                                                * Bind an object to this session, using the specified name. If an object
                                derived                                                                                               * @deprecated                                                                  public StandardSession(Manager manager) {                                           /**                                                                                                 * of the same name is already bound to this session, the object is
                                 *    from this software without prior written permission. For written                                */                                                                                                                                                                                                                                                                     * replaced.
                                 *    permission, please contact apache@apache.org.                                                                                                                                      super();                                                                        }                                                                                                   * <p>
                                 *                                                                                                public void putValue(String name, Object value) {                                      this.manager = manager;                                                                                                                                                             * After this method executes, and if the object implements
                                 * 5. Products derived from this software may not be called "Apache"                                  setAttribute(name, value);                                                                                                                                                                                                                                             * <code>HttpSessionBindingListener</code>, the container calls
                                 *    nor may "Apache" appear in their names without prior written                                }                                                                                  }                                                                                   /**                                                                                                 * <code>valueBound()</code> on the object.
                                 *    permission of the Apache Group.                                                                                                                                                                                                                                     * Set the <code>isNew</code> flag for this session.                                                *
                                 *                                                                                                public void setAttribute(String name, Object value) {                                                                                                                   *                                                                                                  * @param name Name to which the object is bound, cannot be null
                                 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED                                   if (! valid) {                                                           /**                                                                                        * @param isNew The new value for the <code>isNew</code> flag                                       * @param value Object to be bound, cannot be null
                                 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES                                      String msg = sm.getString("applicationSession.session.ise");                * The last accessed time for this Session.                                          */                                                                                                 *
                                 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                                                                                                                        */                                                                                 void setNew(boolean isNew) {                                                                        * @exception IllegalArgumentException if an attempt is made to add a
                                 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR                                           throw new IllegalStateException(msg);                                   private long lastAccessedTime = creationTime;                                                                                                                                           * non-serializable object in an environment marked distributable.
                                 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,                                      }                                                                                                                                                                     this.isNew = isNew;                                                                           * @exception IllegalStateException if this method is called on an
                                 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT                                                                                                                                                                                                                                                                                                          * invalidated session
                                 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF                                      if (name == null) {                                                         /**                                                                                 }                                                                                                   */
                                 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND                                       String msg = sm.getString("applicationSession.value.iae");               * The Manager with which this Session is associated.                                                                                                                                  public void setAttribute(String name, Object value) {
                                 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,                                                                                                                 */
                                 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT                                        throw new IllegalArgumentException(msg);                                private Manager manager = null;                                                     /**                                                                                                    if ((manager != null) && manager.getDistributable() &&
                                 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF                                    }                                                                                                                                                                * Set the <code>isValid</code> flag for this session.                                                   !(value instanceof Serializable))




•
                                 * SUCH DAMAGE.                                                                                                                                                                                                                                                           *                                                                                                         throw new IllegalArgumentException
                                 * ====================================================================                                  removeValue(name);     // remove any existing binding                       /**                                                                                  * @param isValid The new value for the <code>isValid</code> flag                                              (sm.getString("standardSession.setAttribute.iae"));
                                 *                                                                                                                                                                                    * The maximum time interval, in seconds, between client requests before             */
                                 * This software consists of voluntary contributions made by many                                        if (value != null && value instanceof HttpSessionBindingListener) {          * the servlet container may invalidate this session. A negative time               void setValid(boolean isValid) {                                                                       synchronized (attributes) {
                                 * individuals on behalf of the Apache Software Foundation. For more                                         HttpSessionBindingEvent e =                                              * indicates that the session should never time out.                                                                                                                                           removeAttribute(name);
                                 * information on the Apache Software Foundation, please see                                                     new HttpSessionBindingEvent(this, name);                             */                                                                                       this.isValid = isValid;                                                                              attributes.put(name, value);
                                 * <http://www.apache.org/>.                                                                                                                                                         private int maxInactiveInterval = -1;                                               }                                                                                                          if (value instanceof HttpSessionBindingListener)
                                 *                                                                                                           ((HttpSessionBindingListener)value).valueBound(e);                                                                                                                                                                                                                         ((HttpSessionBindingListener) value).valueBound
                                 * [Additional notices, if required by prior licensing conditions]                                       }                                                                                                                                                                                                                                                                                  (new HttpSessionBindingEvent((HttpSession) this, name));
                                 *                                                                                                                                                                                   /**                                                                                 // ------------------------------------------------- HttpSession Properties                            }
                                 */                                                                                                      values.put(name, value);                                                     * Flag indicating whether this session is new or not.
                                                                                                                                  }                                                                                   */                                                                                                                                                                                    }
                                                                                                                                                                                                                     private boolean isNew = true;                                                       /**




    Aspect-Oriented
                                                                                                                                  /**                                                                                                                                                                     * Return the time when this session was created, in milliseconds since
                                package org.apache.tomcat.session;                                                                  * @deprecated                                                                                                                                                         * midnight, January 1, 1970 GMT.                                                                  // -------------------------------------------- HttpSession Private Methods
                                                                                                                                    */                                                                               /**                                                                                  *
                                import org.apache.tomcat.core.*;                                                                  public Object getValue(String name) {                                               * Flag indicating whether this session is valid or not.                             * @exception IllegalStateException if this method is called on an
                                import org.apache.tomcat.util.StringManager;                                                           return getAttribute(name);                                                     */                                                                                  * invalidated session                                                                             /**
                                import java.io.*;                                                                                 }                                                                                  private boolean isValid = false;                                                     */                                                                                                 * Read a serialized version of this session object from the specified
                                import java.net.*;                                                                                                                                                                                                                                                       public long getCreationTime() {                                                                     * object input stream.
                                import java.util.*;                                                                               public Object getAttribute(String name) {                                                                                                                                                                                                                                  * <p>
                                import javax.servlet.*;                                                                               if (! valid) {                                                                 /**                                                                                       return (this.creationTime);                                                                   * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager
                                import javax.servlet.http.*;                                                                              String msg = sm.getString("applicationSession.session.ise");                * The string manager for this package.                                                                                                                                                 * is not restored by this method, and must be set explicitly.
                                                                                                                                                                                                                      */                                                                                 }                                                                                                   *
                                /**                                                                                                          throw new IllegalStateException(msg);                                   private StringManager sm =                                                                                                                                                              * @param stream The input stream to read from
                                 * Core implementation of an application level session                                                   }                                                                               StringManager.getManager("org.apache.tomcat.session");                                                                                                                              *
                                 *                                                                                                                                                                                                                                                                       /**                                                                                                 * @exception ClassNotFoundException if an unknown class is specified
                                 * @author James Duncan Davidson [duncan@eng.sun.com]                                                    if (name == null) {                                                                                                                                              * Return the session context with which this session is associated.                                * @exception IOException if an input/output error occurs
                                 * @author Jason Hunter [jch@eng.sun.com]                                                                    String msg = sm.getString("applicationSession.value.iae");              /**                                                                                  *                                                                                                  */
                                 * @author James Todd [gonzo@eng.sun.com]                                                                                                                                             * The HTTP session context associated with this session.                            * @deprecated As of Version 2.1, this method is deprecated and has no                             private void readObject(ObjectInputStream stream)
                                 */                                                                                                          throw new IllegalArgumentException(msg);                                 */                                                                                  * replacement. It will be removed in a future version of the                                          throws ClassNotFoundException, IOException {
                                                                                                                                         }                                                                           private static HttpSessionContext sessionContext = null;                             * Java Servlet API.
                                public class ApplicationSession implements HttpSession {                                                                                                                                                                                                                  */                                                                                                    // Deserialize the scalar instance variables (except Manager)
                                                                                                                                         return values.get(name);                                                                                                                                        public HttpSessionContext getSessionContext() {                                                        creationTime = ((Long) stream.readObject()).
                                    private StringManager sm =                                                                    }                                                                                  /**                                                                                                                                                                                        isValid = ((Boolean) stream.readObject()).booleanValue();
                                        StringManager.getManager("org.apache.tomcat.session");                                                                                                                        * The current accessed time for this session.                                            if (sessionContext == null)
                                    private Hashtable values = new Hashtable();                                                   /**                                                                                 */                                                                                           sessionContext = new StandardSessionContext();                                               // Deserialize the attribute count and attribute values
                                    private String id;                                                                             * @deprecated                                                                     private long thisAccessedTime = creationTime;                                             return (sessionContext);                                                                         int n = ((Integer) stream.readObject()).intValue();
                                    private ServerSession serverSession;                                                           */                                                                                                                                                                                                                                                                           for (int i = 0; i < n; i++) {
                                    private Context context;                                                                      public String[] getValueNames() {                                                                                                                                      }                                                                                                          String name = (String) stream.readObject();
                                    private long creationTime = System.currentTimeMillis();;                                          Enumeration e = getAttributeNames();                                                                                                                                                                                                                                          Object value = (Object) stream.readObject();
                                    private long thisAccessTime = creationTime;                                                       Vector names = new Vector();                                                                                                                                                                                                                                                  attributes.put(name, value);
                                private boolean valid = true;                                                                                                                                                        // ----------------------------------------------------- Session Properties         // ----------------------------------------------HttpSession Public Methods                            }
                                                                                                                                         while (e.hasMoreElements()) {
                                    ApplicationSession(String id, ServerSession serverSession,                                               names.addElement(e.nextElement());                                                                                                                                                                                                                             }
                                        Context context) {                                                                               }                                                                           /**                                                                                 /**
                                        this.serverSession = serverSession;                                                                                                                                           * Set the creation time for this session. This method is called by the              * Return the object bound with the specified name in this session, or
                                        this.context = context;                                                                          String[] valueNames = new String[names.size()];                              * Manager when an existing Session instance is reused.                              * <code>null</code> if no object is bound with that name.                                         /**




    Programming enables
                                        this.id = id;                                                                                                                                                                 *                                                                                   *                                                                                                  * Write a serialized version of this session object to the specified
                                                                                                                                         names.copyInto(valueNames);                                                  * @param time The new creation time                                                 * @param name Name of the attribute to be returned                                                 * object output stream.
                                        this.inactiveInterval = context.getSessionTimeOut();                                                                                                                          */                                                                                  *                                                                                                  * <p>
                                                                                                                                         return valueNames;                                                          public void setCreationTime(long time) {                                             * @exception IllegalStateException if this method is called on an                                  * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored
                                        if (this.inactiveInterval != -1) {                                                                                                                                                                                                                                * invalidated session                                                                              * in the serialized representation of this Session. After calling
                                            this.inactiveInterval *= 60;                                                          }                                                                                      this.creationTime = time;                                                        */                                                                                                 * <code>readObject()</code>, you must set the associated Manager
                                        }                                                                                                                                                                                this.lastAccessedTime = time;                                                   public Object getAttribute(String name) {                                                           * explicitly.
                                    }                                                                                             public Enumeration getAttributeNames() {                                               this.thisAccessedTime = time;                                                                                                                                                       * <p>
                                                                                                                                      if (! valid) {                                                                                                                                                           return (attributes.get(name));                                                                * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable
                                    ServerSession getServerSession() {                                                                    String msg = sm.getString("applicationSession.session.ise");               }                                                                                                                                                                                       * will be silently ignored. If you do not want any such attributes,
                                        return serverSession;                                                                                                                                                                                                                                            }                                                                                                   * be sure the <code>distributable</code> property of our associated
                                    }                                                                                                        throw new IllegalStateException(msg);                                                                                                                                                                                                                           * Manager is set to <code>true</code>.
                                                                                                                                         }                                                                           /**                                                                                                                                                                                     *
                                    /**                                                                                                                                                                               * Return the session identifier for this session.                                  /**                                                                                                 * @param stream The output stream to write to
                                     * Called by context when request comes in so that accesses and                                      Hashtable valuesClone = (Hashtable)values.clone();                           */                                                                                  * Return an <code>Enumeration</code> of <code>String</code> objects                                *
                                     * inactivities can be dealt with accordingly.                                                                                                                                   public String getId() {                                                              * containing the names of the objects bound to this session.                                       * @exception IOException if an input/output error occurs
                                     */                                                                                                  return (Enumeration)valuesClone.keys();                                                                                                                          *                                                                                                  */
                                                                                                                                  }                                                                                      return (this.id);                                                                * @exception IllegalStateException if this method is called on an                                 private void writeObject(ObjectOutputStream stream) throws IOException {
                                                                                                                                                                                                                                                                                                          * invalidated session
                                    // HTTP SESSION IMPLEMENTATION METHODS                                                                                                                                           }                                                                                    */                                                                                                    // Write the scalar instance variables (except Manager)
                                                                                                                            /**                                                                                                                                                                          public Enumeration getAttributeNames() {                                                               stream.writeObject(new Long(creationTime));
                                    public String getId() {                                                                           * @deprecated                                                                                                                                                                                                                                                             stream.writeObject(id);
                                        if (valid) {                                                                                  */                                                                             /**                                                                                       return (attributes.keys());                                                                      stream.writeObject(new Long(lastAccessedTime));
                                            return id;                                                                                                                                                                * Set the session identifier for this session.                                                                                                                                            stream.writeObject(new Integer(maxInactiveInterval));
                                        } else {                                                                                  public void removeValue(String name) {                                              *                                                                                  }                                                                                                      stream.writeObject(new Boolean(isNew));
                                            String msg = sm.getString("applicationSession.session.ise");                              removeAttribute(name);                                                          * @param id The new session identifier                                                                                                                                                    stream.writeObject(new Boolean(isValid));
                                                                                                                                  }                                                                                   */
                                            throw new IllegalStateException(msg);                                                                                                                                    public void setId(String id) {                                                      /**                                                                                                    // Accumulate the names of serializable attributes
                                        }                                                                                         public void removeAttribute(String name) {                                                                                                                              * Return the object bound with the specified name in this session, or                                 Vector results = new Vector();
                                    }                                                                                                 if (! valid) {                                                                     if ((this.id != null) && (manager != null) &&                                    * <code>null</code> if no object is bound with that name.                                             Enumeration attrs = getAttributeNames();
                                                                                                                                          String msg = sm.getString("applicationSession.session.ise");                     (manager instanceof ManagerBase))                                              *                                                                                                     while (attrs.hasMoreElements()) {
                                    public long getCreationTime() {                                                                                                                                                          ((ManagerBase) manager).remove(this);                                        * @param name Name of the value to be returned                                                            String attr = (String) attrs.nextElement();
                                        if (valid) {                                                                                         throw new IllegalStateException(msg);                                                                                                                        *                                                                                                         Object value = attributes.get(attr);
                                            return creationTime;                                                                         }                                                                               this.id = id;                                                                    * @exception IllegalStateException if this method is called on an                                         if (value instanceof Serializable)
                                        } else {                                                                                                                                                                                                                                                          * invalidated session                                                                                         results.addElement(attr);




    localized implementations
                                            String msg = sm.getString("applicationSession.session.ise");                                 if (name == null) {                                                             if ((manager != null) && (manager instanceof ManagerBase))                       *                                                                                                     }
                                                                                                                                             String msg = sm.getString("applicationSession.value.iae");                      ((ManagerBase) manager).add(this);                                           * @deprecated As of Version 2.2, this method is replaced by
                                            throw new IllegalStateException(msg);                                                                                                                                                                                                                         * <code>getAttribute()</code>                                                                         // Serialize the attribute count and the attribute values
                                        }                                                                                                    throw new IllegalArgumentException(msg);                                }                                                                                    */                                                                                                    stream.writeObject(new Integer(results.size()));
                                    }                                                                                                    }                                                                                                                                                               public Object getValue(String name) {                                                                  Enumeration names = results.elements();
                                                                                                                                                                                                                                                                                                                                                                                                                while (names.hasMoreElements()) {
                                    /**                                                                                                  Object o = values.get(name);                                                /**                                                                                       return (getAttribute(name));                                                                         String name = (String) names.nextElement();
                                     *                                                                                                                                                                                * Return descriptive information about this Session implementation and                                                                                                                        stream.writeObject(name);
                                     * @deprecated                                                                                       if (o instanceof HttpSessionBindingListener) {                               * the corresponding version number, in the format                                  }                                                                                                          stream.writeObject(attributes.get(name));
                                     */                                                                                                      HttpSessionBindingEvent e =                                              * <code>&lt;description&gt;/&lt;version&gt;</code>.                                                                                                                                       }
                                                                                                                                                 new HttpSessionBindingEvent(this,name);                              */
                                    public HttpSessionContext getSessionContext() {                                                                                                                                  public String getInfo() {                                                           /**
                                        return new SessionContextImpl();                                                                     ((HttpSessionBindingListener)o).valueUnbound(e);                                                                                                             * Return the set of names of objects bound to this session. If there                              }
                                    }                                                                                                    }                                                                               return (this.info);                                                              * are no such objects, a zero-length array is returned.
                                                                                                                                                                                                                                                                                                          *                                                                                                 crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() |
                                                                                                                                         values.remove(name);                                                        }                                                                                    * @exception IllegalStateException if this method is called on an                                                                              long getCreationTime() |
                                                                                                                                  }                                                                                                                                                                       * invalidated session                                                                                                                          Object getAttribute(String) |
                                                                                                                                                                                                               /**                                                                                        *                                                                                                                                              Enumeration getAttributeNames() |
                                                                                                                                  public void setMaxInactiveInterval(int interval) {                                  * Return the Manager within which this Session is valid.                            * @deprecated As of Version 2.2, this method is replaced by                                                                                    String[] getValueNames() |
                                                                                                                                      if (! valid) {                                                                  */                                                                                  * <code>getAttributeNames()</code>                                                                                                             void invalidate() |
                                                                                                                                          String msg = sm.getString("applicationSession.session.ise");               public Manager getManager() {                                                        */                                                                                                                                             boolean isNew() |
                                                                                                                                                                                                                                                                                                         public String[] getValueNames() {                                                                                                               void removeAttribute(String) |
                                                                                                                                             throw new IllegalStateException(msg);                                       return (this.manager);                                                                                                                                                                                                          void setAttribute(String, Object));
                                                                                                                                         }                                                                                                                                                                     Vector results = new Vector();
                                                                                                                                                                                                                     }                                                                                         Enumeration attrs = getAttributeNames();                                                     static advice(StandardSession s): invalidate(s) {
                                                                                                                                         inactiveInterval = interval;                                                                                                                                          while (attrs.hasMoreElements()) {                                                                before {
                                                                                                                                  }                                                                                                                                                                                String attr = (String) attrs.nextElement();                                                      if (!s.isValid())
                                                                                                                                                                                                                     /**                                                                                           results.addElement(attr);                                                                             throw new IllegalStateException
                                                                                                                                  public int getMaxInactiveInterval() {                                               * Set the Manager within which this Session is valid.                                    }                                                                                                             (s.sm.getString("standardSession."
                                                                                                                                      if (! valid) {                                                                  *                                                                                        String names[] = new String[results.size()];                                                                                  + thisJoinPoint.methodName
                                                                                                                                          String msg = sm.getString("applicationSession.session.ise");                * @param manager The new Manager                                                         for (int i = 0; i < names.length; i++)                                                                                        + ".ise"));
                                                                                                                                                                                                                      */                                                                                           names[i] = (String) results.elementAt(i);                                                    }
                                                                                                                                             throw new IllegalStateException(msg);                                   public void setManager(Manager manager) {                                                 return (names);                                                                              }
                                                                                                                                         }
                                                                                                                                                                                                                         this.manager = manager;                                                         }




    of CCCs.
                                                                                                                                         return inactiveInterval;
                                                                                                                                  }                                                                                  }
                                                                                                                        }                                                                                                                                                                                /**                                                                                            }
                                                                                                                                                                                                                                                                                                          * Invalidates this session and unbinds any objects bound to it.
                                                                                                                                                                                                                     /**                                                                                  *
                                                                                                                        //-----------------------------------------------------------------------                     * Return the maximum time interval, in seconds, between client requests             * @exception IllegalStateException if this method is called on                                // -------------------------------------------------------------- Private Class
                                                                                                                                                                                                                      * before the servlet container will invalidate the session. A negative              * an invalidated session
                                                                                                                                                                                                                      * time indicates that the session should never time out.                            */
                                                                                                                                                                                                                      *                                                                                  public void invalidate() {                                                                     /**
                                                                                                                                                                                                                      * @exception IllegalStateException if this method is called on                                                                                                                     * This class is a dummy implementation of the <code>HttpSessionContext</code>
                                                                                                                                                                                                                      * an invalidated session                                                                 // Cause this session to expire                                                           * interface, to conform to the requirement that such an object be returned
                                                                                                                                                                                                                      */                                                                                       expire();                                                                                 * when <code>HttpSession.getSessionContext()</code> is called.
                                                                                                                                                                                                                     public int getMaxInactiveInterval() {                                                                                                                                               *
                                                                                                                                                                                                                                                                                                         }                                                                                               * @author Craig R. McClanahan
                                                                                                                                                                                                                         return (this.maxInactiveInterval);                                                                                                                                              *
                                                                                                                                                                                                                                                                                                                                                                                                         * @deprecated As of Java Servlet API 2.1 with no replacement. The
                                                                                                                                                                                                                                                                                                         /**                                                                                             * interface will be removed in a future version of this API.
                                                                                                                                                                                                                                                                                                          * Return <code>true</code> if the client does not yet know about the                           */
                                                                                                                                                                                                                                                                                                          * session, or if the client chooses not to join the session. For
                                                                                                                                                                                                                                                                                                          * example, if the server used only cookie-based sessions, and the client                      final class StandardSessionContext implements HttpSessionContext {
                                                                                                                                                                                                                                                                                                          * has disabled the use of cookies, then a session would be new on each
                                                                                                                                                                                                                                                                                                          * request.
                                                                                                                                                                                                                                                                                                          *                                                                                                 private Vector dummy = new Vector();
                                                                                                                                                                                                                                                                                                          * @exception IllegalStateException if this method is called on an
                                                                                                                                                                                                                                                                                                          * invalidated session                                                                             /**
                                                                                                                                                                                                                                                                                                          */                                                                                                 * Return the session identifiers of all sessions defined
                                                                                                                                                                                                                                                                                                         public boolean isNew() {                                                                            * within this context.
                                                                                                                                                                                                                                                                                                                                                                                                             *
                                                                                                                                                                                                                                                                                                               return (this.isNew);                                                                          * @deprecated As of Java Servlet API 2.1 with no replacement.
                                                                                                                                                                                                                                                                                                                                                                                                             * This method must return an empty <code>Enumeration</code>
                                                                                                                                                                                                                                                                                                         }                                                                                                   * and will be removed in a future version of the API.
                                                                                                                                                                                                                                                                                                                                                                                                             */
                                                                                                                                                                                                                                                                                                                                                                                                            public Enumeration getIds() {

                                                                                                                                                                                                                                                                                                                                                                                                                return (dummy.elements());

                                                                                                                                                                                                                                                                                                                                                                                                            }


                                                                                                                                                                                                                                                                                                                                                                                                            /**
                                                                                                                                                                                                                                                                                                                                                                                                             * Return the <code>HttpSession</code> associated with the
                                                                                                                                                                                                                                                                                                                                                                                                             * specified session identifier.
                                                                                                                                                                                                                                                                                                                                                                                                             *
                                                                                                                                                                                                                                                                                                                                                                                                             * @param id Session identifier for which to look up a session
                                                                                                                                                                                                                                                                                                                                                                                                             *
                                                                                                                                                                                                                                                                                                                                                                                                             * @deprecated As of Java Servlet API 2.1 with no replacement.
                                                                                                                                                                                                                                                                                                                                                                                                             * This method must return null and will be removed in a
                                                                                                                                                                                                                                                                                                                                                                                                             * future version of the API.
                                                                                                                                                                                                                                                                                                                                                                                                             */
                                                                                                                                                                                                                                                                                                                                                                                                            public HttpSession getSession(String id) {

                                                                                                                                                                                                                                                                                                                                                                                                                return (null);

                                                                                                                                                                                                                                                                                                                                                                                                            }

                                                                                                                                                                                                                                                                                                                                                                                                        }




• Pointcuts select (join)
    points in the program
    where a CCC applies.
                                package org.apache.tomcat.session;                                         ynchronized void invalidate() {
                                                                                                                   Enumeration enum = appSessions.keys();
                                import org.apache.tomcat.core.*;
                                import org.apache.tomcat.util.StringManager;                                       while (enum.hasMoreElements()) {
                                import java.io.*;                                                                      Object key = enum.nextElement();
                                import java.net.*;                                                                     ApplicationSession appSession =
                                import java.util.*;                                                                        (ApplicationSession)appSessions.get(key);
                                import javax.servlet.*;
                                import javax.servlet.http.*;                                                           appSession.invalidate();
                                                                                                                   }
                                /**                                                                            }
                                 * Core implementation of a server session
                                 *                                                                             public void putValue(String name, Object value) {
                                 * @author James Duncan Davidson [duncan@eng.sun.com]                              if (name == null) {
                                 * @author James Todd [gonzo@eng.sun.com]                                              String msg = sm.getString("serverSession.value.iae");
                                 */
                                                                                                                       throw new IllegalArgumentException(msg);
                                public class ServerSession {                                                       }

                                    private StringManager sm =                                                     removeValue(name); // remove any existing binding
                                        StringManager.getManager("org.apache.tomcat.session");                     values.put(name, value);
                                    private Hashtable values = new Hashtable();                                }
                                    private Hashtable appSessions = new Hashtable();
                                    private String id;                                                         public Object getValue(String name) {
                                    private long creationTime = System.currentTimeMillis();;                       if (name == null) {
                                    private long thisAccessTime = creationTime;                                        String msg = sm.getString("serverSession.value.iae");
                                    private long lastAccessed = creationTime;
                                    private int inactiveInterval = -1;                                                 throw new IllegalArgumentException(msg);
                                                                                                                   }
                                    ServerSession(String id) {
                                        this.id = id;                                                              return values.get(name);
                                    }                                                                          }

                                    public String getId() {                                                    public Enumeration getValueNames() {
                                        return id;                                                                 return values.keys();
                                    }                                                                          }

                                    public long getCreationTime() {                                            public void removeValue(String name) {
                                        return creationTime;                                                       values.remove(name);
                                    }                                                                          }

                                    public long getLastAccessedTime() {                                        public void setMaxInactiveInterval(int interval) {
                                        return lastAccessed;                                                       inactiveInterval = interval;
                                    }                                                                          }

                                    public ApplicationSession getApplicationSession(Context context,           public int getMaxInactiveInterval() {
                                        boolean create) {                                                          return inactiveInterval;
                                        ApplicationSession appSession =                                        }
                                            (ApplicationSession)appSessions.get(context);
                                                                                                               // XXX
                                        if (appSession == null && create) {                                    // sync'd for safty -- no other thread should be getting something
                                                                                                               // from this while we are reaping. This isn't the most optimal
                                            // XXX                                                             // solution for this, but we'll determine something else later.
                                            // sync to ensure valid?
                                                                                                               synchronized void reap() {
                                            appSession = new ApplicationSession(id, this, context);                Enumeration enum = appSessions.keys();
                                            appSessions.put(context, appSession);
                                        }                                                                          while (enum.hasMoreElements()) {
                                                                                                                       Object key = enum.nextElement();
                                        // XXX                                                                         ApplicationSession appSession =
                                        // make sure that we haven't gone over the end of our                              (ApplicationSession)appSessions.get(key);
                                        // inactive interval -- if so, invalidate and create
                                        // a new appSession                                                            appSession.validate();
                                                                                                                   }
                                        return appSession;                                                     }
                                    }                                                                      }

                                    void removeApplicationSession(Context context) {
                                        appSessions.remove(context);
                                    }

                                    /**
                                     * Called by context when request comes in so that accesses and
                                     * inactivities can be dealt with accordingly.
                                     */


                                    void validate()




                                                                                                                                                                                                                               private long lastAccessed = creationTime;                                                                                                     if (inactiveInterval != -1) {
                                                                                                                                                                                                                                  private int inactiveInterval = -1;                                                                                                                     int thisInterval =
                                                                                                                                                                                                                                                                                                                                                                                             (int)(System.currentTimeMillis() - lastAccessed) / 1000;
                                                                                                                                                                                                                               void accessed() {
                                                                                                                                                                                                                                      // set last accessed to thisAccessTime as it will be left over                                                                                       if (thisInterval > inactiveInterval) {
                                                                                                                                                                                                                                      // from the previous access                                                                                                                              invalidate();
                                                                                                                                                                                                                                      lastAccessed = thisAccessTime;
                                                                                                                                                                                                                                      thisAccessTime = System.currentTimeMillis();                                                                                                             ServerSessionManager ssm =
                                                                                                                                                                                                                                                                                                                                                                                                   ServerSessionManager.getManager();
                                                                                                                                                                                                                                         validate();
                                                                                                                                                                                                                                  }                                                                                                                                                            ssm.removeSession(this);
                                                                                                                                                                                                                                                                                                                                                                                           }
                                                                                                                                                                                                                                  void validate() {                                                                                                                                    }
                                                                                                                                                                                                                                      // if we have an inactive interval, check to see if we've exceeded it                                                                        }
                                                                                                                                                                                                                                      if (inactiveInterval != -1) {
                                                                                                                                                                                                                                          int thisInterval =                                                                                                                    private long lastAccessedTime = creationTime;
                                                                                                                                                                                                                                              (int)(System.currentTimeMillis() - lastAccessed) / 1000;

                                                                                                                                                                                                                                             if (thisInterval > inactiveInterval) {
                                                                                                                                                                                                                                                 invalidate();                                                                                                                     /**
                                                                                                                                                                                                                                             }                                                                                                                                      * 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() {                                                                                                                  */
                                                                                                                                                                                                                                      if (valid) {                                                                                                                                 public long getLastAccessedTime() {
                                                                                                                                                                                                                                          return lastAccessed;
                                                                                                                                                                                                                                      } else {                                                                                                                                         return (this.lastAccessedTime);
                                                                                                                                                                                                                                          String msg = sm.getString("applicationSession.session.ise");
                                                                                                                                                                                                                                                                                                                                                                                   }
                                                                                                                                                                                                                                             throw new IllegalStateException(msg);
                                                                                                                                                                                                                                         }
                                                                                                                                                                                                                                  }                                                                                                                                                    this.lastAccessedTime = time;


                                                                                                                                                                                                                               public long getLastAccessedTime() {
                                                                                                                                                                                                                                      return lastAccessed;
                                                                                                                                                                                                                                  }


                                                                                                                                                                                                                               private long lastAccessed = creationTime;

                                                                                                                                                                                                                               void accessed() {
                                                                                                                                                                                                                                      // set last accessed to thisAccessTime as it will be left over
                                                                                                                                                                                                                                      // from the previous access

                                                                                                                                                                                                                                         lastAccessed = thisAccessTime;
                                                                                                                                                                                                                                         thisAccessTime = System.currentTimeMillis();

                                                                                                                                                                                                                                  }




                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               11
Aspect-Oriented Programming


                                  /*                                                                                      public void invalidate() {                                                             ;                                                                                                                                                                                        * Remove the object bound with the specified name from this session. If
                                   * ====================================================================                         serverSession.removeApplicationSession(context);                                                                                                                         /**                                                                                                 * the session does not have an object bound with this name, this method
                                   *                                                                                                                                                                                                                                                                        * Perform the internal processing required to invalidate this session,                             * does nothing.
                                   * The Apache Software License, Version 1.1                                                              // remove everything in the session                                   /**                                                                                        * without triggering an exception if the session has already expired.                              * <p>
                                   *                                                                                                                                                                              * Standard implementation of the <b>Session</b> interface. This object is                 */                                                                                                 * After this method executes, and if the object implements
                                   * Copyright (c) 1999 The Apache Software Foundation. All rights                                         Enumeration enum = values.keys();                                      * serializable, so that it can be stored in persistent storage or transferred            public void expire() {                                                                              * <code>HttpSessionBindingListener</code>, the container calls
                                   * reserved.                                                                                             while (enum.hasMoreElements()) {                                       * to a different JVM for distributable session support.                                                                                                                                      * <code>valueUnbound()</code> on the object.
                                   *                                                                                                           String name = (String)enum.nextElement();                          * <p>                                                                                          // Remove this session from our manager's active sessions                                     *
                                   * Redistribution and use in source and binary forms, with or without                                        removeValue(name);                                                 * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the                    if ((manager != null) && (manager instanceof ManagerBase))                                    * @param name Name of the object to remove from this session.
                                   * modification, are permitted provided that the following conditions                                    }                                                                      * internal (Session) and application level (HttpSession) view of the session.                      ((ManagerBase) manager).remove(this);                                                     *
                                   * are met:                                                                                                                                                                     * However, because the class itself is not declared public, Java logic outside                                                                                                               * @exception IllegalStateException if this method is called on an
                                   *                                                                                                       valid = false;                                                         * of the <code>org.apache.tomcat.session</code> package cannot cast an                         // Unbind any objects associated with this session                                            * invalidated session
                                   * 1. Redistributions of source code must retain the above copyright                              }                                                                             * HttpSession view of this instance back to a Session view.                                    Vector results = new Vector();                                                                */
                                   *    notice, this list of conditions and the following disclaimer.                                                                                                             *                                                                                              Enumeration attrs = getAttributeNames();                                                     public void removeAttribute(String name) {
                                   *                                                                                                public boolean isNew() {                                                      * @author Craig R. McClanahan                                                                  while (attrs.hasMoreElements()) {
                                   * 2. Redistributions in binary form must reproduce the above copyright                               if (! valid) {                                                            * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $                                           String attr = (String) attrs.nextElement();                                                  synchronized (attributes) {
                                   *    notice, this list of conditions and the following disclaimer in                                     String msg = sm.getString("applicationSession.session.ise");          */                                                                                                 results.addElement(attr);                                                                        Object object = attributes.get(name);
                                   *    the documentation and/or other materials provided with the                                                                                                                                                                                                               }                                                                                                    if (object == null)
                                   *    distribution.                                                                                          throw new IllegalStateException(msg);                             final class StandardSession                                                                     Enumeration names = results.elements();                                                                  return;
                                   *                                                                                                       }                                                                         implements HttpSession, Session {                                                           while (names.hasMoreElements()) {                                                                    attributes.remove(name);
                                   * 3. The end-user documentation included with the redistribution, if                                                                                                                                                                                                              String name = (String) names.nextElement();                                                      //      System.out.println( "Removing attribute " + name );
                                   *    any, must include the following acknowledgment:                                                    if (thisAccessTime == creationTime) {                                                                                                                                     removeAttribute(name);                                                                           if (object instanceof HttpSessionBindingListener) {
                                   *       "This product includes software developed by the                                                    return true;                                                            // ----------------------------------------------------------- Constructors               }                                                                                                        ((HttpSessionBindingListener) object).valueUnbound
                                   *        Apache Software Foundation (http://www.apache.org/)."                                          } else {                                                                                                                                                                                                                                                                           (new HttpSessionBindingEvent((HttpSession) this, name));
                                   *    Alternately, this acknowledgment may appear in the software                                            return false;                                                                                                                                                     // Mark this session as invalid                                                                      }
                                  itself,                                                                                                  }                                                                           /**                                                                                       setValid(false);                                                                                 }
                                   *    if and wherever such third-party acknowledgments normally appear.                           }                                                                                   * Construct a new Session associated with the specified Manager.
                                   *                                                                                                                                                                                    *                                                                                  }                                                                                                  }
                                   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software                                                                                                                 * @param manager The manager with which this Session is associated
                                   *    Foundation" must not be used to endorse or promote products                       /**                                                                                           */                                                                                                                                                                                * Bind an object to this session, using the specified name. If an object
                                  derived                                                                                               * @deprecated                                                                  public StandardSession(Manager manager) {                                           /**                                                                                                 * of the same name is already bound to this session, the object is
                                   *    from this software without prior written permission. For written                                */                                                                                                                                                                                                                                                                     * replaced.
                                   *    permission, please contact apache@apache.org.                                                                                                                                      super();                                                                        }                                                                                                   * <p>
                                   *                                                                                                public void putValue(String name, Object value) {                                      this.manager = manager;                                                                                                                                                             * After this method executes, and if the object implements
                                   * 5. Products derived from this software may not be called "Apache"                                  setAttribute(name, value);                                                                                                                                                                                                                                             * <code>HttpSessionBindingListener</code>, the container calls
                                   *    nor may "Apache" appear in their names without prior written                                }                                                                                  }                                                                                   /**                                                                                                 * <code>valueBound()</code> on the object.
                                   *    permission of the Apache Group.                                                                                                                                                                                                                                     * Set the <code>isNew</code> flag for this session.                                                *
                                   *                                                                                                public void setAttribute(String name, Object value) {                                                                                                                   *                                                                                                  * @param name Name to which the object is bound, cannot be null
                                   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED                                   if (! valid) {                                                           /**                                                                                        * @param isNew The new value for the <code>isNew</code> flag                                       * @param value Object to be bound, cannot be null
                                   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES                                      String msg = sm.getString("applicationSession.session.ise");                * The last accessed time for this Session.                                          */                                                                                                 *
                                   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                                                                                                                        */                                                                                 void setNew(boolean isNew) {                                                                        * @exception IllegalArgumentException if an attempt is made to add a
                                   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR                                           throw new IllegalStateException(msg);                                   private long lastAccessedTime = creationTime;                                                                                                                                           * non-serializable object in an environment marked distributable.
                                   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,                                      }                                                                                                                                                                     this.isNew = isNew;                                                                           * @exception IllegalStateException if this method is called on an
                                   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT                                                                                                                                                                                                                                                                                                          * invalidated session
                                   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF                                      if (name == null) {                                                         /**                                                                                 }                                                                                                   */
                                   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND                                       String msg = sm.getString("applicationSession.value.iae");               * The Manager with which this Session is associated.                                                                                                                                  public void setAttribute(String name, Object value) {
                                   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,                                                                                                                 */
                                   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT                                        throw new IllegalArgumentException(msg);                                private Manager manager = null;                                                     /**                                                                                                    if ((manager != null) && manager.getDistributable() &&
                                   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF                                    }                                                                                                                                                                * Set the <code>isValid</code> flag for this session.                                                   !(value instanceof Serializable))




•
                                   * SUCH DAMAGE.                                                                                                                                                                                                                                                           *                                                                                                         throw new IllegalArgumentException
                                   * ====================================================================                                  removeValue(name);     // remove any existing binding                       /**                                                                                  * @param isValid The new value for the <code>isValid</code> flag                                              (sm.getString("standardSession.setAttribute.iae"));
                                   *                                                                                                                                                                                    * The maximum time interval, in seconds, between client requests before             */
                                   * This software consists of voluntary contributions made by many                                        if (value != null && value instanceof HttpSessionBindingListener) {          * the servlet container may invalidate this session. A negative time               void setValid(boolean isValid) {                                                                       synchronized (attributes) {
                                   * individuals on behalf of the Apache Software Foundation. For more                                         HttpSessionBindingEvent e =                                              * indicates that the session should never time out.                                                                                                                                           removeAttribute(name);
                                   * information on the Apache Software Foundation, please see                                                     new HttpSessionBindingEvent(this, name);                             */                                                                                       this.isValid = isValid;                                                                              attributes.put(name, value);
                                   * <http://www.apache.org/>.                                                                                                                                                         private int maxInactiveInterval = -1;                                               }                                                                                                          if (value instanceof HttpSessionBindingListener)
                                   *                                                                                                           ((HttpSessionBindingListener)value).valueBound(e);                                                                                                                                                                                                                         ((HttpSessionBindingListener) value).valueBound
                                   * [Additional notices, if required by prior licensing conditions]                                       }                                                                                                                                                                                                                                                                                  (new HttpSessionBindingEvent((HttpSession) this, name));
                                   *                                                                                                                                                                                   /**                                                                                 // ------------------------------------------------- HttpSession Properties                            }
                                   */                                                                                                      values.put(name, value);                                                     * Flag indicating whether this session is new or not.
                                                                                                                                    }                                                                                   */                                                                                                                                                                                    }
                                                                                                                                                                                                                       private boolean isNew = true;                                                       /**




    Aspect-Oriented
                                                                                                                                    /**                                                                                                                                                                     * Return the time when this session was created, in milliseconds since
                                  package org.apache.tomcat.session;                                                                  * @deprecated                                                                                                                                                         * midnight, January 1, 1970 GMT.                                                                  // -------------------------------------------- HttpSession Private Methods
                                                                                                                                      */                                                                               /**                                                                                  *
                                  import org.apache.tomcat.core.*;                                                                  public Object getValue(String name) {                                               * Flag indicating whether this session is valid or not.                             * @exception IllegalStateException if this method is called on an
                                  import org.apache.tomcat.util.StringManager;                                                           return getAttribute(name);                                                     */                                                                                  * invalidated session                                                                             /**
                                  import java.io.*;                                                                                 }                                                                                  private boolean isValid = false;                                                     */                                                                                                 * Read a serialized version of this session object from the specified
                                  import java.net.*;                                                                                                                                                                                                                                                       public long getCreationTime() {                                                                     * object input stream.
                                  import java.util.*;                                                                               public Object getAttribute(String name) {                                                                                                                                                                                                                                  * <p>
                                  import javax.servlet.*;                                                                               if (! valid) {                                                                 /**                                                                                       return (this.creationTime);                                                                   * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager
                                  import javax.servlet.http.*;                                                                              String msg = sm.getString("applicationSession.session.ise");                * The string manager for this package.                                                                                                                                                 * is not restored by this method, and must be set explicitly.
                                                                                                                                                                                                                        */                                                                                 }                                                                                                   *
                                  /**                                                                                                          throw new IllegalStateException(msg);                                   private StringManager sm =                                                                                                                                                              * @param stream The input stream to read from
                                   * Core implementation of an application level session                                                   }                                                                               StringManager.getManager("org.apache.tomcat.session");                                                                                                                              *
                                   *                                                                                                                                                                                                                                                                       /**                                                                                                 * @exception ClassNotFoundException if an unknown class is specified
                                   * @author James Duncan Davidson [duncan@eng.sun.com]                                                    if (name == null) {                                                                                                                                              * Return the session context with which this session is associated.                                * @exception IOException if an input/output error occurs
                                   * @author Jason Hunter [jch@eng.sun.com]                                                                    String msg = sm.getString("applicationSession.value.iae");              /**                                                                                  *                                                                                                  */
                                   * @author James Todd [gonzo@eng.sun.com]                                                                                                                                             * The HTTP session context associated with this session.                            * @deprecated As of Version 2.1, this method is deprecated and has no                             private void readObject(ObjectInputStream stream)
                                   */                                                                                                          throw new IllegalArgumentException(msg);                                 */                                                                                  * replacement. It will be removed in a future version of the                                          throws ClassNotFoundException, IOException {
                                                                                                                                           }                                                                           private static HttpSessionContext sessionContext = null;                             * Java Servlet API.
                                  public class ApplicationSession implements HttpSession {                                                                                                                                                                                                                  */                                                                                                    // Deserialize the scalar instance variables (except Manager)
                                                                                                                                           return values.get(name);                                                                                                                                        public HttpSessionContext getSessionContext() {                                                        creationTime = ((Long) stream.readObject()).
                                      private StringManager sm =                                                                    }                                                                                  /**                                                                                                                                                                                        isValid = ((Boolean) stream.readObject()).booleanValue();
                                          StringManager.getManager("org.apache.tomcat.session");                                                                                                                        * The current accessed time for this session.                                            if (sessionContext == null)
                                      private Hashtable values = new Hashtable();                                                   /**                                                                                 */                                                                                           sessionContext = new StandardSessionContext();                                               // Deserialize the attribute count and attribute values
                                      private String id;                                                                             * @deprecated                                                                     private long thisAccessedTime = creationTime;                                             return (sessionContext);                                                                         int n = ((Integer) stream.readObject()).intValue();
                                      private ServerSession serverSession;                                                           */                                                                                                                                                                                                                                                                           for (int i = 0; i < n; i++) {
                                      private Context context;                                                                      public String[] getValueNames() {                                                                                                                                      }                                                                                                          String name = (String) stream.readObject();
                                      private long creationTime = System.currentTimeMillis();;                                          Enumeration e = getAttributeNames();                                                                                                                                                                                                                                          Object value = (Object) stream.readObject();
                                      private long thisAccessTime = creationTime;                                                       Vector names = new Vector();                                                                                                                                                                                                                                                  attributes.put(name, value);
                                  private boolean valid = true;                                                                                                                                                        // ----------------------------------------------------- Session Properties         // ----------------------------------------------HttpSession Public Methods                            }
                                                                                                                                           while (e.hasMoreElements()) {
                                      ApplicationSession(String id, ServerSession serverSession,                                               names.addElement(e.nextElement());                                                                                                                                                                                                                             }
                                          Context context) {                                                                               }                                                                           /**                                                                                 /**
                                          this.serverSession = serverSession;                                                                                                                                           * Set the creation time for this session. This method is called by the              * Return the object bound with the specified name in this session, or
                                          this.context = context;                                                                          String[] valueNames = new String[names.size()];                              * Manager when an existing Session instance is reused.                              * <code>null</code> if no object is bound with that name.                                         /**




    Programming enables
                                          this.id = id;                                                                                                                                                                 *                                                                                   *                                                                                                  * Write a serialized version of this session object to the specified
                                                                                                                                           names.copyInto(valueNames);                                                  * @param time The new creation time                                                 * @param name Name of the attribute to be returned                                                 * object output stream.
                                          this.inactiveInterval = context.getSessionTimeOut();                                                                                                                          */                                                                                  *                                                                                                  * <p>
                                                                                                                                           return valueNames;                                                          public void setCreationTime(long time) {                                             * @exception IllegalStateException if this method is called on an                                  * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored
                                          if (this.inactiveInterval != -1) {                                                                                                                                                                                                                                * invalidated session                                                                              * in the serialized representation of this Session. After calling
                                              this.inactiveInterval *= 60;                                                          }                                                                                      this.creationTime = time;                                                        */                                                                                                 * <code>readObject()</code>, you must set the associated Manager
                                          }                                                                                                                                                                                this.lastAccessedTime = time;                                                   public Object getAttribute(String name) {                                                           * explicitly.
                                      }                                                                                             public Enumeration getAttributeNames() {                                               this.thisAccessedTime = time;                                                                                                                                                       * <p>
                                                                                                                                        if (! valid) {                                                                                                                                                           return (attributes.get(name));                                                                * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable
                                      ServerSession getServerSession() {                                                                    String msg = sm.getString("applicationSession.session.ise");               }                                                                                                                                                                                       * will be silently ignored. If you do not want any such attributes,
                                          return serverSession;                                                                                                                                                                                                                                            }                                                                                                   * be sure the <code>distributable</code> property of our associated
                                      }                                                                                                        throw new IllegalStateException(msg);                                                                                                                                                                                                                           * Manager is set to <code>true</code>.
                                                                                                                                           }                                                                           /**                                                                                                                                                                                     *
                                      /**                                                                                                                                                                               * Return the session identifier for this session.                                  /**                                                                                                 * @param stream The output stream to write to
                                       * Called by context when request comes in so that accesses and                                      Hashtable valuesClone = (Hashtable)values.clone();                           */                                                                                  * Return an <code>Enumeration</code> of <code>String</code> objects                                *
                                       * inactivities can be dealt with accordingly.                                                                                                                                   public String getId() {                                                              * containing the names of the objects bound to this session.                                       * @exception IOException if an input/output error occurs
                                       */                                                                                                  return (Enumeration)valuesClone.keys();                                                                                                                          *                                                                                                  */
                                                                                                                                    }                                                                                      return (this.id);                                                                * @exception IllegalStateException if this method is called on an                                 private void writeObject(ObjectOutputStream stream) throws IOException {
                                                                                                                                                                                                                                                                                                            * invalidated session
                                      // HTTP SESSION IMPLEMENTATION METHODS                                                                                                                                           }                                                                                    */                                                                                                    // Write the scalar instance variables (except Manager)
                                                                                                                              /**                                                                                                                                                                          public Enumeration getAttributeNames() {                                                               stream.writeObject(new Long(creationTime));
                                      public String getId() {                                                                           * @deprecated                                                                                                                                                                                                                                                             stream.writeObject(id);
                                          if (valid) {                                                                                  */                                                                             /**                                                                                       return (attributes.keys());                                                                      stream.writeObject(new Long(lastAccessedTime));
                                              return id;                                                                                                                                                                * Set the session identifier for this session.                                                                                                                                            stream.writeObject(new Integer(maxInactiveInterval));
                                          } else {                                                                                  public void removeValue(String name) {                                              *                                                                                  }                                                                                                      stream.writeObject(new Boolean(isNew));
                                              String msg = sm.getString("applicationSession.session.ise");                              removeAttribute(name);                                                          * @param id The new session identifier                                                                                                                                                    stream.writeObject(new Boolean(isValid));
                                                                                                                                    }                                                                                   */
                                              throw new IllegalStateException(msg);                                                                                                                                    public void setId(String id) {                                                      /**                                                                                                    // Accumulate the names of serializable attributes
                                          }                                                                                         public void removeAttribute(String name) {                                                                                                                              * Return the object bound with the specified name in this session, or                                 Vector results = new Vector();
                                      }                                                                                                 if (! valid) {                                                                     if ((this.id != null) && (manager != null) &&                                    * <code>null</code> if no object is bound with that name.                                             Enumeration attrs = getAttributeNames();
                                                                                                                                            String msg = sm.getString("applicationSession.session.ise");                     (manager instanceof ManagerBase))                                              *                                                                                                     while (attrs.hasMoreElements()) {
                                      public long getCreationTime() {                                                                                                                                                          ((ManagerBase) manager).remove(this);                                        * @param name Name of the value to be returned                                                            String attr = (String) attrs.nextElement();
                                          if (valid) {                                                                                         throw new IllegalStateException(msg);                                                                                                                        *                                                                                                         Object value = attributes.get(attr);
                                              return creationTime;                                                                         }                                                                               this.id = id;                                                                    * @exception IllegalStateException if this method is called on an                                         if (value instanceof Serializable)
                                          } else {                                                                                                                                                                                                                                                          * invalidated session                                                                                         results.addElement(attr);




    localized implementations
                                              String msg = sm.getString("applicationSession.session.ise");                                 if (name == null) {                                                             if ((manager != null) && (manager instanceof ManagerBase))                       *                                                                                                     }
                                                                                                                                               String msg = sm.getString("applicationSession.value.iae");                      ((ManagerBase) manager).add(this);                                           * @deprecated As of Version 2.2, this method is replaced by
                                              throw new IllegalStateException(msg);                                                                                                                                                                                                                         * <code>getAttribute()</code>                                                                         // Serialize the attribute count and the attribute values
                                          }                                                                                                    throw new IllegalArgumentException(msg);                                }                                                                                    */                                                                                                    stream.writeObject(new Integer(results.size()));
                                      }                                                                                                    }                                                                                                                                                               public Object getValue(String name) {                                                                  Enumeration names = results.elements();
                                                                                                                                                                                                                                                                                                                                                                                                                  while (names.hasMoreElements()) {
                                      /**                                                                                                  Object o = values.get(name);                                                /**                                                                                       return (getAttribute(name));                                                                         String name = (String) names.nextElement();
                                       *                                                                                                                                                                                * Return descriptive information about this Session implementation and                                                                                                                        stream.writeObject(name);
                                       * @deprecated                                                                                       if (o instanceof HttpSessionBindingListener) {                               * the corresponding version number, in the format                                  }                                                                                                          stream.writeObject(attributes.get(name));
                                       */                                                                                                      HttpSessionBindingEvent e =                                              * <code>&lt;description&gt;/&lt;version&gt;</code>.                                                                                                                                       }
                                                                                                                                                   new HttpSessionBindingEvent(this,name);                              */
                                      public HttpSessionContext getSessionContext() {                                                                                                                                  public String getInfo() {                                                           /**
                                          return new SessionContextImpl();                                                                     ((HttpSessionBindingListener)o).valueUnbound(e);                                                                                                             * Return the set of names of objects bound to this session. If there                              }
                                      }                                                                                                    }                                                                               return (this.info);                                                              * are no such objects, a zero-length array is returned.
                                                                                                                                                                                                                                                                                                            *                                                                                                 crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() |
                                                                                                                                           values.remove(name);                                                        }                                                                                    * @exception IllegalStateException if this method is called on an                                                                              long getCreationTime() |
                                                                                                                                    }                                                                                                                                                                       * invalidated session                                                                                                                          Object getAttribute(String) |
                                                                                                                                                                                                                 /**                                                                                        *                                                                                                                                              Enumeration getAttributeNames() |
                                                                                                                                    public void setMaxInactiveInterval(int interval) {                                  * Return the Manager within which this Session is valid.                            * @deprecated As of Version 2.2, this method is replaced by                                                                                    String[] getValueNames() |
                                                                                                                                        if (! valid) {                                                                  */                                                                                  * <code>getAttributeNames()</code>                                                                                                             void invalidate() |
                                                                                                                                            String msg = sm.getString("applicationSession.session.ise");               public Manager getManager() {                                                        */                                                                                                                                             boolean isNew() |
                                                                                                                                                                                                                                                                                                           public String[] getValueNames() {                                                                                                               void removeAttribute(String) |
                                                                                                                                               throw new IllegalStateException(msg);                                       return (this.manager);                                                                                                                                                                                                          void setAttribute(String, Object));
                                                                                                                                           }                                                                                                                                                                     Vector results = new Vector();
                                                                                                                                                                                                                       }                                                                                         Enumeration attrs = getAttributeNames();                                                     static advice(StandardSession s): invalidate(s) {
                                                                                                                                           inactiveInterval = interval;                                                                                                                                          while (attrs.hasMoreElements()) {                                                                before {
                                                                                                                                    }                                                                                                                                                                                String attr = (String) attrs.nextElement();                                                      if (!s.isValid())
                                                                                                                                                                                                                       /**                                                                                           results.addElement(attr);                                                                             throw new IllegalStateException
                                                                                                                                    public int getMaxInactiveInterval() {                                               * Set the Manager within which this Session is valid.                                    }                                                                                                             (s.sm.getString("standardSession."
                                                                                                                                        if (! valid) {                                                                  *                                                                                        String names[] = new String[results.size()];                                                                                  + thisJoinPoint.methodName
                                                                                                                                            String msg = sm.getString("applicationSession.session.ise");                * @param manager The new Manager                                                         for (int i = 0; i < names.length; i++)                                                                                        + ".ise"));
                                                                                                                                                                                                                        */                                                                                           names[i] = (String) results.elementAt(i);                                                    }
                                                                                                                                               throw new IllegalStateException(msg);                                   public void setManager(Manager manager) {                                                 return (names);                                                                              }
                                                                                                                                           }
                                                                                                                                                                                                                           this.manager = manager;                                                         }




    of CCCs.
                                                                                                                                           return inactiveInterval;
                                                                                                                                    }                                                                                  }
                                                                                                                          }                                                                                                                                                                                /**                                                                                            }
                                                                                                                                                                                                                                                                                                            * Invalidates this session and unbinds any objects bound to it.
                                                                                                                                                                                                                       /**                                                                                  *
                                                                                                                          //-----------------------------------------------------------------------                     * Return the maximum time interval, in seconds, between client requests             * @exception IllegalStateException if this method is called on                                // -------------------------------------------------------------- Private Class
                                                                                                                                                                                                                        * before the servlet container will invalidate the session. A negative              * an invalidated session
                                                                                                                                                                                                                        * time indicates that the session should never time out.                            */
                                                                                                                                                                                                                        *                                                                                  public void invalidate() {                                                                     /**
                                                                                                                                                                                                                        * @exception IllegalStateException if this method is called on                                                                                                                     * This class is a dummy implementation of the <code>HttpSessionContext</code>
                                                                                                                                                                                                                        * an invalidated session                                                                 // Cause this session to expire                                                           * interface, to conform to the requirement that such an object be returned
                                                                                                                                                                                                                        */                                                                                       expire();                                                                                 * when <code>HttpSession.getSessionContext()</code> is called.
                                                                                                                                                                                                                       public int getMaxInactiveInterval() {                                                                                                                                               *
                                                                                                                                                                                                                                                                                                           }                                                                                               * @author Craig R. McClanahan
                                                                                                                                                                                                                           return (this.maxInactiveInterval);                                                                                                                                              *
                                                                                                                                                                                                                                                                                                                                                                                                           * @deprecated As of Java Servlet API 2.1 with no replacement. The
                                                                                                                                                                                                                                                                                                           /**                                                                                             * interface will be removed in a future version of this API.
                                                                                                                                                                                                                                                                                                            * Return <code>true</code> if the client does not yet know about the                           */
                                                                                                                                                                                                                                                                                                            * session, or if the client chooses not to join the session. For
                                                                                                                                                                                                                                                                                                            * example, if the server used only cookie-based sessions, and the client                      final class StandardSessionContext implements HttpSessionContext {
                                                                                                                                                                                                                                                                                                            * has disabled the use of cookies, then a session would be new on each
                                                                                                                                                                                                                                                                                                            * request.
                                                                                                                                                                                                                                                                                                            *                                                                                                 private Vector dummy = new Vector();
                                                                                                                                                                                                                                                                                                            * @exception IllegalStateException if this method is called on an
                                                                                                                                                                                                                                                                                                            * invalidated session                                                                             /**
                                                                                                                                                                                                                                                                                                            */                                                                                                 * Return the session identifiers of all sessions defined
                                                                                                                                                                                                                                                                                                           public boolean isNew() {                                                                            * within this context.
                                                                                                                                                                                                                                                                                                                                                                                                               *
                                                                                                                                                                                                                                                                                                                 return (this.isNew);                                                                          * @deprecated As of Java Servlet API 2.1 with no replacement.
                                                                                                                                                                                                                                                                                                                                                                                                               * This method must return an empty <code>Enumeration</code>
                                                                                                                                                                                                                                                                                                           }                                                                                                   * and will be removed in a future version of the API.
                                                                                                                                                                                                                                                                                                                                                                                                               */
                                                                                                                                                                                                                                                                                                                                                                                                              public Enumeration getIds() {

                                                                                                                                                                                                                                                                                                                                                                                                                  return (dummy.elements());

                                                                                                                                                                                                                                                                                                                                                                                                              }


                                                                                                                                                                                                                                                                                                                                                                                                              /**
                                                                                                                                                                                                                                                                                                                                                                                                               * Return the <code>HttpSession</code> associated with the
                                                                                                                                                                                                                                                                                                                                                                                                               * specified session identifier.
                                                                                                                                                                                                                                                                                                                                                                                                               *
                                                                                                                                                                                                                                                                                                                                                                                                               * @param id Session identifier for which to look up a session
                                                                                                                                                                                                                                                                                                                                                                                                               *
                                                                                                                                                                                                                                                                                                                                                                                                               * @deprecated As of Java Servlet API 2.1 with no replacement.
                                                                                                                                                                                                                                                                                                                                                                                                               * This method must return null and will be removed in a
                                                                                                                                                                                                                                                                                                                                                                                                               * future version of the API.
                                                                                                                                                                                                                                                                                                                                                                                                               */
                                                                                                                                                                                                                                                                                                                                                                                                              public HttpSession getSession(String id) {

                                                                                                                                                                                                                                                                                                                                                                                                                  return (null);

                                                                                                                                                                                                                                                                                                                                                                                                              }

                                                                                                                                                                                                                                                                                                                                                                                                          }




• Pointcuts select (join)
    points in the program
    where a CCC applies.
                                  package org.apache.tomcat.session;                                         ynchronized void invalidate() {
                                                                                                                     Enumeration enum = appSessions.keys();
                                  import org.apache.tomcat.core.*;
                                  import org.apache.tomcat.util.StringManager;                                       while (enum.hasMoreElements()) {
                                  import java.io.*;                                                                      Object key = enum.nextElement();
                                  import java.net.*;                                                                     ApplicationSession appSession =
                                  import java.util.*;                                                                        (ApplicationSession)appSessions.get(key);
                                  import javax.servlet.*;
                                  import javax.servlet.http.*;                                                           appSession.invalidate();
                                                                                                                     }
                                  /**                                                                            }
                                   * Core implementation of a server session
                                   *                                                                             public void putValue(String name, Object value) {
                                   * @author James Duncan Davidson [duncan@eng.sun.com]                              if (name == null) {
                                   * @author James Todd [gonzo@eng.sun.com]                                              String msg = sm.getString("serverSession.value.iae");
                                   */
                                                                                                                         throw new IllegalArgumentException(msg);
                                  public class ServerSession {                                                       }

                                      private StringManager sm =                                                     removeValue(name); // remove any existing binding
                                          StringManager.getManager("org.apache.tomcat.session");                     values.put(name, value);
                                      private Hashtable values = new Hashtable();                                }
                                      private Hashtable appSessions = new Hashtable();
                                      private String id;                                                         public Object getValue(String name) {
                                      private long creationTime = System.currentTimeMillis();;                       if (name == null) {
                                      private long thisAccessTime = creationTime;                                        String msg = sm.getString("serverSession.value.iae");
                                      private long lastAccessed = creationTime;
                                      private int inactiveInterval = -1;                                                 throw new IllegalArgumentException(msg);
                                                                                                                     }
                                      ServerSession(String id) {
                                          this.id = id;                                                              return values.get(name);
                                      }                                                                          }

                                      public String getId() {                                                    public Enumeration getValueNames() {
                                          return id;                                                                 return values.keys();
                                      }                                                                          }

                                      public long getCreationTime() {                                            public void removeValue(String name) {
                                          return creationTime;                                                       values.remove(name);
                                      }                                                                          }

                                      public long getLastAccessedTime() {                                        public void setMaxInactiveInterval(int interval) {
                                          return lastAccessed;                                                       inactiveInterval = interval;
                                      }                                                                          }

                                      public ApplicationSession getApplicationSession(Context context,           public int getMaxInactiveInterval() {
                                          boolean create) {                                                          return inactiveInterval;
                                          ApplicationSession appSession =                                        }
                                              (ApplicationSession)appSessions.get(context);
                                                                                                                 // XXX
                                          if (appSession == null && create) {                                    // sync'd for safty -- no other thread should be getting something
                                                                                                                 // from this while we are reaping. This isn't the most optimal




•
                                              // XXX                                                             // solution for this, but we'll determine something else later.
                                              // sync to ensure valid?
                                                                                                                 synchronized void reap() {
                                              appSession = new ApplicationSession(id, this, context);                Enumeration enum = appSessions.keys();
                                              appSessions.put(context, appSession);
                                          }                                                                          while (enum.hasMoreElements()) {
                                                                                                                         Object key = enum.nextElement();
                                          // XXX                                                                         ApplicationSession appSession =
                                          // make sure that we haven't gone over the end of our                              (ApplicationSession)appSessions.get(key);
                                          // inactive interval -- if so, invalidate and create
                                          // a new appSession                                                            appSession.validate();
                                                                                                                     }




    Code (advice) is implicitly
                                          return appSession;                                                     }
                                      }                                                                      }

                                      void removeApplicationSession(Context context) {
                                          appSessions.remove(context);
                                      }

                                      /**
                                       * Called by context when request comes in so that accesses and
                                       * inactivities can be dealt with accordingly.
                                       */


                                      void validate()




    executed at those points.
                                                                                                                                                                                                                                 private long lastAccessed = creationTime;                                                                                                     if (inactiveInterval != -1) {
                                                                                                                                                                                                                                    private int inactiveInterval = -1;                                                                                                                     int thisInterval =
                                                                                                                                                                                                                                                                                                                                                                                               (int)(System.currentTimeMillis() - lastAccessed) / 1000;
                                                                                                                                                                                                                                 void accessed() {
                                                                                                                                                                                                                                        // set last accessed to thisAccessTime as it will be left over                                                                                       if (thisInterval > inactiveInterval) {
                                                                                                                                                                                                                                        // from the previous access                                                                                                                              invalidate();
                                                                                                                                                                                                                                        lastAccessed = thisAccessTime;
                                                                                                                                                                                                                                        thisAccessTime = System.currentTimeMillis();                                                                                                             ServerSessionManager ssm =
                                                                                                                                                                                                                                                                                                                                                                                                     ServerSessionManager.getManager();
                                                                                                                                                                                                                                           validate();
                                                                                                                                                                                                                                    }                                                                                                                                                            ssm.removeSession(this);
                                                                                                                                                                                                                                                                                                                                                                                             }
                                                                                                                                                                                                                                    void validate() {                                                                                                                                    }
                                                                                                                                                                                                                                        // if we have an inactive interval, check to see if we've exceeded it                                                                        }
                                                                                                                                                                                                                                        if (inactiveInterval != -1) {
                                                                                                                                                                                                                                            int thisInterval =                                                                                                                    private long lastAccessedTime = creationTime;
                                                                                                                                                                                                                                                (int)(System.currentTimeMillis() - lastAccessed) / 1000;

                                                                                                                                                                                                                                               if (thisInterval > inactiveInterval) {
                                                                                                                                                                                                                                                   invalidate();                                                                                                                     /**
                                                                                                                                                                                                                                               }                                                                                                                                      * 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() {                                                                                                                  */
                                                                                                                                                                                                                                        if (valid) {                                                                                                                                 public long getLastAccessedTime() {
                                                                                                                                                                                                                                            return lastAccessed;
                                                                                                                                                                                                                                        } else {                                                                                                                                         return (this.lastAccessedTime);
                                                                                                                                                                                                                                            String msg = sm.getString("applicationSession.session.ise");
                                                                                                                                                                                                                                                                                                                                                                                     }
                                                                                                                                                                                                                                               throw new IllegalStateException(msg);
                                                                                                                                                                                                                                           }
                                                                                                                                                                                                                                    }                                                                                                                                                    this.lastAccessedTime = time;


                                                                                                                                                                                                                                 public long getLastAccessedTime() {
                                                                                                                                                                                                                                        return lastAccessed;
                                                                                                                                                                                                                                    }


                                                                                                                                                                                                                                 private long lastAccessed = creationTime;

                                                                                                                                                                                                                                 void accessed() {
                                                                                                                                                                                                                                        // set last accessed to thisAccessTime as it will be left over
                                                                                                                                                                                                                                        // from the previous access

                                                                                                                                                                                                                                           lastAccessed = thisAccessTime;
                                                                                                                                                                                                                                           thisAccessTime = System.currentTimeMillis();

                                                                                                                                                                                                                                    }




                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 11
Aspect-Oriented Programming


                                     /*                                                                                      public void invalidate() {                                                             ;                                                                                                                                                                                        * Remove the object bound with the specified name from this session. If
                                      * ====================================================================                         serverSession.removeApplicationSession(context);                                                                                                                         /**                                                                                                 * the session does not have an object bound with this name, this method
                                      *                                                                                                                                                                                                                                                                        * Perform the internal processing required to invalidate this session,                             * does nothing.
                                      * The Apache Software License, Version 1.1                                                              // remove everything in the session                                   /**                                                                                        * without triggering an exception if the session has already expired.                              * <p>
                                      *                                                                                                                                                                              * Standard implementation of the <b>Session</b> interface. This object is                 */                                                                                                 * After this method executes, and if the object implements
                                      * Copyright (c) 1999 The Apache Software Foundation. All rights                                         Enumeration enum = values.keys();                                      * serializable, so that it can be stored in persistent storage or transferred            public void expire() {                                                                              * <code>HttpSessionBindingListener</code>, the container calls
                                      * reserved.                                                                                             while (enum.hasMoreElements()) {                                       * to a different JVM for distributable session support.                                                                                                                                      * <code>valueUnbound()</code> on the object.
                                      *                                                                                                           String name = (String)enum.nextElement();                          * <p>                                                                                          // Remove this session from our manager's active sessions                                     *
                                      * Redistribution and use in source and binary forms, with or without                                        removeValue(name);                                                 * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the                    if ((manager != null) && (manager instanceof ManagerBase))                                    * @param name Name of the object to remove from this session.
                                      * modification, are permitted provided that the following conditions                                    }                                                                      * internal (Session) and application level (HttpSession) view of the session.                      ((ManagerBase) manager).remove(this);                                                     *
                                      * are met:                                                                                                                                                                     * However, because the class itself is not declared public, Java logic outside                                                                                                               * @exception IllegalStateException if this method is called on an
                                      *                                                                                                       valid = false;                                                         * of the <code>org.apache.tomcat.session</code> package cannot cast an                         // Unbind any objects associated with this session                                            * invalidated session
                                      * 1. Redistributions of source code must retain the above copyright                              }                                                                             * HttpSession view of this instance back to a Session view.                                    Vector results = new Vector();                                                                */
                                      *    notice, this list of conditions and the following disclaimer.                                                                                                             *                                                                                              Enumeration attrs = getAttributeNames();                                                     public void removeAttribute(String name) {
                                      *                                                                                                public boolean isNew() {                                                      * @author Craig R. McClanahan                                                                  while (attrs.hasMoreElements()) {
                                      * 2. Redistributions in binary form must reproduce the above copyright                               if (! valid) {                                                            * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $                                           String attr = (String) attrs.nextElement();                                                  synchronized (attributes) {
                                      *    notice, this list of conditions and the following disclaimer in                                     String msg = sm.getString("applicationSession.session.ise");          */                                                                                                 results.addElement(attr);                                                                        Object object = attributes.get(name);
                                      *    the documentation and/or other materials provided with the                                                                                                                                                                                                               }                                                                                                    if (object == null)
                                      *    distribution.                                                                                          throw new IllegalStateException(msg);                             final class StandardSession                                                                     Enumeration names = results.elements();                                                                  return;
                                      *                                                                                                       }                                                                         implements HttpSession, Session {                                                           while (names.hasMoreElements()) {                                                                    attributes.remove(name);
                                      * 3. The end-user documentation included with the redistribution, if                                                                                                                                                                                                              String name = (String) names.nextElement();                                                      //      System.out.println( "Removing attribute " + name );
                                      *    any, must include the following acknowledgment:                                                    if (thisAccessTime == creationTime) {                                                                                                                                     removeAttribute(name);                                                                           if (object instanceof HttpSessionBindingListener) {
                                      *       "This product includes software developed by the                                                    return true;                                                            // ----------------------------------------------------------- Constructors               }                                                                                                        ((HttpSessionBindingListener) object).valueUnbound
                                      *        Apache Software Foundation (http://www.apache.org/)."                                          } else {                                                                                                                                                                                                                                                                           (new HttpSessionBindingEvent((HttpSession) this, name));
                                      *    Alternately, this acknowledgment may appear in the software                                            return false;                                                                                                                                                     // Mark this session as invalid                                                                      }
                                     itself,                                                                                                  }                                                                           /**                                                                                       setValid(false);                                                                                 }
                                      *    if and wherever such third-party acknowledgments normally appear.                           }                                                                                   * Construct a new Session associated with the specified Manager.
                                      *                                                                                                                                                                                    *                                                                                  }                                                                                                  }
                                      * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software                                                                                                                 * @param manager The manager with which this Session is associated
                                      *    Foundation" must not be used to endorse or promote products                       /**                                                                                           */                                                                                                                                                                                * Bind an object to this session, using the specified name. If an object
                                     derived                                                                                               * @deprecated                                                                  public StandardSession(Manager manager) {                                           /**                                                                                                 * of the same name is already bound to this session, the object is
                                      *    from this software without prior written permission. For written                                */                                                                                                                                                                                                                                                                     * replaced.
                                      *    permission, please contact apache@apache.org.                                                                                                                                      super();                                                                        }                                                                                                   * <p>
                                      *                                                                                                public void putValue(String name, Object value) {                                      this.manager = manager;                                                                                                                                                             * After this method executes, and if the object implements
                                      * 5. Products derived from this software may not be called "Apache"                                  setAttribute(name, value);                                                                                                                                                                                                                                             * <code>HttpSessionBindingListener</code>, the container calls
                                      *    nor may "Apache" appear in their names without prior written                                }                                                                                  }                                                                                   /**                                                                                                 * <code>valueBound()</code> on the object.
                                      *    permission of the Apache Group.                                                                                                                                                                                                                                     * Set the <code>isNew</code> flag for this session.                                                *
                                      *                                                                                                public void setAttribute(String name, Object value) {                                                                                                                   *                                                                                                  * @param name Name to which the object is bound, cannot be null
                                      * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED                                   if (! valid) {                                                           /**                                                                                        * @param isNew The new value for the <code>isNew</code> flag                                       * @param value Object to be bound, cannot be null
                                      * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES                                      String msg = sm.getString("applicationSession.session.ise");                * The last accessed time for this Session.                                          */                                                                                                 *
                                      * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                                                                                                                        */                                                                                 void setNew(boolean isNew) {                                                                        * @exception IllegalArgumentException if an attempt is made to add a
                                      * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR                                           throw new IllegalStateException(msg);                                   private long lastAccessedTime = creationTime;                                                                                                                                           * non-serializable object in an environment marked distributable.
                                      * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,                                      }                                                                                                                                                                     this.isNew = isNew;                                                                           * @exception IllegalStateException if this method is called on an
                                      * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT                                                                                                                                                                                                                                                                                                          * invalidated session
                                      * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF                                      if (name == null) {                                                         /**                                                                                 }                                                                                                   */
                                      * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND                                       String msg = sm.getString("applicationSession.value.iae");               * The Manager with which this Session is associated.                                                                                                                                  public void setAttribute(String name, Object value) {
                                      * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,                                                                                                                 */
                                      * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT                                        throw new IllegalArgumentException(msg);                                private Manager manager = null;                                                     /**                                                                                                    if ((manager != null) && manager.getDistributable() &&
                                      * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF                                    }                                                                                                                                                                * Set the <code>isValid</code> flag for this session.                                                   !(value instanceof Serializable))




•
                                      * SUCH DAMAGE.                                                                                                                                                                                                                                                           *                                                                                                         throw new IllegalArgumentException
                                      * ====================================================================                                  removeValue(name);     // remove any existing binding                       /**                                                                                  * @param isValid The new value for the <code>isValid</code> flag                                              (sm.getString("standardSession.setAttribute.iae"));
                                      *                                                                                                                                                                                    * The maximum time interval, in seconds, between client requests before             */
                                      * This software consists of voluntary contributions made by many                                        if (value != null && value instanceof HttpSessionBindingListener) {          * the servlet container may invalidate this session. A negative time               void setValid(boolean isValid) {                                                                       synchronized (attributes) {
                                      * individuals on behalf of the Apache Software Foundation. For more                                         HttpSessionBindingEvent e =                                              * indicates that the session should never time out.                                                                                                                                           removeAttribute(name);
                                      * information on the Apache Software Foundation, please see                                                     new HttpSessionBindingEvent(this, name);                             */                                                                                       this.isValid = isValid;                                                                              attributes.put(name, value);
                                      * <http://www.apache.org/>.                                                                                                                                                         private int maxInactiveInterval = -1;                                               }                                                                                                          if (value instanceof HttpSessionBindingListener)
                                      *                                                                                                           ((HttpSessionBindingListener)value).valueBound(e);                                                                                                                                                                                                                         ((HttpSessionBindingListener) value).valueBound
                                      * [Additional notices, if required by prior licensing conditions]                                       }                                                                                                                                                                                                                                                                                  (new HttpSessionBindingEvent((HttpSession) this, name));
                                      *                                                                                                                                                                                   /**                                                                                 // ------------------------------------------------- HttpSession Properties                            }
                                      */                                                                                                      values.put(name, value);                                                     * Flag indicating whether this session is new or not.
                                                                                                                                       }                                                                                   */                                                                                                                                                                                    }
                                                                                                                                                                                                                          private boolean isNew = true;                                                       /**




    Aspect-Oriented
                                                                                                                                       /**                                                                                                                                                                     * Return the time when this session was created, in milliseconds since
                                     package org.apache.tomcat.session;                                                                  * @deprecated                                                                                                                                                         * midnight, January 1, 1970 GMT.                                                                  // -------------------------------------------- HttpSession Private Methods
                                                                                                                                         */                                                                               /**                                                                                  *
                                     import org.apache.tomcat.core.*;                                                                  public Object getValue(String name) {                                               * Flag indicating whether this session is valid or not.                             * @exception IllegalStateException if this method is called on an
                                     import org.apache.tomcat.util.StringManager;                                                           return getAttribute(name);                                                     */                                                                                  * invalidated session                                                                             /**
                                     import java.io.*;                                                                                 }                                                                                  private boolean isValid = false;                                                     */                                                                                                 * Read a serialized version of this session object from the specified
                                     import java.net.*;                                                                                                                                                                                                                                                       public long getCreationTime() {                                                                     * object input stream.
                                     import java.util.*;                                                                               public Object getAttribute(String name) {                                                                                                                                                                                                                                  * <p>
                                     import javax.servlet.*;                                                                               if (! valid) {                                                                 /**                                                                                       return (this.creationTime);                                                                   * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager
                                     import javax.servlet.http.*;                                                                              String msg = sm.getString("applicationSession.session.ise");                * The string manager for this package.                                                                                                                                                 * is not restored by this method, and must be set explicitly.
                                                                                                                                                                                                                           */                                                                                 }                                                                                                   *
                                     /**                                                                                                          throw new IllegalStateException(msg);                                   private StringManager sm =                                                                                                                                                              * @param stream The input stream to read from
                                      * Core implementation of an application level session                                                   }                                                                               StringManager.getManager("org.apache.tomcat.session");                                                                                                                              *
                                      *                                                                                                                                                                                                                                                                       /**                                                                                                 * @exception ClassNotFoundException if an unknown class is specified
                                      * @author James Duncan Davidson [duncan@eng.sun.com]                                                    if (name == null) {                                                                                                                                              * Return the session context with which this session is associated.                                * @exception IOException if an input/output error occurs
                                      * @author Jason Hunter [jch@eng.sun.com]                                                                    String msg = sm.getString("applicationSession.value.iae");              /**                                                                                  *                                                                                                  */
                                      * @author James Todd [gonzo@eng.sun.com]                                                                                                                                             * The HTTP session context associated with this session.                            * @deprecated As of Version 2.1, this method is deprecated and has no                             private void readObject(ObjectInputStream stream)
                                      */                                                                                                          throw new IllegalArgumentException(msg);                                 */                                                                                  * replacement. It will be removed in a future version of the                                          throws ClassNotFoundException, IOException {
                                                                                                                                              }                                                                           private static HttpSessionContext sessionContext = null;                             * Java Servlet API.
                                     public class ApplicationSession implements HttpSession {                                                                                                                                                                                                                  */                                                                                                    // Deserialize the scalar instance variables (except Manager)
                                                                                                                                              return values.get(name);                                                                                                                                        public HttpSessionContext getSessionContext() {                                                        creationTime = ((Long) stream.readObject()).
                                         private StringManager sm =                                                                    }                                                                                  /**                                                                                                                                                                                        isValid = ((Boolean) stream.readObject()).booleanValue();
                                             StringManager.getManager("org.apache.tomcat.session");                                                                                                                        * The current accessed time for this session.                                            if (sessionContext == null)
                                         private Hashtable values = new Hashtable();                                                   /**                                                                                 */                                                                                           sessionContext = new StandardSessionContext();                                               // Deserialize the attribute count and attribute values
                                         private String id;                                                                             * @deprecated                                                                     private long thisAccessedTime = creationTime;                                             return (sessionContext);                                                                         int n = ((Integer) stream.readObject()).intValue();
                                         private ServerSession serverSession;                                                           */                                                                                                                                                                                                                                                                           for (int i = 0; i < n; i++) {
                                         private Context context;                                                                      public String[] getValueNames() {                                                                                                                                      }                                                                                                          String name = (String) stream.readObject();
                                         private long creationTime = System.currentTimeMillis();;                                          Enumeration e = getAttributeNames();                                                                                                                                                                                                                                          Object value = (Object) stream.readObject();
                                         private long thisAccessTime = creationTime;                                                       Vector names = new Vector();                                                                                                                                                                                                                                                  attributes.put(name, value);
                                     private boolean valid = true;                                                                                                                                                        // ----------------------------------------------------- Session Properties         // ----------------------------------------------HttpSession Public Methods                            }
                                                                                                                                              while (e.hasMoreElements()) {
                                         ApplicationSession(String id, ServerSession serverSession,                                               names.addElement(e.nextElement());                                                                                                                                                                                                                             }
                                             Context context) {                                                                               }                                                                           /**                                                                                 /**
                                             this.serverSession = serverSession;                                                                                                                                           * Set the creation time for this session. This method is called by the              * Return the object bound with the specified name in this session, or
                                             this.context = context;                                                                          String[] valueNames = new String[names.size()];                              * Manager when an existing Session instance is reused.                              * <code>null</code> if no object is bound with that name.                                         /**




    Programming enables
                                             this.id = id;                                                                                                                                                                 *                                                                                   *                                                                                                  * Write a serialized version of this session object to the specified
                                                                                                                                              names.copyInto(valueNames);                                                  * @param time The new creation time                                                 * @param name Name of the attribute to be returned                                                 * object output stream.
                                             this.inactiveInterval = context.getSessionTimeOut();                                                                                                                          */                                                                                  *                                                                                                  * <p>
                                                                                                                                              return valueNames;                                                          public void setCreationTime(long time) {                                             * @exception IllegalStateException if this method is called on an                                  * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored
                                             if (this.inactiveInterval != -1) {                                                                                                                                                                                                                                * invalidated session                                                                              * in the serialized representation of this Session. After calling
                                                 this.inactiveInterval *= 60;                                                          }                                                                                      this.creationTime = time;                                                        */                                                                                                 * <code>readObject()</code>, you must set the associated Manager
                                             }                                                                                                                                                                                this.lastAccessedTime = time;                                                   public Object getAttribute(String name) {                                                           * explicitly.
                                         }                                                                                             public Enumeration getAttributeNames() {                                               this.thisAccessedTime = time;                                                                                                                                                       * <p>
                                                                                                                                           if (! valid) {                                                                                                                                                           return (attributes.get(name));                                                                * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable
                                         ServerSession getServerSession() {                                                                    String msg = sm.getString("applicationSession.session.ise");               }                                                                                                                                                                                       * will be silently ignored. If you do not want any such attributes,
                                             return serverSession;                                                                                                                                                                                                                                            }                                                                                                   * be sure the <code>distributable</code> property of our associated
                                         }                                                                                                        throw new IllegalStateException(msg);                                                                                                                                                                                                                           * Manager is set to <code>true</code>.
                                                                                                                                              }                                                                           /**                                                                                                                                                                                     *
                                         /**                                                                                                                                                                               * Return the session identifier for this session.                                  /**                                                                                                 * @param stream The output stream to write to
                                          * Called by context when request comes in so that accesses and                                      Hashtable valuesClone = (Hashtable)values.clone();                           */                                                                                  * Return an <code>Enumeration</code> of <code>String</code> objects                                *
                                          * inactivities can be dealt with accordingly.                                                                                                                                   public String getId() {                                                              * containing the names of the objects bound to this session.                                       * @exception IOException if an input/output error occurs
                                          */                                                                                                  return (Enumeration)valuesClone.keys();                                                                                                                          *                                                                                                  */
                                                                                                                                       }                                                                                      return (this.id);                                                                * @exception IllegalStateException if this method is called on an                                 private void writeObject(ObjectOutputStream stream) throws IOException {
                                                                                                                                                                                                                                                                                                               * invalidated session
                                         // HTTP SESSION IMPLEMENTATION METHODS                                                                                                                                           }                                                                                    */                                                                                                    // Write the scalar instance variables (except Manager)
                                                                                                                                 /**                                                                                                                                                                          public Enumeration getAttributeNames() {                                                               stream.writeObject(new Long(creationTime));
                                         public String getId() {                                                                           * @deprecated                                                                                                                                                                                                                                                             stream.writeObject(id);
                                             if (valid) {                                                                                  */                                                                             /**                                                                                       return (attributes.keys());                                                                      stream.writeObject(new Long(lastAccessedTime));
                                                 return id;                                                                                                                                                                * Set the session identifier for this session.                                                                                                                                            stream.writeObject(new Integer(maxInactiveInterval));
                                             } else {                                                                                  public void removeValue(String name) {                                              *                                                                                  }                                                                                                      stream.writeObject(new Boolean(isNew));
                                                 String msg = sm.getString("applicationSession.session.ise");                              removeAttribute(name);                                                          * @param id The new session identifier                                                                                                                                                    stream.writeObject(new Boolean(isValid));
                                                                                                                                       }                                                                                   */
                                                 throw new IllegalStateException(msg);                                                                                                                                    public void setId(String id) {                                                      /**                                                                                                    // Accumulate the names of serializable attributes
                                             }                                                                                         public void removeAttribute(String name) {                                                                                                                              * Return the object bound with the specified name in this session, or                                 Vector results = new Vector();
                                         }                                                                                                 if (! valid) {                                                                     if ((this.id != null) && (manager != null) &&                                    * <code>null</code> if no object is bound with that name.                                             Enumeration attrs = getAttributeNames();
                                                                                                                                               String msg = sm.getString("applicationSession.session.ise");                     (manager instanceof ManagerBase))                                              *                                                                                                     while (attrs.hasMoreElements()) {
                                         public long getCreationTime() {                                                                                                                                                          ((ManagerBase) manager).remove(this);                                        * @param name Name of the value to be returned                                                            String attr = (String) attrs.nextElement();
                                             if (valid) {                                                                                         throw new IllegalStateException(msg);                                                                                                                        *                                                                                                         Object value = attributes.get(attr);
                                                 return creationTime;                                                                         }                                                                               this.id = id;                                                                    * @exception IllegalStateException if this method is called on an                                         if (value instanceof Serializable)
                                             } else {                                                                                                                                                                                                                                                          * invalidated session                                                                                         results.addElement(attr);




    localized implementations
                                                 String msg = sm.getString("applicationSession.session.ise");                                 if (name == null) {                                                             if ((manager != null) && (manager instanceof ManagerBase))                       *                                                                                                     }
                                                                                                                                                  String msg = sm.getString("applicationSession.value.iae");                      ((ManagerBase) manager).add(this);                                           * @deprecated As of Version 2.2, this method is replaced by
                                                 throw new IllegalStateException(msg);                                                                                                                                                                                                                         * <code>getAttribute()</code>                                                                         // Serialize the attribute count and the attribute values
                                             }                                                                                                    throw new IllegalArgumentException(msg);                                }                                                                                    */                                                                                                    stream.writeObject(new Integer(results.size()));
                                         }                                                                                                    }                                                                                                                                                               public Object getValue(String name) {                                                                  Enumeration names = results.elements();
                                                                                                                                                                                                                                                                                                                                                                                                                     while (names.hasMoreElements()) {
                                         /**                                                                                                  Object o = values.get(name);                                                /**                                                                                       return (getAttribute(name));                                                                         String name = (String) names.nextElement();
                                          *                                                                                                                                                                                * Return descriptive information about this Session implementation and                                                                                                                        stream.writeObject(name);
                                          * @deprecated                                                                                       if (o instanceof HttpSessionBindingListener) {                               * the corresponding version number, in the format                                  }                                                                                                          stream.writeObject(attributes.get(name));
                                          */                                                                                                      HttpSessionBindingEvent e =                                              * <code>&lt;description&gt;/&lt;version&gt;</code>.                                                                                                                                       }
                                                                                                                                                      new HttpSessionBindingEvent(this,name);                              */
                                         public HttpSessionContext getSessionContext() {                                                                                                                                  public String getInfo() {                                                           /**
                                             return new SessionContextImpl();                                                                     ((HttpSessionBindingListener)o).valueUnbound(e);                                                                                                             * Return the set of names of objects bound to this session. If there                              }
                                         }                                                                                                    }                                                                               return (this.info);                                                              * are no such objects, a zero-length array is returned.
                                                                                                                                                                                                                                                                                                               *                                                                                                 crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() |
                                                                                                                                              values.remove(name);                                                        }                                                                                    * @exception IllegalStateException if this method is called on an                                                                              long getCreationTime() |
                                                                                                                                       }                                                                                                                                                                       * invalidated session                                                                                                                          Object getAttribute(String) |
                                                                                                                                                                                                                    /**                                                                                        *                                                                                                                                              Enumeration getAttributeNames() |
                                                                                                                                       public void setMaxInactiveInterval(int interval) {                                  * Return the Manager within which this Session is valid.                            * @deprecated As of Version 2.2, this method is replaced by                                                                                    String[] getValueNames() |
                                                                                                                                           if (! valid) {                                                                  */                                                                                  * <code>getAttributeNames()</code>                                                                                                             void invalidate() |
                                                                                                                                               String msg = sm.getString("applicationSession.session.ise");               public Manager getManager() {                                                        */                                                                                                                                             boolean isNew() |
                                                                                                                                                                                                                                                                                                              public String[] getValueNames() {                                                                                                               void removeAttribute(String) |
                                                                                                                                                  throw new IllegalStateException(msg);                                       return (this.manager);                                                                                                                                                                                                          void setAttribute(String, Object));
                                                                                                                                              }                                                                                                                                                                     Vector results = new Vector();
                                                                                                                                                                                                                          }                                                                                         Enumeration attrs = getAttributeNames();                                                     static advice(StandardSession s): invalidate(s) {
                                                                                                                                              inactiveInterval = interval;                                                                                                                                          while (attrs.hasMoreElements()) {                                                                before {
                                                                                                                                       }                                                                                                                                                                                String attr = (String) attrs.nextElement();                                                      if (!s.isValid())
                                                                                                                                                                                                                          /**                                                                                           results.addElement(attr);                                                                             throw new IllegalStateException
                                                                                                                                       public int getMaxInactiveInterval() {                                               * Set the Manager within which this Session is valid.                                    }                                                                                                             (s.sm.getString("standardSession."
                                                                                                                                           if (! valid) {                                                                  *                                                                                        String names[] = new String[results.size()];                                                                                  + thisJoinPoint.methodName
                                                                                                                                               String msg = sm.getString("applicationSession.session.ise");                * @param manager The new Manager                                                         for (int i = 0; i < names.length; i++)                                                                                        + ".ise"));
                                                                                                                                                                                                                           */                                                                                           names[i] = (String) results.elementAt(i);                                                    }
                                                                                                                                                  throw new IllegalStateException(msg);                                   public void setManager(Manager manager) {                                                 return (names);                                                                              }
                                                                                                                                              }
                                                                                                                                                                                                                              this.manager = manager;                                                         }




    of CCCs.
                                                                                                                                              return inactiveInterval;
                                                                                                                                       }                                                                                  }
                                                                                                                             }                                                                                                                                                                                /**                                                                                            }
                                                                                                                                                                                                                                                                                                               * Invalidates this session and unbinds any objects bound to it.
                                                                                                                                                                                                                          /**                                                                                  *
                                                                                                                             //-----------------------------------------------------------------------                     * Return the maximum time interval, in seconds, between client requests             * @exception IllegalStateException if this method is called on                                // -------------------------------------------------------------- Private Class
                                                                                                                                                                                                                           * before the servlet container will invalidate the session. A negative              * an invalidated session
                                                                                                                                                                                                                           * time indicates that the session should never time out.                            */
                                                                                                                                                                                                                           *                                                                                  public void invalidate() {                                                                     /**
                                                                                                                                                                                                                           * @exception IllegalStateException if this method is called on                                                                                                                     * This class is a dummy implementation of the <code>HttpSessionContext</code>
                                                                                                                                                                                                                           * an invalidated session                                                                 // Cause this session to expire                                                           * interface, to conform to the requirement that such an object be returned
                                                                                                                                                                                                                           */                                                                                       expire();                                                                                 * when <code>HttpSession.getSessionContext()</code> is called.
                                                                                                                                                                                                                          public int getMaxInactiveInterval() {                                                                                                                                               *
                                                                                                                                                                                                                                                                                                              }                                                                                               * @author Craig R. McClanahan
                                                                                                                                                                                                                              return (this.maxInactiveInterval);                                                                                                                                              *
                                                                                                                                                                                                                                                                                                                                                                                                              * @deprecated As of Java Servlet API 2.1 with no replacement. The
                                                                                                                                                                                                                                                                                                              /**                                                                                             * interface will be removed in a future version of this API.
                                                                                                                                                                                                                                                                                                               * Return <code>true</code> if the client does not yet know about the                           */
                                                                                                                                                                                                                                                                                                               * session, or if the client chooses not to join the session. For
                                                                                                                                                                                                                                                                                                               * example, if the server used only cookie-based sessions, and the client                      final class StandardSessionContext implements HttpSessionContext {
                                                                                                                                                                                                                                                                                                               * has disabled the use of cookies, then a session would be new on each
                                                                                                                                                                                                                                                                                                               * request.
                                                                                                                                                                                                                                                                                                               *                                                                                                 private Vector dummy = new Vector();
                                                                                                                                                                                                                                                                                                               * @exception IllegalStateException if this method is called on an
                                                                                                                                                                                                                                                                                                               * invalidated session                                                                             /**
                                                                                                                                                                                                                                                                                                               */                                                                                                 * Return the session identifiers of all sessions defined
                                                                                                                                                                                                                                                                                                              public boolean isNew() {                                                                            * within this context.
                                                                                                                                                                                                                                                                                                                                                                                                                  *
                                                                                                                                                                                                                                                                                                                    return (this.isNew);                                                                          * @deprecated As of Java Servlet API 2.1 with no replacement.
                                                                                                                                                                                                                                                                                                                                                                                                                  * This method must return an empty <code>Enumeration</code>
                                                                                                                                                                                                                                                                                                              }                                                                                                   * and will be removed in a future version of the API.
                                                                                                                                                                                                                                                                                                                                                                                                                  */
                                                                                                                                                                                                                                                                                                                                                                                                                 public Enumeration getIds() {

                                                                                                                                                                                                                                                                                                                                                                                                                     return (dummy.elements());

                                                                                                                                                                                                                                                                                                                                                                                                                 }


                                                                                                                                                                                                                                                                                                                                                                                                                 /**
                                                                                                                                                                                                                                                                                                                                                                                                                  * Return the <code>HttpSession</code> associated with the
                                                                                                                                                                                                                                                                                                                                                                                                                  * specified session identifier.
                                                                                                                                                                                                                                                                                                                                                                                                                  *
                                                                                                                                                                                                                                                                                                                                                                                                                  * @param id Session identifier for which to look up a session
                                                                                                                                                                                                                                                                                                                                                                                                                  *
                                                                                                                                                                                                                                                                                                                                                                                                                  * @deprecated As of Java Servlet API 2.1 with no replacement.
                                                                                                                                                                                                                                                                                                                                                                                                                  * This method must return null and will be removed in a
                                                                                                                                                                                                                                                                                                                                                                                                                  * future version of the API.
                                                                                                                                                                                                                                                                                                                                                                                                                  */
                                                                                                                                                                                                                                                                                                                                                                                                                 public HttpSession getSession(String id) {

                                                                                                                                                                                                                                                                                                                                                                                                                     return (null);

                                                                                                                                                                                                                                                                                                                                                                                                                 }

                                                                                                                                                                                                                                                                                                                                                                                                             }




• Pointcuts select (join)               Aspects
    points in the program         allow code to be
    where a CCC applies.           localized into a
                                     package org.apache.tomcat.session;                                         ynchronized void invalidate() {
                                                                                                                        Enumeration enum = appSessions.keys();
                                     import org.apache.tomcat.core.*;
                                     import org.apache.tomcat.util.StringManager;                                       while (enum.hasMoreElements()) {
                                     import java.io.*;                                                                      Object key = enum.nextElement();
                                     import java.net.*;                                                                     ApplicationSession appSession =
                                     import java.util.*;                                                                        (ApplicationSession)appSessions.get(key);
                                     import javax.servlet.*;
                                     import javax.servlet.http.*;                                                           appSession.invalidate();
                                                                                                                        }
                                     /**                                                                            }
                                      * Core implementation of a server session
                                      *                                                                             public void putValue(String name, Object value) {
                                      * @author James Duncan Davidson [duncan@eng.sun.com]                              if (name == null) {
                                      * @author James Todd [gonzo@eng.sun.com]                                              String msg = sm.getString("serverSession.value.iae");
                                      */
                                                                                                                            throw new IllegalArgumentException(msg);
                                     public class ServerSession {                                                       }

                                         private StringManager sm =                                                     removeValue(name); // remove any existing binding
                                             StringManager.getManager("org.apache.tomcat.session");                     values.put(name, value);
                                         private Hashtable values = new Hashtable();                                }
                                         private Hashtable appSessions = new Hashtable();
                                         private String id;                                                         public Object getValue(String name) {
                                         private long creationTime = System.currentTimeMillis();;                       if (name == null) {
                                         private long thisAccessTime = creationTime;                                        String msg = sm.getString("serverSession.value.iae");
                                         private long lastAccessed = creationTime;
                                         private int inactiveInterval = -1;                                                 throw new IllegalArgumentException(msg);
                                                                                                                        }
                                         ServerSession(String id) {
                                             this.id = id;                                                              return values.get(name);
                                         }                                                                          }

                                         public String getId() {                                                    public Enumeration getValueNames() {
                                             return id;                                                                 return values.keys();
                                         }                                                                          }

                                         public long getCreationTime() {                                            public void removeValue(String name) {




                                     single module
                                             return creationTime;                                                       values.remove(name);
                                         }                                                                          }

                                         public long getLastAccessedTime() {                                        public void setMaxInactiveInterval(int interval) {
                                             return lastAccessed;                                                       inactiveInterval = interval;
                                         }                                                                          }

                                         public ApplicationSession getApplicationSession(Context context,           public int getMaxInactiveInterval() {
                                             boolean create) {                                                          return inactiveInterval;
                                             ApplicationSession appSession =                                        }
                                                 (ApplicationSession)appSessions.get(context);
                                                                                                                    // XXX
                                             if (appSession == null && create) {                                    // sync'd for safty -- no other thread should be getting something
                                                                                                                    // from this while we are reaping. This isn't the most optimal




•
                                                 // XXX                                                             // solution for this, but we'll determine something else later.
                                                 // sync to ensure valid?
                                                                                                                    synchronized void reap() {
                                                 appSession = new ApplicationSession(id, this, context);                Enumeration enum = appSessions.keys();
                                                 appSessions.put(context, appSession);
                                             }                                                                          while (enum.hasMoreElements()) {
                                                                                                                            Object key = enum.nextElement();
                                             // XXX                                                                         ApplicationSession appSession =
                                             // make sure that we haven't gone over the end of our                              (ApplicationSession)appSessions.get(key);
                                             // inactive interval -- if so, invalidate and create
                                             // a new appSession                                                            appSession.validate();
                                                                                                                        }




    Code (advice) is implicitly
                                             return appSession;                                                     }
                                         }                                                                      }

                                         void removeApplicationSession(Context context) {
                                             appSessions.remove(context);
                                         }

                                         /**
                                          * Called by context when request comes in so that accesses and
                                          * inactivities can be dealt with accordingly.
                                          */


                                         void validate()




    executed at those points.
                                                                                                                                                                                                                                    private long lastAccessed = creationTime;                                                                                                     if (inactiveInterval != -1) {
                                                                                                                                                                                                                                       private int inactiveInterval = -1;                                                                                                                     int thisInterval =
                                                                                                                                                                                                                                                                                                                                                                                                  (int)(System.currentTimeMillis() - lastAccessed) / 1000;
                                                                                                                                                                                                                                    void accessed() {
                                                                                                                                                                                                                                           // set last accessed to thisAccessTime as it will be left over                                                                                       if (thisInterval > inactiveInterval) {
                                                                                                                                                                                                                                           // from the previous access                                                                                                                              invalidate();
                                                                                                                                                                                                                                           lastAccessed = thisAccessTime;
                                                                                                                                                                                                                                           thisAccessTime = System.currentTimeMillis();                                                                                                             ServerSessionManager ssm =
                                                                                                                                                                                                                                                                                                                                                                                                        ServerSessionManager.getManager();
                                                                                                                                                                                                                                              validate();
                                                                                                                                                                                                                                       }                                                                                                                                                            ssm.removeSession(this);
                                                                                                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                       void validate() {                                                                                                                                    }
                                                                                                                                                                                                                                           // if we have an inactive interval, check to see if we've exceeded it                                                                        }
                                                                                                                                                                                                                                           if (inactiveInterval != -1) {
                                                                                                                                                                                                                                               int thisInterval =                                                                                                                    private long lastAccessedTime = creationTime;
                                                                                                                                                                                                                                                   (int)(System.currentTimeMillis() - lastAccessed) / 1000;

                                                                                                                                                                                                                                                  if (thisInterval > inactiveInterval) {
                                                                                                                                                                                                                                                      invalidate();                                                                                                                     /**
                                                                                                                                                                                                                                                  }                                                                                                                                      * 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() {                                                                                                                  */
                                                                                                                                                                                                                                           if (valid) {                                                                                                                                 public long getLastAccessedTime() {
                                                                                                                                                                                                                                               return lastAccessed;
                                                                                                                                                                                                                                           } else {                                                                                                                                         return (this.lastAccessedTime);
                                                                                                                                                                                                                                               String msg = sm.getString("applicationSession.session.ise");
                                                                                                                                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                  throw new IllegalStateException(msg);
                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                       }                                                                                                                                                    this.lastAccessedTime = time;


                                                                                                                                                                                                                                    public long getLastAccessedTime() {
                                                                                                                                                                                                                                           return lastAccessed;
                                                                                                                                                                                                                                       }


                                                                                                                                                                                                                                    private long lastAccessed = creationTime;

                                                                                                                                                                                                                                    void accessed() {
                                                                                                                                                                                                                                           // set last accessed to thisAccessTime as it will be left over
                                                                                                                                                                                                                                           // from the previous access

                                                                                                                                                                                                                                              lastAccessed = thisAccessTime;
                                                                                                                                                                                                                                              thisAccessTime = System.currentTimeMillis();

                                                                                                                                                                                                                                       }




                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    11
Message Encryption Example




                        12
Message Encryption Example




    messageSent():
execution(* send*(..))




                                  12
Message Encryption Example




    messageSent():
execution(* send*(..))

              The
        execution of all
      methods whose name
       begins with “send”
        must have their
      messages encrypted.
                                      12
Fragile Pointcut Problem




                     13
Fragile Pointcut Problem




• A pointcut is robust iff it
  continues to select points
  where the CCC applies in
  subsequent base-code
  versions without textual
  modification.




                                                     13
Fragile Pointcut Problem




• A pointcut is robust iff it
  continues to select points
  where the CCC applies in
  subsequent base-code
  versions without textual
  modification.

• Otherwise, a pointcut is
  fragile.




                                                     13
Fragile Pointcut Problem




• A pointcut is robust iff it
  continues to select points
  where the CCC applies in
  subsequent base-code
  versions without textual
  modification.

• Otherwise, a pointcut is
  fragile.

• Fragile pointcuts can
  cause software to
  silently malfunction!


                                                     13
Pointcut fragility Example




                       14
Pointcut fragility Example




• Suppose a subsequent version, a new method is
 added that sends messages but whose name begins
 with “transmit?”




                                                   14
Pointcut fragility Example




• Suppose a subsequent version, a new method is
 added that sends messages but whose name begins
 with “transmit?”
• Our pointcut breaks as a result.


                                                    14
Pointcut fragility Example




• Suppose a subsequent version, a new method is
 added that sends messages but whose name begins
 with “transmit?”
• Our pointcut breaks as a result.
• Thus, messageSent() is a fragile pointcut.

                                                   14
My Approach to the Fragile Pointcut Problem




                                         15
My Approach to the Fragile Pointcut Problem



• Developed an approach that mechanically aids
 developers in suitably updating pointcuts upon
 changes to the base-code.




                                                  15
My Approach to the Fragile Pointcut Problem



• Developed an approach that mechanically aids
 developers in suitably updating pointcuts upon
 changes to the base-code.
• The approach analyzes arbitrarily deep structural
 commonalities between program elements
 associated with pointcuts in a particular software
 version.




                                                      15
My Approach to the Fragile Pointcut Problem



• Developed an approach that mechanically aids
 developers in suitably updating pointcuts upon
 changes to the base-code.
• The approach analyzes 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.

                                                       15
Contributions




           16
Contributions

• Commonality identification:
 • Developed an open source Eclipse IDE plug-in called
   REJUVENATE POINTCUT that finds new join points
   exhibiting structural properties similar to those
   already selected by a pointcut.




                                                       16
Contributions

• Commonality identification:
 • Developed an open source Eclipse IDE plug-in called
   REJUVENATE POINTCUT that finds new join points
   exhibiting structural properties similar to those
   already selected by a pointcut.
• Correlation analysis:
 • Empirically establish that join points selected by a
   single pointcut typically portray a significant amount
   of unique structural commonality on multiple fronts.



                                                          16
Contributions

• Commonality identification:
 • Developed an open source Eclipse IDE plug-in called
   REJUVENATE POINTCUT that finds new join points
   exhibiting structural properties similar to those
   already selected by a pointcut.
• Correlation analysis:
 • Empirically establish that join points selected by a
   single pointcut typically portray a significant amount
   of unique structural commonality on multiple fronts.
• Expression recovery:
 • Evaluated usefulness by rejuvenating pointcuts in
   multiple versions of three open source AO projects. 16
Abstract Example Base Code


package p;
class A {
  int f;
  void m1() {
    int a = f + 1;
  }
  void m2() {
    int b = f + 2;
  }
  void n() {
    f = 3;
  }
}
                                 17
Abstract Example Base Code


package p;
class A {
  int f;
  void m1() {
    int a = f + 1;
  }
  void m2() {
    int b = f + 2;
  }
  void n() {
    f = 3;
  }
}
                        17
Abstract Example Base Code


                        package p;
                        class A {
• Two methods whose       int f;
 name begins with the
 character m.             void m1
                               m1() {
                            int a = f + 1;
                          }
                          void m2
                               m2() {
                            int b = f + 2;
                          }
                          void n() {
                            f = 3;
                          }
                        }
                                                17
Abstract Example Base Code


                           package p;
                           class A {
• Two methods whose          int f;
 name begins with the
 character m.                void m1() {
                               int a = f + 1;
• One method whose name      }
 does not begin with the
 character m.
                             void m2() {
                               int b = f + 2;
                             }
                             void n
                                  n() {
                               f = 3;
                             }
                           }
                                                   17
Abstract Example Base Code


                            package p;
                            class A {
• Two methods whose           int f;
                                  f
  name begins with the
  character m.                void m1() {
                                int a = f + 1;
• One method whose name       }
  does not begin with the
  character m.
                              void m2() {
                                int b = f + 2;
• Method bodies of m1 and     }
  m2 read from a field f.     void n() {
                                f = 3;
                              }
                            }
                                                    17
Abstract Example Base Code


                            package p;
                            class A {
• Two methods whose           int f;
                                  f
  name begins with the
  character m.                void m1() {
                                int a = f + 1;
• One method whose name       }
  does not begin with the
  character m.
                              void m2() {
                                int b = f + 2;
• Method bodies of m1 and     }
  m2 read from a field f.     void n() {
                                f = 3;
• Method body of n writes     }
  to field f.
                            }
                                                    17
Pointcut Example

pointcut mayBeFragile() :
            execution(* m*(..));




                                      18
Pointcut Example

pointcut mayBeFragile() :
            execution(* m*(..));




• Selects m1() and m2()
  but not n().




                                        18
Pointcut Example

pointcut mayBeFragile() :
            execution(* m*(..));




• Selects m1() and m2()
  but not n().

• Assume that correct join
  points are selected.




                                           18
Pointcut Example

pointcut mayBeFragile() :
            execution(* m*(..));




• Selects m1() and m2()
  but not n().

• Assume that correct join
  points are selected.

                                  CCC
                         applies to m1 and m2
                               but not p.
                                                        18
19
void p() {
    int d = f + 4;      A new method
}                    is added to the base
                             code




                                            19
void p() {
    int d = f + 4;
}

pointcut mayBeFragile() :
            execution(* m*(..));


                            W
                              ha
                                 ta
                             po bo
                               int ut
                                  cu th
                                    t? e




                                           19
void p() {
    int d = f + 4;
}

pointcut mayBeFragile() :
            execution(* m*(..));

• Same pointcut selects m1() and m2() but not
  n() and p().




                                                19
void p() {
    int d = f + 4;
}

pointcut mayBeFragile() :
            execution(* m*(..));

• Same pointcut selects m1() and m2() but not
  n() and p().

• Assume CCC applies to p().



                                                19
void p() {
    int d = f + 4;
}

pointcut mayBeFragile() :
            execution(* m*(..));

• Same pointcut selects m1() and m2() but not
  n() and p().

• Assume CCC applies to p().
• mayBeFragile() is fragile!

                                                19
void p() {
    int d = f + 4;
}

pointcut mayBeFragile() :
            execution(* m*(..));

• Same pointcut selects m1() and m2() but not
  n() and p().

• Assume CCC applies to p().
• mayBeFragile() is fragile!
• p() silently fall out of pointcut’s scope.
                                                19
void p() {
    int d = f + 4;
}

pointcut mayBeFragile() :
            execution(* m*(..));

• Same pointcut selects m1() and m2() but not
  n() and p().

• Assume CCC applies to p().
• mayBeFragile() is fragile!
• p() silently fall out of pointcut’s scope.
• May be difficult to identify in large base codes.   19
Phase I: Leverage Structural Commonality




                                      20
Phase I: Leverage Structural Commonality
• Build a Concern Graph [Robillard, Murphy ’02].



                        m1
             gets                   declares


    f         gets      m2        declares     A
               sets              declares


                        n
                                                   20
Phase I: Leverage Structural Commonality
• Build a Concern Graph [Robillard, Murphy ’02].
• Extract commonalities between currently selected
 join points.



                          m1
                gets                  declares


    f            gets     m2        declares     A
                  sets             declares


                           n
                                                      20
Phase I: Leverage Structural Commonality
• Build a Concern Graph [Robillard, Murphy ’02].
• Extract commonalities between currently selected
 join points.
• Find common sinks and sources in the graph.
                          m1
                gets              (A,declares,?)
                                      declares


    f       (?,gets, f)
                gets      m2         declares      A
                  sets             declares


                           n
                                                       20
Evaluating Patterns
           [Dagenais, Breu, Warr, Robillard ’07]
    (?,gets, f)                           (A,declares,?)




                          m1
             gets                       declares


f              gets       m2           declares       A
               sets                  declares


                           n
                                                           21
Evaluating Patterns
           [Dagenais, Breu, Warr, Robillard ’07]
    (?,gets, f)                           (A,declares,?)



    {m1,m2}
                          m1
              gets                      declares


f              gets       m2           declares       A
                sets                 declares


                           n
                                                           21
Evaluating Patterns
           [Dagenais, Breu, Warr, Robillard ’07]
    (?,gets, f)                           (A,declares,?)
                   100%
                confidence!

    {m1,m2}
                          m1
              gets                      declares


f              gets       m2           declares       A
                sets                 declares


                           n
                                                           21
Evaluating Patterns
           [Dagenais, Breu, Warr, Robillard ’07]
    (?,gets, f)                           (A,declares,?)
                   100%
                confidence!

    {m1,m2}                                     {m1,m2,n}
                          m1
              gets                      declares


f              gets       m2           declares             A
                sets                 declares


                           n
                                                                21
Evaluating Patterns
           [Dagenais, Breu, Warr, Robillard ’07]
    (?,gets, f)                           (A,declares,?)
                   100%           66%
                confidence! confidence

    {m1,m2}                                     {m1,m2,n}
                          m1
              gets                      declares


f              gets       m2           declares             A
                sets                 declares


                           n
                                                                21
Storing patterns for Phase II

(?,gets, f)                              (A,declares,?)
                 100%           66%
              confidence!     confidence




                           XML




                                                          22
Storing patterns for Phase II




XML




                             22
It’s a little more complicated ...




                               23
It’s a little more complicated ...
• Pattern evaluation is done on several other different levels.




                                                                  23
It’s a little more complicated ...
• Pattern evaluation is done on several other different levels.
• Previously illustrated the α evaluation:




                                                                  23
It’s a little more complicated ...
• Pattern evaluation is done on several other different levels.
• Previously illustrated the α evaluation:
 • Considers the strength of the structural relationships between
    elements produced by the pattern and those selected by the
    pointcut.




                                                                 23
It’s a little more complicated ...
• Pattern evaluation is done on several other different levels.
• Previously illustrated the α evaluation:
 • Considers the strength of the structural relationships between
    elements produced by the pattern and those selected by the
    pointcut.

• Another dimension is the β evaluation:




                                                                 23
It’s a little more complicated ...
• Pattern evaluation is done on several other different levels.
• Previously illustrated the α evaluation:
 • Considers the strength of the structural relationships between
    elements produced by the pattern and those selected by the
    pointcut.

• Another dimension is the β evaluation:
 • Considers the completeness of the structural relationship
    expressed by the pattern compared to relationships expressed
    by the pointcut.




                                                                 23
It’s a little more complicated ...
• Pattern evaluation is done on several other different levels.
• Previously illustrated the α evaluation:
 • Considers the strength of the structural relationships between
    elements produced by the pattern and those selected by the
    pointcut.

• Another dimension is the β evaluation:
 • Considers the completeness of the structural relationship
    expressed by the pattern compared to relationships expressed
    by the pointcut.
• Lastly, there is an abstractness evaluation:


                                                                 23
It’s a little more complicated ...
• Pattern evaluation is done on several other different levels.
• Previously illustrated the α evaluation:
 • Considers the strength of the structural relationships between
    elements produced by the pattern and those selected by the
    pointcut.

• Another dimension is the β evaluation:
 • Considers the completeness of the structural relationship
    expressed by the pattern compared to relationships expressed
    by the pointcut.
• Lastly, there is an abstractness evaluation:
 • Considers the ratio of wild-cards (?) to concrete elements in
    the pattern as patterns can be arbitrarily deep.

                                                                   23
It’s a little more complicated ...
• Pattern evaluation is done on several other different levels.
• Previously illustrated the α evaluation:
 • Considers the strength of the structural relationships between
    elements produced by the pattern and those selected by the
    pointcut.

• Another dimension is the β evaluation:
 • Considers the completeness of the structural relationship
    expressed by the pattern compared to relationships expressed
    by the pointcut.
• Lastly, there is an abstractness evaluation:
 • Considers the ratio of wild-cards (?) to concrete elements in
    the pattern as patterns can be arbitrarily deep.
• All three dimensions are combined to produce a patterns
  confidence value.                                                23
SACTIONS OF SOFTWARE ENGINEERING, VOL. X, NO. Y, Z 20AB


                           
                           0                                          if |Match(ˆ , Paths(CG + ))| = 0
                                                                                 π
     err α (ˆ , PCE)
            π          =          |PCE ∩ Match(ˆ , Paths(CG + ))|
                                                   π
                           1 −                                +         otherwise
                                       |Match(ˆ , Paths(CG ))|
                                               π
                           
                           1                                            if |PCE| = 0
     err β (ˆ , PCE)
            π          =          |PCE ∩ Match(ˆ , Paths(CG + ))|
                                                   π
                           1 −                                          otherwise
                                                 |PCE|
                           
                           1                      if |ˆ | = 0
                                                       π
            abs(ˆ )
                π      =          |ˆ | − |W(ˆ )|
                                   π         π
                           1 −                    otherwise
                                        |ˆ |
                                          π
     conf (ˆ , PCE)
           π           =   1 − [err α (ˆ , PCE)(1 − abs(ˆ )) + err β (ˆ , PCE)abs(ˆ )]
                                       π                   π          π            π

Pattern attribute equations.


allSpeed). Thus, the err α rate for this pattern          projection of wild card elements contained
e PCE found on line 3 of Figure 2, which selects          π . Likewise, |W(ˆ )| represents the number o
                                                          ˆ                π
 ution of methods DieselEngine.increase(Fuel) and         elements contained within pattern π . Then, t
                                                                                               ˆ   24
25   25
All join points




25                     25
All join points
Pointcut




       25                     25
All join points
Pointcut

     Pattern




       25                        25
All join points
Pointcut

     Pattern




               α




       25                            25
All join points
    Pointcut
β
         Pattern




                   α




           25                            25
All join points
            Pointcut
        β
                 Pattern




                           α




A   ?              ?                ?            ?
                   25                                25
All join points
            Pointcut
        β
                 Pattern




                           α




A   ?              ?                ?            ?
                  abs
                   25                                25
Phase II: Expression Recovery




                          26
Phase II: Expression Recovery

void p() {
    int d = f + 4;          A new method
}                        is added to the base
                                 code




                                                26
Phase II: Expression Recovery

void p() {
    int d = f + 4;           A new method
}                         is added to the base
                                  code
                m1
       gets                declares


f       gets    m2       declares        A
         sets           declares


        gets    n       declares




                p
                                                 26
Phase II: Expression Recovery

void p() {
    int d = f + 4;               A new method
}                             is added to the base
                                      code
                m1
      (?,gets, f)
          gets            (A,declares,?)
                              declares


f          gets     m2       declares        A
           sets             declares


           gets     n       declares



XML
                    p
                                                     26
27   27
(?,gets, f)




              27   27
(?,gets, f)



{m1,m2,p}




              27   27
(?,gets, f)
                100%
              confidence!

{m1,m2,p}




                           27   27
(?,gets, f)                execution(* m*(..))
                100%
              confidence!

{m1,m2,p}




                             27                  27
(?,gets, f)                execution(* m*(..))
                100%
              confidence!

{m1,m2,p}                         {m1,m2}




                             27                  27
(?,gets, f)                execution(* m*(..))
                100%
              confidence!

{m1,m2,p}                        {m1,m2}   =   {p}




                             27                       27
(?,gets, f)                execution(* m*(..))
                 100%
               confidence!

{m1,m2,p}                         {m1,m2}   =   {p}

(A,declares,?)




                              27                       27
(?,gets, f)                execution(* m*(..))
                 100%
               confidence!

{m1,m2,p}                         {m1,m2}   =   {p}

(A,declares,?)



{m1,m2,n,p}




                              27                       27
(?,gets, f)                execution(* m*(..))
                 100%
               confidence!

{m1,m2,p}                         {m1,m2}   =   {p}

(A,declares,?)

                     66%
                  confidence
{m1,m2,n,p}




                              27                       27
(?,gets, f)                execution(* m*(..))
                 100%
               confidence!

{m1,m2,p}                         {m1,m2}   =   {p}

(A,declares,?)              execution(* m*(..))

                     66%
                  confidence
{m1,m2,n,p}




                              27                       27
(?,gets, f)                execution(* m*(..))
                 100%
               confidence!

{m1,m2,p}                         {m1,m2}   =   {p}

(A,declares,?)              execution(* m*(..))

                     66%
                  confidence
{m1,m2,n,p}                        {m1,m2}




                              27                       27
(?,gets, f)                    execution(* m*(..))
                 100%
               confidence!

{m1,m2,p}                             {m1,m2}   =   {p}

(A,declares,?)              execution(* m*(..))

                     66%
                  confidence
{m1,m2,n,p}                           {m1,m2}   =   {n,p}




                                  27                         27
(?,gets, f)                    execution(* m*(..))
                 100%
               confidence!

{m1,m2,p}                             {m1,m2}   =   {p}

(A,declares,?)              execution(* m*(..))

                     66%
                  confidence
{m1,m2,n,p}                           {m1,m2}   =   {n,p}

  p is suggested with (100 + 66) / 2 ≈ 83% confidence


                                  27                         27
(?,gets, f)                    execution(* m*(..))
                 100%
               confidence!

{m1,m2,p}                             {m1,m2}   =   {p}

(A,declares,?)              execution(* m*(..))

                     66%
                  confidence
{m1,m2,n,p}                           {m1,m2}   =   {n,p}

  p is suggested with (100 + 66) / 2 ≈ 83% confidence
  n is suggested with 66% confidence

                                  27                         27
(?,gets, f)                    execution(* m*(..))
                 100%
               confidence!

{m1,m2,p}                            {m1,m2}   =   {p}

(A,declares,?)              execution(* m*(..))

                     66%
                  confidence
{m1,m2,n,p}                          {m1,m2}   =   {n,p}

  p is suggested with (100 + 66) / 2 ≈ 83% confidence
  n is suggested with 66% confidence
  execution(* m*(..)) || execution (* p())
                               27                           27
(?,gets, f)                    execution(* m*(..))
                 100%
               confidence!

{m1,m2,p}                             {m1,m2}   =   {p}

(A,declares,?)              execution(* m*(..))

                     66%
                  confidence
{m1,m2,n,p}                           {m1,m2}   =   {n,p}

  p is suggested with (100 + 66) / 2 ≈ 83% Suggestions
                                           confidence
  n is suggested with 66% confidence sorted by confidence
                                             in IDE
  execution(* m*(..)) || execution (* p())
                                  27                         27
mplementation   Implementation




                            28
Evaluation: Phase I
      subject     KL. cls. PC shd. KP.       α    β t (s)
  AJHotDraw       21.8 298   32   90 3.36 0.32 0.06   101
          Ants    1.57   33  22  297 1.25 0.15 0.23    43
          Bean    0.12    2   2    4 0.02 0.24 0.23     4
   Contract4J     10.7 199   15  350 1.80 0.26 0.44   115
         DCM      1.68   29   8  343 2.47 0.15 0.45     4
        Figure    0.10    5   1    6 0.02 0.11 0.45     8
      Glassbox    26.0 430   55  208 2.62 0.1 0.29    228
HealthWatcher     5.72   76  27  122 1.00 0.21 0.16    22
        Cactus    7.57   93   4  222 2.15 0.21 0.52     8
          LoD     1.59   29   5  164 0.54 0.15 0.41    46
  MobilePhoto     3.80   52  25   25 0.78 0.23 0.00    11
      MySQLa      44.0 187    2 3016 17.6 0.12 0.58   379
    NullCheck     1.47   27   1  112 0.10 0.17 0.55   293
     N-Version    0.55   15   4    9 0.08 0.19 0.24     1
     Quicksort    0.07    3   4    7 0.06 0.19 0.15     3
      RacerAJ     0.58   13   4    9 0.02 0.23 0.09     5
RecoveryCache     0.22    3   4   14 0.07 0.11 0.21     6
     Spacewar     1.42   21   9   58 0.23 0.15 0.22    37
    StarJ-Pool    38.2 511    1    3 0.07 0.25 0.00    75
      Telecom     0.28   10   4    5 0.03 0.21 0.02     7
         Tetris   1.04    8  18   27 0.50 0.16 0.01    14
   TollSystem     5.20   88  35   85 1.68 0.26 0.06    20
       Tracing    0.37    5  16  132 0.68 0.17 0.4      1
       Totals:     174 2137 298 5308 37.1 0.18 0.16 1431
                                                              29
Evaluation: Phase I
      subject     KL. cls. PC shd. KP.       α    β t (s)
  AJHotDraw       21.8 298   32   90 3.36 0.32 0.06   101
          Ants    1.57   33  22  297 1.25 0.15 0.23    43
          Bean    0.12    2   2    4 0.02 0.24 0.23     4
   Contract4J     10.7 199   15  350 1.80 0.26 0.44   115
         DCM      1.68   29   8  343 2.47 0.15 0.45     4
        Figure    0.10    5   1    6 0.02 0.11 0.45     8
      Glassbox    26.0 430   55  208 2.62 0.1 0.29    228
HealthWatcher     5.72   76  27  122 1.00 0.21 0.16    22
        Cactus    7.57   93   4  222 2.15 0.21 0.52     8
          LoD     1.59   29   5  164 0.54 0.15 0.41    46
  MobilePhoto     3.80   52  25   25 0.78 0.23 0.00    11
      MySQLa      44.0 187    2 3016 17.6 0.12 0.58   379
    NullCheck     1.47   27   1  112 0.10 0.17 0.55   293
     N-Version    0.55   15   4    9 0.08 0.19 0.24     1
     Quicksort    0.07    3   4    7 0.06 0.19 0.15     3
      RacerAJ     0.58   13   4    9 0.02 0.23 0.09     5
RecoveryCache     0.22    3   4   14 0.07 0.11 0.21     6
     Spacewar     1.42   21   9   58 0.23 0.15 0.22    37
    StarJ-Pool    38.2 511    1    3 0.07 0.25 0.00    75
      Telecom     0.28   10   4    5 0.03 0.21 0.02     7
         Tetris   1.04    8  18   27 0.50 0.16 0.01    14
   TollSystem     5.20   88  35   85 1.68 0.26 0.06    20
       Tracing    0.37    5  16  132 0.68 0.17 0.4      1
       Totals:     174 2137 298 5308 37.1 0.18 0.16 1431
                                                              29
Evaluation: Phase I
             subject     KL. cls. PC shd. KP.       α    β t (s)
         AJHotDraw       21.8 298   32   90 3.36 0.32 0.06   101
                 Ants    1.57   33  22  297 1.25 0.15 0.23    43
                 Bean    0.12    2   2    4 0.02 0.24 0.23     4
          Contract4J     10.7 199   15  350 1.80 0.26 0.44   115
                DCM      1.68   29   8  343 2.47 0.15 0.45     4
               Figure    0.10    5   1    6 0.02 0.11 0.45     8
             Glassbox    26.0 430   55  208 2.62 0.1 0.29    228
       HealthWatcher     5.72   76  27  122 1.00 0.21 0.16    22
               Cactus    7.57   93   4  222 2.15 0.21 0.52     8
                 LoD     1.59   29   5  164 0.54 0.15 0.41    46
         MobilePhoto     3.80   52  25   25 0.78 0.23 0.00    11
             MySQLa      44.0 187    2 3016 17.6 0.12 0.58   379
           NullCheck     1.47   27   1  112 0.10 0.17 0.55   293
            N-Version    0.55   15   4    9 0.08 0.19 0.24     1
            Quicksort    0.07    3   4    7 0.06 0.19 0.15     3
             RacerAJ     0.58   13   4    9 0.02 0.23 0.09     5

4.8 secs per
       RecoveryCache
            Spacewar
                         0.22
                         1.42
                                 3
                                21
                                     4
                                     9
                                         14 0.07 0.11 0.21
                                         58 0.23 0.15 0.22
                                                               6
                                                              37
  pointcut StarJ-Pool
             Telecom
                         38.2 511
                         0.28   10
                                     1
                                     4
                                          3 0.07 0.25 0.00
                                          5 0.03 0.21 0.02
                                                              75
                                                               7
                Tetris   1.04    8  18   27 0.50 0.16 0.01    14
          TollSystem     5.20   88  35   85 1.68 0.26 0.06    20
              Tracing    0.37    5  16  132 0.68 0.17 0.4      1
              Totals:     174 2137 298 5308 37.1 0.18 0.16 1431
                                                                     29
Evaluation: Phase 2




                 30
Evaluation: Phase 2

• Applied to 3 multi-versioned AspectJ projects.




                                                     30
Evaluation: Phase 2

• Applied to 3 multi-versioned AspectJ projects.
• Rejuvenated pointcuts (49 in total) over major
 releases (20 in total).




                                                     30
Evaluation: Phase 2

• Applied to 3 multi-versioned AspectJ projects.
• Rejuvenated pointcuts (49 in total) over major
 releases (20 in total).
• Maximum pattern length set to 2 edges.




                                                     30
Evaluation: Phase 2

• Applied to 3 multi-versioned AspectJ projects.
• Rejuvenated pointcuts (49 in total) over major
 releases (20 in total).
• Maximum pattern length set to 2 edges.
• Able to identify 93% of new shadows introduced in
 later versions that were not selected by previous
 pointcut representations.




                                                      30
Evaluation: Phase 2

• Applied to 3 multi-versioned AspectJ projects.
• Rejuvenated pointcuts (49 in total) over major
 releases (20 in total).
• Maximum pattern length set to 2 edges.
• Able to identify 93% of new shadows introduced in
 later versions that were not selected by previous
 pointcut representations.
• On average, 3.97 suggestions appeared before true
 positives.


                                                      30
Evaluation: Phase 2

• Applied to 3 multi-versioned AspectJ projects.
• Rejuvenated pointcuts (49 in total) over major
 releases (20 in total).
• Maximum pattern length set to 2 edges.
• Able to identify 93% of new shadows introduced in
 later versions that were not selected by previous
 pointcut representations.
• On average, 3.97 suggestions appeared before true
 positives.
• On average, 10.95 secs. required to rejuvenate a
 pointcut.
                                                      30
Related Work




          31
Related Work

• Wloka et al. [AOSD 08] automatically modify PCEs
 upon automated base code refactoring.




                                                     31
Related Work

• Wloka et al. [AOSD 08] automatically modify PCEs
 upon automated base code refactoring.
 • Base code changes must only be administered by
   automated refactoring.




                                                     31
Related Work

• Wloka et al. [AOSD 08] automatically modify PCEs
 upon automated base code refactoring.
 • Base code changes must only be administered by
   automated refactoring.

                                    RP works with
                                   arbitrary changes




                                                       31
Related Work

• Wloka et al. [AOSD 08] automatically modify PCEs
 upon automated base code refactoring.
 • Base code changes must only be administered by
   automated refactoring.
 • Adding new base code also breaks pointcuts.




                                                     31
Related Work

• Wloka et al. [AOSD 08] automatically modify PCEs
 upon automated base code refactoring.
 • Base code changes must only be administered by
   automated refactoring.
 • Adding new base code also breaks pointcuts.
• AspectJ Development Tools (AJDT) and Ye and
 Volder [AOSD 08] display join points that are
 currently and almost selected by a pointcut.




                                                     31
Related Work

• Wloka et al. [AOSD 08] automatically modify PCEs
 upon automated base code refactoring.
 • Base code changes must only be administered by
   automated refactoring.
 • Adding new base code also breaks pointcuts.
• AspectJ Development Tools (AJDT) and Ye and
 Volder [AOSD 08] display join points that are
 currently and almost selected by a pointcut.
 • Do not analyze the differences exhibited by join
   points between base code versions.

                                                      31
Related Work

• Wloka et al. [AOSD 08] automatically modify PCEs
 upon automated base code refactoring.
 • Base code changes must only be administered by
   automated refactoring.
 • Adding new base code also breaks pointcuts.
• AspectJ Development Tools (AJDT) and Ye and
 Volder [AOSD 08] display join points that are
 currently and almost selected by a pointcut.
 • Do not analyze the differences exhibited by join
   points between base code versions.
 • Pointcut Doctor uses heuristics general to all AO
   systems.                                            31
Related Work

• Wloka et al. [AOSD 08] automatically modify PCEs
 upon automated base code refactoring.
 • Base code changes must only be administered by
     automated refactoring.
 • Adding new base code also breaks pointcuts.
• AspectJ Development Tools (AJDT) and Ye and
 Volder [AOSD 08] display join points thatuses
                                        RP are
 currently and almost selected by a pointcut.
                                       heuristics
                                    customized to a
 •Do not analyze the differences exhibited by join
                                   particular system
  points between base code versions.
 • Pointcut Doctor uses heuristics general to all AO
     systems.                                          31
Conclusion




       32
Conclusion


• Aspect-Oriented Programming localize
 implementations of CCCs that would otherwise be
 scattered throughout the system and tangled with
 unrelated code.




                                                    32
Conclusion


• Aspect-Oriented Programming localize
 implementations of CCCs that would otherwise be
 scattered throughout the system and tangled with
 unrelated code.
• Evolving Aspect-Oriented programs requires some
 special consideration, especially regarding pointcut
 fragility.




                                                        32
Conclusion


• Aspect-Oriented Programming localize
  implementations of CCCs that would otherwise be
  scattered throughout the system and tangled with
  unrelated code.
• Evolving Aspect-Oriented programs requires some
  special consideration, especially regarding pointcut
  fragility.
• Rejuvenating pointcuts can be non-trivial in large
  systems.



                                                         32
Conclusion


• Aspect-Oriented Programming localize
  implementations of CCCs that would otherwise be
  scattered throughout the system and tangled with
  unrelated code.
• Evolving Aspect-Oriented programs requires some
  special consideration, especially regarding pointcut
  fragility.
• Rejuvenating pointcuts can be non-trivial in large
  systems.
• Mechanical assistance that leverages structural
  commonality can ease the evolution process.
                                                         32
Java 5 Enums
Java 5 Enums

• Java 5 introduced a rich set of new features such as
  generics, metadata annotations, boxing/unboxing,
  and type-safe enumerations.
Java 5 Enums

• Java 5 introduced a rich set of new features such as
  generics, metadata annotations, boxing/unboxing,
  and type-safe enumerations.
• Using enums increases:
Java 5 Enums

• Java 5 introduced a rich set of new features such as
  generics, metadata annotations, boxing/unboxing,
  and type-safe enumerations.
• Using enums increases:
 • Type-safety.
Java 5 Enums

• Java 5 introduced a rich set of new features such as
  generics, metadata annotations, boxing/unboxing,
  and type-safe enumerations.
• Using enums increases:
 • Type-safety.
 • Code comprehension.
Java 5 Enums

• Java 5 introduced a rich set of new features such as
  generics, metadata annotations, boxing/unboxing,
  and type-safe enumerations.
• Using enums increases:
 • Type-safety.
 • Code comprehension.
 • Code simplicity.
Java 5 Enums

• Java 5 introduced a rich set of new features such as
  generics, metadata annotations, boxing/unboxing,
  and type-safe enumerations.
• Using enums increases:
 • Type-safety.
 • Code comprehension.
 • Code simplicity.
 • Resiliency related to separate compilation.
Java 5 Enums

• Java 5 introduced a rich set of new features such as
  generics, metadata annotations, boxing/unboxing,
  and type-safe enumerations.
• Using enums increases:
 • Type-safety.
 • Code comprehension.
 • Code simplicity.
 • Resiliency related to separate compilation.
• Enums replaced a variety of coding patterns used to
  compensate for their absence in legacy software.
Java 5 Enums

• Java 5 introduced a rich set of new features such as
  generics, metadata annotations, boxing/unboxing,
  and type-safe enumerations.
• Using enums increases:
 • Type-safety.
 • Code comprehension.
 • Code simplicity.
 • Resiliency related to separate compilation.
• Enums replaced a variety of coding patterns used to
  compensate for their absence in legacy software.
• Leaves a large body of code to be manually upgraded.
Motivating Example



class TrafficSignal {
  public static final int RED = 0;
  public static final int YELLOW = 1;
  public static final int GREEN = 2;
  /∗ Current color of the traffic signal, initially red by default ∗/
  private int color = RED;
  /∗ Accessor for the light’s current color ∗/
  public int getColor() {return this.color;}}

class Automobile         {
  private static         final    int   IDLE = 0;
  private static         final    int   INCREASE_SPEED = 1;
  private static         final    int   DECREASE_SPEED = 2;
  private static         final    int   STOP = 3;                      34
Motivating Example

                                      Weak Enum
                                       Pattern
class TrafficSignal {
  public static final int RED = 0;
  public static final int YELLOW = 1;
  public static final int GREEN = 2;
  /∗ Current color of the traffic signal, initially red by default ∗/
  private int color = RED;
  /∗ Accessor for the light’s current color ∗/
  public int getColor() {return this.color;}}

class Automobile         {
  private static         final    int   IDLE = 0;
  private static         final    int   INCREASE_SPEED = 1;
  private static         final    int   DECREASE_SPEED = 2;
  private static         final    int   STOP = 3;                      34
Motivating Example



class TrafficSignal {
  public static final int RED = 0;
  public static final int YELLOW = 1;
  public static final int GREEN = 2;
  /∗ Current color of the traffic signal, initially red by default ∗/
  private int color = RED;
  /∗ Accessor for the light’s current color ∗/
  public int getColor() {return this.color;}}

class Automobile {
               Type Safety
  private static final int              IDLE = 0;
  private static final int              INCREASE_SPEED = 1;
  private static final int              DECREASE_SPEED = 2;
  private static final int              STOP = 3;                      34
Motivating Example



class TrafficSignal {
  public static final int RED = 0;
  public static final int YELLOW = 1;
  public static final int GREEN = 2;
  /∗ Current color of the traffic signal, initially red by default ∗/
                                    Manual
  private int color = RED;
                                Enumeration
  /∗ Accessor for the light’s current color ∗/
  public int getColor() {return this.color;}}

class Automobile         {
  private static         final    int   IDLE = 0;
  private static         final    int   INCREASE_SPEED = 1;
  private static         final    int   DECREASE_SPEED = 2;
  private static         final    int   STOP = 3;                      34
Motivating Example



class TrafficSignal {
  public static final int RED = 0;
  public static final int YELLOW = 1;
  public static final int GREEN = 2;
  /∗ Current color of the traffic signal, initially red by default ∗/
  private int color = RED;
  /∗ Accessor for the light’s current color ∗/
                                         Namespacing
  public int getColor() {return this.color;}}

class Automobile         {
  private static         final    int   IDLE = 0;
  private static         final    int   INCREASE_SPEED = 1;
  private static         final    int   DECREASE_SPEED = 2;
  private static         final    int   STOP = 3;                      34
Motivating Example



class TrafficSignal {
  public static final int RED = 0;
  public static final int YELLOW = 1;
  public static final int GREEN = 2;
  /∗ Current color of the traffic signal, initially red by default ∗/
  private int color = RED;                           Brittle
  /∗ Accessor for the light’s current color ∗/
  public int getColor() {return this.color;}}

class Automobile         {
  private static         final    int   IDLE = 0;
  private static         final    int   INCREASE_SPEED = 1;
  private static         final    int   DECREASE_SPEED = 2;
  private static         final    int   STOP = 3;                      34
Motivating Example



class TrafficSignal {
  public static final int RED = 0;
  public static final int YELLOW = 1;
  public static final int GREEN = 2;
  /∗ Current color of the traffic signal, initially red by default ∗/
  private int color = RED;
  /∗ Accessor for the light’s current color ∗/
  public int getColor() {return this.color;}}

class Automobile         {
  private static         final    int   IDLE = 0;
  private static         final    int   INCREASE_SPEED = 1;
  private static         final    int   DECREASE_SPEED = 2;
  private static         final    int   STOP = 3;                      34
Motivating Example Revisited



class TrafficSignal {
  public static final int RED = 0;
  public static final int YELLOW = 1;
  public static final int GREEN = 2;
  /∗ Current color of the traffic signal, initially red by default ∗/
  private int color = RED;
  /∗ Accessor for the light’s current color ∗/
  public int getColor() {return this.color;}}

class Automobile         {
  private static         final    int   IDLE = 0;
  private static         final    int   INCREASE_SPEED = 1;
  private static         final    int   DECREASE_SPEED = 2;
  private static         final    int   STOP = 3;                      35
Motivating Example Revisited



class TrafficSignal {{
        TrafficSignal
  public enum Color {RED, RED = 0;
  public static final int
     YELLOW,
  public static final int YELLOW = 1;
     GREEN};
  public static final int GREEN = 2;
  /∗ Current color of the traffic signal, initially red byby default ∗/
  /* Current color of the traffic signal, initially red default */
  private Color color= =RED;
  private int color                 Color.RED;
  /∗ Accessor for the light’s current color */∗/
  /* Accessor for the light’s current color
  public Color getColor(){return this.color;}}
  public int getColor() {return this.color;}}

class Automobile {
class Automobile {
  private enum Action {IDLE,IDLE = 0;
  private static final int
    INCREASE_SPEED,
  private static final int INCREASE_SPEED = 1;
    DECREASE_SPEED,
  private static final int DECREASE_SPEED = 2;
    STOP};
  private static final int MAX_SPEED = 140;
  private
           static final int STOP = 3;                                    35
Motivating Example Revisited



class TrafficSignal {{
class TrafficSignal
  public enum Color {RED, RED = 0;
  public static final int
     YELLOW,
  public static final int YELLOW = 1;
     GREEN};
  public static final int GREEN = 2;
  /∗ Current color of the traffic signal, initially red byby default ∗/
  /* Current color of the traffic signal, initially red default */
  private Color color= =RED;
  private int color                 Color.RED;
  /∗ Accessor for the light’s current color */∗/
  /* Accessor for the light’s current color
  public Color getColor(){return this.color;}}
  public int getColor() {return this.color;}}

class Automobile {
class Automobile {
  private enum Action {IDLE,IDLE = 0;
  private static final int
    INCREASE_SPEED,
  private static final int INCREASE_SPEED = 1;
    DECREASE_SPEED,
  private static final int DECREASE_SPEED = 2;
    STOP};
  private static final int MAX_SPEED = 140;
  private
           static final int STOP = 3;                                    35
Motivating Example Revisited



class TrafficSignal {{
        TrafficSignal
class TrafficSignal {
  public enum Color {RED, RED = 0;
  public static final int
  public enum Color {RED,
     YELLOW,
  public static final int YELLOW = 1;
     YELLOW,
     GREEN};
  public static final int GREEN = 2;
     GREEN};
  /∗ Current color of the traffic signal, initially red byby default ∗/
  /* Current color of the traffic signal, initially red by default */
  /* Current color of the traffic signal, initially red default */
  private Color color= =RED;
  private Color color = Color.RED;
  private int color                  Color.RED;
  /∗ Accessor for the light’s current color */∗/
  /* Accessor for the light’s current color */
  /* Accessor for the light’s current color
  public Color getColor(){return this.color;}}
  public Color getColor() {return this.color;}}
             int getColor() {return this.color;}}

class Automobile {
class Automobile {
class Automobile {
  private enum Action {IDLE,IDLE = 0;
  private enum Action {IDLE,
  private static final int
    INCREASE_SPEED,
    INCREASE_SPEED,
  private static final int INCREASE_SPEED = 1;
    DECREASE_SPEED,
    DECREASE_SPEED,
  private static final int DECREASE_SPEED = 2;
    STOP};
    STOP}; static final int STOP = 3;
  private static final int MAX_SPEED = 140;
  private                                                                35
Motivating Example Revisited



class TrafficSignal {{
        TrafficSignal
class TrafficSignal {
  public enum Color {RED, RED = 0;
  public static final int
  public enum Color {RED,
     YELLOW,
  public static final int YELLOW = 1;
     YELLOW,
     GREEN};
  public static final int GREEN = 2;
     GREEN};
  /∗ Current color of the traffic signal, initially red byby default ∗/
  /* Current color of the traffic signal, initially red by default */
  /* Current color of the traffic signal, initially red default */
  private Color color= =RED;
  private Color color = Color.RED;
  private int color                  Color.RED;
  /∗ Accessor for the light’s current color */∗/
  /* Accessor for the light’s current color */
  /* Accessor for the light’s current color
  public Color getColor(){return this.color;}}
  public Color getColor() {return this.color;}}
             int getColor() {return this.color;}}

class Automobile {
class Automobile {
class Automobile {
  private enum Action {IDLE,IDLE = 0;
  private enum Action {IDLE,
  private static final int
    INCREASE_SPEED,
    INCREASE_SPEED,
  private static final int INCREASE_SPEED = 1;
    DECREASE_SPEED,
    DECREASE_SPEED,
  private static final int DECREASE_SPEED = 2;
    STOP};
    STOP}; static final int STOP = 3;
  private static final int MAX_SPEED = 140;
  private                                                                36
Motivating Example Revisited


                                     Language Enum
class TrafficSignal {{
        TrafficSignal
class TrafficSignal {
  public enum Color {RED, RED = 0;
  public static final int
  public enum Color {RED,
     YELLOW,
  public static final int YELLOW = 1;
     YELLOW,
     GREEN};
  public static final int GREEN = 2;
     GREEN};
  /∗ Current color of the traffic signal, initially red byby default ∗/
  /* Current color of the traffic signal, initially red by default */
  /* Current color of the traffic signal, initially red default */
  private Color color= =RED;
  private Color color = Color.RED;
  private int color                  Color.RED;
  /∗ Accessor for the light’s current color */∗/
  /* Accessor for the light’s current color */
  /* Accessor for the light’s current color
  public Color getColor(){return this.color;}}
  public Color getColor() {return this.color;}}
             int getColor() {return this.color;}}

class Automobile {
class Automobile {
class Automobile {
  private enum Action {IDLE,IDLE = 0;
  private enum Action {IDLE,
  private static final int
    INCREASE_SPEED,
    INCREASE_SPEED,
  private static final int INCREASE_SPEED = 1;
    DECREASE_SPEED,
    DECREASE_SPEED,
  private static final int DECREASE_SPEED = 2;
    STOP};
    STOP}; static final int STOP = 3;
  private static final int MAX_SPEED = 140;
  private                                                                36
Motivating Example Revisited



class TrafficSignal {{
        TrafficSignal
class TrafficSignal {
  public enum Color {RED, RED = 0;
  public static final int
  public enum Color {RED,
     YELLOW,
  public static final int YELLOW = 1;
     YELLOW,
     GREEN};
  public static final int GREEN = 2;
     GREEN};
  /∗ Current color of the traffic signal, initially red byby default ∗/
  /* Current color of the traffic signal, initially red by default */
  /* Current color of the traffic signal, initially red default */
  private Color color= =RED;
  private Color color = Color.RED;
  private int color                  Color.RED;
  /∗ Accessor for the light’s current color */∗/
  /* Accessor for the light’s current color */
  /* Accessor for the light’s current color
  public Color getColor(){return this.color;}}
  public Color getColor() {return this.color;}}
             int getColor() {return this.color;}}

class Automobile {
class Automobile {
class Automobile {
                Type Safety
  private enum Action {IDLE,IDLE = 0;
  private enum Action {IDLE,
  private static final int
    INCREASE_SPEED,
    INCREASE_SPEED,
  private static final int INCREASE_SPEED = 1;
    DECREASE_SPEED,
    DECREASE_SPEED,
  private static final int DECREASE_SPEED = 2;
    STOP};
    STOP}; static final int STOP = 3;
  private static final int MAX_SPEED = 140;
  private                                                                36
Motivating Example Revisited



class TrafficSignal {{
        TrafficSignal
class TrafficSignal {
  public enum Color {RED, RED = 0;
  public static final int
  public enum Color {RED,
     YELLOW,
  public static final int YELLOW = 1;
     YELLOW,
     GREEN};
  public static final int GREEN = 2;
     GREEN};          Singletons in initially red by default */
  /∗ Current color of the traffic signal, initially red byby default ∗/
  /* Current color of the traffic signal, initially red default */
  /* Current color of the traffic signal,
                        colorOrder
  private ColorNatural = =RED;
  private Color color = Color.RED;
  private int color                  Color.RED;
  /∗ Accessor for the light’s current color */∗/
  /* Accessor for the light’s current color */
  /* Accessor for the light’s current color
  public Color getColor(){return this.color;}}
  public Color getColor() {return this.color;}}
             int getColor() {return this.color;}}

class Automobile {
class Automobile {
class Automobile {
  private enum Action {IDLE,IDLE = 0;
  private enum Action {IDLE,
  private static final int
    INCREASE_SPEED,
    INCREASE_SPEED,
  private static final int INCREASE_SPEED = 1;
    DECREASE_SPEED,
    DECREASE_SPEED,
  private static final int DECREASE_SPEED = 2;
    STOP};
    STOP}; static final int STOP = 3;
  private static final int MAX_SPEED = 140;
  private                                                                36
Motivating Example Revisited



class TrafficSignal {{
        TrafficSignal
class TrafficSignal {
  public enum Color {RED, RED = 0;
  public static final int
  public enum Color {RED,
     YELLOW,
  public static final int YELLOW = 1;
     YELLOW,
     GREEN};
  public static final int GREEN = 2;
     GREEN};
  /∗ Current color of the traffic signal, initially red byby default ∗/
  /* Current color of the traffic signal, initially red by default */
  /* Current color of the traffic signal, initially red default */
  private Color color= =RED;
  private Color color = Color.RED;
  private int color                  Color.RED;
  /∗ Accessor for the light’s current color */∗/
  /* Accessor for the light’s current color */
  /* Accessor for the light’s current color
  public Color getColor(){return Prefixed
  public Color getColor() {return this.color;}}
             int getColor() {return this.color;}}     this.color;}}

class Automobile {
class Automobile {
class Automobile {
  private enum Action {IDLE,IDLE = 0;
  private enum Action {IDLE,
  private static final int
    INCREASE_SPEED,
    INCREASE_SPEED,
  private static final int INCREASE_SPEED = 1;
    DECREASE_SPEED,
    DECREASE_SPEED,
  private static final int DECREASE_SPEED = 2;
    STOP};
    STOP}; static final int STOP = 3;
  private static final int MAX_SPEED = 140;
  private                                                                36
Motivating Example Revisited
                      Supports
                      Separate
                     Compilation
class TrafficSignal {{
        TrafficSignal
class TrafficSignal {
  public enum Color {RED, RED = 0;
  public static final int
  public enum Color {RED,
     YELLOW,
  public static final int YELLOW = 1;
     YELLOW,
     GREEN};
  public static final int GREEN = 2;
     GREEN};
  /∗ Current color of the traffic signal, initially red byby default ∗/
  /* Current color of the traffic signal, initially red by default */
  /* Current color of the traffic signal, initially red default */
  private Color color= =RED;
  private Color color = Color.RED;
  private int color                  Color.RED;
  /∗ Accessor for the light’s current color */∗/
  /* Accessor for the light’s current color */
  /* Accessor for the light’s current color
  public Color getColor(){return this.color;}}
  public Color getColor() {return this.color;}}
             int getColor() {return this.color;}}

class Automobile {
class Automobile {
class Automobile {
  private enum Action {IDLE,IDLE = 0;
  private enum Action {IDLE,
  private static final int
    INCREASE_SPEED,
    INCREASE_SPEED,
  private static final int INCREASE_SPEED = 1;
    DECREASE_SPEED,
    DECREASE_SPEED,
  private static final int DECREASE_SPEED = 2;
    STOP};
    STOP}; static final int STOP = 3;
  private static final int MAX_SPEED = 140;
  private                                                                36
Motivating Example Revisited



class TrafficSignal {{
        TrafficSignal
class TrafficSignal {
  public enum Color {RED, RED = 0;
  public static final int
  public enum Color {RED,
     YELLOW,
  public static final int YELLOW = 1;
     YELLOW,
     GREEN};
  public static final int GREEN = 2;
     GREEN};
  /∗ Current color of the traffic signal, initially red byby default ∗/
  /* Current color of the traffic signal, initially red by default */
  /* Current color of the traffic signal, initially red default */
  private Color color= =RED;
  private Color color = Color.RED;
  private int color                  Color.RED;
  /∗ Accessor for the light’s current color */∗/
  /* Accessor for the light’s current color */
  /* Accessor for the light’s current color
  public Color getColor(){return this.color;}}
  public Color getColor() {return this.color;}}
             int getColor() {return this.color;}}

class Automobile {
class Automobile {
class Automobile {
  private enum Action {IDLE,IDLE = 0;
  private enum Action {IDLE,
  private static final int
    INCREASE_SPEED,
    INCREASE_SPEED,
  private static final int INCREASE_SPEED = 1;
    DECREASE_SPEED,
    DECREASE_SPEED,
  private static final int DECREASE_SPEED = 2;
    STOP};
    STOP}; static final int STOP = 3;
  private static final int MAX_SPEED = 140;
  private                                                                36
this.currentAction &&
    private int color = RED;                        38            (reacti
 INCREASE_SPEED ||automobile is currently performing, idle by default ∗/
    /∗ The action this
    private     for currentAction =
tSpeed <= MAX_SPEED))
                                                  Traffic Signal Client
    /∗ Accessorintthe light’s current color ∗/IDLE; 39             this.c
    public intspeed of the automobile, initially 540
                     getColor() {return this.color;}}                this.
    /∗ The current
rmAction(reaction);}                                 mph. ∗/
                                                  41
       private int currentSpeed = 5;            42       private void
 rmAction(int action) {
    class Automobile {...}}
                                                                 (b) Im
       private int react(TrafficSignal 0;
                    static final int IDLE = signal) {
eger constants for static final int INCREASE_SPEED = 1;
       private enumerated types.
          switch(signal.getColor()) {
       private static final int DECREASE_SPEED = 2;
            case TrafficSignal.RED: return STOP;
Figure 1. Running example: STOP = 3;
       private static final int a hypothetical drive-by-w
            case TrafficSignal.YELLOW:
       private decide whether to stop or go
                // static final int MAX_SPEED = 140;
       /∗ The action (this.shouldGo()) performing, idle by default ∗/
                if this automobile is currently
 ch machinery.int currentAction = IDLE; example, in which
       private return Third, INCREASE_SPEED;
                              the weak enum
       /∗ The to manually enumerate initially 5 mph.language enum
 ogrammercurrent speed of theSTOP; the
                else return automobile,          by ∗/
 ts, whichcaseint currentSpeed = of // no changeAutomobile.
       private TrafficSignal.GREEN:
              increases the likelihood 5;        and
                return this.currentAction;
different enumint react(TrafficSignal signal) of these ne
       private constants may be unin-            ations {
            default: throw new IllegalArgumentException
 he same internal value. Finally, the
                ("Invalid traffic color");}}through compile-tim
          switch(signal.getColor()) {              // required
            case TrafficSignal.RED: return STOP;
rittle public voidthe values {are com-
        [?]:case TrafficSignal.YELLOW:
               since drive()                     between the named
at compile time they are to stop or=go... ; ated values. It is als
          TrafficSignal aSignal into
                // decide whether inlined
  new constants(this.shouldGo())
          int if are added in between
                reaction = this.react(aSignal); Action, whic
                                                 is an                37
this.currentAction &&
    private int color = RED;                        38            (reacti
 INCREASE_SPEED ||automobile is currently performing, idle by default ∗/
    /∗ The action this
    private     for currentAction =
tSpeed <= MAX_SPEED))
                                                  Traffic Signal Client
    /∗ Accessorintthe light’s current color ∗/IDLE; 39             this.c
    public intspeed of the automobile, initially 540
                     getColor() {return this.color;}}                this.
    /∗ The current
rmAction(reaction);}                                 mph. ∗/
                                                  41
       private int currentSpeed = 5;            42       private void
 rmAction(int action) {
    class Automobile {...}}
                                                                 (b) Im
       private int react(TrafficSignal 0;
                    static final int IDLE = signal) {
eger constants for static final int INCREASE_SPEED = 1;
       private enumerated types.
          switch(signal.getColor()) {
       private static final int DECREASE_SPEED = 2;
            case TrafficSignal.RED: return STOP;
Figure 1. Running example: STOP = 3;
       private static final int a hypothetical drive-by-w
            case TrafficSignal.YELLOW:
       private decide whether to stop or go
                // static final int MAX_SPEED = 140;
       /∗ The action (this.shouldGo()) performing, idle by default ∗/
                if this automobile is currently
 ch machinery.int currentAction = IDLE; example, in which
       private return Third, INCREASE_SPEED;
                              the weak enum
       /∗ The to manually enumerate initially 5 mph.language enum
 ogrammercurrent speed of theSTOP; the
                else return automobile,          by ∗/
 ts, whichcaseint currentSpeed = of // no changeAutomobile.
       private TrafficSignal.GREEN:
              increases the likelihood 5;        and
                return this.currentAction;
different enumint react(TrafficSignal signal) of these ne
       private constants may be unin-            ations {
            default: throw new IllegalArgumentException
 he same internal value. Finally, the
                ("Invalid traffic color");}}through compile-tim
          switch(signal.getColor()) {              // required
            case TrafficSignal.RED: return STOP;
rittle public voidthe values {are com-
        [?]:case TrafficSignal.YELLOW:
               since drive()                     between the named
at compile time they are to stop or=go... ; ated values. It is als
          TrafficSignal aSignal into
                // decide whether inlined
  new constants(this.shouldGo())
          int if are added in between
                reaction = this.react(aSignal); Action, whic
                                                 is an                37
this.currentAction &&
    private int color = RED;                        38            (reacti
 INCREASE_SPEED ||automobile is currently performing, idle by default ∗/
    /∗ The action this
    private     for currentAction =
tSpeed <= MAX_SPEED))
                                                  Traffic Signal Client
    /∗ Accessorintthe light’s current color ∗/IDLE; 39             this.c
    public intspeed of the automobile, initially 540
                     getColor() {return this.color;}}                this.
    /∗ The current
rmAction(reaction);}                                 mph. ∗/
                                                  41
       private int currentSpeed = 5;            42       private void
 rmAction(int action) {
    class Automobile {...}}
                                                                 (b) Im
       private int react(TrafficSignal 0;
                    static final int IDLE = signal) {
eger constants for static final int INCREASE_SPEED = 1;
       private enumerated types.
          switch(signal.getColor()) {
       private static final int DECREASE_SPEED = 2;
            case TrafficSignal.RED: return STOP;
Figure 1. Running example: STOP = 3;
       private static final int a hypothetical drive-by-w
            case TrafficSignal.YELLOW:
       private decide whether to stop or go
                // static final int MAX_SPEED = 140;
       /∗ The action (this.shouldGo()) performing, idle by default ∗/
                if this automobile is currently
 ch machinery.int currentAction = IDLE; example, in which
       private return Third, INCREASE_SPEED;
                              the weak enum
       /∗ The to manually enumerate initially 5 mph.language enum
 ogrammercurrent speed of theSTOP; the
                else return automobile,          by ∗/
 ts, whichcaseint currentSpeed = of // no changeAutomobile.
       private TrafficSignal.GREEN:
              increases the likelihood 5;        and
                return this.currentAction;
different enumint react(TrafficSignal signal) of these ne
       private constants may be unin-            ations {
            default: throw new IllegalArgumentException
 he same internal value. Finally, the
                ("Invalid traffic color");}}through compile-tim
          switch(signal.getColor()) {              // required
            case TrafficSignal.RED: return STOP;
rittle public voidthe values {are com-
        [?]:case TrafficSignal.YELLOW:
               since drive()                     between the named
at compile time they are to stop or=go... ; ated values. It is als
          TrafficSignal aSignal into
                // decide whether inlined
  new constants(this.shouldGo())
          int if are added in between
                reaction = this.react(aSignal); Action, whic
                                                 is an                37
this.currentAction &&
    private int color = RED;                        38            (reacti
 INCREASE_SPEED ||automobile is currently performing, idle by default ∗/
    /∗ The action this
    private     for currentAction =
tSpeed <= MAX_SPEED))
                                                  Traffic Signal Client
    /∗ Accessorintthe light’s current color ∗/IDLE; 39             this.c
    public intspeed of the automobile, initially 540
                     getColor() {return this.color;}}                this.
    /∗ The current
rmAction(reaction);}                                 mph. ∗/
                                                  41
       private int currentSpeed = 5;            42       private void
 rmAction(int action) {
    class Automobile {...}}
                                                                 (b) Im
       private int react(TrafficSignal 0;
                    static final int IDLE = signal) {
eger constants for static final int INCREASE_SPEED = 1;
       private enumerated types.
          switch(signal.getColor()) {
       private static final int DECREASE_SPEED = 2;
            case TrafficSignal.RED: return STOP;
Figure 1. Running example: STOP = 3;
       private static final int a hypothetical drive-by-w
            case TrafficSignal.YELLOW:
       private decide whether to stop or go
                // static final int MAX_SPEED = 140;
       /∗ The action (this.shouldGo()) performing, idle by default ∗/
                if this automobile is currently
 ch machinery.int currentAction = IDLE; example, in which
       private return Third, INCREASE_SPEED;
                              the weak enum
       /∗ The to manually enumerate initially 5 mph.language enum
 ogrammercurrent speed of theSTOP; the
                else return automobile,          by ∗/
 ts, whichcaseint currentSpeed = of // no changeAutomobile.
       private TrafficSignal.GREEN:
              increases the likelihood 5;        and
                return this.currentAction;
different enumint react(TrafficSignal signal) of these ne
       private constants may be unin-            ations {
            default: throw new IllegalArgumentException
 he same internal value. Finally, the
                ("Invalid traffic color");}}through compile-tim
          switch(signal.getColor()) {              // required
            case TrafficSignal.RED: return STOP;
rittle public voidthe values {are com-
        [?]:case TrafficSignal.YELLOW:
               since drive()                     between the named
at compile time they are to stop or=go... ; ated values. It is als
          TrafficSignal aSignal into
                // decide whether inlined
  new constants(this.shouldGo())
          int if are added in between
                reaction = this.react(aSignal); Action, whic
                                                 is an                37
this.currentAction &&
    private int color = RED;
                int color = RED;                  38            (reacti
 INCREASE_SPEED ||
    /∗ Accessor for the light’s current color ∗/
       Accessor for the light’s current color ∗/
tSpeed <= MAX_SPEED))
                                                 Traffic Signal Client
                                                  39             this.c
    public int getColor() {return this.color;}}
              int getColor() {return this.color;}}
rmAction(reaction);}
                                                  40  Automobile this.
                                                     41
                                                          Action Enum
                                                     42      private void
rmAction(int action) {
  class Automobile {...}}
         Automobile {                                                 (b) Im
      private static final int IDLE == 0;
                   static final int IDLE               0;
eger constants for static final int INCREASE_SPEED ==1;
                   enumerated types.
      private static final int INCREASE_SPEED
      private                                                          1;
      private static final int DECREASE_SPEED ==2;
      private static final int DECREASE_SPEED                          2;
Figure 1. Running example: STOP == 3;
      private static final int a hypothetical drive-by-w
      private static final int STOP                    3;
      private static final int MAX_SPEED == 140;
      private static final int MAX_SPEED                       140;
      /∗ The action this automobile is currently performing, idle by default ∗/
      /∗ The action Third, the weak enumperforming, idle by default ∗/
                     this automobile is currently
 ch machinery.int currentAction = IDLE; example, in which
      private int currentAction = IDLE;
      private
      /∗ The current speed of the automobile,initially 55by language enum
 ogrammercurrent speed of the automobile,the
      /∗ The   to manually enumerate initially mph. ∗/    mph. ∗/
      private int currentSpeed = 5;
 ts, which increases the likelihood of
      private int currentSpeed = 5;                      and Automobile.
different enumint react(TrafficSignal signal) of these ne
                  constants may be unin-     ations
      private int react(TrafficSignal signal) {{
      private
 he same internal value. Finally, the{
        switch(signal.getColor()) {
        switch(signal.getColor())            through compile-tim
           case TrafficSignal.RED: return STOP;
rittle [?]:case TrafficSignal.YELLOW:
           case TrafficSignal.RED: return STOP; the named
            since the values are com-        between
           case TrafficSignal.YELLOW:
at compile time they are to stop or go
             // decide whether inlined into
             // decide whether to stop or go
                                             ated values. It is als
 new constants(this.shouldGo())
             if are added in between         is an Action, whic            37
this.currentAction &&
    private int color = RED;
                int color = RED;                  38           (reacti
 INCREASE_SPEED ||
    /∗ Accessor for the light’s current color ∗/
       Accessor for the light’s current color ∗/
tSpeed <= MAX_SPEED))
                                                 Traffic Signal Client
                                                  39            this.c
    public int getColor() {return this.color;}}
              int getColor() {return this.color;}}40             this.
rmAction(reaction);}
                                                     41
                                                     42     private void
rmAction(int action) {
  class Automobile {...}}
         Automobile {                                                 (b) Im
      private static final int IDLE == 0;
                   static final int IDLE               0;
eger constants for static final int INCREASE_SPEED ==1;
                   enumerated types.
      private static final int INCREASE_SPEED
      private                                                          1;
      private static final int DECREASE_SPEED ==2;
      private static final int DECREASE_SPEED                          2;
Figure 1. Running example: STOP == 3;
      private static final int a hypothetical drive-by-w
      private static final int STOP                    3;
      private static final int MAX_SPEED == 140;
      private static final int MAX_SPEED                       140;
      /∗ The action this automobile is currently performing, idle by default ∗/
      /∗ The action Third, the weak enumperforming, idle by default ∗/
                     this automobile is currently
 ch machinery.int currentAction = IDLE; example, in which
      private int currentAction = IDLE;
      private
      /∗ The   to manually enumerate initially mph. Named-
      /∗ The current speed of the automobile,initially 55by language enum
 ogrammercurrent speed of the automobile,the                   ∗/
                                                          mph. ∗/
      private int currentSpeed = of
 ts, which increases the likelihood 5;
      private int currentSpeed =               5;             Constant
                                                         and Automobile.
different enumint react(TrafficSignal signal) of these ne
                  constants may be unin-     ations
      private int react(TrafficSignal signal) {{
      private
 he same internal value. Finally, the{
        switch(signal.getColor()) {
        switch(signal.getColor())            through compile-tim
           case TrafficSignal.RED: return STOP;
rittle [?]:case TrafficSignal.YELLOW:
           case TrafficSignal.RED: return STOP; the named
            since the values are com-        between
           case TrafficSignal.YELLOW:
at compile time they are to stop or go
             // decide whether inlined into
             // decide whether to stop or go
                                             ated values. It is als
 new constants(this.shouldGo())
             if are added in between         is an Action, whic            37
this.currentAction &&
    private int color = RED;
                int color = RED;                  38           (reacti
 INCREASE_SPEED ||
    /∗ Accessor for the light’s current color ∗/
       Accessor for the light’s current color ∗/
tSpeed <= MAX_SPEED))
                                                 Traffic Signal Client
                                                  39            this.c
    public int getColor() {return this.color;}}
              int getColor() {return this.color;}}40             this.
rmAction(reaction);}
                                                     41
                                                     42     private void
rmAction(int action) {
  class Automobile {...}}
         Automobile {                                                 (b) Im
      private static final int IDLE == 0;
                   static final int IDLE               0;
eger constants for static final int INCREASE_SPEED ==1;
                   enumerated types.
      private static final int INCREASE_SPEED
      private                                                          1;
      private static final int DECREASE_SPEED ==2;
      private static final int DECREASE_SPEED                          2;
Figure 1. Running example: STOP == 3;
      private static final int a hypothetical drive-by-w
      private static final int STOP                    3;
      private static final int MAX_SPEED == 140;
      private static final int MAX_SPEED            Promising...
                                                               140;
      /∗ The action this automobile is currently performing, idle by default ∗/
      /∗ The action Third, the weak enumperforming, idle by default ∗/
                     this automobile is currently
 ch machinery.int currentAction = IDLE; example, in which
      private int currentAction = IDLE;
      private
      /∗ The current speed of the automobile,initially 55by language enum
 ogrammercurrent speed of the automobile,the
      /∗ The   to manually enumerate initially mph. ∗/    mph. ∗/
      private int currentSpeed = 5;
 ts, which increases the likelihood of
      private int currentSpeed = 5;                      and Automobile.
different enumint react(TrafficSignal signal) of these ne
                  constants may be unin-     ations
      private int react(TrafficSignal signal) {{
      private
 he same internal value. Finally, the{
        switch(signal.getColor()) {
        switch(signal.getColor())            through compile-tim
           case TrafficSignal.RED: return STOP;
rittle [?]:case TrafficSignal.YELLOW:
           case TrafficSignal.RED: return STOP; the named
            since the values are com-        between
           case TrafficSignal.YELLOW:
at compile time they are to stop or go
             // decide whether inlined into
             // decide whether to stop or go
                                             ated values. It is als
 new constants(this.shouldGo())
             if are added in between         is an Action, whic            37
this.currentAction &&
    private int color = RED;
                int color = RED;                  38           (reacti
 INCREASE_SPEED ||
    /∗ Accessor for the light’s current color ∗/
       Accessor for the light’s current color ∗/
tSpeed <= MAX_SPEED))
                                                 Traffic Signal Client
                                                  39            this.c
    public int getColor() {return this.color;}}
              int getColor() {return this.color;}}40             this.
rmAction(reaction);}
                                                     41
                                                     42     private void
rmAction(int action) {
  class Automobile {...}}
         Automobile {                                                 (b) Im
      private static final int IDLE == 0;
                   static final int IDLE               0;
eger constants for static final int INCREASE_SPEED ==1;
                   enumerated types.
      private static final int INCREASE_SPEED
      private                                                          1;
      private static final int DECREASE_SPEED ==2;
      private static final int DECREASE_SPEED                          2;
Figure 1. Running example: STOP == 3;
      private static final int a hypothetical drive-by-w
      private static final int STOP                    3;
      private static final int MAX_SPEED == 140;
      private static final int MAX_SPEED                       140;
      /∗ The action this automobile is currently performing, idle by default ∗/
      /∗ The action Third, the weak enumperforming, idle by default ∗/
                     this automobile is currently
 ch machinery.int currentAction = IDLE; example, in which
      private int currentAction = IDLE;
      private
      /∗ The current speed of the automobile,initially 55by language enum
 ogrammercurrent speed of the automobile,the
      /∗ The   to manually enumerate initially mph. ∗/    mph. ∗/
      private int currentSpeed = 5;
 ts, which increases the likelihood of
      private int currentSpeed = 5;                      and Automobile.
different enumint react(TrafficSignal signal) of these ne
                   constants may be unin-     ations
      private int react(TrafficSignal signal) {{
      private not
        Definitely
 he same internal value. Finally, the{
         switch(signal.getColor()) {
         switch(signal.getColor())            through compile-tim
       enumerizable
           case TrafficSignal.RED: return STOP;
rittle [?]:case TrafficSignal.YELLOW:
           case TrafficSignal.RED: return STOP; the named
            since the values are com-         between
           case TrafficSignal.YELLOW:
at compile time they are to stop or go
              // decide whether inlined into
              // decide whether to stop or go
                                              ated values. It is als
 new constants(this.shouldGo())
              if are added in between         is an Action, whic           37
this.currentAction &&
    private int color = RED;                        38            (reacti
 INCREASE_SPEED ||automobile is currently performing, idle by default ∗/
    /∗ The action this
    private     for currentAction =
tSpeed <= MAX_SPEED))
                                                  Traffic Signal Client
    /∗ Accessorintthe light’s current color ∗/IDLE; 39             this.c
    public intspeed of the automobile, initially 540
                     getColor() {return this.color;}}                this.
    /∗ The current
rmAction(reaction);}                                 mph. ∗/
                                                  41
       private int currentSpeed = 5;            42       private void
 rmAction(int action) {
    class Automobile {...}}
                                                                 (b) Im
       private int react(TrafficSignal 0;
                    static final int IDLE = signal) {
eger constants for static final int INCREASE_SPEED = 1;
       private enumerated types.
          switch(signal.getColor()) {
       private static final int DECREASE_SPEED = 2;
            case TrafficSignal.RED: return STOP;
Figure 1. Running example: STOP = 3;
       private static final int a hypothetical drive-by-w
            case TrafficSignal.YELLOW:
       private decide whether to stop or go
                // static final int MAX_SPEED = 140;
       /∗ The action (this.shouldGo()) performing, idle by default ∗/
                if this automobile is currently
 ch machinery.int currentAction = IDLE; example, in which
       private return Third, INCREASE_SPEED;
                              the weak enum
       /∗ The to manually enumerate initially 5 mph.language enum
 ogrammercurrent speed of theSTOP; the
                else return automobile,          by ∗/
 ts, whichcaseint currentSpeed = of // no changeAutomobile.
       private TrafficSignal.GREEN:
              increases the likelihood 5;        and
                return this.currentAction;
different enumint react(TrafficSignal signal) of these ne
       private constants may be unin-            ations {
            default: throw new IllegalArgumentException
 he same internal value. Finally, the
                ("Invalid traffic color");}}through compile-tim
          switch(signal.getColor()) {              // required
            case TrafficSignal.RED: return STOP;
rittle public voidthe values {are com-
        [?]:case TrafficSignal.YELLOW:
               since drive()                     between the named
at compile time they are to stop or=go... ; ated values. It is als
          TrafficSignal aSignal into
                // decide whether inlined
  new constants(this.shouldGo())
          int if are added in between
                reaction = this.react(aSignal); Action, whic
                                                 is an                37
this.currentAction &&
    private int color = RED;                        38            (reacti
 INCREASE_SPEED ||automobile is currently performing, idle by default ∗/
    /∗ The action this
    private     for currentAction =
tSpeed <= MAX_SPEED))
                                                  Traffic Signal Client
    /∗ Accessorintthe light’s current color ∗/IDLE; 39             this.c
    public intspeed of the automobile, initially 540
                     getColor() {return this.color;}}                this.
    /∗ The current
rmAction(reaction);}                                 mph. ∗/
                                                  41
       private int currentSpeed = 5;            42       private void
 rmAction(int action) {
    class Automobile {...}}
                                                                 (b) Im
       private int react(TrafficSignal 0;
                    static final int IDLE = signal) {
eger constants for static final int INCREASE_SPEED = 1;
       private enumerated types.
          switch(signal.getColor()) {
       private static final int DECREASE_SPEED = 2;
            case TrafficSignal.RED: return STOP;
Figure 1. Running example: STOP = 3;
       private static final int a hypothetical drive-by-w
            case TrafficSignal.YELLOW:
       private decide whether to stop or go
                // static final int MAX_SPEED = 140;
       /∗ The action (this.shouldGo()) performing, idle by default ∗/
                if this automobile is currently
 ch machinery.int currentAction = IDLE; example, in which
       private return Third, INCREASE_SPEED;
                              the weak enum
       /∗ The to manually enumerate initially 5 mph.language enum
 ogrammercurrent speed of theSTOP; the
                else return automobile,          by ∗/
 ts, whichcaseint currentSpeed = of // no changeAutomobile.
       private TrafficSignal.GREEN:
              increases the likelihood 5;        and
                return this.currentAction;
different enumint react(TrafficSignal signal) of these ne
       private constants may be unin-            ations {
            default: throw new IllegalArgumentException
 he same internal value. Finally, the
                ("Invalid traffic color");}}through compile-tim
          switch(signal.getColor()) {              // required
            case TrafficSignal.RED: return STOP;
rittle public voidthe values {are com-
        [?]:case TrafficSignal.YELLOW:
               since drive()                     between the named
at compile time they are to stop or=go... ; ated values. It is als
          TrafficSignal aSignal into
                // decide whether inlined
  new constants(this.shouldGo())
          int if are added in between
                reaction = this.react(aSignal); Action, whic
                                                 is an                37
this.currentAction &&
    private int color = RED;                        38            (reacti
 INCREASE_SPEED ||automobile is currently performing, idle by default ∗/
    /∗ The action this
    private     for currentAction =
tSpeed <= MAX_SPEED))
                                                  Traffic Signal Client
    /∗ Accessorintthe light’s current color ∗/IDLE; 39             this.c
    public intspeed of the automobile, initially 540
                     getColor() {return this.color;}}                this.
    /∗ The current
rmAction(reaction);}                                 mph. ∗/
                                                  41
       private int currentSpeed = 5;            42       private void
 rmAction(int action) {
    class Automobile {...}}
                                                                 (b) Im
       private int react(TrafficSignal 0;
                    static final int IDLE = signal) {
eger constants for static final int INCREASE_SPEED = 1;
       private enumerated types.
          switch(signal.getColor()) {
       private static final int DECREASE_SPEED = 2;
            case TrafficSignal.RED: return STOP;
Figure 1. Running example: STOP = 3;
       private static final int a hypothetical drive-by-w
            case TrafficSignal.YELLOW:
       private decide whether to stop or go
                // static final int MAX_SPEED = 140;
       /∗ The action (this.shouldGo()) performing, idle by default ∗/
                if this automobile is currently
 ch machinery.int currentAction = IDLE; example, in which
       private return Third, INCREASE_SPEED;
                              the weak enum
       /∗ The to manually enumerate initially 5 mph.language enum
 ogrammercurrent speed of theSTOP; the
                else return automobile,          by ∗/
 ts, whichcaseint currentSpeed = of // no changeAutomobile.
       private TrafficSignal.GREEN:
              increases the likelihood 5;        and
                return this.currentAction;
different enumint react(TrafficSignal signal) of these ne
       private constants may be unin-            ations {
            default: throw new IllegalArgumentException
 he same internal value. Finally, the
                ("Invalid traffic color");}}through compile-tim
          switch(signal.getColor()) {              // required
            case TrafficSignal.RED: return STOP;
rittle public voidthe values {are com-
        [?]:case TrafficSignal.YELLOW:
               since drive()                     between the named
at compile time they are to stop or=go... ; ated values. It is als
          TrafficSignal aSignal into
                // decide whether inlined
  new constants(this.shouldGo())
          int if are added in between
                reaction = this.react(aSignal); Action, whic
                                                 is an                37
this.currentAction &&
    /∗ The action this color = RED;               38              (reacti
    private int automobile is currently performing, idle by default */
     /*                                               idle by default ∗/
 INCREASE_SPEED ||
    /∗ Accessor Action currentAction = Action.IDLE; Client
                                                Traffic Signal this.c
    private intthe light’s current color ∗/IDLE; 39
                for currentAction =
tSpeed <= MAX_SPEED))
    public intspeed of the automobile, initially 540
                     getColor() {return this.color;}}                this.
    /∗ The current
     /*
rmAction(reaction);}                               mph. */
                                                        ∗/
                                                  41
       private int currentSpeed = 5;            42       private void
 rmAction(int action) {
    class Automobile {...}}
                                                                 (b) Im
       private int react(TrafficSignal 0; signal) {
                    static final int IDLE = signal) {
                    Action react(TrafficSignal
eger constants for static final int INCREASE_SPEED = 1;
       private enumerated types.
          switch(signal.getColor()) {
       private static final int DECREASE_SPEED = 2;
            case TrafficSignal.RED: return Action.STOP;
                                                   STOP;
Figure 1. Running example: STOP = 3;
       private static final int a hypothetical drive-by-w
            case TrafficSignal.YELLOW:
       private decide whether to stop or go
                // static final int MAX_SPEED = 140;
       /∗ The action (this.shouldGo()) performing, idle by default ∗/
                if this automobile is currently
 ch machinery.int currentAction = IDLE; example, in which
                      Third, INCREASE_SPEED;
                              the weak enum
       private return Action.INCREASE_SPEED;
       /∗ The to manually enumerate initially 5 mph.language enum
 ogrammercurrent speed of theSTOP; the
                                  automobile,
                else return Action.STOP;         by ∗/
 ts, whichcaseint currentSpeed = of // no changeAutomobile.
       private TrafficSignal.GREEN:
              increases the likelihood 5;        and
                return this.currentAction;
different enumint react(TrafficSignal signal) of these ne
       private constants may be unin-            ations {
            default: throw new IllegalArgumentException
 he same internal value. Finally, the
                ("Invalid traffic color");}}through compile-tim
          switch(signal.getColor()) {              // required
            case TrafficSignal.RED: return STOP;
rittle public voidthe values {are com-
        [?]:case TrafficSignal.YELLOW:
               since drive()                     between the named
at compile time they are to stop or=go... ; ated values. It is als
          TrafficSignal aSignal into
                // decide whether inlined
  new constants(this.shouldGo())
          int if reactionthis.react(aSignal); Action, whic
          Action are added in between
                reaction = = this.react(aSignal);is an                38
this.currentAction &&
    /∗ The action this color = RED;               38              (reacti
    private int automobile is currently performing, idle by default */
     /*                                               idle by default ∗/
 INCREASE_SPEED ||
    /∗ Accessor Action currentAction = Action.IDLE; Client
                                                Traffic Signal this.c
    private intthe light’s current color ∗/IDLE; 39
                for currentAction =
tSpeed <= MAX_SPEED))
    public intspeed of the automobile, initially 540
                     getColor() {return this.color;}}                this.
    /∗ The current
     /*
rmAction(reaction);}                               mph. */
                                                        ∗/
                                                  41
       private int currentSpeed = 5;            42       private void
 rmAction(int action) {
    class Automobile {...}}
                                                                 (b) Im
       private int react(TrafficSignal 0; signal) {
                    static final int IDLE = signal) {
                    Action react(TrafficSignal
eger constants for static final int INCREASE_SPEED = 1;
       private enumerated types.
          switch(signal.getColor()) {
       private static final int DECREASE_SPEED = 2;
            case TrafficSignal.RED: return Action.STOP;
                                                   STOP;
Figure 1. Running example: STOP = 3;
       private static final int a hypothetical drive-by-w
            case TrafficSignal.YELLOW:
       private decide whether to stop or go
                // static final int MAX_SPEED = 140;
       /∗ The action (this.shouldGo()) performing, idle by default ∗/
                if this automobile is currently
 ch machinery.int currentAction = IDLE; example, in which
                      Third, INCREASE_SPEED;
                              the weak enum
       private return Action.INCREASE_SPEED;
       /∗ The to manually enumerate initially 5 mph.language enum
 ogrammercurrent speed of theSTOP; the
                                  automobile,
                else return Action.STOP;         by ∗/
 ts, whichcaseint currentSpeed = of // no changeAutomobile.
       private TrafficSignal.GREEN:
              increases the likelihood 5;        and
                return this.currentAction;
different enumint react(TrafficSignal signal) of these ne
       private constants may be unin-            ations {
            default: throw new IllegalArgumentException
 he same internal value. Finally, the
                ("Invalid traffic color");}}through compile-tim
          switch(signal.getColor()) {              // required
            case TrafficSignal.RED: return STOP;
rittle public voidthe values {are com-
        [?]:case TrafficSignal.YELLOW:
               since drive()                     between the named
at compile time they are to stop or=go... ; ated values. It is als
          TrafficSignal aSignal into
                // decide whether inlined
  new constants(this.shouldGo())
          int if reactionthis.react(aSignal); Action, whic
          Action are added in between
                reaction = = this.react(aSignal);is an                38
this.currentAction &&
    /∗ The action this color = RED;               38              (reacti
    private int automobile is currently performing, idle by default */
     /*                                               idle by default ∗/
 INCREASE_SPEED ||
    /∗ Accessor Action currentAction = Action.IDLE; Client
                                                Traffic Signal this.c
    private intthe light’s current color ∗/IDLE; 39
                for currentAction =
tSpeed <= MAX_SPEED))
    public intspeed of the automobile, initially 540
                     getColor() {return this.color;}}                this.
    /∗ The current
     /*
rmAction(reaction);}                               mph. */
                                                        ∗/
                                                  41
       private int currentSpeed = 5;            42       private void
 rmAction(int action) {
    class Automobile {...}}
                                                                 (b) Im
       private int react(TrafficSignal 0; signal) {
                    static final int IDLE = signal) {
                    Action react(TrafficSignal
eger constants for static final int INCREASE_SPEED = 1;
       private enumerated types.
          switch(signal.getColor()) {
       private static final int DECREASE_SPEED = 2;
            case TrafficSignal.RED: return Action.STOP;
                                                   STOP;
Figure 1. Running example: STOP = 3;
       private static final int a hypothetical drive-by-w
            case TrafficSignal.YELLOW:
       private decide whether to stop or go
                // static final int MAX_SPEED = 140;
       /∗ The action (this.shouldGo()) performing, idle by default ∗/
                if this automobile is currently
 ch machinery.int currentAction = IDLE; example, in which
                      Third, INCREASE_SPEED;
                              the weak enum
       private return Action.INCREASE_SPEED;
       /∗ The to manually enumerate initially 5 mph.language enum
 ogrammercurrent speed of theSTOP; the
                                  automobile,
                else return Action.STOP;         by ∗/
 ts, whichcaseint currentSpeed = of // no changeAutomobile.
       private TrafficSignal.GREEN:
              increases the likelihood 5;        and
                return this.currentAction;
different enumint react(TrafficSignal signal) of these ne
       private constants may be unin-            ations {
            default: throw new IllegalArgumentException
 he same internal value. Finally, the
                ("Invalid traffic color");}}through compile-tim
          switch(signal.getColor()) {              // required
            case TrafficSignal.RED: return STOP;
rittle public voidthe values {are com-
        [?]:case TrafficSignal.YELLOW:
               since drive()                     between the named
at compile time they are to stop or=go... ; ated values. It is als
          TrafficSignal aSignal into
                // decide whether inlined
  new constants(this.shouldGo())
          int if reactionthis.react(aSignal); Action, whic
          Action are added in between
                reaction = = this.react(aSignal);is an                38
this.currentAction &&
    /∗ The action this color = RED;               38              (reacti
    private int automobile is currently performing, idle by default */
     /*                                               idle by default ∗/
 INCREASE_SPEED ||
    /∗ Accessor Action currentAction = Action.IDLE; Client
                                                Traffic Signal this.c
    private intthe light’s current color ∗/IDLE; 39
                for currentAction =
tSpeed <= MAX_SPEED))
    public intspeed of the automobile, initially 540
                     getColor() {return this.color;}}                this.
    /∗ The current
     /*
rmAction(reaction);}                               mph. */
                                                        ∗/
                                                  41
       private int currentSpeed = 5;            42       private void
 rmAction(int action) {
    class Automobile {...}}
                                                                 (b) Im
       private int react(TrafficSignal 0; signal) {
                    static final int IDLE = signal) {
                    Action react(TrafficSignal
eger constants for static final int INCREASE_SPEED = 1;
       private enumerated types.
          switch(signal.getColor()) {
       private static final int DECREASE_SPEED = 2;
            case TrafficSignal.RED: return Action.STOP;
                                                   STOP;
Figure 1. Running example: STOP = 3;
       private static final int a hypothetical drive-by-w
            case TrafficSignal.YELLOW:
       private decide whether to stop or go
                // static final int MAX_SPEED = 140;
       /∗ The action (this.shouldGo()) performing, idle by default ∗/
                if this automobile is currently
 ch machinery.int currentAction = IDLE; example, in which
                      Third, INCREASE_SPEED;
                              the weak enum
       private return Action.INCREASE_SPEED;
       /∗ The to manually enumerate initially 5 mph.language enum
 ogrammercurrent speed of theSTOP; the
                                  automobile,
                else return Action.STOP;         by ∗/
 ts, whichcaseint currentSpeed = of // no changeAutomobile.
       private TrafficSignal.GREEN:
              increases the likelihood 5;        and
                return this.currentAction;
different enumint react(TrafficSignal signal) of these ne
       private constants may be unin-            ations {
            default: throw new IllegalArgumentException
 he same internal value. Finally, the
                ("Invalid traffic color");}}through compile-tim
          switch(signal.getColor()) {              // required
            case TrafficSignal.RED: return STOP;
rittle public voidthe values {are com-
        [?]:case TrafficSignal.YELLOW:
               since drive()                     between the named
at compile time they are to stop or=go... ; ated values. It is als
          TrafficSignal aSignal into
                // decide whether inlined
  new constants(this.shouldGo())
          int if reactionthis.react(aSignal); Action, whic
          Action are added in between
                reaction = = this.react(aSignal);is an                38
this.currentAction &&
    /∗ The action this color = RED;               38              (reacti
    private int automobile is currently performing, idle by default */
     /*                                               idle by default ∗/
 INCREASE_SPEED ||
    /∗ Accessor Action currentAction = Action.IDLE; Client
                                                Traffic Signal this.c
    private intthe light’s current color ∗/IDLE; 39
                for currentAction =
tSpeed <= MAX_SPEED))
    public intspeed of the automobile, initially 540
                     getColor() {return this.color;}}                this.
    /∗ The current
     /*
rmAction(reaction);}                               mph. */
                                                        ∗/
                                                  41
       private int currentSpeed = 5;            42       private void
 rmAction(int action) {
    class Automobile {...}}
                                                                 (b) Im
       private int react(TrafficSignal 0; signal) {
                    static final int IDLE = signal) {
                    Action react(TrafficSignal
eger constants for static final int INCREASE_SPEED = 1;
       private enumerated types.
          switch(signal.getColor()) {
       private static final int DECREASE_SPEED = 2;
            case TrafficSignal.RED: return Action.STOP;
                                                   STOP;
Figure 1. Running example: STOP = 3;
       private static final int a hypothetical drive-by-w
            case TrafficSignal.YELLOW:
       private decide whether to stop or go
                // static final int MAX_SPEED = 140;
       /∗ The action (this.shouldGo()) performing, idle by default ∗/
                if this automobile is currently
 ch machinery.int currentAction = IDLE; example, in which
                      Third, INCREASE_SPEED;
                              the weak enum
       private return Action.INCREASE_SPEED;
       /∗ The to manually enumerate initially 5 mph.language enum
 ogrammercurrent speed of theSTOP; the
                                  automobile,
                else return Action.STOP;         by ∗/
 ts, whichcaseint currentSpeed = of // no changeAutomobile.
       private TrafficSignal.GREEN:
              increases the likelihood 5;        and
                return this.currentAction;
different enumint react(TrafficSignal signal) of these ne
       private constants may be unin-            ations {
            default: throw new IllegalArgumentException
 he same internal value. Finally, the
                ("Invalid traffic color");}}through compile-tim
          switch(signal.getColor()) {              // required
            case TrafficSignal.RED: return STOP;
rittle public voidthe values {are com-
        [?]:case TrafficSignal.YELLOW:
               since drive()                     between the named
at compile time they are to stop or=go... ; ated values. It is als
          TrafficSignal aSignal into
                // decide whether inlined
  new constants(this.shouldGo())
          int if reactionthis.react(aSignal); Action, whic
          Action are added in between
                reaction = = this.react(aSignal);is an                38
My Approach to Refactoring to Enums




                                 39
My Approach to Refactoring to Enums



• Developed a semantics preserving, declarative
 type inferencing algorithm that migrates legacy Java
 code to use enums.




                                                        39
My Approach to Refactoring to Enums



• Developed a semantics preserving, declarative
 type inferencing algorithm that migrates legacy Java
 code to use enums.
• Algorithm:



                                                        39
My Approach to Refactoring to Enums



• Developed a semantics preserving, declarative
  type inferencing algorithm that migrates legacy Java
  code to use enums.
• Algorithm:
 • Infers fields that are possibly being used to
   simulate enumerated types.




                                                         39
My Approach to Refactoring to Enums



• Developed a semantics preserving, declarative
  type inferencing algorithm that migrates legacy Java
  code to use enums.
• Algorithm:
 • Infers fields that are possibly being used to
   simulate enumerated types.
 • Identifies all code changes required to introduce
   the inferred enum type.

                                                         39
Contributions




           40
Contributions

• Developed an open source Eclipse IDE plug-in called CONVERT
  CONSTANTS TO ENUM that:
 • Automatically refactors code to use enums.
 • Provides a developer-friendly graphical user interface with
   preview pane, constant selection, etc.
 • Proposed as a Google Summer of Code (GSoC) project in
   2009 and 2010.
 • In progress to be included with the standard distribution of
   Eclipse, proposed by IBM.




                                                                  40
Contributions

• Developed an open source Eclipse IDE plug-in called CONVERT
  CONSTANTS TO ENUM that:
 • Automatically refactors code to use enums.
 • Provides a developer-friendly graphical user interface with
    preview pane, constant selection, etc.
 • Proposed as a Google Summer of Code (GSoC) project in
    2009 and 2010.
 • In progress to be included with the standard distribution of
    Eclipse, proposed by IBM.
• Evaluated plug-in on 17 open source applications:
 • Analysis and transformation costs are practical.
 • Enum-absence compensation patterns are widely used.
 • Large percentage of fields can be automatically refactored.    40
α        '%2"%,&)/ !)&-/ 1)!0#-
  αctxt    30"+$5+ "$ 40"+0 α 1%. Enumerization Approach
                                  #++(2
              !"#$%& '( !)%*+,"-* .)/+/").(
function Enumerizable(C)P)
 .',/&4$'& Enumerize(F,
        R ← Enumerizable(F )
  1: >AW ← C /* seed the worklist with the input constants */

  2: QAN ← ∅ /* the non-enumerizable set ∩ Consistent(R) */
        R ← U nique(R) ∩ Distinct(R) list, initially empty
  3: GAfor all c T ∈ R 4,
        5,' *22 ∈ C do
          T ransf orm(T )
  4: RA MakeSet(c) /* init the union-find data structure */
     ?A &#4 5,'
  5: end for

  6: while W = ∅ do
        !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*(
  7:    /* remove an element from the worklist */
        α ← e | ∈ %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+%
 2)9%+!#2"$37 eM)W
  8:

        W ← W  {α}
 "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. -
  9:

 6)$-)$! 62#32%1 Contexts(α, P) do
 10:    for all αctxt ∈ )$!"!")*7 O0"* %**(16!"#$ +#(&- ,) "$'%
 11:        ¬isEnumerizableContext (α, αctxt ) then
 -%!)-if!02#(30 !0) (*) #9 2)")+!"#$ %$- +(*!#1 +&%** &#%-)41
α        '%2"%,&)/ !)&-/ 1)!0#-
  αctxt    30"+$5+ "$ 40"+0 α 1%. Enumerization Approach
                                  #++(2
              !"#$%& '( !)%*+,"-* .)/+/").(
         Subset of static
function Enumerizable(C)P)
 .',/&4$'& Enumerize(F,
            final fields
        R ← Enumerizable(F )
  1: >AW ← C /* seed the worklist with the input constants */

  2: QAN ← ∅ /* the non-enumerizable set ∩ Consistent(R) */
        R ← U nique(R) ∩ Distinct(R) list, initially empty
  3: GAfor all c T ∈ R 4,
        5,' *22 ∈ C do
          T ransf orm(T )
  4: RA MakeSet(c) /* init the union-find data structure */
     ?A &#4 5,'
  5: end for

 6:  while W = ∅ do
      !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*(
  7:  /* remove an element from the worklist */
      α ← e | ∈ %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+%
 2)9%+!#2"$37 eM)W
  8:

      W ← W  {α}
 "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. -
  9:

 6)$-)$! 62#32%1 Contexts(α, P) do
 10:  for all αctxt ∈ )$!"!")*7 O0"* %**(16!"#$ +#(&- ,) "$'%
 11:      ¬isEnumerizableContext (α, αctxt ) then
 -%!)-if!02#(30 !0) (*) #9 2)")+!"#$ %$- +(*!#1 +&%** &#%-)41
α        '%2"%,&)/ !)&-/ 1)!0#-
  αctxt    30"+$5+ "$ 40"+0 α 1%. Enumerization Approach
                                  #++(2
              !"#$%& '( !)%*+,"-* .)/+/").(
function Enumerizable(C)P) Abstract Syntax Tree (AST)
 .',/&4$'& Enumerize(F,
        R ← Enumerizable(F )
  1: >AW ← C /* seed the worklist with the input constants */

  2: QAN ← ∅ /* the non-enumerizable set ∩ Consistent(R) */
        R ← U nique(R) ∩ Distinct(R) list, initially empty
  3: GAfor all c T ∈ R 4,
        5,' *22 ∈ C do
          T ransf orm(T )
  4: RA MakeSet(c) /* init the union-find data structure */
     ?A &#4 5,'
  5: end for

  6: while W = ∅ do
        !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*(
  7:    /* remove an element from the worklist */
        α ← e | ∈ %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+%
 2)9%+!#2"$37 eM)W
  8:

        W ← W  {α}
 "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. -
  9:

 6)$-)$! 62#32%1 Contexts(α, P) do
 10:    for all αctxt ∈ )$!"!")*7 O0"* %**(16!"#$ +#(&- ,) "$'%
 11:        ¬isEnumerizableContext (α, αctxt ) then
 -%!)-if!02#(30 !0) (*) #9 2)")+!"#$ %$- +(*!#1 +&%** &#%-)41
α        '%2"%,&)/ !)&-/ 1)!0#-
  αctxt    30"+$5+ "$ 40"+0 α 1%. Enumerization Approach
                                  #++(2
              !"#$%& '( !)%*+,"-* .)/+/").(
function Enumerizable(C)P)
 .',/&4$'& Enumerize(F,
 Output: C /* seed the worklist with the input constants */
        R←
  1: >AW ← Enumerizable(F )

  2: QAN ← ∅ /* the non-enumerizable set ∩ Consistent(R) */
        R ← U nique(R) ∩ Distinct(R) list, initially empty
  3: GAfor all c T ∈ R 4,
        5,' *22 ∈ C do
          T ransf orm(T )
  4: RA MakeSet(c) /* init the union-find data structure */
     ?A &#4 5,'
  5: end for

  6: while W = ∅ do
        !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*(
  7:    /* remove an element from the worklist */
        α ← e | ∈ %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+%
 2)9%+!#2"$37 eM)W
  8:

        W ← W  {α}
 "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. -
  9:

 6)$-)$! 62#32%1 Contexts(α, P) do
 10:    for all αctxt ∈ )$!"!")*7 O0"* %**(16!"#$ +#(&- ,) "$'%
 11:        ¬isEnumerizableContext (α, αctxt ) then
 -%!)-if!02#(30 !0) (*) #9 2)")+!"#$ %$- +(*!#1 +&%** &#%-)41
α        '%2"%,&)/ !)&-/ 1)!0#-
  αctxt    30"+$5+ "$ 40"+0 α 1%. Enumerization Approach
                                  #++(2
              !"#$%& '( !)%*+,"-* .)/+/").(
function Enumerizable(C)P)
 .',/&4$'& Enumerize(F,
 Output: C /* seed the worklist with the input constants */
        R←
  1: >AW ← Enumerizable(F )

 •2: QAN ← ∅U nique(R) ∩ Distinct(R) ∩ Consistent(R) */
     Partitioning of program entities: list, initially empty
        R ← /* the non-enumerizable set
  3: GAfor all c T ∈ R 4,
        5,' *22 ∈ C do
    • Fields
          T ransf orm(T )
  4: RA MakeSet(c) /* init the union-find data structure */

  5:
    • end for declarations (return types)
     ?A Method
        &#4 5,'
  6:• while W = ∅ do (including formal parameters)
        Local variables
        !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*(
  7:    /* remove an element from the worklist */
        α ← e | ∈ %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+%
 2)9%+!#2"$37 eM)W
  8:

        W ← W  {α}
 "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. -
  9:

 6)$-)$! 62#32%1 Contexts(α, P) do
 10:    for all αctxt ∈ )$!"!")*7 O0"* %**(16!"#$ +#(&- ,) "$'%
 11:        ¬isEnumerizableContext (α, αctxt ) then
 -%!)-if!02#(30 !0) (*) #9 2)")+!"#$ %$- +(*!#1 +&%** &#%-)41
α        '%2"%,&)/ !)&-/ 1)!0#-
  αctxt    30"+$5+ "$ 40"+0 α 1%. Enumerization Approach
                                  #++(2
              !"#$%& '( !)%*+,"-* .)/+/").(
function Enumerizable(C)P)
 .',/&4$'& Enumerize(F,
 Output: C /* seed the worklist with the input constants */
        R←
  1: >AW ← Enumerizable(F )

 •2: QAN ← ∅U nique(R) ∩ Distinct(R) ∩ Consistent(R) */
     Partitioning of program entities: list, initially empty
        R ← /* the non-enumerizable set
  3: GAfor all c T ∈ R 4,
        5,' *22 ∈ C do
    • Fields
          T ransf orm(T )
  4: RA MakeSet(c) /* init the union-find data structure */

  5:
    • end for declarations (return types)
     ?A Method
        &#4 5,'
  6:• while W = ∅ do (including formal parameters)
        Local variables
        !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*(
        /* remove an element from the worklist */
 • Each partition contains elements that:
  7:

        α ← e | ∈ %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+%
 2)9%+!#2"$37 eM)W
  8:
    • Transitively type-dependent upon one another
        W ← W  {α}
 "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. -
  9:

 10:• Are all αctxt ∈ Contexts(α, P) do
 6)$-)$!safe for enum type transformation +#(&- ,) "$'%
        for 62#32%1 )$!"!")*7 O0"* %**(16!"#$
 11:        ¬isEnumerizableContext (α, αctxt ) then
 -%!)-if!02#(30 !0) (*) #9 2)")+!"#$ %$- +(*!#1 +&%** &#%-)
                                                          41
42
DECREASE_SPEED    IDLE             STOP




                         INCREASE_SPEED

  GREEN
                 RED



   YELLOW                  MAX_SPEED




                                          42
DECREASE_SPEED                  IDLE                           STOP




                                                   INCREASE_SPEED

  GREEN
                            RED




      class
  1 YELLOW      TrafficSignal {                          MAX_SPEED
  2       public enum Color {RED,
  3          YELLOW,
  4          GREEN};
  5       /* Current color of the traffic signal, initially red by default */
  6       private Color color = Color.RED;
  7       /* Accessor for the light’s current color */
  8       public Color getColor() {return this.color;
  9
                                                                       42
 10   class Automobile {
DECREASE_SPEED                  IDLE                           STOP




                                                   INCREASE_SPEED

  GREEN
                            RED

                            color
      class
  1 YELLOW      TrafficSignal {                          MAX_SPEED
  2       public enum Color {RED,
  3          YELLOW,
  4          GREEN};
  5       /* Current color of the traffic signal, initially red by default */
  6       private Color color = Color.RED;
  7       /* Accessor for the light’s current color */
  8       public Color getColor() {return this.color;
  9
                                                                       42
 10   class Automobile {
DECREASE_SPEED                 IDLE                          STOP




                                                      INCREASE_SPEED

      GREEN
                                RED

1   class TrafficSignal color     {
2     public enum Color {RED,
3        YELLOW,
        YELLOW                                               MAX_SPEED
4        GREEN};
5     /* Current color of the traffic signal, initially red by default */
6     private Color color = Color.RED;
7     /* Accessor for the light’s current color */
8     public Color getColor() {return this.color;}}
9
0   class Automobile {
1     private enum Action {IDLE,
                                                                           42
2       INCREASE_SPEED,
DECREASE_SPEED                 IDLE                          STOP




                                                      INCREASE_SPEED

      GREEN
                                RED

1   class TrafficSignal color      {
2     public enum Color {RED,
3        YELLOW,
        YELLOW                                               MAX_SPEED
                                 getColor
4        GREEN};
5     /* Current color of the traffic signal, initially red by default */
6     private Color color = Color.RED;
7     /* Accessor for the light’s current color */
8     public Color getColor() {return this.color;}}
9
0   class Automobile {
1     private enum Action {IDLE,
                                                                           42
2       INCREASE_SPEED,
78     private int the light’s current color ∗/
         /∗ Accessor for color = RED;
89     /∗ Accessorintthe light’s current {return this.color;}}
         public for getColor() color ∗/
                                 IDLE                            STOP
DECREASE_SPEED
 910   public int getColor() {return this.color;}}
1011  class Automobile {
1112 class Automobile {final int IDLE = 0;
         private static
1213   private static final int IDLE INCREASE_SPEED= 1;
         private static final int INCREASE_SPEED     = 0;
1314   private static final int INCREASE_SPEED ==1;
    GREENprivate static final int DECREASE_SPEED                        2;
1415   private static RED
         private staticfinal int DECREASE_SPEED = 2;
                                final int STOP = 3;
1516   private static final int STOP = 3; = 140;
         private static final int MAX_SPEED
1617   private static final int MAX_SPEED = 140; defa
         /∗ The action this automobile is currently performing, idle by
1718     private
                              color
       /∗ The action int automobile is currently performing, idle by defaul
                       this currentAction = IDLE;
1819   private intspeed of the automobile, initially 5 mph. ∗/
         /∗ The current currentAction = IDLE;
     YELLOW                                             MAX_SPEED
1920   /∗ The current speedgetColor
         private int currentSpeed =initially 5 mph. ∗/
                             of the automobile, 5;
2021   private int currentSpeed = 5;
2122     private int react(TrafficSignal signal) {
2223   private int react(TrafficSignal signal) {
            switch(signal.getColor()) {
2324       switch(signal.getColor()) {return STOP;
              case TrafficSignal.RED:
2425         case TrafficSignal.RED: return STOP;
              case TrafficSignal.YELLOW:
2526         case decide whether to stop or go
                   // TrafficSignal.YELLOW:
2627            // if (this.shouldGo())
                    decide whether to stop or go
2728            if (this.shouldGo())
                      return INCREASE_SPEED;                            42
78     private int the light’s current color ∗/
         /∗ Accessor for color = RED;
89     /∗ Accessorintthe light’s current {return this.color;}}
         public for getColor() color ∗/
                                  IDLE                           STOP
DECREASE_SPEED
 910   public int getColor() {return this.color;}}
1011  class Automobile {
1112 class Automobile {final int IDLE = 0;
         private static
1213   private static final int IDLE INCREASE_SPEED= 1;
         private static final int INCREASE_SPEED
                             YELLOW                  = 0;
1314   private static final int INCREASE_SPEED ==1;
    GREENprivate static final int DECREASE_SPEED                        2;
1415   private static RED
         private staticfinal int DECREASE_SPEED = 2;
                                 final int STOP = 3;
1516   private static final int STOP = 3; = 140;
         private static final int MAX_SPEED
1617   private static final int MAX_SPEED = 140; defa
         /∗ The action this automobile is currently performing, idle by
1718     private
                              color
       /∗ The action int automobile is currently performing, idle by defaul
                       this currentAction = IDLE;
1819   private intspeed of the automobile, initially 5 mph. ∗/
         /∗ The current currentAction = IDLE;           MAX_SPEED
1920   /∗ The current speedgetColor
         private int currentSpeed =initially 5 mph. ∗/
                              of the automobile, 5;
2021   private int currentSpeed = 5;
2122     private int react(TrafficSignal signal) {
2223   private int react(TrafficSignal signal) {
            switch(signal.getColor()) {
2324       switch(signal.getColor()) {return STOP;
              case TrafficSignal.RED:
2425         case TrafficSignal.RED: return STOP;
              case TrafficSignal.YELLOW:
2526         case decide whether to stop or go
                   // TrafficSignal.YELLOW:
2627            // if (this.shouldGo())
                    decide whether to stop or go
2728            if (this.shouldGo())
                      return INCREASE_SPEED;                            42
7    13private int static = RED; int INCREASE_SPEED =
            private color final
 8  14 /∗ Accessor for the light’s current color ∗/ DECREASE_SPEED =
            private static final int
                                 IDLE                            STOP
DECREASE_SPEED
 9  15 public int getColor() {return this.color;}}
            private static final int STOP = 3;
10  16      private static final int MAX_SPEED = 140;
11  class /∗ The action this automobile is currently performing, idle by d
    17       Automobile {
12  18 private static final int IDLE = IDLE;
            private int currentAction INCREASE_SPEED
                            YELLOW                    = 0;
13  19 private static final int INCREASE_SPEED = ∗/
   GREEN    /∗ The current speed of the automobile, initially 5 mph. 1;
14  20 private static RED
            private int final int DECREASE_SPEED = 2;
                               currentSpeed = 5;
15  21 private static final int STOP = 3;
16  22 private static final int MAX_SPEED = 140;
            private int react(TrafficSignal signal) {
17  23
                             color
       /∗ The action this automobile is currently performing, idle by defaul
               switch(signal.getColor()) {
18  24 private case currentAction = IDLE;
                    int TrafficSignal.RED: return STOP;  MAX_SPEED
19  25 /∗ The current speedgetColor
                   case TrafficSignal.YELLOW: mph. ∗/
                             of the automobile, initially 5
20  26 private intdecide whether to stop or go
                      // currentSpeed = 5;
21  27                if (this.shouldGo())
22  28 private int return INCREASE_SPEED;
                          react(TrafficSignal signal) {
23  29    switch(signal.getColor()) {
                      else return STOP;
24  30       case TrafficSignal.RED: return no change
                   case TrafficSignal.GREEN: // STOP;
25  31       case TrafficSignal.YELLOW:
                      return this.currentAction;
26  32          // decide whether to stop new IllegalArgumentExce
                   default: throw or go
27  33          if (this.shouldGo()) color");}} // required
                      ("Invalid traffic                                 42
7    13private int static = RED; int INCREASE_SPEED =
            private color final
 8  14 /∗ Accessor for the light’s current color ∗/ DECREASE_SPEED =
            private static final int
                                 IDLE                            STOP
DECREASE_SPEED
 9  15 public int getColor() {return this.color;}}
            private static final int STOP = 3;
10  16      private static final int MAX_SPEED = 140;
11  class /∗ The action this automobile is currently performing, idle by d
    17       Automobile {
12  18 private static final int IDLE = IDLE;
            private int currentAction INCREASE_SPEED
                            YELLOW                    = 0;
13  19 private static final int INCREASE_SPEED = ∗/
            /∗ The current speed of the automobile, initially 5 mph. 1;
14  20 private static RED
            private int final int DECREASE_SPEED = 2;
                               currentSpeed = 5;
15  21 private static final int STOP = 3;
16  22 private static final int MAX_SPEED = 140;
            private int react(TrafficSignal signal) {
             GREEN
17  23
                             color
       /∗ The action this automobile is currently performing, idle by defaul
               switch(signal.getColor()) {
18  24 private case currentAction = IDLE;
                    int TrafficSignal.RED: return STOP;  MAX_SPEED
19  25 /∗ The current speedgetColor
                   case TrafficSignal.YELLOW: mph. ∗/
                             of the automobile, initially 5
20  26 private intdecide whether to stop or go
                      // currentSpeed = 5;
21  27                if (this.shouldGo())
22  28 private int return INCREASE_SPEED;
                          react(TrafficSignal signal) {
23  29    switch(signal.getColor()) {
                      else return STOP;
24  30       case TrafficSignal.RED: return no change
                   case TrafficSignal.GREEN: // STOP;
25  31       case TrafficSignal.YELLOW:
                      return this.currentAction;
26  32          // decide whether to stop new IllegalArgumentExce
                   default: throw or go
27  33          if (this.shouldGo()) color");}} // required
                      ("Invalid traffic                                 42
2     public static final int RED = 0;
DECREASE_SPEED static final int RED_YELLOW = 1;
  3     public                 IDLE                              STOP
  4     public static final int YELLOW = 2;
  5     public static final int GREEN = 3;
  6     /∗ Current color of the traffic signal, initially red by default ∗/
                          YELLOW = RED;             INCREASE_SPEED
  7     private int color
  8     /∗ Accessor for the light’s current color ∗/
  9                        RED
        public int getColor() {return this.color;}}
  10
  11   class Automobile {
            GREEN           color
  12     private static final int IDLE = 0;
  13     private static final int INCREASE_SPEED = 1  MAX_SPEED
                           getColor
  14     private static final int DECREASE_SPEED = 2
  15     private static final int STOP = 3;
  16     private static final int MAX_SPEED = 140;
  17     /∗ The action this automobile is currently performing, idle by de
  18     private int currentAction = IDLE;
  19     /∗ The current speed of the automobile, initially 5 mph. ∗/
  20     private int currentSpeed = 5;
  21
                                                                      42
2     public static final int RED = 0;
DECREASE_SPEED static final int RED_YELLOW = 1;
  3     public                 IDLE       currentAction          STOP
  4     public static final int YELLOW = 2;
  5     public static final int GREEN = 3;
  6     /∗ Current color of the traffic signal, initially red by default ∗/
                          YELLOW = RED;              INCREASE_SPEED
  7     private int color
  8     /∗ Accessor for the light’s current color ∗/
  9                        RED
        public int getColor() {return this.color;}}
  10
  11   class Automobile {
            GREEN           color
  12     private static final int IDLE = 0;
  13     private static final int INCREASE_SPEED = 1  MAX_SPEED
                           getColor
  14     private static final int DECREASE_SPEED = 2
  15     private static final int STOP = 3;
  16     private static final int MAX_SPEED = 140;
  17     /∗ The action this automobile is currently performing, idle by de
  18     private int currentAction = IDLE;
  19     /∗ The current speed of the automobile, initially 5 mph. ∗/
  20     private int currentSpeed = 5;
  21
                                                                      42
l RED;
     signal) {                               23
                                             25         case TrafficSignal.RE
    public int getColor() {return this.color;}} privateorC // decide whether to stop
                                                                 6
 turn STOP;
  7class Automobile color = RED;
            private int {                    22       switch(signal.getColor(
                                             24
                                             26                  7       /* Accessor f
                                                        case (this.shouldGo()
                                                           if TrafficSignal.YE
urrent colorAccessor for thefinal currentIDLE ∗/ 0; // decide whether to stop or
  8         /∗ ∗/
       private static light’s int color currentAction
                                             23
                                            IDLE
                                             25       = casereturn Action.INC
                                                                 TrafficSignal.RE
                                                                           STOP
 turnDECREASE_SPEED{
          STOP;
 lass Automobile                             27                  8       public Co
 () private static final int {return case (this.shouldGo()
       {return this.color;}} 24
  9 private static final int 26 INCREASE_SPEED = 1; Action.
            public int getColor()28                        if TrafficSignal.YE
                                                        this.color;}}
                                             IDLE = 0; else return to stop or
                                             25
                                                                 9
                                                           // decide whether
10 private static final int 27 DECREASE_SPEED = 2;
       private static final int              29         casereturn Action.INC
                                                                 TrafficSignal.GR
                                                                      class Autom
                                             INCREASE_SPEED(this.shouldGo()
                                                                10 = 1;
 // no private static final int STOP = 3; if
       change                                26            else return Action.
11 private static final int 28
        class Automobile {                   30            return this.current
 n; int IDLE = 0;
 l private static final int                  27                return private e
                                             DECREASE_SPEED = 2; Action.INC
                                                                11
                                                               INCREASE_SPEED
            private static final 31
 // no change
 ArgumentException
                                      YELLOW
12 private static final int 29 MAX_SPEED 0; 12int IDLE case TrafficSignal.GR
                                                             = 140;
                                             STOP = 3; default: throwAction.
                                                        = else return INCREAS  new Il
 l intThe action this automobile 1; 28
13 private static final= int 32
             INCREASE_SPEED
       /∗ //private static final 30                        return this.current
                                       is currentlyINCREASE_SPEEDdefault ∗/
                                              int performing, idle by =traffic c
                                                           ("Invalid 1;
 n;
 );}} required                               MAX_SPEED case 13
                                             29          = 140; throw new Il
                                                        default:            DECREAS
                                                                 TrafficSignal.GR
14 /∗ Theprivate automobile = currently = DECREASE_SPEED = 2;
 l int DECREASE_SPEED final 31
 ArgumentException       static is 2; 33 performing, returndefault ∗/
 // no private int currentAction
       change
             action this 3;             RED   int IDLE; idle by this.current
                                             30                 14          STOP};
 n; intThe current static final 34
 l /∗ required =
             STOP                            32            ("Invalid traffic c
15 private int speed of the automobile, initially default:drive()new Il
 );}} //private currentAction31= IDLE; = mph. ∗/ throw {
                                                    public void
                                              int STOP 5 3; 15           private s
                                             33
16 /∗ Theprivate GREEN 140; color initially 5 mph. ∗/ = 140;traffic c
 ArgumentException =
 l int MAX_SPEEDcurrentSpeed = 5; TrafficSignal aSignal =
                         static final 35
       private int of the automobile,         int MAX_SPEED 16 drive() {
 ;           current speed
 );}} ///∗ The action this automobile is ∗/
             required
                                             32
                                             34     public("Invalid /* The this.
                                                             void                action
17 private performing, idle by defaultcurrently performing, idle by default ∗/ A
 e is currently                              36       Action reaction =
 ignal);
 Action && IDLE;
               =  int currentSpeed 33 5;     =
                                             35
                                             37
 ; private int react(TrafficSignal signal) drive() {  if (reaction private =
                                                                17
                                                      TrafficSignal!= this.cu
                                                                          aSignal
 Actionprivate int currentAction = IDLE;void { /* The this.
                                                    public
                                                           (reaction != curren
18                                           34
                                             36       Action 18 MAX_SPEED=Action
                                                                 reaction
automobile,The currentmph. ∗/ the automobile, initially 5 mph. ∗/ aSignal =
 EED ||/∗ initially 5 speed of
 ignal);                                     38
                                      getColor
           switch(signal.getColor()) { TrafficSignal!= this.cu
19 private int react(TrafficSignal signal) { 35
 ;                                           37
                                             39       if (reaction private i
                                                                19
                                                             this.currentSpeed
 X_SPEED))5; TrafficSignal.RED: = 5;
 Speed =case
 Actionprivate int currentSpeed return STOP;
20            &&                             36       Action 20
                                                           (reaction !==Action
                                                                 reaction        this.
 EED switch(signal.getColor()) {
 ignal);                                     38
                                             40                this.performActio
21
        || case TrafficSignal.YELLOW: if (reaction != this.cu
 ction);}                                    37
 Action && TrafficSignal.RED: return STOP;
           case                              39
                                             41              this.currentSpeedA
                                                                21       private
 X_SPEED)) // decide whether to stop or go
 rafficSignal signal) {
22
 EED ||     private int react(TrafficSignal (reaction{!= Action
                                             38
                                             40             signal)
           case{ TrafficSignal.YELLOW: privatethis.currentSpeed
                                             42                this.performActio
                                                                22          switch(
                                                               void performActio
 ction);} {...}}
 Color()) if (this.shouldGo())
23action)// decide whether to stop or go
 X_SPEED))      switch(signal.getColor()) {  39
                                             41               (b) Improvements afte
                                                                23              case
 nal.RED: return STOP;
 ction);}if case TrafficSignal.RED:
24                  (this.shouldGo())
                                             40
                                             42     private this.performActio
                      return INCREASE_SPEED; return 24STOP;    void performActiocase
oraction) {...}}
    enumerated types.
 nal.YELLOW:                                                  (b) Improvements // de
                                                                                   afte
25                else return STOP; 41
                   case TrafficSignal.YELLOW:
                  return INCREASE_SPEED; private void performActio
                                                                25
o stop or gocase //TrafficSignal.GREEN: // no change
oraction)else return STOP; stop or go
26 enumerated types.
                 {...}} decide whether to
                                             42
                                                                                   if
ldGo()) example: a hypothetical drive-by-wire applica
 unning return this.currentAction;        (b) Improvements afte 26
27         if (this.shouldGo())// no change 27
     case TrafficSignal.GREEN:
                                                           42
                                                              r
l RED;
     signal) {                               23
                                             25         case TrafficSignal.RE
    public int getColor() {return this.color;}} privateorC // decide whether to stop
                                                                 6
 turn STOP;
  7class Automobile color = RED;
            private int {                    22       switch(signal.getColor(
                                             24
                                             26                  7       /* Accessor f
                                                        case (this.shouldGo()
                                                           if TrafficSignal.YE
urrent colorAccessor for thefinal currentIDLE ∗/ 0; // decide whether to stop or
  8         /∗ ∗/
       private static light’s int color currentAction
                                             23
                                            IDLE
                                             25       = casereturn Action.INC
                                                                 TrafficSignal.RE
                                                                           STOP
 turnDECREASE_SPEED{
          STOP;
 lass Automobile                             27                  8       public Co
 () private static final int {return case (this.shouldGo()
       {return this.color;}} 24
  9 private static final int 26 INCREASE_SPEED = 1; Action.
            public int getColor()28                        if TrafficSignal.YE
                                                        this.color;}}
                                             IDLE = 0; else return to stop or
                                             25
                                                                 9
                                                           // decide whether
10 private static final int 27 DECREASE_SPEED = 2;
       private static final int              29         casereturn Action.INC
                                                                 TrafficSignal.GR
                                                                      class Autom
                                             INCREASE_SPEED(this.shouldGo()
                                                                10 = 1;
 // no private static final int STOP = 3; if
       change                                26            else return Action.
11 private static final int 28
        class Automobile {                   30            return this.current
 n; int IDLE = 0;
 l private static final int                  27                return private e
                                             DECREASE_SPEED = 2; Action.INC
                                                                11
                                                               INCREASE_SPEED
            private static final 31
 // no change
 ArgumentException
                                      YELLOW
12 private static final int 29 MAX_SPEED 0; 12int IDLE case TrafficSignal.GR
                                                             = 140;
                                             STOP = 3; default: throwAction.
                                                        = else return INCREAS  new Il
 l intThe action this automobile 1; 28
13 private static final= int 32
             INCREASE_SPEED
       /∗ //private static final 30                        return this.current
                                       is currentlyINCREASE_SPEEDdefault ∗/
                                              int performing, idle by =traffic c
                                                           ("Invalid 1;
 n;
 );}} required                               MAX_SPEED case 13
                                             29          = 140; throw new Il
                                                        default:            DECREAS
                                                                 TrafficSignal.GR
14 /∗ Theprivate automobile = currently = DECREASE_SPEED = 2;
 l int DECREASE_SPEED final 31
 ArgumentException       static is 2; 33 performing, returndefault ∗/
 // no private int currentAction
       change
             action this 3;             RED   int IDLE; idle by this.current
                                             30                 14          STOP};
 n; intThe current static final 34
 l /∗ required =
             STOP                            32            ("Invalid traffic c
15 private int speed of the automobile, initially default:drive()new Il
 );}} //private currentAction31= IDLE; = mph. ∗/ throw {
                                                    public void
                                              int STOP 5 3; 15           private s
                                             33
16 /∗ Theprivate GREEN 140; color initially 5 mph. ∗/ = 140;traffic c
 ArgumentException =
 l int MAX_SPEEDcurrentSpeed = 5; TrafficSignal aSignal =
                         static final 35
       private int of the automobile,         int MAX_SPEED 16 drive() {
 ;           current speed
 );}} ///∗ The action this automobile is ∗/
             required
                                             32
                                             34     public("Invalid /* The this.
                                                             void                action
17 private performing, idle by defaultcurrently performing, idle by default ∗/ A
 e is currently                              36       Action reaction =
 ignal);
 Action && IDLE;
               =  int currentSpeed 33 5;     =
                                             35
                                             37
 ; private int react(TrafficSignal signal) drive() {  if (reaction private =
                                                                17
                                                      TrafficSignal!= this.cu
                                                                          aSignal
 Actionprivate int currentAction = IDLE;void { /* The this.
                                                    public
                                                           (reaction != curren
18                                           34
                                             36       Action 18 MAX_SPEED=Action
                                                                 reaction
automobile,The currentmph. ∗/ the automobile, initially 5 mph. ∗/ aSignal =
 EED ||/∗ initially 5 speed of
 ignal);                                     38
                                      getColor
           switch(signal.getColor()) { TrafficSignal!= this.cu
19 private int react(TrafficSignal signal) { 35
 ;                                           37
                                             39       if (reaction private i
                                                                19
                                                             this.currentSpeed
 X_SPEED))5; TrafficSignal.RED: = 5;
 Speed =case
 Actionprivate int currentSpeed return STOP;
20            &&                             36       Action 20
                                                           (reaction !==Action
                                                                 reaction        this.
 EED switch(signal.getColor()) {
 ignal);                                     38
                                             40                this.performActio
21
        || case TrafficSignal.YELLOW: if (reaction != this.cu
 ction);}                                    37
 Action && TrafficSignal.RED: return STOP;
           case                              39
                                             41              this.currentSpeedA
                                                                21       private
 X_SPEED)) // decide whether to stop or go
 rafficSignal signal) {
22
 EED ||     private int react(TrafficSignal (reaction{!= Action
                                             38
                                             40             signal)
           case{ TrafficSignal.YELLOW: privatethis.currentSpeed
                                             42                this.performActio
                                                                22          switch(
                                                               void performActio
 ction);} {...}}
 Color()) if (this.shouldGo())
23action)// decide whether to stop or go
 X_SPEED))      switch(signal.getColor()) {  39
                                             41               (b) Improvements afte
                                                                23              case
 nal.RED: return STOP;
 ction);}if case TrafficSignal.RED:
24                  (this.shouldGo())
                                             40
                                             42     private this.performActio
                      return INCREASE_SPEED; return 24STOP;    void performActiocase
oraction) {...}}
    enumerated types.
 nal.YELLOW:                                                  (b) Improvements // de
                                                                                   afte
25                else return STOP; 41
                   case TrafficSignal.YELLOW:
                  return INCREASE_SPEED; private void performActio
                                                                25
o stop or gocase //TrafficSignal.GREEN: // no change
oraction)else return STOP; stop or go
26 enumerated types.
                 {...}} decide whether to
                                             42
                                                                                   if
ldGo()) example: a hypothetical drive-by-wire applica
 unning return this.currentAction;        (b) Improvements afte 26
27         if (this.shouldGo())// no change 27
     case TrafficSignal.GREEN:
                                                           42
                                                              r
l RED;
     signal) {                               23
                                             25         case TrafficSignal.RE
    public int getColor() {return this.color;}} privateorC // decide whether to stop
                                                                 6
 turn STOP;
  7class Automobile color = RED;
            private int {                    22       switch(signal.getColor(
                                             24
                                             26                  7       /* Accessor f
                                                        case (this.shouldGo()
                                                           if TrafficSignal.YE
urrent colorAccessor for thefinal currentIDLE ∗/ 0; // decide whether to stop or
  8         /∗ ∗/
       private static light’s int color currentAction
                                             23
                                            IDLE
                                             25       = casereturn Action.INC
                                                                 TrafficSignal.RE
 turnDECREASE_SPEED{
 lass STOP; this.color;}} 27
           Automobile                                            8       public Co
 () private static final int {return case (this.shouldGo()
       {return int getColor()24
  9 private static final int 26 INCREASE_SPEED = 1; Action.
            public                                         if TrafficSignal.YE
                                                        this.color;}}
                                             IDLE = 0; else return to stop or
                                             28                  9
       private static final int              27 DECREASE_SPEED whether
                                             25            // decide STOP
                                                        casereturn 2;   Action.INC
10 private static final int 29               INCREASE_SPEED     10 = =
                                                                 TrafficSignal.GR
                                                                      class Autom
                                                                     1;
 // no private static final int STOP = 3; if (this.shouldGo()
       change                                26            else return Action.
11 private static final int 28
        class Automobile {                   30            return this.current
 n; int IDLE = 0;
 l private static final int                  27                return private e
                                             DECREASE_SPEED = 2; Action.INC
                                                                11
                                                               INCREASE_SPEED
            private static final 31
 // no change
 ArgumentException
                                      YELLOW
12 private static final int 29 MAX_SPEED 0; 12int IDLE case TrafficSignal.GR
                                                             = 140;
                                             STOP = 3; default: throwAction.
                                                        = else return INCREAS  new Il
 l intThe action this automobile 1; 28
13 private static final= int 32
             INCREASE_SPEED
       /∗ //private static final 30                        return this.current
                                       is currentlyINCREASE_SPEEDdefault ∗/
                                              int performing, idle by =traffic c
                                                           ("Invalid 1;
 n;
 );}} required                               MAX_SPEED case 13
                                             29          = 140; throw new Il
                                                        default:            DECREAS
                                                                 TrafficSignal.GR
14 /∗ Theprivate automobile = currently = DECREASE_SPEED = 2;
 l int DECREASE_SPEED final 31
 ArgumentException       static is 2; 33 performing, returndefault ∗/
 // no private int currentAction
       change
             action this 3;             RED   int IDLE; idle by this.current
                                             30                 14          STOP};
 n; intThe current static final 34
 l /∗ required =
             STOP                            32            ("Invalid traffic c
15 private int speed of the automobile, initially default:drive()new Il
 );}} //private currentAction31= IDLE; = mph. ∗/ throw {
                                                    public void
                                              int STOP 5 3; 15           private s
                                             33
16 /∗ Theprivate GREEN 140; color initially 5 mph. ∗/ = 140;traffic c
 ArgumentException =
 l int MAX_SPEEDcurrentSpeed = 5; TrafficSignal aSignal =
                         static final 35
       private int of the automobile,         int MAX_SPEED 16 drive() {
 ;           current speed
 );}} ///∗ The action this automobile is ∗/
             required
                                             32
                                             34     public("Invalid /* The this.
                                                             void                action
17 private performing, idle by defaultcurrently performing, idle by default ∗/ A
 e is currently                              36       Action reaction =
 ignal);
 Action && IDLE;
               =  int currentSpeed 33 5;     =
                                             35
                                             37
 ; private int react(TrafficSignal signal) drive() {  if (reaction private =
                                                                17
                                                      TrafficSignal!= this.cu
                                                                          aSignal
 Actionprivate int currentAction = IDLE;void { /* The this.
                                                    public
                                                           (reaction != curren
18                                           34
                                             36       Action 18 MAX_SPEED=Action
                                                                 reaction
automobile,The currentmph. ∗/ the automobile, initially 5 mph. ∗/ aSignal =
 EED ||/∗ initially 5 speed of
 ignal);                                     38
                                      getColor
           switch(signal.getColor()) { TrafficSignal!= this.cu
19 private int react(TrafficSignal signal) { 35
 ;                                           37
                                             39       if (reaction private i
                                                                19
                                                             this.currentSpeed
 X_SPEED))5; TrafficSignal.RED: = 5;
 Speed =case
 Actionprivate int currentSpeed return STOP;
20            &&                             36       Action 20
                                                           (reaction !==Action
                                                                 reaction        this.
 EED switch(signal.getColor()) {
 ignal);                                     38
                                             40                this.performActio
21
        || case TrafficSignal.YELLOW: if (reaction != this.cu
 ction);}                                    37
 Action && TrafficSignal.RED: return STOP;
           case                              39
                                             41              this.currentSpeedA
                                                                21       private
 X_SPEED)) // decide whether to stop or go
 rafficSignal signal) {
22
 EED ||     private int react(TrafficSignal (reaction{!= Action
                                             38
                                             40             signal)
           case{ TrafficSignal.YELLOW: privatethis.currentSpeed
                                             42                this.performActio
                                                                22          switch(
                                                               void performActio
 ction);} {...}}
 Color()) if (this.shouldGo())
23action)// decide whether to stop or go
 X_SPEED))      switch(signal.getColor()) {  39
                                             41               (b) Improvements afte
                                                                23              case
 nal.RED: return STOP;
 ction);}if case TrafficSignal.RED:
24                  (this.shouldGo())
                                             40
                                             42     private this.performActio
                      return INCREASE_SPEED; return 24STOP;    void performActiocase
oraction) {...}}
    enumerated types.
 nal.YELLOW:                                                  (b) Improvements // de
                                                                                   afte
25                else return STOP; 41
                   case TrafficSignal.YELLOW:
                  return INCREASE_SPEED; private void performActio
                                                                25
o stop or gocase //TrafficSignal.GREEN: // no change
oraction)else return STOP; stop or go
26 enumerated types.
                 {...}} decide whether to
                                             42
                                                                                   if
ldGo()) example: a hypothetical drive-by-wire applica
 unning return this.currentAction;        (b) Improvements afte 26
27         if (this.shouldGo())// no change 27
     case TrafficSignal.GREEN:
                                                           42
                                                              r
l RED;
     signal) {                               23
                                             25         case TrafficSignal.RE
    public int getColor() {return this.color;}} privateorC // decide whether to stop
                                                                 6
 turn STOP;
  7class Automobile color = RED;
            private int {                    22       switch(signal.getColor(
                                             24
                                             26                  7       /* Accessor f
                                                        case (this.shouldGo()
                                                           if TrafficSignal.YE
urrent colorAccessor for thefinal currentIDLE ∗/ 0; // decide whether to stop or
  8         /∗ ∗/
       private static light’s int color currentAction
                                             23
                                            IDLE
                                             25       = casereturn Action.INC
                                                                 TrafficSignal.RE
 turnDECREASE_SPEED{
 lass STOP; this.color;}} 27
           Automobile                                            8       public Co
 () private static final int {return case (this.shouldGo()
       {return int getColor()24
  9 private static final int 26 INCREASE_SPEED = 1; Action.
            public                                         if TrafficSignal.YE
                                                        this.color;}}
                                             IDLE = 0; else return to stop or
                                             28                  9
       private static final int              27 DECREASE_SPEED whether
                                             25            // decide STOP
                                                        casereturn 2;   Action.INC
10 private static final int 29               INCREASE_SPEED     10 = =
                                                                 TrafficSignal.GR
                                                                      class Autom
                                                                     1;
 // no private static final int STOP = 3; if (this.shouldGo()
       change                                26            else return Action.
11 private static final int 28
        class Automobile {                   30            return this.current
 n; int IDLE = 0;
 l private static final int                  27                return private e
                                             DECREASE_SPEED = 2; Action.INC
                                                                11
                                                               INCREASE_SPEED
            private static final 31
 // no change
 ArgumentException
                                      YELLOW
12 private static final int 29 MAX_SPEED 0; 12int IDLE case TrafficSignal.GR
                                                             = 140;
                                             STOP = 3; default: throwAction.
                                                        = else return INCREAS  new Il
 l intThe action this automobile 1; 28
13 private static final= int 32
             INCREASE_SPEED
       /∗ //private static final 30                        return this.current
                                       is currentlyINCREASE_SPEEDdefault ∗/
                                              int performing, idle by =traffic c
                                                           ("Invalid 1;
 n;
 );}} required                               MAX_SPEED case 13 react DECREAS
                                             29          = 140;  TrafficSignal.GR
                                                        default: throw new Il
14 /∗ Theprivate automobile = currently = DECREASE_SPEED = 2;
 l int DECREASE_SPEED final 33
                         static is 2; 30 performing, returndefault ∗/
 // no private int currentAction
       change                                31
 ArgumentException
             action this 3;             RED   int IDLE; idle by this.current
                                                                14          STOP};
 n; intThe current static final 34
 l /∗ required =
             STOP                            32            ("Invalid traffic c
15 private int speed of the automobile, initially default:drive()new Il
 );}} //private currentAction31= IDLE; = mph. ∗/ throw {
                                                    public void
                                              int STOP 5 3; 15           private s
                                             33
16 /∗ Theprivate GREEN 140; color initially 5 mph. ∗/ = 140;traffic c
 ArgumentException =
 l int MAX_SPEEDcurrentSpeed = 5; TrafficSignal aSignal =
                         static final 35
       private int of the automobile,         int MAX_SPEED 16 drive() {
 ;           current speed
 );}} ///∗ The action this automobile is ∗/
             required
                                             32
                                             34     public("Invalid /* The this.
                                                             void                action
17 private performing, idle by defaultcurrently performing, idle by default ∗/ A
 e is currently                              36       Action reaction =
 ignal);
 Action && IDLE;
               =  int currentSpeed 33 5;     =
                                             35
                                             37
 ; private int react(TrafficSignal signal) drive() {  if (reaction private =
                                                                17
                                                      TrafficSignal!= this.cu
                                                                          aSignal
 Actionprivate int currentAction = IDLE;void { /* The this.
                                                    public
                                                           (reaction != curren
18                                           34
                                             36       Action 18 MAX_SPEED=Action
                                                                 reaction
automobile,The currentmph. ∗/ the automobile, initially 5 mph. ∗/ aSignal =
 EED ||/∗ initially 5 speed of
 ignal);                                     38
                                      getColor
           switch(signal.getColor()) { TrafficSignal!= this.cu
19 private int react(TrafficSignal signal) { 35
 ;                                           37
                                             39       if (reaction private i
                                                                19
                                                             this.currentSpeed
 X_SPEED))5; TrafficSignal.RED: = 5;
 Speed =case
 Actionprivate int currentSpeed return STOP;
20            &&                             36       Action 20
                                                           (reaction !==Action
                                                                 reaction        this.
 EED switch(signal.getColor()) {
 ignal);                                     38
                                             40                this.performActio
21
        || case TrafficSignal.YELLOW: if (reaction != this.cu
 ction);}                                    37
 Action && TrafficSignal.RED: return STOP;
           case                              39
                                             41              this.currentSpeedA
                                                                21       private
 X_SPEED)) // decide whether to stop or go
 rafficSignal signal) {
22
 EED ||     private int react(TrafficSignal (reaction{!= Action
                                             38
                                             40             signal)
           case{ TrafficSignal.YELLOW: privatethis.currentSpeed
                                             42                this.performActio
                                                                22          switch(
                                                               void performActio
 ction);} {...}}
 Color()) if (this.shouldGo())
23action)// decide whether to stop or go
 X_SPEED))      switch(signal.getColor()) {  39
                                             41               (b) Improvements afte
                                                                23              case
 nal.RED: return STOP;
 ction);}if case TrafficSignal.RED:
24                  (this.shouldGo())
                                             40
                                             42     private this.performActio
                      return INCREASE_SPEED; return 24STOP;    void performActiocase
oraction) {...}}
    enumerated types.
 nal.YELLOW:                                                  (b) Improvements // de
                                                                                   afte
25                else return STOP; 41
                   case TrafficSignal.YELLOW:
                  return INCREASE_SPEED; private void performActio
                                                                25
o stop or gocase //TrafficSignal.GREEN: // no change
oraction)else return STOP; stop or go
26 enumerated types.
                 {...}} decide whether to
                                             42
                                                                                   if
ldGo()) example: a hypothetical drive-by-wire applica
 unning return this.currentAction;        (b) Improvements afte 26
27         if (this.shouldGo())// no change 27
     case TrafficSignal.GREEN:
                                                           42
                                                              r
l RED;
     signal) {                              23
                                            25          case TrafficSignal.RE
    public int getColor() {return this.color;}} privateorC // decide whether to stop
                                                                 6
 turn STOP;
  7class Automobile color = RED;
            private int {                   22        switch(signal.getColor(
                                            24
                                            26                   7       /* Accessor f
                                                        case (this.shouldGo()
                                                           if TrafficSignal.YE
urrent colorAccessor for thefinal currentIDLE ∗/ 0; // decide whether to stop or
  8         /∗ ∗/
       private static light’s int color = casereturn Action.INC
                                            23
                                            25                   TrafficSignal.RE
 turnDECREASE_SPEED{
 lass STOP; this.color;}} 27
           Automobile                                            8   IDLEpublic Co
 () private static final int {return case (this.shouldGo()
       {return int getColor()24
  9 private static final int 26 INCREASE_SPEED = 1; Action.
            public                                         if TrafficSignal.YE
                                                        this.color;}}
                                            IDLE = 0; else return to stop or
                                            28                   9
       private static final int             27 DECREASE_SPEED whether
                                            25             // decide STOP
                                                        casereturn 2;   Action.INC
10 private static final int 29              INCREASE_SPEED      10 = =
                                                                 TrafficSignal.GR
                                                                      class Autom
                                                                     1;
 // no private static final int STOP = 3; if (this.shouldGo()
       change                               26             else return Action.
11 private static final int 28
        class Automobile {                  30             return this.current
 n; int IDLE = 0;
 l private static final int                 27                 return private e
                                            DECREASE_SPEED = 2; Action.INC
                                                                11
                                                               INCREASE_SPEED
            private static final 31
 // no change
 ArgumentException
                                      YELLOW int IDLE case TrafficSignal.GR
12 private static final int 29 MAX_SPEED 0; 12               = 140;
                                            STOP = 3; default: throwAction.
                                                        = else return INCREAS  new Il
 l intThe action this automobile 1; 28
13 private static final= int 32
             INCREASE_SPEED
       /∗ //private static final 30                        return this.current
                                       is currentlyINCREASE_SPEEDdefault ∗/
                                             int performing, idle by =traffic c
                                                           ("Invalid 1;
 n;
 );}} required                              MAX_SPEED case 13 react DECREAS
                                            29           = 140;  TrafficSignal.GR
                                                        default: throw new Il
14 /∗ Theprivate automobile = currently = DECREASE_SPEED = 2;
 l int DECREASE_SPEED final 33
                         static is 2; 30 performing, returndefault ∗/
 // no private int currentAction
       change                               31
 ArgumentException
             action this 3;             RED  int IDLE; idle by this.current
                                                                14          STOP};
 n; intThe current static final 34
 l /∗ required =
             STOP                           32             ("Invalid traffic c
15 private int speed of the automobile, initially default:drive()new Il
 );}} //private currentAction31= IDLE; = mph. ∗/ throw {
                                                    public void
                                             int STOP 5 3; 15currentAction
                                                                         private s
                                            33
16 /∗ Theprivate GREEN 140; color initially 5 mph. ∗/ = 140;traffic c
 ArgumentException =
 l int MAX_SPEEDcurrentSpeed = 5; TrafficSignal aSignal =
                         static final 35
       private int of the automobile,        int MAX_SPEED 16 drive() {
 ;           current speed
 );}} ///∗ The action this automobile is ∗/
             required
                                            32
                                            34      public("Invalid /* The this.
                                                             void                action
17 private performing, idle by defaultcurrently performing, idle by default ∗/ A
 e is currently                             36        Action reaction =
 ignal);
 Action && IDLE;
               =  int currentSpeed 33 5;    =
                                            35
                                            37
 ; private int react(TrafficSignal signal) drive() {  if (reaction private =
                                                                17
                                                      TrafficSignal!= this.cu
                                                                          aSignal
 Actionprivate int currentAction = IDLE;void { /* The this.
                                                    public
                                                           (reaction != curren
18                                          34
                                            36        Action 18 MAX_SPEED=Action
                                                                 reaction
automobile,The currentmph. ∗/ the automobile, initially 5 mph. ∗/ aSignal =
 EED ||/∗ initially 5 speed of
 ignal);                                    38
                                      getColor
           switch(signal.getColor()) { TrafficSignal!= this.cu
19 private int react(TrafficSignal signal) {35
 ;                                          37
                                            39        if (reaction private i
                                                                19
                                                             this.currentSpeed
 X_SPEED))5; TrafficSignal.RED: = 5;
 Speed =case
 Actionprivate int currentSpeed return STOP;
20            &&                            36        Action 20
                                                           (reaction !==Action
                                                                 reaction        this.
 EED switch(signal.getColor()) {
 ignal);                                    38
                                            40                 this.performActio
21
        || case TrafficSignal.YELLOW: if (reaction != this.cu
 ction);}                                   37
 Action && TrafficSignal.RED: return STOP;
           case                             39
                                            41               this.currentSpeedA
                                                                21       private
 X_SPEED)) // decide whether to stop or go
 rafficSignal signal) {
22
 EED ||     private int react(TrafficSignal (reaction{!= Action
                                            38
                                            40              signal)
           case{ TrafficSignal.YELLOW: privatethis.currentSpeed
                                            42                 this.performActio
                                                                22          switch(
                                                               void performActio
 ction);} {...}}
 Color()) if (this.shouldGo())
23action)// decide whether to stop or go
 X_SPEED))      switch(signal.getColor()) { 39
                                            41                (b) Improvements afte
                                                                23              case
 nal.RED: return STOP;
 ction);}if case TrafficSignal.RED:
24                  (this.shouldGo())
                                            40
                                            42      private this.performActio
                      return INCREASE_SPEED; return 24STOP;    void performActiocase
oraction) {...}}
    enumerated types.
 nal.YELLOW:                                                  (b) Improvements // de
                                                                                   afte
25                else return STOP; 41
                   case TrafficSignal.YELLOW:
                  return INCREASE_SPEED; private void performActio
                                                                25
o stop or gocase //TrafficSignal.GREEN: // no change
oraction)else return STOP; stop or go
26 enumerated types.
                 {...}} decide whether to
                                            42
                                                                                   if
ldGo()) example: a hypothetical drive-by-wire applica
 unning return this.currentAction;        (b) Improvements afte 26
27         if (this.shouldGo())// no change 27
     case TrafficSignal.GREEN:
                                                           42
                                                              r
Identifiers                                                             Array access/creation expressions
Identifiers                                                     Conditional expressions                                                   Identifiers                                                             Array access/creation expressions
                   Identifiers                                                      Conditional expressions                function XA(α,ID)                                                      function XA(α, E XP1 [E XP2 ])
function EA(α,ID)                                              function EA(α, E XP1 ? E XP2 : E XP3 )                                    function XA(α,ID)                                                      function XA(α, E XP1 [E XP2 ])
                   function EA(α,ID)                                               function EA(α, E XP1 ? E XP2 : E XP3 ) return XA(α, P arent(ID))
                                                                                                                            1:
  1: return EA(α, P arent(ID))                                                                                                             1: return XA(α, P arent(ID))                            1: if contains(E XP2 , α) then
                                                                 1: if contains(E XP2 , α) ∨ contains (E XP3 , α) then                                                                                            1: if contains(E XP2 , α) then
                     1: return EA(α, P arent(ID))                                    1: if contains(E XP2 , α) ∨ contains (E XP3 , α) then
                                                                                                                          Parenthesized expressions
Parenthesized expressions                                             return EA(α, P arent(E XP1 ? E XP2 : E XP3 ))                      Parenthesized expressions                                 2:   return ∅
                   Parenthesized expressions
                                                                 2:
                                                                                          return EA(α, P arent(E XP1 ? E XP2 : XA(α,(ID))                                                                         2:   return ∅
                                                                                     2:                                   function E XP3 ))                                                        3: else
function EA(α,(ID))                                              3: else                                                                 function XA(α,(ID))                                                      3: else
                   function EA(α,(ID))                                               3: else
                                                                                                                            1: return XA(α, P arent(ID))                                           4:   return XA(α, P arent(E XP1 ))
  1: return EA(α, P arent(ID))                                   4:   return true                                                          1: return XA(α, P arent(ID))                                           4:   return XA(α, P arent(E XP1 ))
                     1: return EA(α, P arent(ID))                                    4:   return true                                                                                              5: end if
                                                                 5: end if                                                Cast expressions                                                                        5: end if
Cast expressions                                                                     5: end if                                           Cast expressions
                   Cast expressions                            Array access/creation expressions                          function XA(α, (T YPE)E XP)                                            Array initialization expressions
function EA(α, (T YPE)E XP)                                                        Array access/creation expressions                     function XA(α, (T YPE)E XP)                                            Array initialization expressions
                   function EA(α, (T YPE)E XP)                 function EA(α, E XP1 [E XP2 ])                               1: return ∅
                                                                                                                                                                                                 function XA(α, {E XP1 , . . . , E XPn })
  1: return false                                                                  function EA(α, E XP1 [E XP2 ])                          1: return ∅
                                                                                                                                                                                                                function XA(α, {E XP1 , . . . , E XPn })
                     1: return false
                                                                                                                          Field access expressions                                                 1: R ← ∅
                                                                 1: if contains(E XP2 , α) then                                                                                                                   1: R ← ∅
Field access expressions                                                             1: if contains(E XP2 , α) then                      Field access expressions                                  2: for E XPi , 1 ≤ i ≤ n do
                   Field access expressions                      2:   return false                                        function XA(α, E XP.ID)                                                                 2: for E XPi , 1 ≤ i ≤ n do
function EA(α, E XP.ID)                                                              2:   return false                                   function XA(α, E XP.ID)                                        R ← R ∪ XD(E XPi )
                   function EA(α, E XP.ID)                       3: else                                                    1: return XA(α, P arent(E XP))
                                                                                                                                                                                                   3:
                                                                                                                                                                                                                  3:   R ← R ∪ XD(E XPi )
  1: return EA(α, P arent(E XP))                                                     3: else                                               1: return XA(α, P arent(E XP))                          4: end for
                     1: return EA(α, P arent(E XP))                   return EA(α, P arent(E XP1 ))                                                                                                               4: end for
                                                                 4:
                                                                                          return EA(α, P arent(E XP1 ))   Assignment expressions                                                   5: return R
Assignment expressions                                           5: end if
                                                                                     4:                                                  Assignment expressions
                   Assignment expressions                                                                                 function XA(α,E XP1 = E XP2 )                                                           5: return R
function EA(α,E XP1 = E XP2 )                                                        5: end if                                           function XA(α,E XP1 = E XP2 )
                   function EA(α,E XP1 = E XP2 )               Array initialization expressions                                                                                                  Return statements
                                                                                   Array initialization expressions         1: return XD(E XP1 ) ∪ XD(E XP2 )                                                   Return statements
  1: return ED(E XP1 ) ∧ ED(E XP2 )
                                                               function EA(α, {E XP1 , . . . , E XPn })                                    1: return XD(E XP1 ) ∪ XD(E XP2 )                     function XA(α,return E XP)
                     1: return ED(E XP1 ) ∧ ED(E XP2 )
                                                                                                                          Subtract assignment expressions
                                                                                   function EA(α, {E XP1 , . . . , E XPn })                                                                                     function XA(α,return E XP)
Subtract assignment expressions                                                                                                          Subtract assignment expressions                           1: return XD(M ethodDecl(return E XP ))
                   Subtract assignment expressions               1: let ie = true                                         function XA(α,E XP1 -= E XP2 )                                                          1: return XD(M ethodDecl(return E XP ))
function EA(α,E XP1 -= E XP2 )                                                       1: let ie = true                                    function XA(α,E XP1 -= E XP2 )
                   function EA(α,E XP1 -= E XP2 )                2: for E XPi , 1 ≤ i ≤ n do                                                                                                     Method declaration statements
                                                                                     2: for E XPi , 1 ≤ i ≤ n do            1: return ∅                                                                         Method declaration statements
  1: return false                                                3:   ie ← ie ∧ ED(E XPi )                                                 1: return ∅                                           function XA(α,ID(P 1 , . . . ,P n ))
                     1: return false                                                 3:   ie ← ie ∧ ED(E XPi )            Divide assignment expressions                                                         function XA(α,ID(P 1 , . . . ,P n ))
Divide assignment expressions                                    4: end for                                                              Divide assignment expressions                             1: R ← ∅
                   Divide assignment expressions                                     4: end for                           function XA(α,E XP1 /= E XP2 )                                                          1: R ← ∅
function EA(α,E XP1 /= E XP2 )                                   5: return ie                                                            function XA(α,E XP1 /= E XP2 )                            2: for all return E XPr ∈ returnStmts(ID(P 1, . . . , P n )) do
                   function EA(α,E XP1 /= E XP2 )                                    5: return ie                                                                                                                 2: for all return E XPr ∈ returnStmts(ID(P 1, . . . , P n )) do
                                                                                                                            1: return ∅                                                                 R ← R ∪ XD(E XPr )
  1: return false                                              Return statements                                                           1: return ∅                                             3:
                                                                                                                                                                                                                       R ← R ∪ XD(E XPr )
                     1: return false                                               Return statements                      Infix addition expressions
                                                                                                                                                                                                                  3:
                                                               function EA(α,return E XP)                                                                                                          4: end for
Infix addition expressions                                                          function EA(α,return E XP)                            Infix addition expressions                                                4: end for
                   Infix addition expressions                                                                              function XA(α,E XP1 + E XP2 )                                            5: return R
function EA(α,E XP1 + E XP2 )                                    1: return true                                                          function XA(α,E XP1 + E XP2 )                                            5: return R
                   function EA(α,E XP1 + E XP2 )                                     1: return true                         1: return ∅                                                          Formal parameters
  1: return false                                              Method declaration statements                                               1: return ∅                                                          Formal parameters
                     1: return false                                               Method declaration statements          Infix multiplication expressions                                        function XA(α,P i )
                                                               function EA(α,ID(P 1 , . . . ,P n ))                                                                                                             function XA(α,P i )
Infix multiplication expressions
                   Infix multiplication expressions                                 function EA(α,ID(P 1 , . . . ,P n )) function XA(α,Emultiplication expressions
                                                                                                                                         Infix
                                                                                                                                                XP1 * E XP2 )                                      1: R ← ∅
function EA(α,E XP1 * E XP2 )                                    1: let re = true                                                        function XA(α,E XP1 * E XP2 )                                            1: R ← ∅
                   function EA(α,E XP1 * E XP2 )                                     1: let re = true                       1: return ∅                                                            2: /*extract the ith argument of each invocation of the declaring
  1: return false                                                2: for all return E XPr ∈ returnStmts(ID(P 1, . . . , P n )) do           1: return ∅                                                            2: /*extract the ith argument of each invocation of the declaring
                     1: return false                                                 2: for all return E XPr ∈ returnStmts(ID(P 1, . . . , P n )) do                                                  method*/
                                                                 3:   re ← re ∧ ED(E XPr )                                Prefix unary minus expressions                                                              method*/
Prefix unary minus expressions                                                        3:   re ← re ∧ ED(E XPr )                           Prefix unary minus expressions                             3: let α = M ethodDecl(P i )
                                                                                                                                                                                                           ˆ
                   Prefix unary minus expressions                 4: end for                                               function XA(α,-E XP)                                                                    3: let α = M ethodDecl(P i )
                                                                                                                                                                                                                          ˆ
function EA(α,-E XP)                                                                 4: end for                                          function XA(α,-E XP)                                      4: for all αctxt ∈ Invocations(α, P) do
                                                                                                                                                                                                              ˆ                         ˆ
                   function EA(α,-E XP)                          5: return re                                               1: return ∅                                                                           4: for all αctxt ∈ Invocations(α, P) do
                                                                                                                                                                                                                             ˆ                       ˆ
  1: return false                                                                    5: return re                                          1: return ∅                                             5:   R ← R ∪ XD(Arg(αctxt, i)) ˆ
                     1: return false                           Formal parameters                                                                                                                                       R ← R ∪ XD(Arg(αctxt, i))
                                                                                                                                                                                                                                             ˆ
                                                                                                                          Postfix increment expressions                                                            5:
Postfix increment expressions                                                       Formal parameters                                     Postfix increment expressions                              6: end for
                   Postfix increment expressions                function EA(α,P i )                                        function XA(α,E XP ++)                                                                  6: end for
function EA(α,E XP ++)                                                             function EA(α,P i )                                   function XA(α,E XP ++)                                    7: return R
                   function EA(α,E XP ++)                                                                                                                                                                         7: return R
                                                                 1: let ae = true                                           1: return ∅
  1: return false                                                                    1: let ae = true                                      1: return ∅                                           Method invocation expressions
                     1: return false                             2: /*check the ith argument of each invocation of the declaring
                                                                                                                          Equality expressions                                                                  Method invocation expressions
Equality expressions                                                                 2: /*check the ith argument of each invocation of the declaring
                                                                                                                                         Equality expressions                                    function XA(α,ID(E XP1 , . . . , E XPn ))
                   Equality expressions                             method*/                                              function XA(α,E XP1 == E XP2 )                                                        function XA(α,ID(E XP1 , . . . , E XPn ))
function EA(α,E XP1 == E XP2 )                                                          method*/                                         function XA(α,E XP1 == E XP2 )                            1: R ← ∅
                   function EA(α,E XP1 == E XP2 )                3: let α = M ethodDecl(P i )
                                                                         ˆ                                                                                                                                        1: R ← ∅
                                                                                     3: let α = M ethodDecl(P i )
                                                                                             ˆ                              1: return XD(E XP2 ) ∪ XD(E XP1 )                                      2: for E XPi , 1 ≤ i ≤ n do
  1: return ED(E XP1 ) ∧ ED(E XP2 )                              4: for all αctxt ∈ Invocations(α, P) do
                                                                            ˆ                         ˆ                                    1: return XD(E XP2 ) ∪ XD(E XP1 )                                      2: for E XPi , 1 ≤ i ≤ n do
                     1: return ED(E XP1 ) ∧ ED(E XP2 )                               4: for all αctxt ∈ Invocations(α,Inequality expressions
                                                                                                 ˆ                      ˆ P) do
Inequality expressions                                                                                                                   Inequality expressions                                    3:   if contains(E XPi , α) then
                   Inequality expressions                        5:   ae ← ae ∧ ED(Arg(αctxt, i))
                                                                                               ˆ                                                                                                                  3:   if contains(E XPi , α) then
                                                                                     5:   ae ← ae ∧ ED(Arg(αctxt, i))function XA(α,E XP1 != E XP2 )
                                                                                                                ˆ                                                                                  4:     R ← R ∪ XD(E XP1 )
function EA(α,E XP1 != E XP2 )                                   6: end for                                                              function XA(α,E XP1 != E XP2 )                                           4:     R ← R ∪ XD(E XP1 )
                   function EA(α,E XP1 != E XP2 )                                    6: end for                             1: return XD(E XP1 ) ∪ XD(E XP2 )                                      5:   end if
  1: return ED(E XP1 ) ∧ ED(E XP2 )                              7: return ae                                                              1: return XD(E XP1 ) ∪ XD(E XP2 )                                      5:   end if
                     1: return ED(E XP1 ) ∧ ED(E XP2 )                               7: return ae                                                                                                  6: end for
                                                               Method invocation expressions                              Switch statements                                                                       6: end for
Switch statements                                                                  Method invocation expressions                         Switch statements                                         7: if R = ∅ then
                   Switch statements                                                                                      function XA(α, switch(E XP))                                                            7: if R = ∅ then
function EA(α, switch(E EA(α, switch(E XP))
                              XP))                             function EA(α,ID(E XP1 , . . . , E XPn ))                                 function XA(α, switch(E XP))
                   function                                                        function EA(α,ID(E XP1 , . . . , E XPn )) R ← XD(E XP)                                                          8:   return R
                                                                 1: for E XPi , 1 ≤ i ≤ n do
                                                                                                                            1:
                                                                                                                                           1: R ← XD(E XP)
                                                                                                                                                                                                                  8:   return R
  1: let se = ED(E XP)                                                                                                                                                                             9: else
                     1: let se = ED(E XP)                                            1: for E XPi , 1 ≤ i ≤ n do            2: for all case E XP c ∈ cases(switch(E XP )) do                                      9: else
  2: let ce = true                                               2:   if contains(E XPiif α) then
                                                                                           , contains(E XP , α) then                       2: for all case E XP c ∈ cases(switch(E XP )) do       10:   return XA(α, P arent(ID(E XP1 , . . . , E XPn )))
                     2: let ce = true                                                2:                     i               3:   R ← XD(E XPc )                                                                  10:   return XA(α, P arent(ID(E XP1 , . . . , E XPn )))
  3: for all case E XP c ∈ cases(switch(E XP )) do               3:     return true3:       return true                                    3:   R ← XD(E XPc )                                    11: end if
                     3: for all case E XP c ∈ cases(switch(E XP )) do                                                       4: end for                                                                           11: end if
  4:   ce ← ce ∧ ED(Ece ← ce ∧ ED(E XP )
                          XPc )                                  4:   end if              end if                                           4: end for
                     4:                        c                                     4:                                     5: return R                                                          General statements
  5: end for                                                     5: end for                                                                5: return R                                                          General statements
                     5: end for                                                      5: end for                                                                                                  function XA(α,S MT )
  6: return se ∧ ce                                              6: return EA(α, P arent(ID(E XP1 , . . . , E XPn ))) Switch case statements                                                                    function XA(α,S MT )
                     6: return se ∧ ce                                               6: return EA(α, P arent(ID(E XP1 , . . . , E XPnSwitch case statements
                                                                                                                                         )))                                                       1: R ← ∅
                                                               General statements                                         function XA(α,case E XP)                                                                1: R ← ∅
Switch case statements case statements                                             General statements                                    function XA(α,case E XP)                                  2: for E XP ∈ Children(S MT) do
                   Switch                                                                                                   1: return XA(α, switchStmt(case E XP ))                                               2: for E XP ∈ Children(S MT) do
function EA(α,case E XP) EA(α,case E XP)                       function XA(α,Sfunction XA(α,S MT )
                                                                                    MT )                                                   1: return XA(α, switchStmt(case E XP ))
                   function                                                                                                                                                                        3:   R ← R ∪ XD(E XP)
  1: return EA(α, switchStmt(case E XP ))                        1: let se = true                                         Conditional expressions                                                                 3:   R ← R ∪ XD(E XP)
                                                                                     1: let se = true                                    Conditional expressions                                   4: end for
                     1: return EA(α, switchStmt(case E XP ))                                                                                                                                                      4: end for
                                                                 2: for E XP ∈ Children(S MT) do                          function XA(α, E XP1 ? E XP2 : E XP3 )
                                                                                     2: for E XP ∈ Children(S MT) do                     function XA(α, E XP1 ? E XP2 : E XP3 )                    5: return R
                                                                                                                            1: if contains(E XP2 , α) ∨ contains (E XP3 , α) then                                 5: return R
                                                                 3:   se ← se ∨ED(E XP)← se ∨ED(E XP)
                                                                                          se
                                                                                     3:                                                    1: if contains(E XP2 , α) ∨ contains (E XP3 , α) then
                                                                 4: end for                                                 2:   return XA(α, P arent(E XP1 ? E XP2 : E XP3 ))
                                                                                     4: end for                                            2:   return XA(α, P arent(E XP1 ? E XP2 : E XP3 ))
                                                                 5: return se                                               3: else
                                                                                     5: return se                                          3: else
                                                                                                                            4:   return ∅
                                               Figure 7. EnumerizableEnumerizable ascender.                                                     return ∅
                                                            Figure 7. ascender.
                                                                                                                                           4:
                                                                                                                            5: end if                                                           12            12
                                                                                                                                           5: end if
                                                                        10            10                                                                                      Figure 9. Extraction ascender.
                                                                                                                                                                                        Figure 9. Extraction ascender.
                                                                                                                                                                                                                                                                                  43
this.currentAction &&
         case TrafficSignal.YELLOW:
    private int color = RED;                       38         (reacti
 INCREASE_SPEED ||
    /∗ Accessor for the light’s current or go ∗/ Enums vs. Constants
            // decide whether toDistinction:
               Algorithmic stop color
tSpeed <= MAX_SPEED))
                                                   39          this.c
    publicif (this.shouldGo())
              int getColor() {return this.color;}} 40           this.
rmAction(reaction);}
                    return INCREASE_SPEED;        41

                else return STOP;                 42     private void
 rmAction(int action) {
    class Automobile {...}}
            casestatic final int IDLE = no change
                     TrafficSignal.GREEN: // 0;                   (b) Im
       private
eger constants for static final int INCREASE_SPEED = 1;
       private enumerated types.
                return this.currentAction;
            default: throw new IllegalArgumentException
       private static final int DECREASE_SPEED = 2;
Figure 1. Running example:color");}} // required
                ("Invalid traffic a hypothetical drive-by-w
       private static final int STOP = 3;
       private static final int MAX_SPEED = 140;
       public void drive() is currently performing, idle by default ∗/
       /∗ The action this automobile {
 ch machinery.int currentAction = IDLE; example, in which
          TrafficSignal the weak enum ;
       private        Third, aSignal = ...
       /∗ The to manually enumerate initially 5 mph.language enum
 ogrammercurrent speed of the automobile,the
          int reaction = this.react(aSignal); ∗/   by
          if (reaction != this.currentAction &&
 ts, which increases the likelihood 5;
       private int currentSpeed = of
                (reaction != INCREASE_SPEED ||
                                                   and Automobile.
different enumint react(TrafficSignal signal) of these ne
       privatethis.currentSpeed unin-
                     constants may be <= MAX_SPEED)) {
                                                   ations
 he same internal value. Finally, the
                    this.performAction(reaction);}
          switch(signal.getColor()) {              through compile-tim
            case TrafficSignal.RED: return STOP;
rittle private void performAction(int action) {...}}named
        [?]:case TrafficSignal.YELLOW:
               since the values are com-           between the
at compile time they are to stop or go
                // decide whether inlined into     ated values. It is als
  new constants if(a)are added in constants for enumerated types., whic
                        Using integer
                     (this.shouldGo()) between     is an Action 44
this.currentAction &&
         case TrafficSignal.YELLOW:
    private int color = RED;                       38         (reacti
 INCREASE_SPEED ||
    /∗ Accessor for the light’s current or go ∗/ Enums vs. Constants
            // decide whether toDistinction:
               Algorithmic stop color
tSpeed <= MAX_SPEED))
                                                   39          this.c
    publicif (this.shouldGo())
              int getColor() {return this.color;}} 40           this.
rmAction(reaction);}
                    return INCREASE_SPEED;        41

                else return STOP;                 42     private void
 rmAction(int action) {
    class Automobile {...}}
            casestatic final int IDLE = no change
                     TrafficSignal.GREEN: // 0;                   (b) Im
       private
eger constants for static final int INCREASE_SPEED = 1;
       private enumerated types.
                return this.currentAction;
            default: throw new IllegalArgumentException
       private static final int DECREASE_SPEED = 2;
Figure 1. Running example:color");}} // required
                ("Invalid traffic a hypothetical drive-by-w
       private static final int STOP = 3;
       private static final int MAX_SPEED = 140;
       public void drive() is currently performing, idle by default ∗/
       /∗ The action this automobile {
 ch machinery.int currentAction = IDLE; example, in which
          TrafficSignal the weak enum ;
       private        Third, aSignal = ...
       /∗ The to manually enumerate initially 5 mph.language enum
 ogrammercurrent speed of the automobile,the
          int reaction = this.react(aSignal); ∗/   by
          if (reaction != this.currentAction &&
 ts, which increases the likelihood 5;
       private int currentSpeed = of
                (reaction != INCREASE_SPEED ||
                                                   and Automobile.
different enumint react(TrafficSignal signal) of these ne
       privatethis.currentSpeed unin-
                     constants may be <= MAX_SPEED)) {
                                                   ations
 he same internal value. Finally, the
                    this.performAction(reaction);}
          switch(signal.getColor()) {              through compile-tim
            case TrafficSignal.RED: return STOP;
rittle private void performAction(int action) {...}}named
        [?]:case TrafficSignal.YELLOW:
               since the values are com-           between the
at compile time they are to stop or go
                // decide whether inlined into     ated values. It is als
  new constants if(a)are added in constants for enumerated types., whic
                        Using integer
                     (this.shouldGo()) between     is an Action 44
this.currentAction &&
         case TrafficSignal.YELLOW:
    private int color = RED;                       38         (reacti
 INCREASE_SPEED ||
    /∗ Accessor for the light’s current or go ∗/ Enums vs. Constants
            // decide whether toDistinction:
               Algorithmic stop color
tSpeed <= MAX_SPEED))
                                                   39          this.c
    publicif (this.shouldGo())
              int getColor() {return this.color;}} 40           this.
rmAction(reaction);}
                    return INCREASE_SPEED;        41

                else return STOP;                 42     private void
 rmAction(int action) {
    class Automobile {...}}
            casestatic final int IDLE = no change
                     TrafficSignal.GREEN: // 0;                   (b) Im
       private
eger constants for static final int INCREASE_SPEED = 1;
       private enumerated types.
                return this.currentAction;
            default: throw new IllegalArgumentException
       private static final int DECREASE_SPEED = 2;
Figure 1. Running example:color");}} // required
                ("Invalid traffic a hypothetical drive-by-w
       private static final int STOP = 3;
       private static final int MAX_SPEED = 140;
       public void drive() is currently performing, idle by default ∗/
       /∗ The action this automobile {
 ch machinery.int currentAction = IDLE; example, in which
          TrafficSignal the weak enum ;
       private        Third, aSignal = ...
       /∗ The to manually enumerate initially 5 mph.language enum
 ogrammercurrent speed of the automobile,the
          int reaction = this.react(aSignal); ∗/   by
          if (reaction != this.currentAction &&
 ts, which increases the likelihood 5;
       private int currentSpeed = of
                (reaction != INCREASE_SPEED ||
                                                   and Automobile.
different enumint react(TrafficSignal signal) of these ne
       privatethis.currentSpeed unin-
                     constants may be <= MAX_SPEED)) {
                                                   ations
 he same internal value. Finally, the
                    this.performAction(reaction);}
          switch(signal.getColor()) {              through compile-tim
            case TrafficSignal.RED: return STOP;
rittle private void performAction(int action) {...}}named
        [?]:case TrafficSignal.YELLOW:
               since the values are com-           between the
at compile time they are to stop or go
                // decide whether inlined into     ated values. It is als
  new constants if(a)are added in constants for enumerated types., whic
                        Using integer
                     (this.shouldGo()) between     is an Action 44
this.currentAction &&
         case TrafficSignal.YELLOW:
    private int color = RED;                       38         (reacti
 INCREASE_SPEED ||
    /∗ Accessor for the light’s current or go ∗/ Enums vs. Constants
            // decide whether toDistinction:
               Algorithmic stop color
tSpeed <= MAX_SPEED))
                                                   39          this.c
    publicif (this.shouldGo())
              int getColor() {return this.color;}} 40           this.
rmAction(reaction);}
                    return INCREASE_SPEED;        41

                else return STOP;                 42     private void
 rmAction(int action) {
    class Automobile {...}}
            casestatic final int IDLE = no change
                     TrafficSignal.GREEN: // 0;                   (b) Im
       private
eger constants for static final int INCREASE_SPEED = 1;
       private enumerated types.
                return this.currentAction;
            default: throw new IllegalArgumentException
       private static final int DECREASE_SPEED = 2;
Figure 1. Running example:color");}} // required
                ("Invalid traffic a hypothetical drive-by-w
       private static final int STOP = 3;
       private static final int MAX_SPEED = 140;
       public void drive() is currently performing, idle by default ∗/
       /∗ The action this automobile {
 ch machinery.int currentAction = IDLE; example, in which
          TrafficSignal the weak enum ;
       private        Third, aSignal = ...
       /∗ The to manually enumerate initially 5 mph.language enum
 ogrammercurrent speed of the automobile,the
          int reaction = this.react(aSignal); ∗/   by
          if (reaction != this.currentAction &&
 ts, which increases the likelihood 5;
       private int currentSpeed = of
                (reaction != INCREASE_SPEED ||
                                                   and Automobile.
different enumint react(TrafficSignal signal) of these ne
       privatethis.currentSpeed unin-
                     constants may be <= MAX_SPEED)) {
                                                   ations
 he same internal value. Finally, the
                    this.performAction(reaction);}
          switch(signal.getColor()) {              through compile-tim
            case TrafficSignal.RED: return STOP;
rittle private void performAction(int action) {...}}named
        [?]:case TrafficSignal.YELLOW:
               since the values are com-           between the
at compile time they are to stop or go
                // decide whether inlined into     ated values. It is als
  new constants if(a)are added in constants for enumerated types., whic
                        Using integer
                     (this.shouldGo()) between     is an Action 44
this.currentAction &&
         case TrafficSignal.YELLOW:
    private int color = RED;
  class Automobile {
                                                 38 (reacti
 INCREASE_SPEED ||
    /∗ Accessor static final int go ∗/ Enums vs. Constants
     private
               Algorithmic Distinction: = 0;
            // decide whether current or
                for the light’s to stop color
tSpeed <= MAX_SPEED))                       IDLE
                                                 39  this.c
    publicif static final int INCREASE_SPEED = 1; this.
                 (this.shouldGo())               40
              int getColor() {return this.color;}}
rmAction(reaction);}
     private
                    return INCREASE_SPEED;               41
       private static final int DECREASE_SPEED = 2; void 42       private
                else return STOP;
 rmAction(int action) {
    class Automobile {...}} int STOP = 3;
       private static final                                                 (b) Im
            casestatic final int IDLE = no change
                     TrafficSignal.GREEN: // 0;
       private static final int MAX_SPEED = 140;
       private enumerated types.
eger constants for static final int INCREASE_SPEED = 1;
       private  return this.currentAction;
       /∗ The action this automobile is currently performing, idle by default ∗/
            default: throw new IllegalArgumentException
       private static final int DECREASE_SPEED = 2;
       private int currentAction = IDLE; // required
Figure 1. current speed oftraffic color");}} mph. ∗/ drive-by-w
       private static example: STOP = 3;
       /∗ The
               Running final int a hypothetical
                ("Invalid
                               the automobile, initially 5
       private static final int MAX_SPEED = 140;
       privatevoid drive() {
       public       int currentSpeed = 5;
       /∗ The action this automobile is currently performing, idle by default ∗/
 ch machinery.int currentAction = IDLE; example, in which
          TrafficSignal the weak enum ;
       private        Third, aSignal = ...
       private int react(TrafficSignal signal) {
 ogrammercurrent speed of the automobile,the{ 5 mph.language enum
       /∗ The to manually enumerate initially by ∗/
          int reaction = this.react(aSignal);
          switch(signal.getColor())
          if (reaction != this.currentAction &&
 ts, whichcaseint currentSpeed = ofreturn STOP;
       privateincreases the likelihood 5;
                     TrafficSignal.RED:
                (reaction != INCREASE_SPEED ||
                                                          and Automobile.
different enumint react(TrafficSignal signal) of these ne
             case constants may be unin-
       private       TrafficSignal.YELLOW:
                  this.currentSpeed <= MAX_SPEED)) {      ations
                // decide whether to stop or go {
 he same internal value. Finally, the
                    this.performAction(reaction);}
          switch(signal.getColor())
                if (this.shouldGo())
                                                          through compile-tim
            case TrafficSignal.RED: return STOP;
rittle private void performAction(int action) {...}}named
        [?]:case returnvalues are com-
               since the INCREASE_SPEED; between the
                     TrafficSignal.YELLOW:
at compile time they are to stop or go
                // decide whether STOP; into
                else return inlined                       ated values. It is als
                if(a)are added in constants for enumerated types., whic
                        Using integer
                     TrafficSignal.GREEN: // no change
             case (this.shouldGo())
  new constants                         between           is an Action 44
this.currentAction &&
         case TrafficSignal.YELLOW:
     private int color = RED;
    private int color = RED;
  class Automobile {
                                                  38 (reacti
 INCREASE_SPEED ||
    /∗ Accessor static final int go ∗/ Enums vs. Constants
     private
            // decide whether toDistinction:
               Algorithmiccurrentcolor ∗/
       Accessor for the light’s current or IDLE = 0;
                 for the light’s stop color
tSpeed <= MAX_SPEED))
                                                  39  this.c
    publicif static final int INCREASE_SPEED = 1; this.
                  (this.shouldGo())
     public int getColor() {return this.color;}}  40
               int getColor() {return this.color;}}
rmAction(reaction);}
     private
                    return INCREASE_SPEED;                 41
       private static final int DECREASE_SPEED = 2; void   42     private
                else return STOP;
             Automobile final
 rmAction(int action) {        {
    class Automobile {...}} int STOP = 3;
       private static                                                       (b) Im
            casestatic final int IDLE ==no change
                     TrafficSignal.GREEN: // 0;
       private static final int IDLE
       private static final int MAX_SPEED = 140;          0;
       private enumerated types.
eger constants for static final int INCREASE_SPEED ==1;
                return this.currentAction;
       private static final isint INCREASE_SPEED by default ∗/
       private this automobile currently performing, idle               1;
       /∗ The action
            default: throw new IllegalArgumentException
       private static final int DECREASE_SPEED ==2;
       private int currentActionDECREASE_SPEED
       private static final int = IDLE; // required 2;
Figure 1. current speed oftraffic color");}} mph. ∗/ drive-by-w
       private static example: STOP == 3;
       private static final int a hypothetical
       /∗ The
               Running final int STOP 3;
                ("Invalid
                                 the automobile, initially 5
       private static final int MAX_SPEED == 140;
       private int currentSpeed MAX_SPEED
       privatevoid drive() { int = 5;
       public
                    static final                                 140;
       /∗ The action this automobile is currently performing, idle by default ∗/∗/
              action Third, the weak enumperforming, idle by in which
                      this automobile is currently                     default
 ch machinery.int currentAction == IDLE; example,
       private int currentAction ... ;
          TrafficSignal aSignal =
       private int react(TrafficSignal signal) {   IDLE;
       private
 ogrammercurrent speed of the automobile,the{ 55mph.language enum
       /∗ The current speed of the automobile,initially by ∗/
       /∗ The to manually enumerate initially mph. ∗/
          int reaction = this.react(aSignal);
          switch(signal.getColor())
          if (reaction != this.currentAction &&
 ts, whichcaseint currentSpeed == ofreturn STOP;
       private int currentSpeed 5;
              increases the likelihood
       private TrafficSignal.RED:5;
                (reaction != INCREASE_SPEED ||
                                                            and Automobile.
different enumint react(TrafficSignal signal) of these ne
             case constants may be unin-
                     TrafficSignal.YELLOW:
                  this.currentSpeed <= MAX_SPEED)) {{
       private int react(TrafficSignal signal)
       private decide whether to stop or go
                                                            ations
                // this.performAction(reaction);}
 he same internal value. Finally, the{
          switch(signal.getColor()) {
          switch(signal.getColor())
                if (this.shouldGo())
                                                            through compile-tim
            case TrafficSignal.RED: return STOP;
rittle private void performAction(int action) {...}}named
        [?]:case returnvalues are com-return STOP; the
               since the INCREASE_SPEED; between
             case TrafficSignal.RED:
             case TrafficSignal.YELLOW:
                     TrafficSignal.YELLOW:
at compile time return to stop or go
                // decide whether STOP; into
                else they are to stop or go
                // decide whether inlined                   ated values. It is als
                if(a)are added in constants for enumerated types., whic
                        Using integer
                     TrafficSignal.GREEN: // no change
             case (this.shouldGo())
  new constants (this.shouldGo())
                if                       between            is an Action 44
this.currentAction &&
         case TrafficSignal.YELLOW:
     private int color = RED;
    private int color = RED;
  class Automobile {
                                               38   (reacti
 INCREASE_SPEED ||
  class Automobile final int go ∗/ Enums vs. Constants
       Accessor for the light’s toDistinction:
     private
               Algorithmic stop color
    /∗ Accessor static { current or IDLE = 0;
            // decide whether currentcolor ∗/
                 for the light’s
tSpeed <= MAX_SPEED))
                                               39    this.c
    publicif static final int IDLE this.color;}}1; this.
                  (this.shouldGo())
     public int getColor() int INCREASE_SPEED =40
               int getColor() {return this.color;}}
     private static
rmAction(reaction);} final
     private                         {return = 0;
                    return INCREASE_SPEED;              41
       private static final int INCREASE_SPEED = 1; void
       private static final int DECREASE_SPEED = 2;     42      private
                else return STOP;
             Automobile final
 rmAction(int action) {       {
    class Automobile {...}} int DECREASE_SPEED = 2;


                                                                  ?
       private static final int STOP = 3;
       private static                                                   (b) Im
            casestatic final int IDLE ==no change
                     TrafficSignal.GREEN: // 0;
       private static final int IDLE
       private static final int STOP                    0;
                                                        3;
       private enumerated types.             MAX_SPEED = 140;
eger constants for static final int INCREASE_SPEED ==1;
                return this.currentAction;
       private static final isint INCREASE_SPEED by default ∗/
       private this automobile currently performing, idle
                                             MAX_SPEED = 140; 1;
       /∗ The action
            default: throw new currently performing, idle
       /∗ The action this automobile int IllegalArgumentException
       private static final isint DECREASE_SPEED ==2;
       private int currentActionDECREASE_SPEED by default ∗/
                    static final
       private                                = IDLE; // required 2;
Figure 1. current speed oftraffic color");}} mph. ∗/ drive-by-w
       private static example: STOPIDLE;
               Running final int a =initially3;
                ("Invalid final int hypothetical
       private int currentActionSTOP == 3;
       /∗ The       static the automobile,              5
       private static of the automobile, initially 5 mph.140;
       private int currentSpeed MAX_SPEED == 140;
       /∗ The current speed final int MAX_SPEED
       privatevoid drive() { int = 5;
                    static final
       public int automobile is currently5;
                                                                ∗/
       /∗ The action this currentSpeed = performing, idle by default ∗/∗/
       private Third, the weak enumperforming, idle by in which
              action this automobile is currently                   default
 ch machinery.int currentAction == IDLE; example,
       private int currentAction ... ;
          TrafficSignal aSignal =
       private int react(TrafficSignal signal) {  IDLE;
       private
       /∗ The current speed of the automobile,initially 5by language enum
 ogrammercurrent speed of the automobile,the{ 5signal) {
       /∗ The to manually enumerate initially mph. ∗/
          int reaction = this.react(aSignal); ∗/
       private int react(TrafficSignal
          switch(signal.getColor())                        mph.
          if (reaction != this.currentAction &&
 ts, whichcaseint currentSpeed == ofreturn STOP;
       private int currentSpeed 5;{
              increases the likelihood
       private TrafficSignal.RED:5;
          switch(signal.getColor())
                (reaction != INCREASE_SPEED ||
                                                         and Automobile.
             case constants may be unin-return STOP; these ne
                     TrafficSignal.RED:
different enum int react(TrafficSignal signal){{
             caseint react(TrafficSignal signal) of
                     TrafficSignal.YELLOW:               ations
                  this.currentSpeed <= MAX_SPEED))
       private TrafficSignal.YELLOW:
       private decide whether to stop or go
             case
                // this.performAction(reaction);}
 he same internal value. to stop or go {{
                // decide whether Finally, the
          switch(signal.getColor())
          switch(signal.getColor())
                if (this.shouldGo())
                                                         through compile-tim
            case TrafficSignal.RED: return STOP;
rittle private void performAction(int action) {...}}named
        [?]:case returnvalues are com-return STOP; the
               since the INCREASE_SPEED; between
             case TrafficSignal.RED:
                if (this.shouldGo())
                     TrafficSignal.YELLOW:
             casereturn INCREASE_SPEED;
                     TrafficSignal.YELLOW:
at compile time return to stop or go
                // decide whether STOP; into
                else they are to stop or go
                                  inlined
                // decide whether STOP;                  ated values. It is als
                else Using integer constants for enumerated types.
                   (a) return
                if TrafficSignal.GREEN: // nois an Action, whic
             case (this.shouldGo())                        change
  new constants (this.shouldGo())
                if are added in between                                     44
this.currentAction && {
  class case int color = RED;
          Automobile
     private TrafficSignal.YELLOW:
    private int color = RED;
  class Automobile {
 INCREASE_SPEED ||
                                             38         (reacti
     private decide whether toDistinction: Enums vs. Constants
                static final int IDLE = 0;
            // Algorithmiccurrentor go ∗/
       Accessor for the light’s stop color
                for the light’s                          this.c
    /∗ Accessor static { current color ∗/
  class Automobile final int IDLE = 0;
     private static
                                             39
tSpeed <= MAX_SPEED)) final int INCREASE_SPEED = 1;
     privateint getColor() {return this.color;}} this.
    publicif static final int IDLE this.color;}}1;
                 (this.shouldGo())
     private static final                    40
     public int getColor() int INCREASE_SPEED =
                                   {return = 0;
rmAction(reaction);} final int DECREASE_SPEED = 2;
     private static
     private         return INCREASE_SPEED;                41
       private static final int INCREASE_SPEED = 1; void
       private static final int DECREASE_SPEED = 2;
       private static { STOP;   final int STOP = 3;        42      private
                else return
             Automobile {
    class Automobile final int STOP = 3;


                                                                   ?
 rmAction(int action) {...}} int DECREASE_SPEED = 2;
       private static final int MAX_SPEED = 140;
       private static final
       private static final int IDLE ==no change
                     static
            case static final int IDLE // 0;
                      TrafficSignal.GREEN:                                 (b) Im
       private static final int STOP
       private                                             0;
                                                           3;
       private enumerated types. currently performing, idle by default ∗/
                                               MAX_SPEED = 140;
eger constantsaction this automobile isint INCREASE_SPEED ==1;
       /∗ The for static final int INCREASE_SPEED
                return this.currentAction;
       private static final is currently performing, idle by default ∗/
       private this automobile                 MAX_SPEED = 140; 1;
       /∗ The action
       private static final int DECREASE_SPEED
            default: currentAction = IDLE;
                     int throw new IllegalArgumentException
       private static final isint DECREASE_SPEED ==2;
       private int currentAction = IDLE;                                2;
       /∗ The action this automobile currently performing, idle by default ∗/
       private
       private static of the automobile,hypothetical
       /∗ The current speed example: STOP == 3; mph. ∗/
                                                  initially 5
Figure 1. current speed oftraffic color");}} mph. ∗/ drive-by-w
               Running final int a =initially3; // required
                ("Invalid final int STOP
       private int currentAction
                     static the automobile, IDLE;
       /∗ The
       private static final int MAX_SPEED == 140;
                     int currentSpeed MAX_SPEED= 5;         5
       private static of the automobile, initially 5 mph.140;
       private int currentSpeed = 5;
       /∗ The current speed final int                              ∗/
       privatevoid drive() {
       public int automobile is currently5;
       /∗ The action this currentSpeed = performing, idle by default ∗/∗/
       private int react(TrafficSignal signal) by in which
              action Third, the weak enumperforming, idle default
                       this automobile is currently
 ch machinery.int currentAction == IDLE; example,
       private
       private int currentAction ... ;
          TrafficSignal aSignal =
       private int react(TrafficSignal signal) {    IDLE;             {
       private
       /∗ The current speed of the automobile,initially 5by language enum
 ogrammercurrent speed of the automobile,the{ 5signal) {
          int to manually enumerate initially mph. ∗/
          switch(signal.getColor()) {
       /∗ The reaction = this.react(aSignal); ∗/
       private int react(TrafficSignal
          switch(signal.getColor())                           mph.
          if caseint currentSpeed = 5;return STOP;
                      TrafficSignal.RED:5;
              (reaction != this.currentAction &&
       private int currentSpeed = of{
 ts, whichcase TrafficSignal.RED: return STOP;
       privateincreases the likelihood
          switch(signal.getColor())
             case TrafficSignal.YELLOW:
                (reaction != INCREASE_SPEED ||
                                                             and Automobile.
             case constants may beor go return STOP; these ne
                      TrafficSignal.RED:
different enum int react(TrafficSignal signal){{
             caseint react(TrafficSignal signal) of
                 //this.currentSpeed unin-
                      TrafficSignal.YELLOW:
                    decide whether to stop <= MAX_SPEED))    ations
       private TrafficSignal.YELLOW:
       private decide whether to stop or go
             case (this.shouldGo())
                // this.performAction(reaction);}
                 if
 he same internal value. to stop or go {{
                // decide whether Finally, the
          switch(signal.getColor())
          switch(signal.getColor())
                if TrafficSignal.RED: return STOP;
                      (this.shouldGo())
                                                             through compile-tim
            case return INCREASE_SPEED;
rittle private void performAction(int action) {...}}named
        [?]:case returnvalues are com-return STOP; the
               since the INCREASE_SPEED; between
             case TrafficSignal.RED:
                if (this.shouldGo())
                 else return STOP;
                      TrafficSignal.YELLOW:
             casereturn INCREASE_SPEED;
                      TrafficSignal.YELLOW:
at compile timeTrafficSignal.GREEN: // noated values. It is als
                else they are to stop or go
             case         return STOP; into
                                   inlined
                // decide whether to stop or go
                // decide whether STOP;                       change
                else Using integer constants for enumerated types.
                    (a) return
                if TrafficSignal.GREEN: // nois an Action, whic
                 return this.currentAction; change
             case (this.shouldGo())
  new constants (this.shouldGo())
                if are added in between                                        44
this.currentAction && {
  class case int color = RED;
          Automobile
     private TrafficSignal.YELLOW:
    private int color = RED;
  class Automobile {
 INCREASE_SPEED ||
                                             38         (reacti
     private decide whether toDistinction: Enums vs. Constants
                static final int IDLE = 0;
            // Algorithmiccurrentor go ∗/
       Accessor for the light’s stop color
                for the light’s                          this.c
    /∗ Accessor static { current color ∗/
  class Automobile final int IDLE = 0;
     private static
                                             39
tSpeed <= MAX_SPEED)) final int INCREASE_SPEED = 1;
     privateint getColor() {return this.color;}} this.
    publicif static final int IDLE this.color;}}1;
                 (this.shouldGo())
     private static final                    40
     public int getColor() int INCREASE_SPEED =
                                   {return = 0;
rmAction(reaction);} final int DECREASE_SPEED = 2;
     private static
     private         return INCREASE_SPEED;                41
       private static final int INCREASE_SPEED = 1; void
       private static final int DECREASE_SPEED = 2;
       private static { STOP;   final int STOP = 3;        42      private
                else return
             Automobile {
    class Automobile final int STOP = 3;
 rmAction(int action) {...}} int DECREASE_SPEED = 2;
       private static final int MAX_SPEED = 140;
       private static final
       private static final int IDLE ==no change
                     static                                                (b) Im
            case static final int IDLE // 0;
       private        TrafficSignal.GREEN:
       private static final int STOP                       0;
                                                           3;
       private enumerated types. currently performing, idle by default ∗/
                                               MAX_SPEED = 140;
eger constantsaction this automobile isint INCREASE_SPEED ==1;
       /∗ The for static final int INCREASE_SPEED
                return this.currentAction;
       private static final is currently performing, idle by default ∗/
       private this automobile                 MAX_SPEED = 140; 1;
       /∗ The action
       private static final int DECREASE_SPEED
            default: currentAction = IDLE;
                     int throw new IllegalArgumentException
       private static final isint DECREASE_SPEED ==2;
       private int currentAction = IDLE;                                2;
       /∗ The action this automobile currently performing, idle by default ∗/
       private
       private static of the automobile,hypothetical
       /∗ The current speed example: STOP == 3; mph. ∗/
                                                  initially 5
Figure 1. current speed oftraffic color");}} mph. ∗/ drive-by-w
               Running final int a =initially3; // required
                ("Invalid final int STOP
       private int currentAction
                     static the automobile, IDLE;
       /∗ The
       private static final int MAX_SPEED == 140;
                     int currentSpeed MAX_SPEED= 5;         5
       private static of the automobile, initially 5 mph.140;
       private int currentSpeed = 5;
       /∗ The current speed final int                              ∗/
       privatevoid drive() {
       public int automobile is currently5;
       /∗ The action this currentSpeed = performing, idle by default ∗/∗/
       private int react(TrafficSignal signal) by in which
              action Third, the weak enumperforming, idle default
                       this automobile is currently
 ch machinery.int currentAction == IDLE; example,
       private
       private int currentAction ... ;
          TrafficSignal aSignal =
       private int react(TrafficSignal signal) {    IDLE;             {
       private
       /∗ The current speed of the automobile,initially 5by language enum
 ogrammercurrent speed of the automobile,the{ 5signal) {
          int to manually enumerate initially mph. ∗/
          switch(signal.getColor()) {
       /∗ The reaction = this.react(aSignal); ∗/
       private int react(TrafficSignal
          switch(signal.getColor())                           mph.
          if caseint currentSpeed = 5;return STOP;
                      TrafficSignal.RED:5;
              (reaction != this.currentAction &&
       private int currentSpeed = of{
 ts, whichcase TrafficSignal.RED: return STOP;
       privateincreases the likelihood
          switch(signal.getColor())
             case TrafficSignal.YELLOW:
                (reaction != INCREASE_SPEED ||
                                                             and Automobile.
             case constants may beor go return STOP; these ne
                      TrafficSignal.RED:
different enum int react(TrafficSignal signal){{
             caseint react(TrafficSignal signal) of
                 //this.currentSpeed unin-
                      TrafficSignal.YELLOW:
                    decide whether to stop <= MAX_SPEED))    ations
       private TrafficSignal.YELLOW:
       private decide whether to stop or go
             case (this.shouldGo())
                // this.performAction(reaction);}
                 if
 he same internal value. to stop or go {{
                // decide whether Finally, the
          switch(signal.getColor())
          switch(signal.getColor())
                if TrafficSignal.RED: return STOP;
                      (this.shouldGo())
                                                             through compile-tim
            case return INCREASE_SPEED;
rittle private void performAction(int action) {...}}named
        [?]:case returnvalues are com-return STOP; the
               since the INCREASE_SPEED; between
             case TrafficSignal.RED:
                if (this.shouldGo())
                 else return STOP;
                      TrafficSignal.YELLOW:
             casereturn INCREASE_SPEED;
                      TrafficSignal.YELLOW:
at compile timeTrafficSignal.GREEN: // noated values. It is als
                else they are to stop or go
             case         return STOP; into
                                   inlined
                // decide whether to stop or go
                // decide whether STOP;                       change
                else Using integer constants for enumerated types.
                    (a) return
                if TrafficSignal.GREEN: // nois an Action, whic
                 return this.currentAction; change
             case (this.shouldGo())
  new constants (this.shouldGo())
                if are added in between                                        44
µ(P)     {m | m "* % 1)!0#- "$ P}
 υ(P)                  Top-level Enumerization Algorithm
          {l | l "* % '%2"%,&) "$ P}
 α        '%2"%,&)/ !)&-/ 1)!0#-
 αctxt    30"+$5+ "$ 40"+0 α 1%. #++(2
            !"#$%& '( !)%*+,"-* .)/+/").(
.',/&4$'& Enumerize(F, P)
 >A R ← Enumerizable(F )

 QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R)

 GA 5,' *22 T ∈ R 4,

 RA  T ransf orm(T )
 ?A &#4 5,'


   !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*(

2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+
"-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&.
                                                        45
µ(P)      {m | m "* % 1)!0#- "$ P}
 υ(P)                   Top-level Enumerization Algorithm
           {l | l "* % '%2"%,&) "$ P}
 α         '%2"%,&)/ !)&-/ 1)!0#-
                                               ic
 αctxt     30"+$5+ "$ 40"+0 α 1%. #++(2     at
                                       of st ds
                                     et l fiel
                                   bs a
              !"#$%& '( !)%*+,"-* .)/+/").(
                                 Su in
.',/&4$'& Enumerize(F, P) f
 >A R ← Enumerizable(F )

 QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R)

 GA 5,' *22 T ∈ R 4,

 RA  T ransf orm(T )
 ?A &#4 5,'


   !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*(

2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+
"-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&.
                                                        45
µ(P)      {m | m "* % 1)!0#- "$ P}
 υ(P)                   Top-level Enumerization Algorithm
           {l | l "* % '%2"%,&) "$ P}
 α         '%2"%,&)/ !)&-/ 1)!0#-
 αctxt     30"+$5+ "$ 40"+0 α 1%. #++(2
          Orig
                inal P
              !"#$%&g '( !)%*+,"-* .)/+/").(
                      ro ra
.',/&4$'& Enumerize(F,     m P)
 >A R ← Enumerizable(F )

 QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R)

 GA 5,' *22 T ∈ R 4,

 RA  T ransf orm(T )
 ?A &#4 5,'


   !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*(

2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+
"-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&.
                                                        45
µ(P)      {m | m "* % 1)!0#- "$ P}
 υ(P)                   Top-level Enumerization Algorithm
           {l | l "* % '%2"%,&) "$ P}
 α         '%2"%,&)/ !)&-/ 1)!0#-
 αctxt     30"+$5+ "$ 40"+0 α 1%. #++(2Infers which
              !"#$%& '( !)%*+,"-* .)/+/").( being
                                    candidate fields are
.',/&4$'& Enumerize(F, P)               used as enums
 >A R ← Enumerizable(F )

 QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R)

 GA 5,' *22 T ∈ R 4,

 RA  T ransf orm(T )
 ?A &#4 5,'


   !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*(

2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+
"-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&.
                                                        45
µ(P)     {m | m "* % 1)!0#- "$ P}
 υ(P)                  Top-level Enumerization Algorithm
          {l | l "* % '%2"%,&) "$ P}
 α        '%2"%,&)/ !)&-/ 1)!0#-
 αctxt    30"+$5+ "$ 40"+0 α 1%. #++(2
            !"#$%& '( !)%*+,"-* .)/+/").(
.',/&4$'& Enumerize(F, P)
 >A R ← Enumerizable(F )

 QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R)

 GA 5,' *22 T ∈ R 4,

 RA  T ransf orm(T )               Groups
 ?A &#4 5,'
                            them into minimal sets

   !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*(

2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+
"-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&.
                                                        45
µ(P)     {m | m "* % 1)!0#- "$ P}
 υ(P)                  Top-level Enumerization Algorithm
          {l | l "* % '%2"%,&) "$ P}
 α        '%2"%,&)/ !)&-/ 1)!0#-
 αctxt    30"+$5+ "$ 40"+0 α 1%. #++(2
            !"#$%& '( !)%*+,"-* .)/+/").(
.',/&4$'& Enumerize(F, P)
 >A R ← Enumerizable(F )

 QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R)

 GA 5,' *22 T ∈ R 4,

 RA  T ransf orm(T )
 ?A &#4 5,'


   !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*(

2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+
"-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&.
                                                        45
µ(P)     {m | m "* % 1)!0#- "$ P}
 υ(P)                  Top-level Enumerization Algorithm
          {l | l "* % '%2"%,&) "$ P}
 α        '%2"%,&)/ !)&-/ 1)!0#-
 αctxt    30"+$5+ "$ 40"+0 α 1%. #++(2
            !"#$%& '( !)%*+,"-* .)/+/").(
.',/&4$'& Enumerize(F, P)
 >A R ← Enumerizable(F )

 QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R)

 GA 5,' *22 T ∈ R 4,

 RA  T ransf orm(T )
 ?A &#4 5,'


   !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*(

2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+
"-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&.
                                                        45
µ(P)     {m | m "* % 1)!0#- "$ P}
 υ(P)                  Top-level Enumerization Algorithm
          {l | l "* % '%2"%,&) "$ P}
 α        '%2"%,&)/ !)&-/ 1)!0#-
 αctxt    30"+$5+ "$ 40"+0 α 1%. #++(2
            !"#$%& '( !)%*+,"-* .)/+/").(
.',/&4$'& Enumerize(F, P)
 >A R ← Enumerizable(F )

 QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R)

 GA 5,' *22 T ∈ R 4,

 RA  T ransf orm(T )
 ?A &#4 5,'


   !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*(

2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+
"-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&.
                                                        45
µ(P)     {m | m "* % 1)!0#- "$ P}
 υ(P)                  Top-level Enumerization Algorithm
          {l | l "* % '%2"%,&) "$ P}
 α        '%2"%,&)/ !)&-/ 1)!0#-
 αctxt    30"+$5+ "$ 40"+0 α 1%. #++(2
            !"#$%& '( !)%*+,"-* .)/+/").(
.',/&4$'& Enumerize(F, P)
 >A R ← Enumerizable(F )

 QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R)

 GA 5,' *22 T ∈ R 4,

 RA  T ransf orm(T )
 ?A &#4 5,'


   !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*(
                   Natural
                  ordering
2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+
"-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&.
                                                        45
Empirical Evaluation
 Benchmark      KLOC   Classes    Sites   Time (s)
ArtOfIllusion    75     378       111       207
  Azureus       272     1894       635     1269
    java5       180     1586       572      760
  JavaCup        6       41         3       19
  jdepend        3       28         1        1
    JFlex        10      46        27       75
 JFreeChart      71     420        43       128
    jGap         6      137         5        7
   jgraph        14      91         6       11
 JHotDraw        29     496        24       14
    junit        8      271         3        1
    jwps         20     155        102      60
  sablecc        29     237        10        9
  tomcat6       153     1164       400      346
   verbos        5       41        15        3
  VietPad        11      84        22        8
   Violet        7       73        20        9
   Totals       899     7142      1999     2227
                                                     46
Empirical Evaluation
 Benchmark      KLOC   Classes      Sites   Time (s)
ArtOfIllusion    75     378         111       207
  Azureus       272     1894        635      1269
    java5       180     1586        572       760
  JavaCup        6       41          3        19
  jdepend        3       28          1         1
    JFlex        10      46          27       75
 JFreeChart      71     420          43       128
    jGap         6      137          5         7
   jgraph        14      91          6        11
 JHotDraw        29     496          24       14
    junit        8      271          3         1
    jwps         20     155         102       60
  sablecc        29     237          10        9
  tomcat6       153     1164        400       346
   verbos        5       41          15        3
  VietPad        11      84    2.4 / KLOC
                                      22       8
   Violet        7       73          20        9
   Totals       899     7142        1999     2227
                                                       46
Empirical Evaluation
 Benchmark      KLOC       Classes    Sites   Time (s)
ArtOfIllusion    75         378       111       207
  Azureus       272         1894       635     1269
    java5       180
                       384 sites /
                           1586        572      760
  JavaCup        6     Benchmark
                            41          3       19
  jdepend        3           28         1        1
    JFlex        10          46        27       75
 JFreeChart      71         420        43       128
    jGap         6          137         5        7
   jgraph        14          91         6       11
 JHotDraw        29         496        24       14
    junit        8          271         3        1
    jwps         20         155        102      60
  sablecc        29         237        10        9
  tomcat6       153         1164       400      346
   verbos        5           41        15        3
  VietPad        11          84        22        8
   Violet        7           73        20        9
   Totals       899         7142      1999     2227
                                                         46
Filtered Contexts




               47
Filtered Contexts


• Certain fields cannot be refactored.




                                                        47
Filtered Contexts


• Certain fields cannot be refactored.
 • Program semantics preservation depends on the
   actual values of these fields.




                                                   47
Filtered Contexts


• Certain fields cannot be refactored.
 • Program semantics preservation depends on the
   actual values of these fields.
  • For example, named-constants (used in
    mathematical calculations).




                                                   47
Filtered Contexts


• Certain fields cannot be refactored.
 • Program semantics preservation depends on the
   actual values of these fields.
  • For example, named-constants (used in
    mathematical calculations).
 • Transitive dependency of an element outside
   available source code.




                                                    47
Filtered Contexts


• Certain fields cannot be refactored.
 • Program semantics preservation depends on the
   actual values of these fields.
  • For example, named-constants (used in
    mathematical calculations).
 • Transitive dependency of an element outside
   available source code.
 • Language constraints prohibit enumerization.
                                                    47
Filtered Contexts


• Certain fields cannot be refactored.
 • Program semantics preservation depends on the
   actual values of these fields.
  • For example, named-constants (used in
    mathematical calculations).
 • Transitive dependency of an element outside
   available source code.
 • Language constraints prohibit enumerization.
• Remaining fields denoted as candidates.
                                                     47
Filtered Contexts


• Certain fields cannot be refactored.
 • Program semantics preservation depends on the
   actual values of these fields.
  • For example, named-constants (used in
    mathematical calculations).
 • Transitive dependency of an element outside
                                         arr[RED]
   available source code.
 • Language constraints prohibit enumerization.
• Remaining fields denoted as candidates.
                                                     47
Filtered Contexts


• Certain fields cannot be refactored.
 • Program semantics preservation depends on the
   actual values of these fields.
  • For example, named-constants (used in
    mathematical calculations).
 • Transitive dependency of an element outside
   available source code.
 • Language constraints prohibit enumerization.
• Remaining fields denoted as candidates.
                                                     47
Enum Identification Effectiveness




cands               enum               48
Enum Identification Effectiveness
                       0    140          280          420       560
ArtOfIllusion
    Azureus
         java5
     JavaCup
      jdepend
           JFlex
   JFreeChart
            jGap
          jgraph
     JHotDraw
             junit
              jwps
          sablecc
         tomcat6
            verbos
            VietPad
              Violet




                           cands               enum               48
Enum Identification Effectiveness
                       0    140          280          420       560
ArtOfIllusion
    Azureus
         java5
     JavaCup
      jdepend
           JFlex
   JFreeChart
            jGap
          jgraph                                  Refactored
     JHotDraw
             junit                                   87%
              jwps
          sablecc
         tomcat6
            verbos
            VietPad
              Violet




                           cands               enum               48
Result Summary




            49
Result Summary




• 37% of all primitive constant fields identified as
  candidates.




                                                       49
Result Summary




• 37% of all primitive constant fields identified as
  candidates.
• 87% of candidate fields found safe for refactoring.




                                                        49
Result Summary




• 37% of all primitive constant fields identified as
  candidates.
• 87% of candidate fields found safe for refactoring.
• Remaining 13% required more sophisticated analysis:



                                                       49
Result Summary




• 37% of all primitive constant fields identified as
  candidates.
• 87% of candidate fields found safe for refactoring.
• Remaining 13% required more sophisticated analysis:
 • Explicit primitive conversion analysis (casts).


                                                       49
Result Summary




• 37% of all primitive constant fields identified as
  candidates.
• 87% of candidate fields found safe for refactoring.
• Remaining 13% required more sophisticated analysis:
 • Explicit primitive conversion analysis (casts).
 • Native array copying method usage.

                                                       49
Related Work




          50
Related Work



• Fowler [99] and Kerievsky [04] present a RE- PLACE
 TYPE CODE WITH CLASS refactoring.




                                                   50
Related to a
                                     Manual, not  Work
                                   language enum type,
                                     and no inference

• Fowler [99] and Kerievsky [04] present a RE- PLACE
 TYPE CODE WITH CLASS refactoring.




                                                    50
Related Work



• Fowler [99] and Kerievsky [04] present a RE- PLACE
 TYPE CODE WITH CLASS refactoring.
• Deursen and Moonen [IWPC 99] identify
 enumerated types in COBOL.




                                                   50
Related Work

      Different
      semantics
•   preservation
    Fowler [99] and Kerievsky [04] present a RE- PLACE
    Tconstraints WITH CLASS refactoring.
     YPE CODE

• Deursen and Moonen [IWPC 99] identify
    enumerated types in COBOL.




                                                     50
Related Work



• Fowler [99] and Kerievsky [04] present a RE- PLACE
 TYPE CODE WITH CLASS refactoring.
• Deursen and Moonen [IWPC 99] identify
 enumerated types in COBOL.
• Gravley and Lakhotia [WCRE 96] identify
 enumerated types in C.




                                                   50
Related Work



• Fowler [99] and Kerievsky [04] present a RE- PLACE
    TYPE CODE WITH CLASS refactoring.
•   Deursen and Moonen [IWPC 99] identify  No
                                       transitivity
    enumerated types in COBOL.
• Gravley and Lakhotia [WCRE 96] identify
    enumerated types in C.




                                                      50
Related Work



• Fowler [99] and Kerievsky [04] present a RE- PLACE
 TYPE CODE WITH CLASS refactoring.
• Deursen and Moonen [IWPC 99] identify
 enumerated types in COBOL.
• Gravley and Lakhotia [WCRE 96] identify
 enumerated types in C.
• Lawal and Lo [ASE 10] also identify enumerated
 types in C, specifically, in Linux kernel.

                                                        50
Related Work



• Fowler [99] and Kerievsky [04] present a RE- PLACE
 TYPE CODE WITH CLASS refactoring.
• Deursen and Moonen [IWPC 99] identify
 enumerated types in COBOL.
• Gravley and Lakhotia [WCRE 96] identify
 enumerated types in C.
• Lawal and Lo [ASE 10] also identify enumerated
 types in C, specifically, in Linux kernel.
                                                  Intra-
                                                procedural
                                                             50
Conclusions




         51
Conclusions


• Semantics preserving, declarative type inferencing
 algorithm migrating legacy Java code to the enum
 language construct introduced in Java 5.




                                                       51
Conclusions


• Semantics preserving, declarative type inferencing
 algorithm migrating legacy Java code to the enum
 language construct introduced in Java 5.
• Implemented algorithm as a plug-in for the Eclipse
 IDE and evaluated it on 17 open source applications:




                                                        51
Conclusions


• Semantics preserving, declarative type inferencing
 algorithm migrating legacy Java code to the enum
 language construct introduced in Java 5.
• Implemented algorithm as a plug-in for the Eclipse
 IDE and evaluated it on 17 open source applications:
 • Analysis cost is practical.



                                                        51
Conclusions


• Semantics preserving, declarative type inferencing
 algorithm migrating legacy Java code to the enum
 language construct introduced in Java 5.
• Implemented algorithm as a plug-in for the Eclipse
 IDE and evaluated it on 17 open source applications:
 • Analysis cost is practical.
 • Weak enum pattern is commonly used in legacy
   Java software.



                                                        51
Conclusions


• Semantics preserving, declarative type inferencing
 algorithm migrating legacy Java code to the enum
 language construct introduced in Java 5.
• Implemented algorithm as a plug-in for the Eclipse
 IDE and evaluated it on 17 open source applications:
 • Analysis cost is practical.
 • Weak enum pattern is commonly used in legacy
   Java software.
 • Proposal successfully refactors a large number of
   static final fields into enumerated types.
                                                         51
Reasoning about Evolving AO Programs




                                  52
Reasoning about Evolving AO Programs




• AOP enables modular implementation of CCCs.




                                                52
Reasoning about Evolving AO Programs




• AOP enables modular implementation of CCCs.
• Both formal and informal reasoning about AOP
 presents unique challenges especially in respect to
 evolution.




                                                       52
Reasoning about Evolving AO Programs




• AOP enables modular implementation of CCCs.
• Both formal and informal reasoning about AOP
 presents unique challenges especially in respect to
 evolution.
• As components enter, exit, and re-enter software,
 conclusions about behavior of components may be
 invalidated.


                                                       52
C


53
A




C


53
A




C


53
A




C


53
A




     C

Behavior of C+A
       53
C

Behavior of C+A
       53
C

Behavior of C+A




      53
C

    Behavior of C+A




                      53
C




53
The Invasiveness of AOP




                     54
The Invasiveness of AOP




• Desire a compositional reasoning approach, however
 the invasive nature of AOP makes this difficult.




                                                    54
The Invasiveness of AOP




• Desire a compositional reasoning approach, however
 the invasive nature of AOP makes this difficult.
• In the worst case, changes made to a single
 component require reexamining the entire program.




                                                     54
Research Questions




                55
Research Questions



• Can we draw meaningful conclusions about
 component code without considering the actual
 advice code?




                                                 55
Research Questions



• Can we draw meaningful conclusions about
 component code without considering the actual
 advice code?
• Can we specify the behavior of components without
 any particular advice in mind?




                                                      55
Research Questions



• Can we draw meaningful conclusions about
 component code without considering the actual
 advice code?
• Can we specify the behavior of components without
 any particular advice in mind?
• Can we parameterize specifications over all possibly
 applicable aspects?




                                                         55
Research Questions



• Can we draw meaningful conclusions about
 component code without considering the actual
 advice code?
• Can we specify the behavior of components without
 any particular advice in mind?
• Can we parameterize specifications over all possibly
 applicable aspects?
• Can we suitably constrain the behavior of aspects as
 the software evolves?

                                                         55
Hiding Behind Interfaces




                      56
Hiding Behind Interfaces




• Using interface is
 one answer (e.g.,
 XPIs [Griswold
 ’06], Open Modules
 [Aldrich ’05])




                                             56
Hiding Behind Interfaces




• Using interface is
 one answer (e.g.,
 XPIs [Griswold
 ’06], Open Modules
 [Aldrich ’05])

• But it would be nice
 to have a way to
 derive the enriched
 behavior of the base
 plus the aspects at
 compile time.                                 56
Contributions




           57
Contributions




• Developed an approach to specify the behavior of
 aspects so that:




                                                     57
Contributions




• Developed an approach to specify the behavior of
 aspects so that:
 • They can be combined with the behavior of the base-
   code to arrive at the overall system behavior




                                                     57
Contributions




• Developed an approach to specify the behavior of
 aspects so that:
 • They can be combined with the behavior of the base-
   code to arrive at the overall system behavior
 • Are not invalidated upon evolution.


                                                     57
Contributions




• Developed an approach to specify the behavior of
 aspects so that:
 • They can be combined with the behavior of the base-
   code to arrive at the overall system behavior
 • Are not invalidated upon evolution.
• Inspired subsequent work by Bagherzadeh et al.
 [AOSD 11].


                                                     57
Proposal




     58
Proposal




• AO programs inherently enjoy plug-n-play
 capabilities [Laddad ’03]




                                                  58
Proposal




• AO programs inherently enjoy plug-n-play
 capabilities [Laddad ’03]
• Crosscutting features can be plugged-in to enrich the
 behavior of advised components.




                                                      58
Proposal




• AO programs inherently enjoy plug-n-play
 capabilities [Laddad ’03]
• Crosscutting features can be plugged-in to enrich the
 behavior of advised components.
• My proposal involves developing an reasoning
 technique that enables developers to specify
 components so that their behaviors can be derive in a
 similar fashion.


                                                      58
C
Spec(C)

  C
Spec(C)




  C
Spec(C)




  C
Spec(C)




A1     C       A2
Spec(C)




Spec(A1 )             Spec(A2 )

   A1         C         A2
Spec(A1 )   Spec(C)   Spec(A2 )
Spec(A1 )          Spec(C)   Spec(A2 )

      Compose




Behavior of C+A1
Spec(A1 )          Spec(C)    Spec(A2 )

      Compose




                                   Compose
Behavior of C+A1             Behavior of C+A2
Spec(A1 )             Spec(C)             Spec(A2 )

      Compose




                           Compose




                                               Compose
Behavior of C+A1   Behavior of C+A1+A2   Behavior of C+A2
Obstacles




      60
Obstacles




• Usefulness




                     60
Obstacles




• Usefulness
 • Is it possible to draw meaningful conclusions from
   such incomplete information?




                                                        60
Obstacles




• Usefulness
 • Is it possible to draw meaningful conclusions from
   such incomplete information?
• Obliviousness



                                                        60
Obstacles




• Usefulness
 • Is it possible to draw meaningful conclusions from
   such incomplete information?
• Obliviousness
 • Specifications contain “slots” for applications of
   crosscutting concerns.



                                                        60
Obstacles




      61
Obstacles


• Abstraction




                      61
Obstacles


• Abstraction
 • Competing forces:




                             61
Obstacles


• Abstraction
 • Competing forces:
   • Specs abstract internal details components,
    aspects directly manipulate them.




                                                    61
Obstacles


• Abstraction
 • Competing forces:
   • Specs abstract internal details components,
    aspects directly manipulate them.
• Composition



                                                    61
Obstacles


• Abstraction
 • Competing forces:
   • Specs abstract internal details components,
    aspects directly manipulate them.
• Composition
 • Which pegs go into which holes?


                                                    61
Obstacles


• Abstraction
 • Competing forces:
   • Specs abstract internal details components,
    aspects directly manipulate them.
• Composition
 • Which pegs go into which holes?
 • How to deal with dynamic and lexical pointcuts?

                                                     61
Obstacles


• Abstraction
 • Competing forces:
   • Specs abstract internal details components,
    aspects directly manipulate them.
• Composition
 • Which pegs go into which holes?
 • How to deal with dynamic and lexical pointcuts?
• Complexity
                                                     61
Obstacles


• Abstraction
 • Competing forces:
   • Specs abstract internal details components,
    aspects directly manipulate them.
• Composition
 • Which pegs go into which holes?
 • How to deal with dynamic and lexical pointcuts?
• Complexity
 • What if no advice is applicable?
                                                     61
Tackling Specification Complexity




                              62
Tackling Specification Complexity

• May need to make assumptions about the behavior of
 evolving components.




                                                   62
Tackling Specification Complexity

• May need to make assumptions about the behavior of
 evolving components.
• Specification pointcuts




                                                    62
Tackling Specification Complexity

• May need to make assumptions about the behavior of
 evolving components.
• Specification pointcuts
 • Pointcut interfaces [Gudmundson ’01] annotated
   with behavioral specifications.




                                                    62
Tackling Specification Complexity

• May need to make assumptions about the behavior of
 evolving components.
• Specification pointcuts
 • Pointcut interfaces [Gudmundson ’01] annotated
   with behavioral specifications.
 • “Exported” internal semantic events within the
   component.




                                                    62
Tackling Specification Complexity

• May need to make assumptions about the behavior of
 evolving components.
• Specification pointcuts
 • Pointcut interfaces [Gudmundson ’01] annotated
   with behavioral specifications.
 • “Exported” internal semantic events within the
   component.
 • Adopt a rely-guarantee approach [Xu ’97] from
   concurrent programming to constrain the behavior
   of all possibly applicable advice using a rely clause.

                                                        62
Tackling Specification Complexity

• May need to make assumptions about the behavior of
 evolving components.
• Specification pointcuts
 • Pointcut interfaces [Gudmundson ’01] annotated
   with behavioral specifications.
 • “Exported” internal semantic events within the
   component.
 • Adopt a rely-guarantee approach [Xu ’97] from
   concurrent programming to constrain the behavior
   of all possibly applicable advice using a rely clause.
 • A guar clause may be used to constrain components.   62
Review of R/G for AOP [Khatchadourian07,
                                Soundarajan07]



                the set of all variables of
     σ          the program

                states in which each
σi , σj , ...   variable has a particular
                value



                                              63
64
!1




!2




!3

 64
64
Techniques for Automated Software Evolution
!1

      Aspect




!2'




!3
66
!a

     Aspect




!b




              66
The state at a point in the execution
       of a component is σa.

      !a

                        Aspect




      !b




                                        66
The state at a point in the execution
       of a component is σa.

      !a

                        Aspect




      !b

The state when the class gets control
     back from an aspect is σb.
                                        66
The state at a point in the execution
       of a component is σa.

      !a

                        Aspect
  rely(σa, σb)


      !b

The state when the class gets control
     back from an aspect is σb.
                                        66
Rely() Example




rely(σ, σ ) ≡ (σ = σ )
                    




                             67
Rely() Example



         The entire state of
                 C


rely(σ, σ ) ≡ (σ = σ )
                                  




                                           67
Rely() Example




rely(σ, σ ) ≡ (σ = σ )
                                     

                           le y
                         ab an
                      lic g
                   pp kin e!
                 a a
               ny m stat
            s a om he
          id fr
        rb e          t
       o ic
      F v          in
         d ang  es
        a
          ch                                  67
Rely() Example

      This is
 “Harmless”[DW
     POPL’06]



rely(σ, σ ) ≡ (σ = σ )
                     




                              67
Deriving Effective Behavior




                        68
Deriving Effective Behavior


• Constraining parameterized behavior reduces
 complexity, but ...




                                                   68
Deriving Effective Behavior


• Constraining parameterized behavior reduces
 complexity, but ...
 • How are formal parameters expressed?




                                                   68
Deriving Effective Behavior


• Constraining parameterized behavior reduces
 complexity, but ...
 • How are formal parameters expressed?
 • How are actual parameters deduced?




                                                   68
Deriving Effective Behavior


• Constraining parameterized behavior reduces
 complexity, but ...
 • How are formal parameters expressed?
 • How are actual parameters deduced?
 • How are the specifications composed?



                                                   68
Deriving Effective Behavior


• Constraining parameterized behavior reduces
  complexity, but ...
 • How are formal parameters expressed?
 • How are actual parameters deduced?
 • How are the specifications composed?
• Aspects are typically used to enrich the behavior of
  the an underlying component.



                                                         68
Deriving Effective Behavior


• Constraining parameterized behavior reduces
  complexity, but ...
 • How are formal parameters expressed?
 • How are actual parameters deduced?
 • How are the specifications composed?
• Aspects are typically used to enrich the behavior of
  the an underlying component.
• Thus, desire to derive the actual behavior of
  components combined with the aspects.
                                                         68
Join Point Traces




              69
Join Point Traces



• A Join Point Trace (JPT) variable is introduced to
 track the flow-of-control through various join points
 within a component.




                                                       69
Join Point Traces



• A Join Point Trace (JPT) variable is introduced to
  track the flow-of-control through various join points
  within a component.
• A JPT is used as a parameter over the actions of all
  possibly applicable aspects.




                                                         69
Join Point Traces



• A Join Point Trace (JPT) variable is introduced to
  track the flow-of-control through various join points
  within a component.
• A JPT is used as a parameter over the actions of all
  possibly applicable aspects.
• Method post-conditions will references to the JPT.


                                                         69
Join Point Traces



• A Join Point Trace (JPT) variable is introduced to
  track the flow-of-control through various join points
  within a component.
• A JPT is used as a parameter over the actions of all
  possibly applicable aspects.
• Method post-conditions will references to the JPT.
• Informally, a JPT is used to refer to the actions and
  resulting values taken by advice at certain join point.


                                                          69
Elements of the JPT




                70
Elements of the JPT




• The JPT is composed of several components that are
 associated with each join point.




                                                    70
Elements of the JPT




• The JPT is composed of several components that are
  associated with each join point.
• Just as there are different kinds of join points (e.g.,
  call, execution), there different kinds of JPT
  entries.




                                                            70
JPT Method Call Completion Element




(oid , mid , aid , args, res, σ, σ )   




                                           71
JPT Method Call Completion Element




(oid , mid , aid , args, res, σ, σ )      

     Called Object




                                              71
JPT Method Call Completion Element




 Called
 Method

(oid , mid , aid , args, res, σ, σ )      

     Called Object




                                              71
JPT Method Call Completion Element




 Called
 Method

(oid , mid , aid , args, res, σ, σ )      

                     Applicable
     Called Object
                       Aspect




                                              71
JPT Method Call Completion Element




 Called       Argument
 Method         Values

(oid , mid , aid , args, res, σ, σ )      

                         Applicable
     Called Object
                           Aspect




                                              71
JPT Method Call Completion Element




 Called       Argument
 Method         Values

(oid , mid , aid , args, res, σ, σ )          

                         Applicable     Method
     Called Object                    Return Value
                           Aspect




                                                     71
JPT Method Call Completion Element




          
   σ, σ



                                71
JPT Method Call Completion Element




  State Vectors
          
   σ, σ



                                71
JPT Method Call Completion Element




           State Vectors
                    
            σ, σ
σ[oid]    State of object oid after
         completion of method mid




                                         71
JPT Method Call Completion Element




            State Vectors
                     
             σ, σ
σ[oid]     State of object oid after
          completion of method mid
σ [oid]
           State of object oid after
           completion of aspect aid


                                          71
JPT Method Call Completion Element




            State Vectors
                       
             σ, σ
σ[oid]     State of object oid after
          completion of method mid
σ [oid]
           State of object oid after
           completion of aspect aid
No applicable advice   =⇒ σ = σ    

                                          71
Rule for method specification




                           72
Rule for method specification




   Normal
pre-condition




                                72
Rule for method specification




  Post-condition, may
include references to
    portions of JPT
                                                   72
Rule for method specification




             R/G Clauses

                           72
Rule for method specification




                           72
Rule for method specification




                           73
Rule for method specification




Invocation of C.m
  on the local JPT




                                                73
Rule for method specification




                           73
Rule for method specification




                           74
Rule for method specification




      Classic
    Hoare Triple




                           74
Rule for method specification




                           74
Rule for method specification




                           75
Rule for method specification




Don’t forget
about the
guarantee




                                          75
Rule for method specification




                           75
Rule for method specification




                           76
Rule for method specification




      If when q holds and
   applicable advice behaves
    properly implies that ...


                                76
Rule for method specification




                           76
Rule for method specification




                           77
Rule for method specification




    ... our post-
condition holds with a a
 new entry in the local
           JPT

                                           77
Rule for method specification




     Not sure which
aspect is applicable yet, so
   we’ll leave this blank




                                                          77
Rule for method specification




          Replace all
        occurrences of
           σ with σ’




                           77
Rule for Method Calls




                   78
Rule for Method Calls




                   79
Rule for Method Calls


    Substitute
actuals for formals




                                         79
Rule for Method Calls




                   79
Rule for Method Calls




                   80
Rule for Method Calls



Local JPT for
   caller




                   80
Rule for Method Calls




Local JPT for
   callee




                                   80
Rule for Method Calls




    Substitute
formals for actuals




                          80
Rule for Aspect Application (Simple)




                                  81
Rule for Aspect Application (Simple)




             Base-code
           plus an aspect




                                  81
Rule for Aspect Application (Simple)




  Base-code
pre-condition




                                       81
Rule for Aspect Application (Simple)




 Aspect pre-
  condition



                                  81
Rule for Aspect Application (Simple)




                    Base-code
                   post-condition



                                    81
Rule for Aspect Application (Simple)




        Aspect post-
         condition




                                  81
Rule for Aspect Application (Simple)




                                  82
Rule for Aspect Application (Simple)


 Base-code
satisfies guar




                                            82
Rule for Aspect Application (Simple)



    Advice body




                                  82
Rule for Aspect Application (Simple)




         State
  vector immediately
prior to the execution
     of the advice




                                        82
Rule for Aspect Application (Simple)




                                  83
Future Work




         84
Future Work




         84
Future Work




• (More) Complete axiomatic proof system.




                                                     84
Future Work




• (More) Complete axiomatic proof system.
 • Develop for a core calculus, expand as necessarily.




                                                         84
Future Work




• (More) Complete axiomatic proof system.
 • Develop for a core calculus, expand as necessarily.
 • Advice advising other advice.



                                                         84
Future Work




• (More) Complete axiomatic proof system.
 • Develop for a core calculus, expand as necessarily.
 • Advice advising other advice.
 • Multiple advice acting on a single join point.


                                                         84
Future Work




• (More) Complete axiomatic proof system.
 • Develop for a core calculus, expand as necessarily.
 • Advice advising other advice.
 • Multiple advice acting on a single join point.
• Dealing with object aliasing.

                                                         84
Future Work




• (More) Complete axiomatic proof system.
 • Develop for a core calculus, expand as necessarily.
 • Advice advising other advice.
 • Multiple advice acting on a single join point.
• Dealing with object aliasing.
 • Separation Logic [Ishtiaq, O’Hearn ’01] may help.
                                                         84
Future Work




         85
Future Work


• Curbing complexity:




                                 85
Future Work


• Curbing complexity:
 • Specifications may (easily!) become unwieldy.




                                                   85
Future Work


• Curbing complexity:
 • Specifications may (easily!) become unwieldy.
 • Find suitable restrictions on aspects.




                                                   85
Future Work


• Curbing complexity:
 • Specifications may (easily!) become unwieldy.
 • Find suitable restrictions on aspects.
   • Module “sealing” ([Aldrich ’05])



                                                   85
Future Work


• Curbing complexity:
 • Specifications may (easily!) become unwieldy.
 • Find suitable restrictions on aspects.
   • Module “sealing” ([Aldrich ’05])
    • Advice not applicable to internal join points.


                                                       85
Future Work


• Curbing complexity:
 • Specifications may (easily!) become unwieldy.
 • Find suitable restrictions on aspects.
   • Module “sealing” ([Aldrich ’05])
    • Advice not applicable to internal join points.
• Semi-automation:

                                                       85
Future Work


• Curbing complexity:
 • Specifications may (easily!) become unwieldy.
 • Find suitable restrictions on aspects.
   • Module “sealing” ([Aldrich ’05])
    • Advice not applicable to internal join points.
• Semi-automation:
 • Integration with IDE/theorem provers, AJDT.
                                                       85
Future Work


• Curbing complexity:
 • Specifications may (easily!) become unwieldy.
 • Find suitable restrictions on aspects.
   • Module “sealing” ([Aldrich ’05])
    • Advice not applicable to internal join points.
• Semi-automation:
 • Integration with IDE/theorem provers, AJDT.
 • Extend specification languages (e.g., JML, Pipa)
                                                       85
Conclusion




       86
Conclusion




• Presented techniques to:




                                    86
Conclusion




• Presented techniques to:
 1. Mechanically alleviate burden of fragile pointcuts in
    Aspect-Oriented software.




                                                       86
Conclusion




• Presented techniques to:
 1. Mechanically alleviate burden of fragile pointcuts in
    Aspect-Oriented software.
 2.Automatically refactor legacy Java software to
   language enumerated (enum) types.




                                                       86
Conclusion




• Presented techniques to:
 1. Mechanically alleviate burden of fragile pointcuts in
    Aspect-Oriented software.
 2.Automatically refactor legacy Java software to
   language enumerated (enum) types.
 3.Robustly specify evolving Aspect-Oriented software
   components.


                                                       86

More Related Content

PDF
Whipp q3 2008_sv
PDF
[2015/2016] Software systems engineering PRINCIPLES
PDF
Zehr dv club_12052006
PDF
Selected Aspects of Software Development
PDF
RAMP: Requirements Authors Mentoring Program
PPTX
Juc deck 16x9_dev_ops_mvp
PPT
Introduction to OSLC
PDF
Embedded systems course - student resume template
Whipp q3 2008_sv
[2015/2016] Software systems engineering PRINCIPLES
Zehr dv club_12052006
Selected Aspects of Software Development
RAMP: Requirements Authors Mentoring Program
Juc deck 16x9_dev_ops_mvp
Introduction to OSLC
Embedded systems course - student resume template

What's hot (14)

DOC
Yogesh_Kadam
PDF
SADT & IDEF0 for Augmenting UML, Algile & Usability Engineering
DOC
Neeraj_Virmani_Resume
DOC
DheepthiResume
PDF
Oop01 6
PDF
Jagannath Basu July 2016
PPTX
Next-gen IDE v2 - OpenSlava 2013-10-11
PDF
KumarjitSharma_28011985
PDF
Primavera _ Rebecca King _ Mind the Gap - Strategies and tools to help bridge...
PPT
01 the big_idea
PDF
Oop 1
PDF
Oop 2
DOC
Mannu_Kumar_CV
PPSX
Catalyst college-presentation
Yogesh_Kadam
SADT & IDEF0 for Augmenting UML, Algile & Usability Engineering
Neeraj_Virmani_Resume
DheepthiResume
Oop01 6
Jagannath Basu July 2016
Next-gen IDE v2 - OpenSlava 2013-10-11
KumarjitSharma_28011985
Primavera _ Rebecca King _ Mind the Gap - Strategies and tools to help bridge...
01 the big_idea
Oop 1
Oop 2
Mannu_Kumar_CV
Catalyst college-presentation
Ad

Viewers also liked (7)

PPTX
Software Evolution
PDF
Software evolution evangelisation
PDF
Software Evolution Introduction (EVO 2008)
ODP
Software evolution -- Good practices
PPTX
Software Evolution
PPTX
PDF
Software Evolution
Software Evolution
Software evolution evangelisation
Software Evolution Introduction (EVO 2008)
Software evolution -- Good practices
Software Evolution
Software Evolution
Ad

Similar to Techniques for Automated Software Evolution (20)

PPTX
Software development philosophies v1
PPTX
01 fse software&sw-engineering
PPTX
Twelve Factor - Designing for Change
KEY
Pointcut Rejuvenation: Recovering Pointcut Expressions in Evolving Aspect-Ori...
PDF
SE notes 2.pdf
PDF
Engineering Software Products: 10. Devops and code management
PPTX
SE&PM-MODULE-1 2.pptx Software engineering
PPTX
Il paradigma DevOps e Continuous Delivery Automation
PDF
Il paradigma DevOps e Continuous Delivery Automation
PDF
1. introducción a la Ingeniería de Software (UTM 2071)
PDF
Make software like they make cars!
PPTX
DevOps and Build Automation
PDF
The Product and Process(1).pdf
PPT
Introduction to Agile Software Development & Python
PDF
Code Craftsmanship Checklist
PDF
Software Engineering Lecture for Computer Science.pdf
PPTX
1-SUMSEM2024-25_CSI3014_TH_VL2024250700241_2025-05-13_Reference-Material-I.pptx
PPTX
The quality attribute of upgradability
PPTX
Software Engineering- Crisis and Process Models
ODP
Writting Better Software
Software development philosophies v1
01 fse software&sw-engineering
Twelve Factor - Designing for Change
Pointcut Rejuvenation: Recovering Pointcut Expressions in Evolving Aspect-Ori...
SE notes 2.pdf
Engineering Software Products: 10. Devops and code management
SE&PM-MODULE-1 2.pptx Software engineering
Il paradigma DevOps e Continuous Delivery Automation
Il paradigma DevOps e Continuous Delivery Automation
1. introducción a la Ingeniería de Software (UTM 2071)
Make software like they make cars!
DevOps and Build Automation
The Product and Process(1).pdf
Introduction to Agile Software Development & Python
Code Craftsmanship Checklist
Software Engineering Lecture for Computer Science.pdf
1-SUMSEM2024-25_CSI3014_TH_VL2024250700241_2025-05-13_Reference-Material-I.pptx
The quality attribute of upgradability
Software Engineering- Crisis and Process Models
Writting Better Software

More from Raffi Khatchadourian (20)

PDF
Challenges in Migrating Imperative Deep Learning Programs to Graph Execution:...
PDF
Hybridize Functions: A Tool for Automatically Refactoring Imperative Deep Lea...
PDF
Hybridize Functions: A Tool for Automatically Refactoring Imperative Deep Lea...
PDF
Towards Safe Automated Refactoring of Imperative Deep Learning Programs to Gr...
PDF
Automated Evolution of Feature Logging Statement Levels Using Git Histories a...
PDF
A Tool for Rejuvenating Feature Logging Levels via Git Histories and Degree o...
PDF
Challenges in Migrating Imperative Deep Learning Programs to Graph Execution:...
PPTX
Actor Concurrency Bugs: A Comprehensive Study on Symptoms, Root Causes, API U...
PDF
An Empirical Study of Refactorings and Technical Debt in Machine Learning Sys...
PDF
Automated Evolution of Feature Logging Statement Levels Using Git Histories a...
PDF
An Empirical Study on the Use and Misuse of Java 8 Streams
PDF
Safe Automated Refactoring for Intelligent Parallelization of Java 8 Streams
PDF
Safe Automated Refactoring for Intelligent Parallelization of Java 8 Streams
PDF
A Brief Introduction to Type Constraints
PDF
Safe Automated Refactoring for Intelligent Parallelization of Java 8 Streams ...
PDF
A Tool for Optimizing Java 8 Stream Software via Automated Refactoring
PDF
Porting the NetBeans Java 8 Enhanced For Loop Lambda Expression Refactoring t...
PDF
Towards Safe Refactoring for Intelligent Parallelization of Java 8 Streams
PDF
Proactive Empirical Assessment of New Language Feature Adoption via Automated...
PDF
Defaultification Refactoring: A Tool for Automatically Converting Java Method...
Challenges in Migrating Imperative Deep Learning Programs to Graph Execution:...
Hybridize Functions: A Tool for Automatically Refactoring Imperative Deep Lea...
Hybridize Functions: A Tool for Automatically Refactoring Imperative Deep Lea...
Towards Safe Automated Refactoring of Imperative Deep Learning Programs to Gr...
Automated Evolution of Feature Logging Statement Levels Using Git Histories a...
A Tool for Rejuvenating Feature Logging Levels via Git Histories and Degree o...
Challenges in Migrating Imperative Deep Learning Programs to Graph Execution:...
Actor Concurrency Bugs: A Comprehensive Study on Symptoms, Root Causes, API U...
An Empirical Study of Refactorings and Technical Debt in Machine Learning Sys...
Automated Evolution of Feature Logging Statement Levels Using Git Histories a...
An Empirical Study on the Use and Misuse of Java 8 Streams
Safe Automated Refactoring for Intelligent Parallelization of Java 8 Streams
Safe Automated Refactoring for Intelligent Parallelization of Java 8 Streams
A Brief Introduction to Type Constraints
Safe Automated Refactoring for Intelligent Parallelization of Java 8 Streams ...
A Tool for Optimizing Java 8 Stream Software via Automated Refactoring
Porting the NetBeans Java 8 Enhanced For Loop Lambda Expression Refactoring t...
Towards Safe Refactoring for Intelligent Parallelization of Java 8 Streams
Proactive Empirical Assessment of New Language Feature Adoption via Automated...
Defaultification Refactoring: A Tool for Automatically Converting Java Method...

Recently uploaded (20)

PDF
Network Security Unit 5.pdf for BCA BBA.
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
DOCX
The AUB Centre for AI in Media Proposal.docx
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Approach and Philosophy of On baking technology
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PDF
Unlocking AI with Model Context Protocol (MCP)
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PPTX
Big Data Technologies - Introduction.pptx
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Network Security Unit 5.pdf for BCA BBA.
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
The AUB Centre for AI in Media Proposal.docx
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
Digital-Transformation-Roadmap-for-Companies.pptx
MYSQL Presentation for SQL database connectivity
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Approach and Philosophy of On baking technology
NewMind AI Weekly Chronicles - August'25 Week I
Unlocking AI with Model Context Protocol (MCP)
Programs and apps: productivity, graphics, security and other tools
Per capita expenditure prediction using model stacking based on satellite ima...
Big Data Technologies - Introduction.pptx
Advanced methodologies resolving dimensionality complications for autism neur...
“AI and Expert System Decision Support & Business Intelligence Systems”
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Spectral efficient network and resource selection model in 5G networks
Build a system with the filesystem maintained by OSTree @ COSCUP 2025

Techniques for Automated Software Evolution

  • 1. 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
  • 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 Computer Science. • Worked as: • A Software Engineer at State of New Jersey Office of Information Technology in Trenton, NJ. • A UNIX Systems Administrator for pharmaceutical website in Toms River, NJ. • Entered PhD program at OSU in September, 2005. • M.S. in Computer Science from OSU in March, 2010. • Start as an RF (wireless) Systems Integration Engineer on the iPhone development team at Apple Inc. in Cupertino, CA on Monday (4/4/2011). 2
  • 3. Publication Highlights • Raffi Khatchadourian, Phil Greenwood, Awais Rashid, and Guoqing Xu. Pointcut rejuvenation: Recovering pointcut expressions in evolving aspect-oriented software. IEEE Transactions on Software Engineering, 99(PrePrints), 2011. ISSN 0098-5589. • Raffi Khatchadourian, Phil Greenwood, Awais Rashid, and Guoqing Xu. Pointcut rejuvenation: Recovering pointcut expressions in evolving aspect-oriented software. In Proceedings of the 24th International Conference on Automated Software Engineering (ASE ’09), pages 575–579, Auckland, New Zealand, November 2009. IEEE/ACM. • Raffi Khatchadourian, Johan Dovland, and Neelam Soundarajan. Enforcing behavioral constraints in evolving aspect-oriented programs. In Proceedings of the 7th International Workshop on Foundations of Aspect- Oriented Languages (FOAL ’08) at the 7th International Conference on Aspect- Oriented Software Development (AOSD ’08), pages 19–28, Brussels, Belgium, April 2008. ACM. • Raffi Khatchadourian, Jason Sawin, and Atanas Rountev. Automated refactoring of legacy Java software to enumerated types. In Proceedings of the 23rd International Conference on Software Maintenance (ICSM ’07), pages 224–233, Paris, France, October 2007. IEEE. • Peer-reviewed totals (2005-): 1 paper to appear in a journal, 5 papers appearing in conference proceedings, and 5 papers appearing in workshop proceedings. 3
  • 4. Activity Highlights • Helped develop new Applied Software Engineering course ECE/CSE 668 based on Challenge-X hybrid SUV automobile simulation at OSU CAR in 2006. • Summer intern at Bell Labs under Rick Hull and Kedar Namjoshi (program language design for shared-experience, multimedia, multi- protocol, event-driven applications) in 2007. • Visiting Graduate Research Associate with the Aspect-Oriented Software Engineering (AOSE) Group at the Computing Department of Lancaster University, UK under Awais Rashid in 2008. • Visiting Researcher with the Programming Principles and Practices (PPP) Group at the Department of Graphics and Computer Science of the University of Tokyo under Hidehiko Masuhara in 2010. • Proposed project mentor for Google Summer of Code (GSoC) in 2009 and 2010. Project based on refactoring to enumerated types in Java. • Organizing committee member (Web Chair) for the European Conference on Object-Oriented Programming (ECOOP). 4
  • 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
  • 8. Motivation • Software changes over time: • Requirements evolve 6
  • 9. Motivation • Software changes over time: • Requirements evolve • New platforms emerge (e.g., mobile devices) 6
  • 10. Motivation • Software changes over time: • Requirements evolve • New platforms emerge (e.g., mobile devices) • Frameworks change (e.g., XML vs. annotation-based) 6
  • 12. Motivation Changing and/or maintaining large, complex software systems can be non-trivial: Tedious: May require changing many lines of code. Error-prone: Changes may be implemented incorrectly. Omission- May opportunities to produce better prone: code. 7
  • 13. Motivation Changing and/or maintaining large, complex software systems can be non-trivial: Tedious: May require changing many lines of code. Error-prone: Changes may be implemented incorrectly. Omission- May opportunities to produce better prone: code. 7
  • 14. Motivation Adding a parameter to a Changing and/or maintaining large, complex software systems can be non-trivial: method Tedious: May require changing many lines of code. Error-prone: Changes may be implemented incorrectly. Omission- May opportunities to produce better prone: code. 7
  • 15. Motivation Changing and/or maintaining large, complex software systems can be non-trivial: Tedious: May require changing many lines of code. Error-prone: Changes may be implemented incorrectly. Omission- May opportunities to produce better prone: code. 7
  • 16. Motivation Removing a Changing and/or maintaining large, complex software systemsparameter may method can be non-trivial: alter overloading to Tedious: May require changing many lines of overriding code. Error-prone: Changes may be implemented incorrectly. Omission- May opportunities to produce better prone: code. 7
  • 17. Motivation Changing and/or maintaining large, complex software systems can be non-trivial: Tedious: May require changing many lines of code. Error-prone: Changes may be implemented incorrectly. Omission- May opportunities to produce better prone: code. 7
  • 18. Motivation Changing and/or maintaining large, complex software systems can be non-trivial: Tedious: May require changing many lines of code. HashTable vs. Error-prone: Changes may be implemented incorrectly. HashMap Omission- May opportunities to produce better prone: code. 7
  • 19. Motivation Changing and/or maintaining large, complex software systems can be non-trivial: Tedious: May require changing many lines of code. Error-prone: Changes may be implemented incorrectly. Omission- May opportunities to produce better prone: code. 7
  • 20. Approach 8
  • 21. Approach • Approaches made to provide mechanical assistance in evolution tasks. 8
  • 22. Approach • Approaches made to provide mechanical assistance in evolution tasks. • Typically in the form of plug-ins to IDEs. 8
  • 23. Approach • Approaches made to provide mechanical assistance in evolution tasks. • Typically in the form of plug-ins to IDEs. • Ease the burden of software maintenance and evolution. 8
  • 24. Approach Restrict workspace to only • Approaches made to displays elements provide mechanical relevant to the assistance in evolution task tasks. • Typically in the form of plug-ins to IDEs. • Ease the burden of software maintenance and evolution. 8
  • 25. Approach Restrict workspace to only • Approaches made to displays elements provide mechanical relevant to the assistance in evolution task tasks. • Typically in the form of plug-ins to IDEs. Restructure •code the burden of Ease while preserving semantics (i.e., software maintenance and evolution. refactoring) 8
  • 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 in Aspect-Oriented software. 9
  • 29. Thesis Outline • For my thesis, I have pursed three directions: 1. Mechanically alleviate burden of fragile pointcuts in Aspect-Oriented software. 2.Automatically refactor legacy Java software to language enumerated (enum) types. 9
  • 30. Thesis Outline • For my thesis, I have pursed three directions: 1. Mechanically alleviate burden of fragile pointcuts in Aspect-Oriented software. 2.Automatically refactor legacy Java software to language enumerated (enum) types. 3.Robustly specify evolving Aspect-Oriented software components. 9
  • 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 /** * <p> * * Standard implementation of the <b>Session</b> interface. This object is * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. */ * notice, this list of conditions and the following disclaimer. * public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ Object object = attributes.get(name); * the documentation and/or other materials provided with the if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession return; * } implements HttpSession, Session { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { /** if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors * Update the accessed time information for this session. This method ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { * should be called by the context when a request comes in for a particular (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; * session, even if the application does not reference it. } itself, } /** */ } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. public void access() { * * } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated this.lastAccessedTime = this.thisAccessedTime; * Foundation" must not be used to endorse or promote products /** */ this.thisAccessedTime = System.currentTimeMillis(); * Bind an object to this session, using the specified name. If an object derived * @deprecated public StandardSession(Manager manager) { this.isNew=false; * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ } * replaced. * permission, please contact apache@apache.org. super(); * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); /** * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } * Perform the internal processing required to invalidate this session, * <code>valueBound()</code> on the object. * permission of the Apache Group. * without triggering an exception if the session has already expired. * * public void setAttribute(String name, Object value) { */ * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED if (! valid) { /** public void expire() { * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ // Remove this session from our manager's active sessions * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; if ((manager != null) && (manager instanceof ManagerBase)) * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } ((ManagerBase) manager).remove(this); * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** // Unbind any objects associated with this session */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. Vector results = new Vector(); public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ Enumeration attrs = getAttributeNames(); * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; while (attrs.hasMoreElements()) { if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } String attr = (String) attrs.nextElement(); !(value instanceof Serializable)) * SUCH DAMAGE. results.addElement(attr); throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** } (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before Enumeration names = results.elements(); * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time while (names.hasMoreElements()) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. String name = (String) names.nextElement(); removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ removeAttribute(name); attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } // Mark this session as invalid (new HttpSessionBindingEvent((HttpSession) this, name)); * /** setValid(false); } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } } private boolean isNew = true; /** package org.apache.tomcat.session; * @deprecated /** // -------------------------------------------- HttpSession Private Methods */ /** import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. } import org.apache.tomcat.util.StringManager; return getAttribute(name); */ /** import java.io.*; } private boolean isValid = false; * Read a serialized version of this session object from the specified import java.net.*; /** * object input stream. import java.util.*; public Object getAttribute(String name) { * Set the <code>isNew</code> flag for this session. * <p> import javax.servlet.*; if (! valid) { /** * * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager import javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * @param isNew The new value for the <code>isNew</code> flag * is not restored by this method, and must be set explicitly. */ */ * /** throw new IllegalStateException(msg); private StringManager sm = void setNew(boolean isNew) { * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * this.isNew = isNew; * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * @exception IOException if an input/output error occurs * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** } */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; /** public class ApplicationSession implements HttpSession { * Set the <code>isValid</code> flag for this session. // Deserialize the scalar instance variables (except Manager) return values.get(name); * creationTime = ((Long) stream.readObject()).longValue(); private StringManager sm = } /** * @param isValid The new value for the <code>isValid</code> flag id = (String) stream.readObject(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. */ lastAccessedTime = ((Long) stream.readObject()).longValue(); private Hashtable values = new Hashtable(); /** */ void setValid(boolean isValid) { maxInactiveInterval = ((Integer) stream.readObject()).intValue(); private String id; * @deprecated private long thisAccessedTime = creationTime; isNew = ((Boolean) stream.readObject()).booleanValue(); private ServerSession serverSession; */ this.isValid = isValid; isValid = ((Boolean) stream.readObject()).booleanValue(); private Context context; public String[] getValueNames() { } private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); // Deserialize the attribute count and attribute values private long thisAccessTime = creationTime; Vector names = new Vector(); int n = ((Integer) stream.readObject()).intValue(); private long lastAccessed = creationTime; // ----------------------------------------------------- Session Properties // ------------------------------------------------- HttpSession Properties for (int i = 0; i < n; i++) { private int inactiveInterval = -1; while (e.hasMoreElements()) { String name = (String) stream.readObject(); private boolean valid = true; names.addElement(e.nextElement()); Object value = (Object) stream.readObject(); } /** /** attributes.put(name, value); ApplicationSession(String id, ServerSession serverSession, * Set the creation time for this session. This method is called by the * Return the time when this session was created, in milliseconds since } Context context) { String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * midnight, January 1, 1970 GMT. this.serverSession = serverSession; * * } this.context = context; names.copyInto(valueNames); * @param time The new creation time * @exception IllegalStateException if this method is called on an this.id = id; */ * invalidated session return valueNames; public void setCreationTime(long time) { */ /** this.inactiveInterval = context.getSessionTimeOut(); public long getCreationTime() { * Write a serialized version of this session object to the specified } this.creationTime = time; * object output stream. if (this.inactiveInterval != -1) { this.lastAccessedTime = time; return (this.creationTime); * <p> this.inactiveInterval *= 60; public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored } if (! valid) { } * in the serialized representation of this Session. After calling } String msg = sm.getString("applicationSession.session.ise"); * <code>readObject()</code>, you must set the associated Manager * explicitly. ServerSession getServerSession() { throw new IllegalStateException(msg); /** * <p> return serverSession; } * Return the session context with which this session is associated. * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable } * * will be silently ignored. If you do not want any such attributes, Hashtable valuesClone = (Hashtable)values.clone(); * @deprecated As of Version 2.1, this method is deprecated and has no * be sure the <code>distributable</code> property of our associated /** * replacement. It will be removed in a future version of the * Manager is set to <code>true</code>. * Called by context when request comes in so that accesses and return (Enumeration)valuesClone.keys(); * Java Servlet API. * * inactivities can be dealt with accordingly. } */ * @param stream The output stream to write to */ public HttpSessionContext getSessionContext() { * * @exception IOException if an input/output error occurs void accessed() { /** if (sessionContext == null) */ // set last accessed to thisAccessTime as it will be left over * @deprecated sessionContext = new StandardSessionContext(); private void writeObject(ObjectOutputStream stream) throws IOException { // from the previous access */ return (sessionContext); lastAccessed = thisAccessTime; // Write the scalar instance variables (except Manager) thisAccessTime = System.currentTimeMillis(); public void removeValue(String name) { } stream.writeObject(new Long(creationTime)); removeAttribute(name); stream.writeObject(id); validate(); } stream.writeObject(new Long(lastAccessedTime)); } // ----------------------------------------------HttpSession Public Methods stream.writeObject(new Integer(maxInactiveInterval)); public void removeAttribute(String name) { stream.writeObject(new Boolean(isNew)); void validate() { if (! valid) { } stream.writeObject(new Boolean(isValid)); // if we have an inactive interval, check to see if we've exceeded it String msg = sm.getString("applicationSession.session.ise"); /** if (inactiveInterval != -1) { * Return the object bound with the specified name in this session, or // Accumulate the names of serializable attributes int thisInterval = throw new IllegalStateException(msg); * <code>null</code> if no object is bound with that name. Vector results = new Vector(); (int)(System.currentTimeMillis() - lastAccessed) / 1000; } * Enumeration attrs = getAttributeNames(); * @param name Name of the attribute to be returned while (attrs.hasMoreElements()) { if (thisInterval > inactiveInterval) { if (name == null) { * String attr = (String) attrs.nextElement(); invalidate(); String msg = sm.getString("applicationSession.value.iae"); * @exception IllegalStateException if this method is called on an Object value = attributes.get(attr); } * invalidated session if (value instanceof Serializable) } throw new IllegalArgumentException(msg); */ results.addElement(attr); } } public Object getAttribute(String name) { } // HTTP SESSION IMPLEMENTATION METHODS Object o = values.get(name); return (attributes.get(name)); // Serialize the attribute count and the attribute values stream.writeObject(new Integer(results.size())); public String getId() { if (o instanceof HttpSessionBindingListener) { } Enumeration names = results.elements(); if (valid) { HttpSessionBindingEvent e = while (names.hasMoreElements()) { return id; new HttpSessionBindingEvent(this,name); String name = (String) names.nextElement(); } else { /** stream.writeObject(name); String msg = sm.getString("applicationSession.session.ise"); ((HttpSessionBindingListener)o).valueUnbound(e); * Return an <code>Enumeration</code> of <code>String</code> objects stream.writeObject(attributes.get(name)); } * containing the names of the objects bound to this session. } throw new IllegalStateException(msg); * } values.remove(name); * @exception IllegalStateException if this method is called on an } } * invalidated session } */ public long getCreationTime() { public void setMaxInactiveInterval(int interval) { public Enumeration getAttributeNames() { crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | if (valid) { if (! valid) { long getCreationTime() | return creationTime; String msg = sm.getString("applicationSession.session.ise"); return (attributes.keys()); Object getAttribute(String) | } else { Enumeration getAttributeNames() | String msg = sm.getString("applicationSession.session.ise"); throw new IllegalStateException(msg); } String[] getValueNames() | } void invalidate() | throw new IllegalStateException(msg); boolean isNew() | } /** void removeAttribute(String) | } * Return the object bound with the specified name in this session, or void setAttribute(String, Object)); * <code>null</code> if no object is bound with that name. /** * static advice(StandardSession s): invalidate(s) { * * @param name Name of the value to be returned before { * @deprecated * if (!s.isValid()) * @exception IllegalStateException if this method is called on an throw new IllegalStateException * invalidated session (s.sm.getString("standardSession." * + thisJoinPoint.methodName * @deprecated As of Version 2.2, this method is replaced by + ".ise")); * <code>getAttribute()</code> } */ } /** public Object getValue(String name) { * Return the session identifier for this session. */ return (getAttribute(name)); public String getId() { } } /** // -------------------------------------------------------------- Private Class * Return the set of names of objects bound to this session. If there * are no such objects, a zero-length array is returned. * /** * @exception IllegalStateException if this method is called on an * This class is a dummy implementation of the <code>HttpSessionContext</code> * invalidated session * interface, to conform to the requirement that such an object be returned * * when <code>HttpSession.getSessionContext()</code> is called. * @deprecated As of Version 2.2, this method is replaced by * * <code>getAttributeNames()</code> * @author Craig R. McClanahan */ * public String[] getValueNames() { * @deprecated As of Java Servlet API 2.1 with no replacement. The * interface will be removed in a future version of this API. Vector results = new Vector(); */ Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { final class StandardSessionContext implements HttpSessionContext { String attr = (String) attrs.nextElement(); results.addElement(attr); } private Vector dummy = new Vector(); return (this.id); String names[] = new String[results.size()]; for (int i = 0; i < names.length; i++) /** names[i] = (String) results.elementAt(i); * Return the session identifiers of all sessions defined return (names); * within this context. * } * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> * and will be removed in a future version of the API. /** */ * Invalidates this session and unbinds any objects bound to it. public Enumeration getIds() { * * @exception IllegalStateException if this method is called on return (dummy.elements()); * an invalidated session */ public void invalidate() { // Cause this session to expire expire(); } } /** * Return <code>true</code> if the client does not yet know about the * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client * has disabled the use of cookies, then a session would be new on each * request. * * @exception IllegalStateException if this method is called on an * invalidated session */ public boolean isNew() { return (this.isNew); } package org.apache.tomcat.session; void validate() { // if we have an inactive interval, check to see if import org.apache.tomcat.core.*; // we've exceeded it import org.apache.tomcat.util.StringManager; import java.io.*; if (inactiveInterval != -1) { import java.net.*; int thisInterval = import java.util.*; (int)(System.currentTimeMillis() - lastAccessed) / 1000; import javax.servlet.*; import javax.servlet.http.*; if (thisInterval > inactiveInterval) { invalidate(); /** * Core implementation of a server session ServerSessionManager ssm = * ServerSessionManager.getManager(); * @author James Duncan Davidson [duncan@eng.sun.com] * @author James Todd [gonzo@eng.sun.com] ssm.removeSession(this); */ } } public class ServerSession { } private StringManager sm = synchronized void invalidate() { StringManager.getManager("org.apache.tomcat.session"); Enumeration enum = appSessions.keys(); /** private Hashtable values = new Hashtable(); * Set the session identifier for this session. private Hashtable appSessions = new Hashtable(); while (enum.hasMoreElements()) { * private String id; Object key = enum.nextElement(); * @param id The new session identifier private long creationTime = System.currentTimeMillis();; ApplicationSession appSession = */ private long thisAccessTime = creationTime; (ApplicationSession)appSessions.get(key); public void setId(String id) { private long lastAccessed = creationTime; private int inactiveInterval = -1; appSession.invalidate(); } ServerSession(String id) { } this.id = id; } public void putValue(String name, Object value) { if (name == null) { public String getId() { String msg = sm.getString("serverSession.value.iae"); return id; } throw new IllegalArgumentException(msg); } public long getCreationTime() { return creationTime; removeValue(name); // remove any existing binding } values.put(name, value); } public long getLastAccessedTime() { return lastAccessed; public Object getValue(String name) { } if (name == null) { String msg = sm.getString("serverSession.value.iae"); public ApplicationSession getApplicationSession(Context context, boolean create) { throw new IllegalArgumentException(msg); ApplicationSession appSession = } if ((this.id != null) && (manager != null) && (ApplicationSession)appSessions.get(context); (manager instanceof ManagerBase)) return values.get(name); ((ManagerBase) manager).remove(this); if (appSession == null && create) { } // XXX public Enumeration getValueNames() { // sync to ensure valid? return values.keys(); } appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); public void removeValue(String name) { } values.remove(name); } // XXX // make sure that we haven't gone over the end of our public void setMaxInactiveInterval(int interval) { // inactive interval -- if so, invalidate and create inactiveInterval = interval; // a new appSession } return appSession; public int getMaxInactiveInterval() { } return inactiveInterval; } void removeApplicationSession(Context context) { appSessions.remove(context); // XXX } // sync'd for safty -- no other thread should be getting something // from this while we are reaping. This isn't the most optimal /** // solution for this, but we'll determine something else later. this.id = id; * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. synchronized void reap() { */ Enumeration enum = appSessions.keys(); void accessed() { while (enum.hasMoreElements()) { // set last accessed to thisAccessTime as it will be left over if ((manager != null) && (manager instanceof ManagerBase)) ((ManagerBase) manager).add(this); } /** * Return descriptive information about this Session implementation and * the corresponding version number, in the format * <code>&lt;description&gt;/&lt;version&gt;</code>. */ public String getInfo() { return (this.info); } /** * Return the last time the client sent a request associated with this * session, as the number of milliseconds since midnight, January 1, 1970 * GMT. Actions that your application takes, such as getting or setting * a value associated with the session, do not affect the access time. */ public long getLastAccessedTime() { return (this.lastAccessedTime); } /** * Return the Manager within which this Session is valid. */ public Manager getManager() { return (this.manager); } /** * Set the Manager within which this Session is valid. * * @param manager The new Manager */ public void setManager(Manager manager) { 10
  • 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 /** * <p> * * Standard implementation of the <b>Session</b> interface. This object is * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. */ * notice, this list of conditions and the following disclaimer. * public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ Object object = attributes.get(name); * the documentation and/or other materials provided with the if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession return; * } implements HttpSession, Session { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { /** if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors * Update the accessed time information for this session. This method ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { * should be called by the context when a request comes in for a particular (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; * session, even if the application does not reference it. } itself, } /** */ } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. public void access() { * * } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated this.lastAccessedTime = this.thisAccessedTime; • Crosscutting concerns * Foundation" must not be used to endorse or promote products /** */ this.thisAccessedTime = System.currentTimeMillis(); * Bind an object to this session, using the specified name. If an object derived * @deprecated public StandardSession(Manager manager) { this.isNew=false; * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ } * replaced. * permission, please contact apache@apache.org. super(); * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); /** * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } * Perform the internal processing required to invalidate this session, * <code>valueBound()</code> on the object. * permission of the Apache Group. * without triggering an exception if the session has already expired. * * public void setAttribute(String name, Object value) { */ * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED if (! valid) { /** public void expire() { * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ // Remove this session from our manager's active sessions * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; if ((manager != null) && (manager instanceof ManagerBase)) * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } ((ManagerBase) manager).remove(this); * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** // Unbind any objects associated with this session */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. Vector results = new Vector(); public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ Enumeration attrs = getAttributeNames(); * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; while (attrs.hasMoreElements()) { if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } String attr = (String) attrs.nextElement(); !(value instanceof Serializable)) * SUCH DAMAGE. results.addElement(attr); throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** } (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before Enumeration names = results.elements(); * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time while (names.hasMoreElements()) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. String name = (String) names.nextElement(); removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ removeAttribute(name); attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } // Mark this session as invalid (new HttpSessionBindingEvent((HttpSession) this, name)); * /** setValid(false); } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } } private boolean isNew = true; /** package org.apache.tomcat.session; * @deprecated /** // -------------------------------------------- HttpSession Private Methods */ /** import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. } import org.apache.tomcat.util.StringManager; return getAttribute(name); */ /** import java.io.*; } private boolean isValid = false; * Read a serialized version of this session object from the specified import java.net.*; /** * object input stream. import java.util.*; public Object getAttribute(String name) { * Set the <code>isNew</code> flag for this session. * <p> import javax.servlet.*; if (! valid) { /** * * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager import javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * @param isNew The new value for the <code>isNew</code> flag * is not restored by this method, and must be set explicitly. */ */ * /** throw new IllegalStateException(msg); private StringManager sm = void setNew(boolean isNew) { * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * this.isNew = isNew; * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * @exception IOException if an input/output error occurs (CCCs) affect many * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** } */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; /** public class ApplicationSession implements HttpSession { * Set the <code>isValid</code> flag for this session. // Deserialize the scalar instance variables (except Manager) return values.get(name); * creationTime = ((Long) stream.readObject()).longValue(); private StringManager sm = } /** * @param isValid The new value for the <code>isValid</code> flag id = (String) stream.readObject(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. */ lastAccessedTime = ((Long) stream.readObject()).longValue(); private Hashtable values = new Hashtable(); /** */ void setValid(boolean isValid) { maxInactiveInterval = ((Integer) stream.readObject()).intValue(); private String id; * @deprecated private long thisAccessedTime = creationTime; isNew = ((Boolean) stream.readObject()).booleanValue(); private ServerSession serverSession; */ this.isValid = isValid; isValid = ((Boolean) stream.readObject()).booleanValue(); private Context context; public String[] getValueNames() { } private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); // Deserialize the attribute count and attribute values private long thisAccessTime = creationTime; Vector names = new Vector(); int n = ((Integer) stream.readObject()).intValue(); private long lastAccessed = creationTime; // ----------------------------------------------------- Session Properties // ------------------------------------------------- HttpSession Properties for (int i = 0; i < n; i++) { private int inactiveInterval = -1; while (e.hasMoreElements()) { String name = (String) stream.readObject(); private boolean valid = true; names.addElement(e.nextElement()); Object value = (Object) stream.readObject(); } /** /** attributes.put(name, value); ApplicationSession(String id, ServerSession serverSession, * Set the creation time for this session. This method is called by the * Return the time when this session was created, in milliseconds since } Context context) { String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * midnight, January 1, 1970 GMT. this.serverSession = serverSession; * * } this.context = context; names.copyInto(valueNames); * @param time The new creation time * @exception IllegalStateException if this method is called on an this.id = id; */ * invalidated session return valueNames; public void setCreationTime(long time) { */ /** this.inactiveInterval = context.getSessionTimeOut(); public long getCreationTime() { * Write a serialized version of this session object to the specified } this.creationTime = time; * object output stream. if (this.inactiveInterval != -1) { this.lastAccessedTime = time; return (this.creationTime); * <p> this.inactiveInterval *= 60; public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored } if (! valid) { } * in the serialized representation of this Session. After calling } String msg = sm.getString("applicationSession.session.ise"); * <code>readObject()</code>, you must set the associated Manager * explicitly. ServerSession getServerSession() { throw new IllegalStateException(msg); /** * <p> return serverSession; } * Return the session context with which this session is associated. * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable } * * will be silently ignored. If you do not want any such attributes, Hashtable valuesClone = (Hashtable)values.clone(); * @deprecated As of Version 2.1, this method is deprecated and has no * be sure the <code>distributable</code> property of our associated heterogeneous software /** * replacement. It will be removed in a future version of the * Manager is set to <code>true</code>. * Called by context when request comes in so that accesses and return (Enumeration)valuesClone.keys(); * Java Servlet API. * * inactivities can be dealt with accordingly. } */ * @param stream The output stream to write to */ public HttpSessionContext getSessionContext() { * * @exception IOException if an input/output error occurs void accessed() { /** if (sessionContext == null) */ // set last accessed to thisAccessTime as it will be left over * @deprecated sessionContext = new StandardSessionContext(); private void writeObject(ObjectOutputStream stream) throws IOException { // from the previous access */ return (sessionContext); lastAccessed = thisAccessTime; // Write the scalar instance variables (except Manager) thisAccessTime = System.currentTimeMillis(); public void removeValue(String name) { } stream.writeObject(new Long(creationTime)); removeAttribute(name); stream.writeObject(id); validate(); } stream.writeObject(new Long(lastAccessedTime)); } // ----------------------------------------------HttpSession Public Methods stream.writeObject(new Integer(maxInactiveInterval)); public void removeAttribute(String name) { stream.writeObject(new Boolean(isNew)); void validate() { if (! valid) { } stream.writeObject(new Boolean(isValid)); // if we have an inactive interval, check to see if we've exceeded it String msg = sm.getString("applicationSession.session.ise"); /** if (inactiveInterval != -1) { * Return the object bound with the specified name in this session, or // Accumulate the names of serializable attributes int thisInterval = throw new IllegalStateException(msg); * <code>null</code> if no object is bound with that name. Vector results = new Vector(); (int)(System.currentTimeMillis() - lastAccessed) / 1000; } * Enumeration attrs = getAttributeNames(); * @param name Name of the attribute to be returned while (attrs.hasMoreElements()) { if (thisInterval > inactiveInterval) { if (name == null) { * String attr = (String) attrs.nextElement(); invalidate(); String msg = sm.getString("applicationSession.value.iae"); * @exception IllegalStateException if this method is called on an Object value = attributes.get(attr); } * invalidated session if (value instanceof Serializable) } throw new IllegalArgumentException(msg); */ results.addElement(attr); } } public Object getAttribute(String name) { } // HTTP SESSION IMPLEMENTATION METHODS Object o = values.get(name); return (attributes.get(name)); // Serialize the attribute count and the attribute values stream.writeObject(new Integer(results.size())); public String getId() { if (o instanceof HttpSessionBindingListener) { } Enumeration names = results.elements(); if (valid) { HttpSessionBindingEvent e = while (names.hasMoreElements()) { return id; new HttpSessionBindingEvent(this,name); String name = (String) names.nextElement(); } else { /** stream.writeObject(name); String msg = sm.getString("applicationSession.session.ise"); ((HttpSessionBindingListener)o).valueUnbound(e); * Return an <code>Enumeration</code> of <code>String</code> objects stream.writeObject(attributes.get(name)); } * containing the names of the objects bound to this session. } throw new IllegalStateException(msg); * modules. } values.remove(name); * @exception IllegalStateException if this method is called on an } } * invalidated session } */ public long getCreationTime() { public void setMaxInactiveInterval(int interval) { public Enumeration getAttributeNames() { crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | if (valid) { if (! valid) { long getCreationTime() | return creationTime; String msg = sm.getString("applicationSession.session.ise"); return (attributes.keys()); Object getAttribute(String) | } else { Enumeration getAttributeNames() | String msg = sm.getString("applicationSession.session.ise"); throw new IllegalStateException(msg); } String[] getValueNames() | } void invalidate() | throw new IllegalStateException(msg); boolean isNew() | } /** void removeAttribute(String) | } * Return the object bound with the specified name in this session, or void setAttribute(String, Object)); * <code>null</code> if no object is bound with that name. /** * static advice(StandardSession s): invalidate(s) { * * @param name Name of the value to be returned before { * @deprecated * if (!s.isValid()) * @exception IllegalStateException if this method is called on an throw new IllegalStateException * invalidated session (s.sm.getString("standardSession." * + thisJoinPoint.methodName * @deprecated As of Version 2.2, this method is replaced by + ".ise")); * <code>getAttribute()</code> } */ } /** public Object getValue(String name) { * Return the session identifier for this session. */ return (getAttribute(name)); public String getId() { } } /** // -------------------------------------------------------------- Private Class * Return the set of names of objects bound to this session. If there * are no such objects, a zero-length array is returned. * /** * @exception IllegalStateException if this method is called on an * This class is a dummy implementation of the <code>HttpSessionContext</code> * invalidated session * interface, to conform to the requirement that such an object be returned * * when <code>HttpSession.getSessionContext()</code> is called. * @deprecated As of Version 2.2, this method is replaced by * * <code>getAttributeNames()</code> * @author Craig R. McClanahan */ * public String[] getValueNames() { * @deprecated As of Java Servlet API 2.1 with no replacement. The * interface will be removed in a future version of this API. Vector results = new Vector(); */ Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { final class StandardSessionContext implements HttpSessionContext { String attr = (String) attrs.nextElement(); results.addElement(attr); } private Vector dummy = new Vector(); return (this.id); String names[] = new String[results.size()]; for (int i = 0; i < names.length; i++) /** names[i] = (String) results.elementAt(i); * Return the session identifiers of all sessions defined return (names); * within this context. * } * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> * and will be removed in a future version of the API. /** */ * Invalidates this session and unbinds any objects bound to it. public Enumeration getIds() { * * @exception IllegalStateException if this method is called on return (dummy.elements()); * an invalidated session */ public void invalidate() { // Cause this session to expire expire(); } } /** * Return <code>true</code> if the client does not yet know about the * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client * has disabled the use of cookies, then a session would be new on each * request. * * @exception IllegalStateException if this method is called on an * invalidated session */ public boolean isNew() { return (this.isNew); } package org.apache.tomcat.session; void validate() { // if we have an inactive interval, check to see if import org.apache.tomcat.core.*; // we've exceeded it import org.apache.tomcat.util.StringManager; import java.io.*; if (inactiveInterval != -1) { import java.net.*; int thisInterval = import java.util.*; (int)(System.currentTimeMillis() - lastAccessed) / 1000; import javax.servlet.*; import javax.servlet.http.*; if (thisInterval > inactiveInterval) { invalidate(); /** * Core implementation of a server session ServerSessionManager ssm = * ServerSessionManager.getManager(); * @author James Duncan Davidson [duncan@eng.sun.com] * @author James Todd [gonzo@eng.sun.com] ssm.removeSession(this); */ } } public class ServerSession { } private StringManager sm = synchronized void invalidate() { StringManager.getManager("org.apache.tomcat.session"); Enumeration enum = appSessions.keys(); /** private Hashtable values = new Hashtable(); * Set the session identifier for this session. private Hashtable appSessions = new Hashtable(); while (enum.hasMoreElements()) { * private String id; Object key = enum.nextElement(); * @param id The new session identifier private long creationTime = System.currentTimeMillis();; ApplicationSession appSession = */ private long thisAccessTime = creationTime; (ApplicationSession)appSessions.get(key); public void setId(String id) { private long lastAccessed = creationTime; private int inactiveInterval = -1; appSession.invalidate(); } ServerSession(String id) { } this.id = id; } public void putValue(String name, Object value) { if (name == null) { public String getId() { String msg = sm.getString("serverSession.value.iae"); return id; } throw new IllegalArgumentException(msg); } public long getCreationTime() { return creationTime; removeValue(name); // remove any existing binding } values.put(name, value); } public long getLastAccessedTime() { return lastAccessed; public Object getValue(String name) { } if (name == null) { String msg = sm.getString("serverSession.value.iae"); public ApplicationSession getApplicationSession(Context context, boolean create) { throw new IllegalArgumentException(msg); ApplicationSession appSession = } if ((this.id != null) && (manager != null) && (ApplicationSession)appSessions.get(context); (manager instanceof ManagerBase)) return values.get(name); ((ManagerBase) manager).remove(this); if (appSession == null && create) { } // XXX public Enumeration getValueNames() { // sync to ensure valid? return values.keys(); } appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); public void removeValue(String name) { } values.remove(name); } // XXX // make sure that we haven't gone over the end of our public void setMaxInactiveInterval(int interval) { // inactive interval -- if so, invalidate and create inactiveInterval = interval; // a new appSession } return appSession; public int getMaxInactiveInterval() { } return inactiveInterval; } void removeApplicationSession(Context context) { appSessions.remove(context); // XXX } // sync'd for safty -- no other thread should be getting something // from this while we are reaping. This isn't the most optimal /** // solution for this, but we'll determine something else later. this.id = id; * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. synchronized void reap() { */ Enumeration enum = appSessions.keys(); void accessed() { while (enum.hasMoreElements()) { // set last accessed to thisAccessTime as it will be left over if ((manager != null) && (manager instanceof ManagerBase)) ((ManagerBase) manager).add(this); } /** * Return descriptive information about this Session implementation and * the corresponding version number, in the format * <code>&lt;description&gt;/&lt;version&gt;</code>. */ public String getInfo() { return (this.info); } /** * Return the last time the client sent a request associated with this * session, as the number of milliseconds since midnight, January 1, 1970 * GMT. Actions that your application takes, such as getting or setting * a value associated with the session, do not affect the access time. */ public long getLastAccessedTime() { return (this.lastAccessedTime); } /** * Return the Manager within which this Session is valid. */ public Manager getManager() { return (this.manager); } /** * Set the Manager within which this Session is valid. * * @param manager The new Manager */ public void setManager(Manager manager) { 10
  • 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 /** * <p> * * Standard implementation of the <b>Session</b> interface. This object is * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. */ * notice, this list of conditions and the following disclaimer. * public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ Object object = attributes.get(name); * the documentation and/or other materials provided with the if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession return; * } implements HttpSession, Session { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { /** if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors * Update the accessed time information for this session. This method ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { * should be called by the context when a request comes in for a particular (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; * session, even if the application does not reference it. } itself, } /** */ } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. public void access() { * * } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated this.lastAccessedTime = this.thisAccessedTime; • Crosscutting concerns * Foundation" must not be used to endorse or promote products /** */ this.thisAccessedTime = System.currentTimeMillis(); * Bind an object to this session, using the specified name. If an object derived * @deprecated public StandardSession(Manager manager) { this.isNew=false; * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ } * replaced. * permission, please contact apache@apache.org. super(); * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); /** * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } * Perform the internal processing required to invalidate this session, * <code>valueBound()</code> on the object. * permission of the Apache Group. * without triggering an exception if the session has already expired. * * public void setAttribute(String name, Object value) { */ * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED if (! valid) { /** public void expire() { * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ // Remove this session from our manager's active sessions * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; if ((manager != null) && (manager instanceof ManagerBase)) * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } ((ManagerBase) manager).remove(this); * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** // Unbind any objects associated with this session */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. Vector results = new Vector(); public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ Enumeration attrs = getAttributeNames(); * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; while (attrs.hasMoreElements()) { if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } String attr = (String) attrs.nextElement(); !(value instanceof Serializable)) * SUCH DAMAGE. results.addElement(attr); throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** } (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before Enumeration names = results.elements(); * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time while (names.hasMoreElements()) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. String name = (String) names.nextElement(); removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ removeAttribute(name); attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } // Mark this session as invalid (new HttpSessionBindingEvent((HttpSession) this, name)); * /** setValid(false); } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } } private boolean isNew = true; /** package org.apache.tomcat.session; * @deprecated /** // -------------------------------------------- HttpSession Private Methods */ /** import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. } import org.apache.tomcat.util.StringManager; return getAttribute(name); */ /** import java.io.*; } private boolean isValid = false; * Read a serialized version of this session object from the specified import java.net.*; /** * object input stream. import java.util.*; public Object getAttribute(String name) { * Set the <code>isNew</code> flag for this session. * <p> import javax.servlet.*; if (! valid) { /** * * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager import javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * @param isNew The new value for the <code>isNew</code> flag * is not restored by this method, and must be set explicitly. */ */ * /** throw new IllegalStateException(msg); private StringManager sm = void setNew(boolean isNew) { * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * this.isNew = isNew; * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * @exception IOException if an input/output error occurs (CCCs) affect many * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** } */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; /** public class ApplicationSession implements HttpSession { * Set the <code>isValid</code> flag for this session. // Deserialize the scalar instance variables (except Manager) return values.get(name); * creationTime = ((Long) stream.readObject()).longValue(); private StringManager sm = } /** * @param isValid The new value for the <code>isValid</code> flag id = (String) stream.readObject(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. */ lastAccessedTime = ((Long) stream.readObject()).longValue(); private Hashtable values = new Hashtable(); /** */ void setValid(boolean isValid) { maxInactiveInterval = ((Integer) stream.readObject()).intValue(); private String id; * @deprecated private long thisAccessedTime = creationTime; isNew = ((Boolean) stream.readObject()).booleanValue(); private ServerSession serverSession; */ this.isValid = isValid; isValid = ((Boolean) stream.readObject()).booleanValue(); private Context context; public String[] getValueNames() { } private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); // Deserialize the attribute count and attribute values private long thisAccessTime = creationTime; Vector names = new Vector(); int n = ((Integer) stream.readObject()).intValue(); private long lastAccessed = creationTime; // ----------------------------------------------------- Session Properties // ------------------------------------------------- HttpSession Properties for (int i = 0; i < n; i++) { private int inactiveInterval = -1; while (e.hasMoreElements()) { String name = (String) stream.readObject(); private boolean valid = true; names.addElement(e.nextElement()); Object value = (Object) stream.readObject(); } /** /** attributes.put(name, value); ApplicationSession(String id, ServerSession serverSession, * Set the creation time for this session. This method is called by the * Return the time when this session was created, in milliseconds since } Context context) { String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * midnight, January 1, 1970 GMT. this.serverSession = serverSession; * * } this.context = context; names.copyInto(valueNames); * @param time The new creation time * @exception IllegalStateException if this method is called on an this.id = id; */ * invalidated session return valueNames; public void setCreationTime(long time) { */ /** this.inactiveInterval = context.getSessionTimeOut(); public long getCreationTime() { * Write a serialized version of this session object to the specified } this.creationTime = time; * object output stream. if (this.inactiveInterval != -1) { this.lastAccessedTime = time; return (this.creationTime); * <p> this.inactiveInterval *= 60; public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored } if (! valid) { } * in the serialized representation of this Session. After calling } String msg = sm.getString("applicationSession.session.ise"); * <code>readObject()</code>, you must set the associated Manager * explicitly. ServerSession getServerSession() { throw new IllegalStateException(msg); /** * <p> return serverSession; } * Return the session context with which this session is associated. * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable } * * will be silently ignored. If you do not want any such attributes, Hashtable valuesClone = (Hashtable)values.clone(); * @deprecated As of Version 2.1, this method is deprecated and has no * be sure the <code>distributable</code> property of our associated heterogeneous software /** * replacement. It will be removed in a future version of the * Manager is set to <code>true</code>. * Called by context when request comes in so that accesses and return (Enumeration)valuesClone.keys(); * Java Servlet API. * * inactivities can be dealt with accordingly. } */ * @param stream The output stream to write to */ public HttpSessionContext getSessionContext() { * * @exception IOException if an input/output error occurs void accessed() { /** if (sessionContext == null) */ // set last accessed to thisAccessTime as it will be left over * @deprecated sessionContext = new StandardSessionContext(); private void writeObject(ObjectOutputStream stream) throws IOException { // from the previous access */ return (sessionContext); lastAccessed = thisAccessTime; // Write the scalar instance variables (except Manager) thisAccessTime = System.currentTimeMillis(); public void removeValue(String name) { } stream.writeObject(new Long(creationTime)); removeAttribute(name); stream.writeObject(id); validate(); } stream.writeObject(new Long(lastAccessedTime)); } // ----------------------------------------------HttpSession Public Methods stream.writeObject(new Integer(maxInactiveInterval)); public void removeAttribute(String name) { stream.writeObject(new Boolean(isNew)); void validate() { if (! valid) { } stream.writeObject(new Boolean(isValid)); // if we have an inactive interval, check to see if we've exceeded it String msg = sm.getString("applicationSession.session.ise"); /** if (inactiveInterval != -1) { * Return the object bound with the specified name in this session, or // Accumulate the names of serializable attributes int thisInterval = throw new IllegalStateException(msg); * <code>null</code> if no object is bound with that name. Vector results = new Vector(); (int)(System.currentTimeMillis() - lastAccessed) / 1000; } * Enumeration attrs = getAttributeNames(); * @param name Name of the attribute to be returned while (attrs.hasMoreElements()) { if (thisInterval > inactiveInterval) { if (name == null) { * String attr = (String) attrs.nextElement(); invalidate(); String msg = sm.getString("applicationSession.value.iae"); * @exception IllegalStateException if this method is called on an Object value = attributes.get(attr); } * invalidated session if (value instanceof Serializable) } throw new IllegalArgumentException(msg); */ results.addElement(attr); } } public Object getAttribute(String name) { } // HTTP SESSION IMPLEMENTATION METHODS Object o = values.get(name); return (attributes.get(name)); // Serialize the attribute count and the attribute values stream.writeObject(new Integer(results.size())); public String getId() { if (o instanceof HttpSessionBindingListener) { } Enumeration names = results.elements(); if (valid) { HttpSessionBindingEvent e = while (names.hasMoreElements()) { return id; new HttpSessionBindingEvent(this,name); String name = (String) names.nextElement(); } else { /** stream.writeObject(name); String msg = sm.getString("applicationSession.session.ise"); ((HttpSessionBindingListener)o).valueUnbound(e); * Return an <code>Enumeration</code> of <code>String</code> objects stream.writeObject(attributes.get(name)); } * containing the names of the objects bound to this session. } throw new IllegalStateException(msg); * modules. } values.remove(name); * @exception IllegalStateException if this method is called on an } } * invalidated session } */ public long getCreationTime() { public void setMaxInactiveInterval(int interval) { public Enumeration getAttributeNames() { crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | if (valid) { if (! valid) { long getCreationTime() | return creationTime; String msg = sm.getString("applicationSession.session.ise"); return (attributes.keys()); Object getAttribute(String) | } else { Enumeration getAttributeNames() | String msg = sm.getString("applicationSession.session.ise"); throw new IllegalStateException(msg); } String[] getValueNames() | } void invalidate() | throw new IllegalStateException(msg); boolean isNew() | } /** void removeAttribute(String) | } * Return the object bound with the specified name in this session, or void setAttribute(String, Object)); * <code>null</code> if no object is bound with that name. /** * static advice(StandardSession s): invalidate(s) { * * @param name Name of the value to be returned before { * @deprecated * if (!s.isValid()) * @exception IllegalStateException if this method is called on an throw new IllegalStateException * invalidated session (s.sm.getString("standardSession." * + thisJoinPoint.methodName * @deprecated As of Version 2.2, this method is replaced by + ".ise")); * <code>getAttribute()</code> } */ } /** public Object getValue(String name) { * Return the session identifier for this session. */ return (getAttribute(name)); public String getId() { } } /** // -------------------------------------------------------------- Private Class * Return the set of names of objects bound to this session. If there * are no such objects, a zero-length array is returned. * /** * @exception IllegalStateException if this method is called on an * This class is a dummy implementation of the <code>HttpSessionContext</code> * invalidated session * interface, to conform to the requirement that such an object be returned * * when <code>HttpSession.getSessionContext()</code> is called. * @deprecated As of Version 2.2, this method is replaced by * * <code>getAttributeNames()</code> * @author Craig R. McClanahan */ * public String[] getValueNames() { * @deprecated As of Java Servlet API 2.1 with no replacement. The * interface will be removed in a future version of this API. Vector results = new Vector(); */ Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { final class StandardSessionContext implements HttpSessionContext { String attr = (String) attrs.nextElement(); results.addElement(attr); } private Vector dummy = new Vector(); return (this.id); String names[] = new String[results.size()]; for (int i = 0; i < names.length; i++) /** names[i] = (String) results.elementAt(i); * Return the session identifiers of all sessions defined return (names); * within this context. * } * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> * and will be removed in a future version of the API. /** */ * Invalidates this session and unbinds any objects bound to it. public Enumeration getIds() { * * @exception IllegalStateException if this method is called on return (dummy.elements()); * an invalidated session • Code is: */ public void invalidate() { // Cause this session to expire expire(); } } /** * Return <code>true</code> if the client does not yet know about the * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client * has disabled the use of cookies, then a session would be new on each * request. * * @exception IllegalStateException if this method is called on an * invalidated session */ public boolean isNew() { return (this.isNew); } package org.apache.tomcat.session; void validate() { // if we have an inactive interval, check to see if import org.apache.tomcat.core.*; // we've exceeded it import org.apache.tomcat.util.StringManager; import java.io.*; if (inactiveInterval != -1) { import java.net.*; int thisInterval = import java.util.*; (int)(System.currentTimeMillis() - lastAccessed) / 1000; import javax.servlet.*; import javax.servlet.http.*; if (thisInterval > inactiveInterval) { invalidate(); /** * Core implementation of a server session ServerSessionManager ssm = * ServerSessionManager.getManager(); * @author James Duncan Davidson [duncan@eng.sun.com] * @author James Todd [gonzo@eng.sun.com] ssm.removeSession(this); */ } } public class ServerSession { } private StringManager sm = synchronized void invalidate() { StringManager.getManager("org.apache.tomcat.session"); Enumeration enum = appSessions.keys(); /** private Hashtable values = new Hashtable(); * Set the session identifier for this session. private Hashtable appSessions = new Hashtable(); while (enum.hasMoreElements()) { * private String id; Object key = enum.nextElement(); * @param id The new session identifier private long creationTime = System.currentTimeMillis();; ApplicationSession appSession = */ private long thisAccessTime = creationTime; (ApplicationSession)appSessions.get(key); public void setId(String id) { private long lastAccessed = creationTime; private int inactiveInterval = -1; appSession.invalidate(); } ServerSession(String id) { } this.id = id; } public void putValue(String name, Object value) { if (name == null) { public String getId() { String msg = sm.getString("serverSession.value.iae"); return id; } throw new IllegalArgumentException(msg); } public long getCreationTime() { return creationTime; removeValue(name); // remove any existing binding } values.put(name, value); } public long getLastAccessedTime() { return lastAccessed; public Object getValue(String name) { } if (name == null) { String msg = sm.getString("serverSession.value.iae"); public ApplicationSession getApplicationSession(Context context, boolean create) { throw new IllegalArgumentException(msg); ApplicationSession appSession = } if ((this.id != null) && (manager != null) && (ApplicationSession)appSessions.get(context); (manager instanceof ManagerBase)) return values.get(name); ((ManagerBase) manager).remove(this); if (appSession == null && create) { } // XXX public Enumeration getValueNames() { // sync to ensure valid? return values.keys(); } appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); public void removeValue(String name) { } values.remove(name); } // XXX // make sure that we haven't gone over the end of our public void setMaxInactiveInterval(int interval) { // inactive interval -- if so, invalidate and create inactiveInterval = interval; // a new appSession } return appSession; public int getMaxInactiveInterval() { } return inactiveInterval; } void removeApplicationSession(Context context) { appSessions.remove(context); // XXX } // sync'd for safty -- no other thread should be getting something // from this while we are reaping. This isn't the most optimal /** // solution for this, but we'll determine something else later. this.id = id; * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. synchronized void reap() { */ Enumeration enum = appSessions.keys(); void accessed() { while (enum.hasMoreElements()) { // set last accessed to thisAccessTime as it will be left over if ((manager != null) && (manager instanceof ManagerBase)) ((ManagerBase) manager).add(this); } /** * Return descriptive information about this Session implementation and * the corresponding version number, in the format * <code>&lt;description&gt;/&lt;version&gt;</code>. */ public String getInfo() { return (this.info); } /** * Return the last time the client sent a request associated with this * session, as the number of milliseconds since midnight, January 1, 1970 * GMT. Actions that your application takes, such as getting or setting * a value associated with the session, do not affect the access time. */ public long getLastAccessedTime() { return (this.lastAccessedTime); } /** * Return the Manager within which this Session is valid. */ public Manager getManager() { return (this.manager); } /** * Set the Manager within which this Session is valid. * * @param manager The new Manager */ public void setManager(Manager manager) { 10
  • 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 /** * <p> * * Standard implementation of the <b>Session</b> interface. This object is * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. */ * notice, this list of conditions and the following disclaimer. * public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ Object object = attributes.get(name); * the documentation and/or other materials provided with the if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession return; * } implements HttpSession, Session { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { /** if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors * Update the accessed time information for this session. This method ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { * should be called by the context when a request comes in for a particular (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; * session, even if the application does not reference it. } itself, } /** */ } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. public void access() { * * } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated this.lastAccessedTime = this.thisAccessedTime; • Crosscutting concerns * Foundation" must not be used to endorse or promote products /** */ this.thisAccessedTime = System.currentTimeMillis(); * Bind an object to this session, using the specified name. If an object derived * @deprecated public StandardSession(Manager manager) { this.isNew=false; * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ } * replaced. * permission, please contact apache@apache.org. super(); * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); /** * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } * Perform the internal processing required to invalidate this session, * <code>valueBound()</code> on the object. * permission of the Apache Group. * without triggering an exception if the session has already expired. * * public void setAttribute(String name, Object value) { */ * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED if (! valid) { /** public void expire() { * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ // Remove this session from our manager's active sessions * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; if ((manager != null) && (manager instanceof ManagerBase)) * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } ((ManagerBase) manager).remove(this); * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** // Unbind any objects associated with this session */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. Vector results = new Vector(); public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ Enumeration attrs = getAttributeNames(); * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; while (attrs.hasMoreElements()) { if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } String attr = (String) attrs.nextElement(); !(value instanceof Serializable)) * SUCH DAMAGE. results.addElement(attr); throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** } (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before Enumeration names = results.elements(); * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time while (names.hasMoreElements()) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. String name = (String) names.nextElement(); removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ removeAttribute(name); attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } // Mark this session as invalid (new HttpSessionBindingEvent((HttpSession) this, name)); * /** setValid(false); } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } } private boolean isNew = true; /** package org.apache.tomcat.session; * @deprecated /** // -------------------------------------------- HttpSession Private Methods */ /** import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. } import org.apache.tomcat.util.StringManager; return getAttribute(name); */ /** import java.io.*; } private boolean isValid = false; * Read a serialized version of this session object from the specified import java.net.*; /** * object input stream. import java.util.*; public Object getAttribute(String name) { * Set the <code>isNew</code> flag for this session. * <p> import javax.servlet.*; if (! valid) { /** * * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager import javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * @param isNew The new value for the <code>isNew</code> flag * is not restored by this method, and must be set explicitly. */ */ * /** throw new IllegalStateException(msg); private StringManager sm = void setNew(boolean isNew) { * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * this.isNew = isNew; * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * @exception IOException if an input/output error occurs (CCCs) affect many * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** } */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; /** public class ApplicationSession implements HttpSession { * Set the <code>isValid</code> flag for this session. // Deserialize the scalar instance variables (except Manager) return values.get(name); * creationTime = ((Long) stream.readObject()).longValue(); private StringManager sm = } /** * @param isValid The new value for the <code>isValid</code> flag id = (String) stream.readObject(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. */ lastAccessedTime = ((Long) stream.readObject()).longValue(); private Hashtable values = new Hashtable(); /** */ void setValid(boolean isValid) { maxInactiveInterval = ((Integer) stream.readObject()).intValue(); private String id; * @deprecated private long thisAccessedTime = creationTime; isNew = ((Boolean) stream.readObject()).booleanValue(); private ServerSession serverSession; */ this.isValid = isValid; isValid = ((Boolean) stream.readObject()).booleanValue(); private Context context; public String[] getValueNames() { } private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); // Deserialize the attribute count and attribute values private long thisAccessTime = creationTime; Vector names = new Vector(); int n = ((Integer) stream.readObject()).intValue(); private long lastAccessed = creationTime; // ----------------------------------------------------- Session Properties // ------------------------------------------------- HttpSession Properties for (int i = 0; i < n; i++) { private int inactiveInterval = -1; while (e.hasMoreElements()) { String name = (String) stream.readObject(); private boolean valid = true; names.addElement(e.nextElement()); Object value = (Object) stream.readObject(); } /** /** attributes.put(name, value); ApplicationSession(String id, ServerSession serverSession, * Set the creation time for this session. This method is called by the * Return the time when this session was created, in milliseconds since } Context context) { String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * midnight, January 1, 1970 GMT. this.serverSession = serverSession; * * } this.context = context; names.copyInto(valueNames); * @param time The new creation time * @exception IllegalStateException if this method is called on an this.id = id; */ * invalidated session return valueNames; public void setCreationTime(long time) { */ /** this.inactiveInterval = context.getSessionTimeOut(); public long getCreationTime() { * Write a serialized version of this session object to the specified } this.creationTime = time; * object output stream. if (this.inactiveInterval != -1) { this.lastAccessedTime = time; return (this.creationTime); * <p> this.inactiveInterval *= 60; public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored } if (! valid) { } * in the serialized representation of this Session. After calling } String msg = sm.getString("applicationSession.session.ise"); * <code>readObject()</code>, you must set the associated Manager * explicitly. ServerSession getServerSession() { throw new IllegalStateException(msg); /** * <p> return serverSession; } * Return the session context with which this session is associated. * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable } * * will be silently ignored. If you do not want any such attributes, Hashtable valuesClone = (Hashtable)values.clone(); * @deprecated As of Version 2.1, this method is deprecated and has no * be sure the <code>distributable</code> property of our associated heterogeneous software /** * replacement. It will be removed in a future version of the * Manager is set to <code>true</code>. * Called by context when request comes in so that accesses and return (Enumeration)valuesClone.keys(); * Java Servlet API. * * inactivities can be dealt with accordingly. } */ * @param stream The output stream to write to */ public HttpSessionContext getSessionContext() { * * @exception IOException if an input/output error occurs void accessed() { /** if (sessionContext == null) */ // set last accessed to thisAccessTime as it will be left over * @deprecated sessionContext = new StandardSessionContext(); private void writeObject(ObjectOutputStream stream) throws IOException { // from the previous access */ return (sessionContext); lastAccessed = thisAccessTime; // Write the scalar instance variables (except Manager) thisAccessTime = System.currentTimeMillis(); public void removeValue(String name) { } stream.writeObject(new Long(creationTime)); removeAttribute(name); stream.writeObject(id); validate(); } stream.writeObject(new Long(lastAccessedTime)); } // ----------------------------------------------HttpSession Public Methods stream.writeObject(new Integer(maxInactiveInterval)); public void removeAttribute(String name) { stream.writeObject(new Boolean(isNew)); void validate() { if (! valid) { } stream.writeObject(new Boolean(isValid)); // if we have an inactive interval, check to see if we've exceeded it String msg = sm.getString("applicationSession.session.ise"); /** if (inactiveInterval != -1) { * Return the object bound with the specified name in this session, or // Accumulate the names of serializable attributes int thisInterval = throw new IllegalStateException(msg); * <code>null</code> if no object is bound with that name. Vector results = new Vector(); (int)(System.currentTimeMillis() - lastAccessed) / 1000; } * Enumeration attrs = getAttributeNames(); * @param name Name of the attribute to be returned while (attrs.hasMoreElements()) { if (thisInterval > inactiveInterval) { if (name == null) { * String attr = (String) attrs.nextElement(); invalidate(); String msg = sm.getString("applicationSession.value.iae"); * @exception IllegalStateException if this method is called on an Object value = attributes.get(attr); } * invalidated session if (value instanceof Serializable) } throw new IllegalArgumentException(msg); */ results.addElement(attr); } } public Object getAttribute(String name) { } // HTTP SESSION IMPLEMENTATION METHODS Object o = values.get(name); return (attributes.get(name)); // Serialize the attribute count and the attribute values stream.writeObject(new Integer(results.size())); public String getId() { if (o instanceof HttpSessionBindingListener) { } Enumeration names = results.elements(); if (valid) { HttpSessionBindingEvent e = while (names.hasMoreElements()) { return id; new HttpSessionBindingEvent(this,name); String name = (String) names.nextElement(); } else { /** stream.writeObject(name); String msg = sm.getString("applicationSession.session.ise"); ((HttpSessionBindingListener)o).valueUnbound(e); * Return an <code>Enumeration</code> of <code>String</code> objects stream.writeObject(attributes.get(name)); } * containing the names of the objects bound to this session. } throw new IllegalStateException(msg); * modules. } values.remove(name); * @exception IllegalStateException if this method is called on an } } * invalidated session } */ public long getCreationTime() { public void setMaxInactiveInterval(int interval) { public Enumeration getAttributeNames() { crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | if (valid) { if (! valid) { long getCreationTime() | return creationTime; String msg = sm.getString("applicationSession.session.ise"); return (attributes.keys()); Object getAttribute(String) | } else { Enumeration getAttributeNames() | String msg = sm.getString("applicationSession.session.ise"); throw new IllegalStateException(msg); } String[] getValueNames() | } void invalidate() | throw new IllegalStateException(msg); boolean isNew() | } /** void removeAttribute(String) | } * Return the object bound with the specified name in this session, or void setAttribute(String, Object)); * <code>null</code> if no object is bound with that name. /** * static advice(StandardSession s): invalidate(s) { * * @param name Name of the value to be returned before { * @deprecated * if (!s.isValid()) * @exception IllegalStateException if this method is called on an throw new IllegalStateException * invalidated session (s.sm.getString("standardSession." * + thisJoinPoint.methodName * @deprecated As of Version 2.2, this method is replaced by + ".ise")); * <code>getAttribute()</code> } */ } /** public Object getValue(String name) { * Return the session identifier for this session. */ return (getAttribute(name)); public String getId() { } } /** // -------------------------------------------------------------- Private Class * Return the set of names of objects bound to this session. If there * are no such objects, a zero-length array is returned. * /** * @exception IllegalStateException if this method is called on an * This class is a dummy implementation of the <code>HttpSessionContext</code> * invalidated session * interface, to conform to the requirement that such an object be returned * * when <code>HttpSession.getSessionContext()</code> is called. * @deprecated As of Version 2.2, this method is replaced by * * <code>getAttributeNames()</code> * @author Craig R. McClanahan */ * public String[] getValueNames() { * @deprecated As of Java Servlet API 2.1 with no replacement. The * interface will be removed in a future version of this API. Vector results = new Vector(); */ Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { final class StandardSessionContext implements HttpSessionContext { String attr = (String) attrs.nextElement(); results.addElement(attr); } private Vector dummy = new Vector(); return (this.id); String names[] = new String[results.size()]; for (int i = 0; i < names.length; i++) /** names[i] = (String) results.elementAt(i); * Return the session identifiers of all sessions defined return (names); * within this context. * } * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> * and will be removed in a future version of the API. /** */ * Invalidates this session and unbinds any objects bound to it. public Enumeration getIds() { * * @exception IllegalStateException if this method is called on return (dummy.elements()); * an invalidated session • Code is: */ public void invalidate() { // Cause this session to expire expire(); } } /** * Return <code>true</code> if the client does not yet know about the * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client * has disabled the use of cookies, then a session would be new on each * request. * * @exception IllegalStateException if this method is called on an * invalidated session */ public boolean isNew() { return (this.isNew); } package org.apache.tomcat.session; void validate() { // if we have an inactive interval, check to see if import org.apache.tomcat.core.*; // we've exceeded it import org.apache.tomcat.util.StringManager; import java.io.*; if (inactiveInterval != -1) { import java.net.*; int thisInterval = import java.util.*; (int)(System.currentTimeMillis() - lastAccessed) / 1000; import javax.servlet.*; import javax.servlet.http.*; if (thisInterval > inactiveInterval) { invalidate(); /** * Core implementation of a server session ServerSessionManager ssm = * ServerSessionManager.getManager(); * @author James Duncan Davidson [duncan@eng.sun.com] * @author James Todd [gonzo@eng.sun.com] ssm.removeSession(this); */ } } public class ServerSession { } private StringManager sm = synchronized void invalidate() { StringManager.getManager("org.apache.tomcat.session"); Enumeration enum = appSessions.keys(); /** private Hashtable values = new Hashtable(); * Set the session identifier for this session. private Hashtable appSessions = new Hashtable(); while (enum.hasMoreElements()) { * private String id; Object key = enum.nextElement(); * @param id The new session identifier private long creationTime = System.currentTimeMillis();; ApplicationSession appSession = */ private long thisAccessTime = creationTime; (ApplicationSession)appSessions.get(key); public void setId(String id) { private long lastAccessed = creationTime; private int inactiveInterval = -1; appSession.invalidate(); } ServerSession(String id) { } this.id = id; } public void putValue(String name, Object value) { if (name == null) { public String getId() { String msg = sm.getString("serverSession.value.iae"); return id; } throw new IllegalArgumentException(msg); } public long getCreationTime() { return creationTime; removeValue(name); // remove any existing binding } values.put(name, value); } • Scattered throughout public long getLastAccessedTime() { return lastAccessed; public Object getValue(String name) { } if (name == null) { String msg = sm.getString("serverSession.value.iae"); public ApplicationSession getApplicationSession(Context context, boolean create) { throw new IllegalArgumentException(msg); ApplicationSession appSession = } if ((this.id != null) && (manager != null) && (ApplicationSession)appSessions.get(context); (manager instanceof ManagerBase)) return values.get(name); ((ManagerBase) manager).remove(this); if (appSession == null && create) { } // XXX public Enumeration getValueNames() { // sync to ensure valid? return values.keys(); } appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); public void removeValue(String name) { } values.remove(name); } // XXX // make sure that we haven't gone over the end of our public void setMaxInactiveInterval(int interval) { // inactive interval -- if so, invalidate and create inactiveInterval = interval; // a new appSession } return appSession; public int getMaxInactiveInterval() { } return inactiveInterval; } void removeApplicationSession(Context context) { appSessions.remove(context); // XXX } // sync'd for safty -- no other thread should be getting something // from this while we are reaping. This isn't the most optimal /** // solution for this, but we'll determine something else later. this.id = id; * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. synchronized void reap() { */ Enumeration enum = appSessions.keys(); void accessed() { while (enum.hasMoreElements()) { // set last accessed to thisAccessTime as it will be left over many modules. if ((manager != null) && (manager instanceof ManagerBase)) ((ManagerBase) manager).add(this); } /** * Return descriptive information about this Session implementation and * the corresponding version number, in the format * <code>&lt;description&gt;/&lt;version&gt;</code>. */ public String getInfo() { return (this.info); } /** * Return the last time the client sent a request associated with this * session, as the number of milliseconds since midnight, January 1, 1970 * GMT. Actions that your application takes, such as getting or setting * a value associated with the session, do not affect the access time. */ public long getLastAccessedTime() { return (this.lastAccessedTime); } /** * Return the Manager within which this Session is valid. */ public Manager getManager() { return (this.manager); } /** * Set the Manager within which this Session is valid. * * @param manager The new Manager */ public void setManager(Manager manager) { 10
  • 35. Crosscutting Concerns /* public void invalidate() { ; * Remove the object bound with the specified name from this session. If * ==================================================================== serverSession.removeApplicationSession(context); * the session does not have an object bound with this name, this method * * does nothing. * The Apache Software License, Version 1.1 // remove everything in the session /** * <p> * * Standard implementation of the <b>Session</b> interface. This object is * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. */ * notice, this list of conditions and the following disclaimer. * public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ Object object = attributes.get(name); * the documentation and/or other materials provided with the if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession return; * } implements HttpSession, Session { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { /** if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors * Update the accessed time information for this session. This method ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { * should be called by the context when a request comes in for a particular (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; * session, even if the application does not reference it. } itself, } /** */ } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. public void access() { * * } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated this.lastAccessedTime = this.thisAccessedTime; • Crosscutting concerns * Foundation" must not be used to endorse or promote products /** */ this.thisAccessedTime = System.currentTimeMillis(); * Bind an object to this session, using the specified name. If an object derived * @deprecated public StandardSession(Manager manager) { this.isNew=false; * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ } * replaced. * permission, please contact apache@apache.org. super(); * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); /** * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } * Perform the internal processing required to invalidate this session, * <code>valueBound()</code> on the object. * permission of the Apache Group. * without triggering an exception if the session has already expired. * * public void setAttribute(String name, Object value) { */ * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED if (! valid) { /** public void expire() { * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ // Remove this session from our manager's active sessions * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; if ((manager != null) && (manager instanceof ManagerBase)) * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } ((ManagerBase) manager).remove(this); * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** // Unbind any objects associated with this session */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. Vector results = new Vector(); public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ Enumeration attrs = getAttributeNames(); * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; while (attrs.hasMoreElements()) { if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } String attr = (String) attrs.nextElement(); !(value instanceof Serializable)) * SUCH DAMAGE. results.addElement(attr); throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** } (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before Enumeration names = results.elements(); * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time while (names.hasMoreElements()) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. String name = (String) names.nextElement(); removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ removeAttribute(name); attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } // Mark this session as invalid (new HttpSessionBindingEvent((HttpSession) this, name)); * /** setValid(false); } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } } private boolean isNew = true; /** package org.apache.tomcat.session; * @deprecated /** // -------------------------------------------- HttpSession Private Methods */ /** import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. } import org.apache.tomcat.util.StringManager; return getAttribute(name); */ /** import java.io.*; } private boolean isValid = false; * Read a serialized version of this session object from the specified import java.net.*; /** * object input stream. import java.util.*; public Object getAttribute(String name) { * Set the <code>isNew</code> flag for this session. * <p> import javax.servlet.*; if (! valid) { /** * * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager import javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * @param isNew The new value for the <code>isNew</code> flag * is not restored by this method, and must be set explicitly. */ */ * /** throw new IllegalStateException(msg); private StringManager sm = void setNew(boolean isNew) { * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * this.isNew = isNew; * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * @exception IOException if an input/output error occurs (CCCs) affect many * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** } */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; /** public class ApplicationSession implements HttpSession { * Set the <code>isValid</code> flag for this session. // Deserialize the scalar instance variables (except Manager) return values.get(name); * creationTime = ((Long) stream.readObject()).longValue(); private StringManager sm = } /** * @param isValid The new value for the <code>isValid</code> flag id = (String) stream.readObject(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. */ lastAccessedTime = ((Long) stream.readObject()).longValue(); private Hashtable values = new Hashtable(); /** */ void setValid(boolean isValid) { maxInactiveInterval = ((Integer) stream.readObject()).intValue(); private String id; * @deprecated private long thisAccessedTime = creationTime; isNew = ((Boolean) stream.readObject()).booleanValue(); private ServerSession serverSession; */ this.isValid = isValid; isValid = ((Boolean) stream.readObject()).booleanValue(); private Context context; public String[] getValueNames() { } private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); // Deserialize the attribute count and attribute values private long thisAccessTime = creationTime; Vector names = new Vector(); int n = ((Integer) stream.readObject()).intValue(); private long lastAccessed = creationTime; // ----------------------------------------------------- Session Properties // ------------------------------------------------- HttpSession Properties for (int i = 0; i < n; i++) { private int inactiveInterval = -1; while (e.hasMoreElements()) { String name = (String) stream.readObject(); private boolean valid = true; names.addElement(e.nextElement()); Object value = (Object) stream.readObject(); } /** /** attributes.put(name, value); ApplicationSession(String id, ServerSession serverSession, * Set the creation time for this session. This method is called by the * Return the time when this session was created, in milliseconds since } Context context) { String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * midnight, January 1, 1970 GMT. this.serverSession = serverSession; * * } this.context = context; names.copyInto(valueNames); * @param time The new creation time * @exception IllegalStateException if this method is called on an this.id = id; */ * invalidated session return valueNames; public void setCreationTime(long time) { */ /** this.inactiveInterval = context.getSessionTimeOut(); public long getCreationTime() { * Write a serialized version of this session object to the specified } this.creationTime = time; * object output stream. if (this.inactiveInterval != -1) { this.lastAccessedTime = time; return (this.creationTime); * <p> this.inactiveInterval *= 60; public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored } if (! valid) { } * in the serialized representation of this Session. After calling } String msg = sm.getString("applicationSession.session.ise"); * <code>readObject()</code>, you must set the associated Manager * explicitly. ServerSession getServerSession() { throw new IllegalStateException(msg); /** * <p> return serverSession; } * Return the session context with which this session is associated. * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable } * * will be silently ignored. If you do not want any such attributes, Hashtable valuesClone = (Hashtable)values.clone(); * @deprecated As of Version 2.1, this method is deprecated and has no * be sure the <code>distributable</code> property of our associated heterogeneous software /** * replacement. It will be removed in a future version of the * Manager is set to <code>true</code>. * Called by context when request comes in so that accesses and return (Enumeration)valuesClone.keys(); * Java Servlet API. * * inactivities can be dealt with accordingly. } */ * @param stream The output stream to write to */ public HttpSessionContext getSessionContext() { * * @exception IOException if an input/output error occurs void accessed() { /** if (sessionContext == null) */ // set last accessed to thisAccessTime as it will be left over * @deprecated sessionContext = new StandardSessionContext(); private void writeObject(ObjectOutputStream stream) throws IOException { // from the previous access */ return (sessionContext); lastAccessed = thisAccessTime; // Write the scalar instance variables (except Manager) thisAccessTime = System.currentTimeMillis(); public void removeValue(String name) { } stream.writeObject(new Long(creationTime)); removeAttribute(name); stream.writeObject(id); validate(); } stream.writeObject(new Long(lastAccessedTime)); } // ----------------------------------------------HttpSession Public Methods stream.writeObject(new Integer(maxInactiveInterval)); public void removeAttribute(String name) { stream.writeObject(new Boolean(isNew)); void validate() { if (! valid) { } stream.writeObject(new Boolean(isValid)); // if we have an inactive interval, check to see if we've exceeded it String msg = sm.getString("applicationSession.session.ise"); /** if (inactiveInterval != -1) { * Return the object bound with the specified name in this session, or // Accumulate the names of serializable attributes int thisInterval = throw new IllegalStateException(msg); * <code>null</code> if no object is bound with that name. Vector results = new Vector(); (int)(System.currentTimeMillis() - lastAccessed) / 1000; } * Enumeration attrs = getAttributeNames(); * @param name Name of the attribute to be returned while (attrs.hasMoreElements()) { if (thisInterval > inactiveInterval) { if (name == null) { * String attr = (String) attrs.nextElement(); invalidate(); String msg = sm.getString("applicationSession.value.iae"); * @exception IllegalStateException if this method is called on an Object value = attributes.get(attr); } * invalidated session if (value instanceof Serializable) } throw new IllegalArgumentException(msg); */ results.addElement(attr); } } public Object getAttribute(String name) { } // HTTP SESSION IMPLEMENTATION METHODS Object o = values.get(name); return (attributes.get(name)); // Serialize the attribute count and the attribute values stream.writeObject(new Integer(results.size())); public String getId() { if (o instanceof HttpSessionBindingListener) { } Enumeration names = results.elements(); if (valid) { HttpSessionBindingEvent e = while (names.hasMoreElements()) { return id; new HttpSessionBindingEvent(this,name); String name = (String) names.nextElement(); } else { /** stream.writeObject(name); String msg = sm.getString("applicationSession.session.ise"); ((HttpSessionBindingListener)o).valueUnbound(e); * Return an <code>Enumeration</code> of <code>String</code> objects stream.writeObject(attributes.get(name)); } * containing the names of the objects bound to this session. } throw new IllegalStateException(msg); * modules. } values.remove(name); * @exception IllegalStateException if this method is called on an } } * invalidated session } */ public long getCreationTime() { public void setMaxInactiveInterval(int interval) { public Enumeration getAttributeNames() { crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | if (valid) { if (! valid) { long getCreationTime() | return creationTime; String msg = sm.getString("applicationSession.session.ise"); return (attributes.keys()); Object getAttribute(String) | } else { Enumeration getAttributeNames() | String msg = sm.getString("applicationSession.session.ise"); throw new IllegalStateException(msg); } String[] getValueNames() | } void invalidate() | throw new IllegalStateException(msg); boolean isNew() | } /** void removeAttribute(String) | } * Return the object bound with the specified name in this session, or void setAttribute(String, Object)); * <code>null</code> if no object is bound with that name. /** * static advice(StandardSession s): invalidate(s) { * * @param name Name of the value to be returned before { * @deprecated * if (!s.isValid()) * @exception IllegalStateException if this method is called on an throw new IllegalStateException * invalidated session (s.sm.getString("standardSession." * + thisJoinPoint.methodName * @deprecated As of Version 2.2, this method is replaced by + ".ise")); * <code>getAttribute()</code> } */ } /** public Object getValue(String name) { * Return the session identifier for this session. */ return (getAttribute(name)); public String getId() { } } /** // -------------------------------------------------------------- Private Class * Return the set of names of objects bound to this session. If there * are no such objects, a zero-length array is returned. * /** * @exception IllegalStateException if this method is called on an * This class is a dummy implementation of the <code>HttpSessionContext</code> * invalidated session * interface, to conform to the requirement that such an object be returned * * when <code>HttpSession.getSessionContext()</code> is called. * @deprecated As of Version 2.2, this method is replaced by * * <code>getAttributeNames()</code> * @author Craig R. McClanahan */ * public String[] getValueNames() { * @deprecated As of Java Servlet API 2.1 with no replacement. The * interface will be removed in a future version of this API. Vector results = new Vector(); */ Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { final class StandardSessionContext implements HttpSessionContext { String attr = (String) attrs.nextElement(); results.addElement(attr); } private Vector dummy = new Vector(); return (this.id); String names[] = new String[results.size()]; for (int i = 0; i < names.length; i++) /** names[i] = (String) results.elementAt(i); * Return the session identifiers of all sessions defined return (names); * within this context. * } * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> * and will be removed in a future version of the API. /** */ * Invalidates this session and unbinds any objects bound to it. public Enumeration getIds() { * * @exception IllegalStateException if this method is called on return (dummy.elements()); * an invalidated session • Code is: */ public void invalidate() { // Cause this session to expire expire(); } } /** * Return <code>true</code> if the client does not yet know about the * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client * has disabled the use of cookies, then a session would be new on each * request. * * @exception IllegalStateException if this method is called on an * invalidated session */ public boolean isNew() { return (this.isNew); } package org.apache.tomcat.session; void validate() { // if we have an inactive interval, check to see if import org.apache.tomcat.core.*; // we've exceeded it import org.apache.tomcat.util.StringManager; import java.io.*; if (inactiveInterval != -1) { import java.net.*; int thisInterval = import java.util.*; (int)(System.currentTimeMillis() - lastAccessed) / 1000; import javax.servlet.*; import javax.servlet.http.*; if (thisInterval > inactiveInterval) { invalidate(); /** * Core implementation of a server session ServerSessionManager ssm = * ServerSessionManager.getManager(); * @author James Duncan Davidson [duncan@eng.sun.com] * @author James Todd [gonzo@eng.sun.com] ssm.removeSession(this); */ } } public class ServerSession { } private StringManager sm = synchronized void invalidate() { StringManager.getManager("org.apache.tomcat.session"); Enumeration enum = appSessions.keys(); /** private Hashtable values = new Hashtable(); * Set the session identifier for this session. private Hashtable appSessions = new Hashtable(); while (enum.hasMoreElements()) { * private String id; Object key = enum.nextElement(); * @param id The new session identifier private long creationTime = System.currentTimeMillis();; ApplicationSession appSession = */ private long thisAccessTime = creationTime; (ApplicationSession)appSessions.get(key); public void setId(String id) { private long lastAccessed = creationTime; private int inactiveInterval = -1; appSession.invalidate(); } ServerSession(String id) { } this.id = id; } public void putValue(String name, Object value) { if (name == null) { public String getId() { String msg = sm.getString("serverSession.value.iae"); return id; } throw new IllegalArgumentException(msg); } public long getCreationTime() { return creationTime; removeValue(name); // remove any existing binding } values.put(name, value); } • Scattered throughout public long getLastAccessedTime() { return lastAccessed; public Object getValue(String name) { } if (name == null) { String msg = sm.getString("serverSession.value.iae"); public ApplicationSession getApplicationSession(Context context, boolean create) { throw new IllegalArgumentException(msg); ApplicationSession appSession = } if ((this.id != null) && (manager != null) && (ApplicationSession)appSessions.get(context); (manager instanceof ManagerBase)) return values.get(name); ((ManagerBase) manager).remove(this); if (appSession == null && create) { } // XXX public Enumeration getValueNames() { // sync to ensure valid? return values.keys(); } appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); public void removeValue(String name) { } values.remove(name); } // XXX // make sure that we haven't gone over the end of our public void setMaxInactiveInterval(int interval) { // inactive interval -- if so, invalidate and create inactiveInterval = interval; // a new appSession } return appSession; public int getMaxInactiveInterval() { } return inactiveInterval; } void removeApplicationSession(Context context) { appSessions.remove(context); // XXX } // sync'd for safty -- no other thread should be getting something // from this while we are reaping. This isn't the most optimal /** // solution for this, but we'll determine something else later. this.id = id; * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. synchronized void reap() { */ Enumeration enum = appSessions.keys(); void accessed() { while (enum.hasMoreElements()) { // set last accessed to thisAccessTime as it will be left over many modules. if ((manager != null) && (manager instanceof ManagerBase)) ((ManagerBase) manager).add(this); } • Tangled with unrelated /** * Return descriptive information about this Session implementation and * the corresponding version number, in the format * <code>&lt;description&gt;/&lt;version&gt;</code>. */ public String getInfo() { return (this.info); modules. } /** * Return the last time the client sent a request associated with this * session, as the number of milliseconds since midnight, January 1, 1970 * GMT. Actions that your application takes, such as getting or setting * a value associated with the session, do not affect the access time. */ public long getLastAccessedTime() { return (this.lastAccessedTime); } /** * Return the Manager within which this Session is valid. */ public Manager getManager() { return (this.manager); } /** * Set the Manager within which this Session is valid. * * @param manager The new Manager */ public void setManager(Manager manager) { 10
  • 36. Crosscutting Concerns /* public void invalidate() { ; * Remove the object bound with the specified name from this session. If * ==================================================================== serverSession.removeApplicationSession(context); * the session does not have an object bound with this name, this method * * does nothing. * The Apache Software License, Version 1.1 // remove everything in the session /** * <p> * * Standard implementation of the <b>Session</b> interface. This object is * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. */ * notice, this list of conditions and the following disclaimer. * public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ Object object = attributes.get(name); * the documentation and/or other materials provided with the if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession return; * } implements HttpSession, Session { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { /** if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors * Update the accessed time information for this session. This method ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { * should be called by the context when a request comes in for a particular (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; * session, even if the application does not reference it. } itself, } /** */ } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. public void access() { * * } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated this.lastAccessedTime = this.thisAccessedTime; • Crosscutting concerns * Foundation" must not be used to endorse or promote products /** */ this.thisAccessedTime = System.currentTimeMillis(); * Bind an object to this session, using the specified name. If an object derived * @deprecated public StandardSession(Manager manager) { this.isNew=false; * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ } * replaced. * permission, please contact apache@apache.org. super(); * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); /** * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } * Perform the internal processing required to invalidate this session, * <code>valueBound()</code> on the object. * permission of the Apache Group. * without triggering an exception if the session has already expired. * * public void setAttribute(String name, Object value) { */ * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED if (! valid) { /** public void expire() { * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ // Remove this session from our manager's active sessions * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; if ((manager != null) && (manager instanceof ManagerBase)) * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } ((ManagerBase) manager).remove(this); * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** // Unbind any objects associated with this session */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. Vector results = new Vector(); public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ Enumeration attrs = getAttributeNames(); * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; while (attrs.hasMoreElements()) { if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } String attr = (String) attrs.nextElement(); !(value instanceof Serializable)) * SUCH DAMAGE. results.addElement(attr); throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** } (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before Enumeration names = results.elements(); * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time while (names.hasMoreElements()) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. String name = (String) names.nextElement(); removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ removeAttribute(name); attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } // Mark this session as invalid (new HttpSessionBindingEvent((HttpSession) this, name)); * /** setValid(false); } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } } private boolean isNew = true; /** package org.apache.tomcat.session; * @deprecated /** // -------------------------------------------- HttpSession Private Methods */ /** import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. } import org.apache.tomcat.util.StringManager; return getAttribute(name); */ /** import java.io.*; } private boolean isValid = false; * Read a serialized version of this session object from the specified import java.net.*; /** * object input stream. import java.util.*; public Object getAttribute(String name) { * Set the <code>isNew</code> flag for this session. * <p> import javax.servlet.*; if (! valid) { /** * * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager import javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * @param isNew The new value for the <code>isNew</code> flag * is not restored by this method, and must be set explicitly. */ */ * /** throw new IllegalStateException(msg); private StringManager sm = void setNew(boolean isNew) { * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * this.isNew = isNew; * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * @exception IOException if an input/output error occurs (CCCs) affect many * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** } */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; /** public class ApplicationSession implements HttpSession { * Set the <code>isValid</code> flag for this session. // Deserialize the scalar instance variables (except Manager) return values.get(name); * creationTime = ((Long) stream.readObject()).longValue(); private StringManager sm = } /** * @param isValid The new value for the <code>isValid</code> flag id = (String) stream.readObject(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. */ lastAccessedTime = ((Long) stream.readObject()).longValue(); private Hashtable values = new Hashtable(); /** */ void setValid(boolean isValid) { maxInactiveInterval = ((Integer) stream.readObject()).intValue(); private String id; * @deprecated private long thisAccessedTime = creationTime; isNew = ((Boolean) stream.readObject()).booleanValue(); private ServerSession serverSession; */ this.isValid = isValid; isValid = ((Boolean) stream.readObject()).booleanValue(); private Context context; public String[] getValueNames() { } private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); // Deserialize the attribute count and attribute values private long thisAccessTime = creationTime; Vector names = new Vector(); int n = ((Integer) stream.readObject()).intValue(); private long lastAccessed = creationTime; // ----------------------------------------------------- Session Properties // ------------------------------------------------- HttpSession Properties for (int i = 0; i < n; i++) { private int inactiveInterval = -1; while (e.hasMoreElements()) { String name = (String) stream.readObject(); private boolean valid = true; names.addElement(e.nextElement()); Object value = (Object) stream.readObject(); } /** /** attributes.put(name, value); ApplicationSession(String id, ServerSession serverSession, * Set the creation time for this session. This method is called by the * Return the time when this session was created, in milliseconds since } Context context) { String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * midnight, January 1, 1970 GMT. this.serverSession = serverSession; * * } this.context = context; names.copyInto(valueNames); * @param time The new creation time * @exception IllegalStateException if this method is called on an this.id = id; */ * invalidated session return valueNames; public void setCreationTime(long time) { */ /** this.inactiveInterval = context.getSessionTimeOut(); public long getCreationTime() { * Write a serialized version of this session object to the specified } this.creationTime = time; * object output stream. if (this.inactiveInterval != -1) { this.lastAccessedTime = time; return (this.creationTime); * <p> this.inactiveInterval *= 60; public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored } if (! valid) { } * in the serialized representation of this Session. After calling } String msg = sm.getString("applicationSession.session.ise"); * <code>readObject()</code>, you must set the associated Manager * explicitly. ServerSession getServerSession() { throw new IllegalStateException(msg); /** * <p> return serverSession; } * Return the session context with which this session is associated. * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable } * * will be silently ignored. If you do not want any such attributes, Hashtable valuesClone = (Hashtable)values.clone(); * @deprecated As of Version 2.1, this method is deprecated and has no * be sure the <code>distributable</code> property of our associated heterogeneous software /** * replacement. It will be removed in a future version of the * Manager is set to <code>true</code>. * Called by context when request comes in so that accesses and return (Enumeration)valuesClone.keys(); * Java Servlet API. * * inactivities can be dealt with accordingly. } */ * @param stream The output stream to write to Message */ public HttpSessionContext getSessionContext() { * * @exception IOException if an input/output error occurs void accessed() { /** if (sessionContext == null) */ // set last accessed to thisAccessTime as it will be left over * @deprecated sessionContext = new StandardSessionContext(); private void writeObject(ObjectOutputStream stream) throws IOException { // from the previous access */ return (sessionContext); lastAccessed = thisAccessTime; // Write the scalar instance variables (except Manager) thisAccessTime = System.currentTimeMillis(); public void removeValue(String name) { } stream.writeObject(new Long(creationTime)); removeAttribute(name); stream.writeObject(id); validate(); } stream.writeObject(new Long(lastAccessedTime)); } // ----------------------------------------------HttpSession Public Methods stream.writeObject(new Integer(maxInactiveInterval)); public void removeAttribute(String name) { stream.writeObject(new Boolean(isNew)); void validate() { if (! valid) { } stream.writeObject(new Boolean(isValid)); // if we have an inactive interval, check to see if we've exceeded it String msg = sm.getString("applicationSession.session.ise"); /** if (inactiveInterval != -1) { * Return the object bound with the specified name in this session, or // Accumulate the names of serializable attributes int thisInterval = throw new IllegalStateException(msg); * <code>null</code> if no object is bound with that name. Vector results = new Vector(); (int)(System.currentTimeMillis() - lastAccessed) / 1000; } * Enumeration attrs = getAttributeNames(); * @param name Name of the attribute to be returned while (attrs.hasMoreElements()) { if (thisInterval > inactiveInterval) { if (name == null) { * String attr = (String) attrs.nextElement(); invalidate(); String msg = sm.getString("applicationSession.value.iae"); * @exception IllegalStateException if this method is called on an Object value = attributes.get(attr); } * invalidated session if (value instanceof Serializable) } throw new IllegalArgumentException(msg); */ results.addElement(attr); } } public Object getAttribute(String name) { } // HTTP SESSION IMPLEMENTATION METHODS Object o = values.get(name); return (attributes.get(name)); // Serialize the attribute count and the attribute values stream.writeObject(new Integer(results.size())); public String getId() { if (o instanceof HttpSessionBindingListener) { } Enumeration names = results.elements(); if (valid) { HttpSessionBindingEvent e = while (names.hasMoreElements()) { return id; new HttpSessionBindingEvent(this,name); String name = (String) names.nextElement(); } else { /** stream.writeObject(name); String msg = sm.getString("applicationSession.session.ise"); ((HttpSessionBindingListener)o).valueUnbound(e); * Return an <code>Enumeration</code> of <code>String</code> objects stream.writeObject(attributes.get(name)); } * containing the names of the objects bound to this session. } throw new IllegalStateException(msg); * modules. } values.remove(name); * @exception IllegalStateException if this method is called on an } } * invalidated session } */ public long getCreationTime() { public void setMaxInactiveInterval(int interval) { public Enumeration getAttributeNames() { crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | if (valid) { if (! valid) { long getCreationTime() | return creationTime; String msg = sm.getString("applicationSession.session.ise"); return (attributes.keys()); Object getAttribute(String) | } else { Enumeration getAttributeNames() | String msg = sm.getString("applicationSession.session.ise"); throw new IllegalStateException(msg); } String[] getValueNames() | } void invalidate() | throw new IllegalStateException(msg); boolean isNew() | } /** void removeAttribute(String) | } * Return the object bound with the specified name in this session, or void setAttribute(String, Object)); encryption is an * <code>null</code> if no object is bound with that name. /** * static advice(StandardSession s): invalidate(s) { * * @param name Name of the value to be returned before { * @deprecated * if (!s.isValid()) * @exception IllegalStateException if this method is called on an throw new IllegalStateException * invalidated session (s.sm.getString("standardSession." * + thisJoinPoint.methodName * @deprecated As of Version 2.2, this method is replaced by + ".ise")); * <code>getAttribute()</code> } */ } /** public Object getValue(String name) { * Return the session identifier for this session. */ return (getAttribute(name)); public String getId() { } } /** // -------------------------------------------------------------- Private Class * Return the set of names of objects bound to this session. If there * are no such objects, a zero-length array is returned. * /** * @exception IllegalStateException if this method is called on an * This class is a dummy implementation of the <code>HttpSessionContext</code> * invalidated session * interface, to conform to the requirement that such an object be returned * * when <code>HttpSession.getSessionContext()</code> is called. * @deprecated As of Version 2.2, this method is replaced by * * <code>getAttributeNames()</code> * @author Craig R. McClanahan */ * public String[] getValueNames() { * @deprecated As of Java Servlet API 2.1 with no replacement. The * interface will be removed in a future version of this API. Vector results = new Vector(); */ Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { final class StandardSessionContext implements HttpSessionContext { String attr = (String) attrs.nextElement(); results.addElement(attr); } private Vector dummy = new Vector(); return (this.id); String names[] = new String[results.size()]; for (int i = 0; i < names.length; i++) /** names[i] = (String) results.elementAt(i); * Return the session identifiers of all sessions defined return (names); * within this context. * } * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> * and will be removed in a future version of the API. /** */ example since many * Invalidates this session and unbinds any objects bound to it. public Enumeration getIds() { * * @exception IllegalStateException if this method is called on return (dummy.elements()); * an invalidated session • Code is: */ public void invalidate() { // Cause this session to expire expire(); } } /** * Return <code>true</code> if the client does not yet know about the * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client * has disabled the use of cookies, then a session would be new on each * request. * * @exception IllegalStateException if this method is called on an * invalidated session */ public boolean isNew() { return (this.isNew); } package org.apache.tomcat.session; void validate() { // if we have an inactive interval, check to see if import org.apache.tomcat.core.*; // we've exceeded it import org.apache.tomcat.util.StringManager; import java.io.*; if (inactiveInterval != -1) { import java.net.*; int thisInterval = import java.util.*; (int)(System.currentTimeMillis() - lastAccessed) / 1000; import javax.servlet.*; parts of a program import javax.servlet.http.*; if (thisInterval > inactiveInterval) { invalidate(); /** * Core implementation of a server session ServerSessionManager ssm = * ServerSessionManager.getManager(); * @author James Duncan Davidson [duncan@eng.sun.com] * @author James Todd [gonzo@eng.sun.com] ssm.removeSession(this); */ } } public class ServerSession { } private StringManager sm = synchronized void invalidate() { StringManager.getManager("org.apache.tomcat.session"); Enumeration enum = appSessions.keys(); /** private Hashtable values = new Hashtable(); * Set the session identifier for this session. private Hashtable appSessions = new Hashtable(); while (enum.hasMoreElements()) { * private String id; Object key = enum.nextElement(); * @param id The new session identifier private long creationTime = System.currentTimeMillis();; ApplicationSession appSession = */ private long thisAccessTime = creationTime; (ApplicationSession)appSessions.get(key); public void setId(String id) { private long lastAccessed = creationTime; private int inactiveInterval = -1; appSession.invalidate(); } ServerSession(String id) { } this.id = id; } public void putValue(String name, Object value) { if (name == null) { public String getId() { String msg = sm.getString("serverSession.value.iae"); return id; } throw new IllegalArgumentException(msg); } public long getCreationTime() { return creationTime; removeValue(name); // remove any existing binding } values.put(name, value); } • Scattered throughout public long getLastAccessedTime() { return lastAccessed; public Object getValue(String name) { } if (name == null) { String msg = sm.getString("serverSession.value.iae"); public ApplicationSession getApplicationSession(Context context, boolean create) { throw new IllegalArgumentException(msg); ApplicationSession appSession = } if ((this.id != null) && (manager != null) && (ApplicationSession)appSessions.get(context); (manager instanceof ManagerBase)) return values.get(name); ((ManagerBase) manager).remove(this); if (appSession == null && create) { } involve security // XXX public Enumeration getValueNames() { // sync to ensure valid? return values.keys(); } appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); public void removeValue(String name) { } values.remove(name); } // XXX // make sure that we haven't gone over the end of our public void setMaxInactiveInterval(int interval) { // inactive interval -- if so, invalidate and create inactiveInterval = interval; // a new appSession } return appSession; public int getMaxInactiveInterval() { } return inactiveInterval; } void removeApplicationSession(Context context) { appSessions.remove(context); // XXX } // sync'd for safty -- no other thread should be getting something // from this while we are reaping. This isn't the most optimal /** // solution for this, but we'll determine something else later. this.id = id; * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. synchronized void reap() { */ Enumeration enum = appSessions.keys(); void accessed() { while (enum.hasMoreElements()) { // set last accessed to thisAccessTime as it will be left over many modules. if ((manager != null) && (manager instanceof ManagerBase)) ((ManagerBase) manager).add(this); } • Tangled with unrelated /** * Return descriptive information about this Session implementation and * the corresponding version number, in the format * <code>&lt;description&gt;/&lt;version&gt;</code>. */ public String getInfo() { return (this.info); modules. } /** * Return the last time the client sent a request associated with this * session, as the number of milliseconds since midnight, January 1, 1970 * GMT. Actions that your application takes, such as getting or setting * a value associated with the session, do not affect the access time. */ public long getLastAccessedTime() { return (this.lastAccessedTime); } /** * Return the Manager within which this Session is valid. */ public Manager getManager() { return (this.manager); } /** * Set the Manager within which this Session is valid. * * @param manager The new Manager */ public void setManager(Manager manager) { 10
  • 37. Aspect-Oriented Programming /* public void invalidate() { ; * Remove the object bound with the specified name from this session. If * ==================================================================== serverSession.removeApplicationSession(context); /** * the session does not have an object bound with this name, this method * * Perform the internal processing required to invalidate this session, * does nothing. * The Apache Software License, Version 1.1 // remove everything in the session /** * without triggering an exception if the session has already expired. * <p> * * Standard implementation of the <b>Session</b> interface. This object is */ * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred public void expire() { * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> // Remove this session from our manager's active sessions * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the if ((manager != null) && (manager instanceof ManagerBase)) * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. ((ManagerBase) manager).remove(this); * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an // Unbind any objects associated with this session * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. Vector results = new Vector(); */ * notice, this list of conditions and the following disclaimer. * Enumeration attrs = getAttributeNames(); public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan while (attrs.hasMoreElements()) { * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ String attr = (String) attrs.nextElement(); synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ results.addElement(attr); Object object = attributes.get(name); * the documentation and/or other materials provided with the } if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession Enumeration names = results.elements(); return; * } implements HttpSession, Session { while (names.hasMoreElements()) { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if String name = (String) names.nextElement(); // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { removeAttribute(name); if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors } ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; // Mark this session as invalid } itself, } /** setValid(false); } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. * * } } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated * Foundation" must not be used to endorse or promote products /** */ * Bind an object to this session, using the specified name. If an object derived * @deprecated public StandardSession(Manager manager) { /** * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ * replaced. * permission, please contact apache@apache.org. super(); } * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } /** * <code>valueBound()</code> on the object. * permission of the Apache Group. * Set the <code>isNew</code> flag for this session. * * public void setAttribute(String name, Object value) { * * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED if (! valid) { /** * @param isNew The new value for the <code>isNew</code> flag * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. */ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ void setNew(boolean isNew) { * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } this.isNew = isNew; * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** } */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; /** if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } * Set the <code>isValid</code> flag for this session. !(value instanceof Serializable)) * SUCH DAMAGE. * throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** * @param isValid The new value for the <code>isValid</code> flag (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before */ * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time void setValid(boolean isValid) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ this.isValid = isValid; attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } (new HttpSessionBindingEvent((HttpSession) this, name)); * /** // ------------------------------------------------- HttpSession Properties } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } private boolean isNew = true; /** /** * Return the time when this session was created, in milliseconds since package org.apache.tomcat.session; * @deprecated * midnight, January 1, 1970 GMT. // -------------------------------------------- HttpSession Private Methods */ /** * import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. * @exception IllegalStateException if this method is called on an import org.apache.tomcat.util.StringManager; return getAttribute(name); */ * invalidated session /** import java.io.*; } private boolean isValid = false; */ * Read a serialized version of this session object from the specified import java.net.*; public long getCreationTime() { * object input stream. import java.util.*; public Object getAttribute(String name) { * <p> import javax.servlet.*; if (! valid) { /** return (this.creationTime); * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager import javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * is not restored by this method, and must be set explicitly. */ } * /** throw new IllegalStateException(msg); private StringManager sm = * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * /** * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * Return the session context with which this session is associated. * @exception IOException if an input/output error occurs * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** * */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. * @deprecated As of Version 2.1, this method is deprecated and has no private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ * replacement. It will be removed in a future version of the throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; * Java Servlet API. public class ApplicationSession implements HttpSession { */ // Deserialize the scalar instance variables (except Manager) return values.get(name); public HttpSessionContext getSessionContext() { creationTime = ((Long) stream.readObject()). private StringManager sm = } /** isValid = ((Boolean) stream.readObject()).booleanValue(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. if (sessionContext == null) private Hashtable values = new Hashtable(); /** */ sessionContext = new StandardSessionContext(); // Deserialize the attribute count and attribute values private String id; * @deprecated private long thisAccessedTime = creationTime; return (sessionContext); int n = ((Integer) stream.readObject()).intValue(); private ServerSession serverSession; */ for (int i = 0; i < n; i++) { private Context context; public String[] getValueNames() { } String name = (String) stream.readObject(); private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); Object value = (Object) stream.readObject(); private long thisAccessTime = creationTime; Vector names = new Vector(); attributes.put(name, value); private boolean valid = true; // ----------------------------------------------------- Session Properties // ----------------------------------------------HttpSession Public Methods } while (e.hasMoreElements()) { ApplicationSession(String id, ServerSession serverSession, names.addElement(e.nextElement()); } Context context) { } /** /** this.serverSession = serverSession; * Set the creation time for this session. This method is called by the * Return the object bound with the specified name in this session, or this.context = context; String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * <code>null</code> if no object is bound with that name. /** this.id = id; * * * Write a serialized version of this session object to the specified names.copyInto(valueNames); * @param time The new creation time * @param name Name of the attribute to be returned * object output stream. this.inactiveInterval = context.getSessionTimeOut(); */ * * <p> return valueNames; public void setCreationTime(long time) { * @exception IllegalStateException if this method is called on an * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored if (this.inactiveInterval != -1) { * invalidated session * in the serialized representation of this Session. After calling this.inactiveInterval *= 60; } this.creationTime = time; */ * <code>readObject()</code>, you must set the associated Manager } this.lastAccessedTime = time; public Object getAttribute(String name) { * explicitly. } public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <p> if (! valid) { return (attributes.get(name)); * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable ServerSession getServerSession() { String msg = sm.getString("applicationSession.session.ise"); } * will be silently ignored. If you do not want any such attributes, return serverSession; } * be sure the <code>distributable</code> property of our associated } throw new IllegalStateException(msg); * Manager is set to <code>true</code>. } /** * /** * Return the session identifier for this session. /** * @param stream The output stream to write to * Called by context when request comes in so that accesses and Hashtable valuesClone = (Hashtable)values.clone(); */ * Return an <code>Enumeration</code> of <code>String</code> objects * * inactivities can be dealt with accordingly. public String getId() { * containing the names of the objects bound to this session. * @exception IOException if an input/output error occurs */ return (Enumeration)valuesClone.keys(); * */ } return (this.id); * @exception IllegalStateException if this method is called on an private void writeObject(ObjectOutputStream stream) throws IOException { * invalidated session // HTTP SESSION IMPLEMENTATION METHODS } */ // Write the scalar instance variables (except Manager) /** public Enumeration getAttributeNames() { stream.writeObject(new Long(creationTime)); public String getId() { * @deprecated stream.writeObject(id); if (valid) { */ /** return (attributes.keys()); stream.writeObject(new Long(lastAccessedTime)); return id; * Set the session identifier for this session. stream.writeObject(new Integer(maxInactiveInterval)); } else { public void removeValue(String name) { * } stream.writeObject(new Boolean(isNew)); String msg = sm.getString("applicationSession.session.ise"); removeAttribute(name); * @param id The new session identifier stream.writeObject(new Boolean(isValid)); } */ throw new IllegalStateException(msg); public void setId(String id) { /** // Accumulate the names of serializable attributes } public void removeAttribute(String name) { * Return the object bound with the specified name in this session, or Vector results = new Vector(); } if (! valid) { if ((this.id != null) && (manager != null) && * <code>null</code> if no object is bound with that name. Enumeration attrs = getAttributeNames(); String msg = sm.getString("applicationSession.session.ise"); (manager instanceof ManagerBase)) * while (attrs.hasMoreElements()) { public long getCreationTime() { ((ManagerBase) manager).remove(this); * @param name Name of the value to be returned String attr = (String) attrs.nextElement(); if (valid) { throw new IllegalStateException(msg); * Object value = attributes.get(attr); return creationTime; } this.id = id; * @exception IllegalStateException if this method is called on an if (value instanceof Serializable) } else { * invalidated session results.addElement(attr); String msg = sm.getString("applicationSession.session.ise"); if (name == null) { if ((manager != null) && (manager instanceof ManagerBase)) * } String msg = sm.getString("applicationSession.value.iae"); ((ManagerBase) manager).add(this); * @deprecated As of Version 2.2, this method is replaced by throw new IllegalStateException(msg); * <code>getAttribute()</code> // Serialize the attribute count and the attribute values } throw new IllegalArgumentException(msg); } */ stream.writeObject(new Integer(results.size())); } } public Object getValue(String name) { Enumeration names = results.elements(); while (names.hasMoreElements()) { /** Object o = values.get(name); /** return (getAttribute(name)); String name = (String) names.nextElement(); * * Return descriptive information about this Session implementation and stream.writeObject(name); * @deprecated if (o instanceof HttpSessionBindingListener) { * the corresponding version number, in the format } stream.writeObject(attributes.get(name)); */ HttpSessionBindingEvent e = * <code>&lt;description&gt;/&lt;version&gt;</code>. } new HttpSessionBindingEvent(this,name); */ public HttpSessionContext getSessionContext() { public String getInfo() { /** return new SessionContextImpl(); ((HttpSessionBindingListener)o).valueUnbound(e); * Return the set of names of objects bound to this session. If there } } } return (this.info); * are no such objects, a zero-length array is returned. * crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | values.remove(name); } * @exception IllegalStateException if this method is called on an long getCreationTime() | } * invalidated session Object getAttribute(String) | /** * Enumeration getAttributeNames() | public void setMaxInactiveInterval(int interval) { * Return the Manager within which this Session is valid. * @deprecated As of Version 2.2, this method is replaced by String[] getValueNames() | if (! valid) { */ * <code>getAttributeNames()</code> void invalidate() | String msg = sm.getString("applicationSession.session.ise"); public Manager getManager() { */ boolean isNew() | public String[] getValueNames() { void removeAttribute(String) | throw new IllegalStateException(msg); return (this.manager); void setAttribute(String, Object)); } Vector results = new Vector(); } Enumeration attrs = getAttributeNames(); static advice(StandardSession s): invalidate(s) { inactiveInterval = interval; while (attrs.hasMoreElements()) { before { } String attr = (String) attrs.nextElement(); if (!s.isValid()) /** results.addElement(attr); throw new IllegalStateException public int getMaxInactiveInterval() { * Set the Manager within which this Session is valid. } (s.sm.getString("standardSession." if (! valid) { * String names[] = new String[results.size()]; + thisJoinPoint.methodName String msg = sm.getString("applicationSession.session.ise"); * @param manager The new Manager for (int i = 0; i < names.length; i++) + ".ise")); */ names[i] = (String) results.elementAt(i); } throw new IllegalStateException(msg); public void setManager(Manager manager) { return (names); } } this.manager = manager; } return inactiveInterval; } } } /** } * Invalidates this session and unbinds any objects bound to it. /** * //----------------------------------------------------------------------- * Return the maximum time interval, in seconds, between client requests * @exception IllegalStateException if this method is called on // -------------------------------------------------------------- Private Class * before the servlet container will invalidate the session. A negative * an invalidated session * time indicates that the session should never time out. */ * public void invalidate() { /** * @exception IllegalStateException if this method is called on * This class is a dummy implementation of the <code>HttpSessionContext</code> * an invalidated session // Cause this session to expire * interface, to conform to the requirement that such an object be returned */ expire(); * when <code>HttpSession.getSessionContext()</code> is called. public int getMaxInactiveInterval() { * } * @author Craig R. McClanahan return (this.maxInactiveInterval); * * @deprecated As of Java Servlet API 2.1 with no replacement. The /** * interface will be removed in a future version of this API. * Return <code>true</code> if the client does not yet know about the */ * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client final class StandardSessionContext implements HttpSessionContext { * has disabled the use of cookies, then a session would be new on each * request. * private Vector dummy = new Vector(); * @exception IllegalStateException if this method is called on an * invalidated session /** */ * Return the session identifiers of all sessions defined public boolean isNew() { * within this context. * return (this.isNew); * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> } * and will be removed in a future version of the API. */ public Enumeration getIds() { return (dummy.elements()); } /** * Return the <code>HttpSession</code> associated with the * specified session identifier. * * @param id Session identifier for which to look up a session * * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return null and will be removed in a * future version of the API. */ public HttpSession getSession(String id) { return (null); } } package org.apache.tomcat.session; ynchronized void invalidate() { Enumeration enum = appSessions.keys(); import org.apache.tomcat.core.*; import org.apache.tomcat.util.StringManager; while (enum.hasMoreElements()) { import java.io.*; Object key = enum.nextElement(); import java.net.*; ApplicationSession appSession = import java.util.*; (ApplicationSession)appSessions.get(key); import javax.servlet.*; import javax.servlet.http.*; appSession.invalidate(); } /** } * Core implementation of a server session * public void putValue(String name, Object value) { * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * @author James Todd [gonzo@eng.sun.com] String msg = sm.getString("serverSession.value.iae"); */ throw new IllegalArgumentException(msg); public class ServerSession { } private StringManager sm = removeValue(name); // remove any existing binding StringManager.getManager("org.apache.tomcat.session"); values.put(name, value); private Hashtable values = new Hashtable(); } private Hashtable appSessions = new Hashtable(); private String id; public Object getValue(String name) { private long creationTime = System.currentTimeMillis();; if (name == null) { private long thisAccessTime = creationTime; String msg = sm.getString("serverSession.value.iae"); private long lastAccessed = creationTime; private int inactiveInterval = -1; throw new IllegalArgumentException(msg); } ServerSession(String id) { this.id = id; return values.get(name); } } public String getId() { public Enumeration getValueNames() { return id; return values.keys(); } } public long getCreationTime() { public void removeValue(String name) { return creationTime; values.remove(name); } } public long getLastAccessedTime() { public void setMaxInactiveInterval(int interval) { return lastAccessed; inactiveInterval = interval; } } public ApplicationSession getApplicationSession(Context context, public int getMaxInactiveInterval() { boolean create) { return inactiveInterval; ApplicationSession appSession = } (ApplicationSession)appSessions.get(context); // XXX if (appSession == null && create) { // sync'd for safty -- no other thread should be getting something // from this while we are reaping. This isn't the most optimal // XXX // solution for this, but we'll determine something else later. // sync to ensure valid? synchronized void reap() { appSession = new ApplicationSession(id, this, context); Enumeration enum = appSessions.keys(); appSessions.put(context, appSession); } while (enum.hasMoreElements()) { Object key = enum.nextElement(); // XXX ApplicationSession appSession = // make sure that we haven't gone over the end of our (ApplicationSession)appSessions.get(key); // inactive interval -- if so, invalidate and create // a new appSession appSession.validate(); } return appSession; } } } void removeApplicationSession(Context context) { appSessions.remove(context); } /** * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. */ void validate() private long lastAccessed = creationTime; if (inactiveInterval != -1) { private int inactiveInterval = -1; int thisInterval = (int)(System.currentTimeMillis() - lastAccessed) / 1000; void accessed() { // set last accessed to thisAccessTime as it will be left over if (thisInterval > inactiveInterval) { // from the previous access invalidate(); lastAccessed = thisAccessTime; thisAccessTime = System.currentTimeMillis(); ServerSessionManager ssm = ServerSessionManager.getManager(); validate(); } ssm.removeSession(this); } void validate() { } // if we have an inactive interval, check to see if we've exceeded it } if (inactiveInterval != -1) { int thisInterval = private long lastAccessedTime = creationTime; (int)(System.currentTimeMillis() - lastAccessed) / 1000; if (thisInterval > inactiveInterval) { invalidate(); /** } * 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() { */ if (valid) { public long getLastAccessedTime() { return lastAccessed; } else { return (this.lastAccessedTime); String msg = sm.getString("applicationSession.session.ise"); } throw new IllegalStateException(msg); } } this.lastAccessedTime = time; public long getLastAccessedTime() { return lastAccessed; } private long lastAccessed = creationTime; void accessed() { // set last accessed to thisAccessTime as it will be left over // from the previous access lastAccessed = thisAccessTime; thisAccessTime = System.currentTimeMillis(); } 11
  • 38. Aspect-Oriented Programming /* public void invalidate() { ; * Remove the object bound with the specified name from this session. If * ==================================================================== serverSession.removeApplicationSession(context); /** * the session does not have an object bound with this name, this method * * Perform the internal processing required to invalidate this session, * does nothing. * The Apache Software License, Version 1.1 // remove everything in the session /** * without triggering an exception if the session has already expired. * <p> * * Standard implementation of the <b>Session</b> interface. This object is */ * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred public void expire() { * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> // Remove this session from our manager's active sessions * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the if ((manager != null) && (manager instanceof ManagerBase)) * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. ((ManagerBase) manager).remove(this); * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an // Unbind any objects associated with this session * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. Vector results = new Vector(); */ * notice, this list of conditions and the following disclaimer. * Enumeration attrs = getAttributeNames(); public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan while (attrs.hasMoreElements()) { * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ String attr = (String) attrs.nextElement(); synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ results.addElement(attr); Object object = attributes.get(name); * the documentation and/or other materials provided with the } if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession Enumeration names = results.elements(); return; * } implements HttpSession, Session { while (names.hasMoreElements()) { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if String name = (String) names.nextElement(); // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { removeAttribute(name); if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors } ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; // Mark this session as invalid } itself, } /** setValid(false); } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. * * } } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated * Foundation" must not be used to endorse or promote products /** */ * Bind an object to this session, using the specified name. If an object derived * @deprecated public StandardSession(Manager manager) { /** * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ * replaced. * permission, please contact apache@apache.org. super(); } * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } /** * <code>valueBound()</code> on the object. * permission of the Apache Group. * Set the <code>isNew</code> flag for this session. * * public void setAttribute(String name, Object value) { * * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED if (! valid) { /** * @param isNew The new value for the <code>isNew</code> flag * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. */ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ void setNew(boolean isNew) { * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } this.isNew = isNew; * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** } */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; /** if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } * Set the <code>isValid</code> flag for this session. !(value instanceof Serializable)) • * SUCH DAMAGE. * throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** * @param isValid The new value for the <code>isValid</code> flag (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before */ * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time void setValid(boolean isValid) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ this.isValid = isValid; attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } (new HttpSessionBindingEvent((HttpSession) this, name)); * /** // ------------------------------------------------- HttpSession Properties } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } private boolean isNew = true; /** Aspect-Oriented /** * Return the time when this session was created, in milliseconds since package org.apache.tomcat.session; * @deprecated * midnight, January 1, 1970 GMT. // -------------------------------------------- HttpSession Private Methods */ /** * import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. * @exception IllegalStateException if this method is called on an import org.apache.tomcat.util.StringManager; return getAttribute(name); */ * invalidated session /** import java.io.*; } private boolean isValid = false; */ * Read a serialized version of this session object from the specified import java.net.*; public long getCreationTime() { * object input stream. import java.util.*; public Object getAttribute(String name) { * <p> import javax.servlet.*; if (! valid) { /** return (this.creationTime); * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager import javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * is not restored by this method, and must be set explicitly. */ } * /** throw new IllegalStateException(msg); private StringManager sm = * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * /** * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * Return the session context with which this session is associated. * @exception IOException if an input/output error occurs * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** * */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. * @deprecated As of Version 2.1, this method is deprecated and has no private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ * replacement. It will be removed in a future version of the throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; * Java Servlet API. public class ApplicationSession implements HttpSession { */ // Deserialize the scalar instance variables (except Manager) return values.get(name); public HttpSessionContext getSessionContext() { creationTime = ((Long) stream.readObject()). private StringManager sm = } /** isValid = ((Boolean) stream.readObject()).booleanValue(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. if (sessionContext == null) private Hashtable values = new Hashtable(); /** */ sessionContext = new StandardSessionContext(); // Deserialize the attribute count and attribute values private String id; * @deprecated private long thisAccessedTime = creationTime; return (sessionContext); int n = ((Integer) stream.readObject()).intValue(); private ServerSession serverSession; */ for (int i = 0; i < n; i++) { private Context context; public String[] getValueNames() { } String name = (String) stream.readObject(); private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); Object value = (Object) stream.readObject(); private long thisAccessTime = creationTime; Vector names = new Vector(); attributes.put(name, value); private boolean valid = true; // ----------------------------------------------------- Session Properties // ----------------------------------------------HttpSession Public Methods } while (e.hasMoreElements()) { ApplicationSession(String id, ServerSession serverSession, names.addElement(e.nextElement()); } Context context) { } /** /** this.serverSession = serverSession; * Set the creation time for this session. This method is called by the * Return the object bound with the specified name in this session, or this.context = context; String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * <code>null</code> if no object is bound with that name. /** Programming enables this.id = id; * * * Write a serialized version of this session object to the specified names.copyInto(valueNames); * @param time The new creation time * @param name Name of the attribute to be returned * object output stream. this.inactiveInterval = context.getSessionTimeOut(); */ * * <p> return valueNames; public void setCreationTime(long time) { * @exception IllegalStateException if this method is called on an * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored if (this.inactiveInterval != -1) { * invalidated session * in the serialized representation of this Session. After calling this.inactiveInterval *= 60; } this.creationTime = time; */ * <code>readObject()</code>, you must set the associated Manager } this.lastAccessedTime = time; public Object getAttribute(String name) { * explicitly. } public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <p> if (! valid) { return (attributes.get(name)); * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable ServerSession getServerSession() { String msg = sm.getString("applicationSession.session.ise"); } * will be silently ignored. If you do not want any such attributes, return serverSession; } * be sure the <code>distributable</code> property of our associated } throw new IllegalStateException(msg); * Manager is set to <code>true</code>. } /** * /** * Return the session identifier for this session. /** * @param stream The output stream to write to * Called by context when request comes in so that accesses and Hashtable valuesClone = (Hashtable)values.clone(); */ * Return an <code>Enumeration</code> of <code>String</code> objects * * inactivities can be dealt with accordingly. public String getId() { * containing the names of the objects bound to this session. * @exception IOException if an input/output error occurs */ return (Enumeration)valuesClone.keys(); * */ } return (this.id); * @exception IllegalStateException if this method is called on an private void writeObject(ObjectOutputStream stream) throws IOException { * invalidated session // HTTP SESSION IMPLEMENTATION METHODS } */ // Write the scalar instance variables (except Manager) /** public Enumeration getAttributeNames() { stream.writeObject(new Long(creationTime)); public String getId() { * @deprecated stream.writeObject(id); if (valid) { */ /** return (attributes.keys()); stream.writeObject(new Long(lastAccessedTime)); return id; * Set the session identifier for this session. stream.writeObject(new Integer(maxInactiveInterval)); } else { public void removeValue(String name) { * } stream.writeObject(new Boolean(isNew)); String msg = sm.getString("applicationSession.session.ise"); removeAttribute(name); * @param id The new session identifier stream.writeObject(new Boolean(isValid)); } */ throw new IllegalStateException(msg); public void setId(String id) { /** // Accumulate the names of serializable attributes } public void removeAttribute(String name) { * Return the object bound with the specified name in this session, or Vector results = new Vector(); } if (! valid) { if ((this.id != null) && (manager != null) && * <code>null</code> if no object is bound with that name. Enumeration attrs = getAttributeNames(); String msg = sm.getString("applicationSession.session.ise"); (manager instanceof ManagerBase)) * while (attrs.hasMoreElements()) { public long getCreationTime() { ((ManagerBase) manager).remove(this); * @param name Name of the value to be returned String attr = (String) attrs.nextElement(); if (valid) { throw new IllegalStateException(msg); * Object value = attributes.get(attr); return creationTime; } this.id = id; * @exception IllegalStateException if this method is called on an if (value instanceof Serializable) } else { * invalidated session results.addElement(attr); localized implementations String msg = sm.getString("applicationSession.session.ise"); if (name == null) { if ((manager != null) && (manager instanceof ManagerBase)) * } String msg = sm.getString("applicationSession.value.iae"); ((ManagerBase) manager).add(this); * @deprecated As of Version 2.2, this method is replaced by throw new IllegalStateException(msg); * <code>getAttribute()</code> // Serialize the attribute count and the attribute values } throw new IllegalArgumentException(msg); } */ stream.writeObject(new Integer(results.size())); } } public Object getValue(String name) { Enumeration names = results.elements(); while (names.hasMoreElements()) { /** Object o = values.get(name); /** return (getAttribute(name)); String name = (String) names.nextElement(); * * Return descriptive information about this Session implementation and stream.writeObject(name); * @deprecated if (o instanceof HttpSessionBindingListener) { * the corresponding version number, in the format } stream.writeObject(attributes.get(name)); */ HttpSessionBindingEvent e = * <code>&lt;description&gt;/&lt;version&gt;</code>. } new HttpSessionBindingEvent(this,name); */ public HttpSessionContext getSessionContext() { public String getInfo() { /** return new SessionContextImpl(); ((HttpSessionBindingListener)o).valueUnbound(e); * Return the set of names of objects bound to this session. If there } } } return (this.info); * are no such objects, a zero-length array is returned. * crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | values.remove(name); } * @exception IllegalStateException if this method is called on an long getCreationTime() | } * invalidated session Object getAttribute(String) | /** * Enumeration getAttributeNames() | public void setMaxInactiveInterval(int interval) { * Return the Manager within which this Session is valid. * @deprecated As of Version 2.2, this method is replaced by String[] getValueNames() | if (! valid) { */ * <code>getAttributeNames()</code> void invalidate() | String msg = sm.getString("applicationSession.session.ise"); public Manager getManager() { */ boolean isNew() | public String[] getValueNames() { void removeAttribute(String) | throw new IllegalStateException(msg); return (this.manager); void setAttribute(String, Object)); } Vector results = new Vector(); } Enumeration attrs = getAttributeNames(); static advice(StandardSession s): invalidate(s) { inactiveInterval = interval; while (attrs.hasMoreElements()) { before { } String attr = (String) attrs.nextElement(); if (!s.isValid()) /** results.addElement(attr); throw new IllegalStateException public int getMaxInactiveInterval() { * Set the Manager within which this Session is valid. } (s.sm.getString("standardSession." if (! valid) { * String names[] = new String[results.size()]; + thisJoinPoint.methodName String msg = sm.getString("applicationSession.session.ise"); * @param manager The new Manager for (int i = 0; i < names.length; i++) + ".ise")); */ names[i] = (String) results.elementAt(i); } throw new IllegalStateException(msg); public void setManager(Manager manager) { return (names); } } this.manager = manager; } of CCCs. return inactiveInterval; } } } /** } * Invalidates this session and unbinds any objects bound to it. /** * //----------------------------------------------------------------------- * Return the maximum time interval, in seconds, between client requests * @exception IllegalStateException if this method is called on // -------------------------------------------------------------- Private Class * before the servlet container will invalidate the session. A negative * an invalidated session * time indicates that the session should never time out. */ * public void invalidate() { /** * @exception IllegalStateException if this method is called on * This class is a dummy implementation of the <code>HttpSessionContext</code> * an invalidated session // Cause this session to expire * interface, to conform to the requirement that such an object be returned */ expire(); * when <code>HttpSession.getSessionContext()</code> is called. public int getMaxInactiveInterval() { * } * @author Craig R. McClanahan return (this.maxInactiveInterval); * * @deprecated As of Java Servlet API 2.1 with no replacement. The /** * interface will be removed in a future version of this API. * Return <code>true</code> if the client does not yet know about the */ * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client final class StandardSessionContext implements HttpSessionContext { * has disabled the use of cookies, then a session would be new on each * request. * private Vector dummy = new Vector(); * @exception IllegalStateException if this method is called on an * invalidated session /** */ * Return the session identifiers of all sessions defined public boolean isNew() { * within this context. * return (this.isNew); * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> } * and will be removed in a future version of the API. */ public Enumeration getIds() { return (dummy.elements()); } /** * Return the <code>HttpSession</code> associated with the * specified session identifier. * * @param id Session identifier for which to look up a session * * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return null and will be removed in a * future version of the API. */ public HttpSession getSession(String id) { return (null); } } package org.apache.tomcat.session; ynchronized void invalidate() { Enumeration enum = appSessions.keys(); import org.apache.tomcat.core.*; import org.apache.tomcat.util.StringManager; while (enum.hasMoreElements()) { import java.io.*; Object key = enum.nextElement(); import java.net.*; ApplicationSession appSession = import java.util.*; (ApplicationSession)appSessions.get(key); import javax.servlet.*; import javax.servlet.http.*; appSession.invalidate(); } /** } * Core implementation of a server session * public void putValue(String name, Object value) { * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * @author James Todd [gonzo@eng.sun.com] String msg = sm.getString("serverSession.value.iae"); */ throw new IllegalArgumentException(msg); public class ServerSession { } private StringManager sm = removeValue(name); // remove any existing binding StringManager.getManager("org.apache.tomcat.session"); values.put(name, value); private Hashtable values = new Hashtable(); } private Hashtable appSessions = new Hashtable(); private String id; public Object getValue(String name) { private long creationTime = System.currentTimeMillis();; if (name == null) { private long thisAccessTime = creationTime; String msg = sm.getString("serverSession.value.iae"); private long lastAccessed = creationTime; private int inactiveInterval = -1; throw new IllegalArgumentException(msg); } ServerSession(String id) { this.id = id; return values.get(name); } } public String getId() { public Enumeration getValueNames() { return id; return values.keys(); } } public long getCreationTime() { public void removeValue(String name) { return creationTime; values.remove(name); } } public long getLastAccessedTime() { public void setMaxInactiveInterval(int interval) { return lastAccessed; inactiveInterval = interval; } } public ApplicationSession getApplicationSession(Context context, public int getMaxInactiveInterval() { boolean create) { return inactiveInterval; ApplicationSession appSession = } (ApplicationSession)appSessions.get(context); // XXX if (appSession == null && create) { // sync'd for safty -- no other thread should be getting something // from this while we are reaping. This isn't the most optimal // XXX // solution for this, but we'll determine something else later. // sync to ensure valid? synchronized void reap() { appSession = new ApplicationSession(id, this, context); Enumeration enum = appSessions.keys(); appSessions.put(context, appSession); } while (enum.hasMoreElements()) { Object key = enum.nextElement(); // XXX ApplicationSession appSession = // make sure that we haven't gone over the end of our (ApplicationSession)appSessions.get(key); // inactive interval -- if so, invalidate and create // a new appSession appSession.validate(); } return appSession; } } } void removeApplicationSession(Context context) { appSessions.remove(context); } /** * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. */ void validate() private long lastAccessed = creationTime; if (inactiveInterval != -1) { private int inactiveInterval = -1; int thisInterval = (int)(System.currentTimeMillis() - lastAccessed) / 1000; void accessed() { // set last accessed to thisAccessTime as it will be left over if (thisInterval > inactiveInterval) { // from the previous access invalidate(); lastAccessed = thisAccessTime; thisAccessTime = System.currentTimeMillis(); ServerSessionManager ssm = ServerSessionManager.getManager(); validate(); } ssm.removeSession(this); } void validate() { } // if we have an inactive interval, check to see if we've exceeded it } if (inactiveInterval != -1) { int thisInterval = private long lastAccessedTime = creationTime; (int)(System.currentTimeMillis() - lastAccessed) / 1000; if (thisInterval > inactiveInterval) { invalidate(); /** } * 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() { */ if (valid) { public long getLastAccessedTime() { return lastAccessed; } else { return (this.lastAccessedTime); String msg = sm.getString("applicationSession.session.ise"); } throw new IllegalStateException(msg); } } this.lastAccessedTime = time; public long getLastAccessedTime() { return lastAccessed; } private long lastAccessed = creationTime; void accessed() { // set last accessed to thisAccessTime as it will be left over // from the previous access lastAccessed = thisAccessTime; thisAccessTime = System.currentTimeMillis(); } 11
  • 39. Aspect-Oriented Programming /* public void invalidate() { ; * Remove the object bound with the specified name from this session. If * ==================================================================== serverSession.removeApplicationSession(context); /** * the session does not have an object bound with this name, this method * * Perform the internal processing required to invalidate this session, * does nothing. * The Apache Software License, Version 1.1 // remove everything in the session /** * without triggering an exception if the session has already expired. * <p> * * Standard implementation of the <b>Session</b> interface. This object is */ * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred public void expire() { * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> // Remove this session from our manager's active sessions * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the if ((manager != null) && (manager instanceof ManagerBase)) * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. ((ManagerBase) manager).remove(this); * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an // Unbind any objects associated with this session * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. Vector results = new Vector(); */ * notice, this list of conditions and the following disclaimer. * Enumeration attrs = getAttributeNames(); public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan while (attrs.hasMoreElements()) { * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ String attr = (String) attrs.nextElement(); synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ results.addElement(attr); Object object = attributes.get(name); * the documentation and/or other materials provided with the } if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession Enumeration names = results.elements(); return; * } implements HttpSession, Session { while (names.hasMoreElements()) { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if String name = (String) names.nextElement(); // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { removeAttribute(name); if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors } ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; // Mark this session as invalid } itself, } /** setValid(false); } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. * * } } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated * Foundation" must not be used to endorse or promote products /** */ * Bind an object to this session, using the specified name. If an object derived * @deprecated public StandardSession(Manager manager) { /** * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ * replaced. * permission, please contact apache@apache.org. super(); } * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } /** * <code>valueBound()</code> on the object. * permission of the Apache Group. * Set the <code>isNew</code> flag for this session. * * public void setAttribute(String name, Object value) { * * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED if (! valid) { /** * @param isNew The new value for the <code>isNew</code> flag * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. */ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ void setNew(boolean isNew) { * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } this.isNew = isNew; * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** } */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; /** if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } * Set the <code>isValid</code> flag for this session. !(value instanceof Serializable)) • * SUCH DAMAGE. * throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** * @param isValid The new value for the <code>isValid</code> flag (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before */ * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time void setValid(boolean isValid) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ this.isValid = isValid; attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } (new HttpSessionBindingEvent((HttpSession) this, name)); * /** // ------------------------------------------------- HttpSession Properties } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } private boolean isNew = true; /** Aspect-Oriented /** * Return the time when this session was created, in milliseconds since package org.apache.tomcat.session; * @deprecated * midnight, January 1, 1970 GMT. // -------------------------------------------- HttpSession Private Methods */ /** * import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. * @exception IllegalStateException if this method is called on an import org.apache.tomcat.util.StringManager; return getAttribute(name); */ * invalidated session /** import java.io.*; } private boolean isValid = false; */ * Read a serialized version of this session object from the specified import java.net.*; public long getCreationTime() { * object input stream. import java.util.*; public Object getAttribute(String name) { * <p> import javax.servlet.*; if (! valid) { /** return (this.creationTime); * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager import javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * is not restored by this method, and must be set explicitly. */ } * /** throw new IllegalStateException(msg); private StringManager sm = * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * /** * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * Return the session context with which this session is associated. * @exception IOException if an input/output error occurs * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** * */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. * @deprecated As of Version 2.1, this method is deprecated and has no private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ * replacement. It will be removed in a future version of the throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; * Java Servlet API. public class ApplicationSession implements HttpSession { */ // Deserialize the scalar instance variables (except Manager) return values.get(name); public HttpSessionContext getSessionContext() { creationTime = ((Long) stream.readObject()). private StringManager sm = } /** isValid = ((Boolean) stream.readObject()).booleanValue(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. if (sessionContext == null) private Hashtable values = new Hashtable(); /** */ sessionContext = new StandardSessionContext(); // Deserialize the attribute count and attribute values private String id; * @deprecated private long thisAccessedTime = creationTime; return (sessionContext); int n = ((Integer) stream.readObject()).intValue(); private ServerSession serverSession; */ for (int i = 0; i < n; i++) { private Context context; public String[] getValueNames() { } String name = (String) stream.readObject(); private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); Object value = (Object) stream.readObject(); private long thisAccessTime = creationTime; Vector names = new Vector(); attributes.put(name, value); private boolean valid = true; // ----------------------------------------------------- Session Properties // ----------------------------------------------HttpSession Public Methods } while (e.hasMoreElements()) { ApplicationSession(String id, ServerSession serverSession, names.addElement(e.nextElement()); } Context context) { } /** /** this.serverSession = serverSession; * Set the creation time for this session. This method is called by the * Return the object bound with the specified name in this session, or this.context = context; String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * <code>null</code> if no object is bound with that name. /** Programming enables this.id = id; * * * Write a serialized version of this session object to the specified names.copyInto(valueNames); * @param time The new creation time * @param name Name of the attribute to be returned * object output stream. this.inactiveInterval = context.getSessionTimeOut(); */ * * <p> return valueNames; public void setCreationTime(long time) { * @exception IllegalStateException if this method is called on an * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored if (this.inactiveInterval != -1) { * invalidated session * in the serialized representation of this Session. After calling this.inactiveInterval *= 60; } this.creationTime = time; */ * <code>readObject()</code>, you must set the associated Manager } this.lastAccessedTime = time; public Object getAttribute(String name) { * explicitly. } public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <p> if (! valid) { return (attributes.get(name)); * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable ServerSession getServerSession() { String msg = sm.getString("applicationSession.session.ise"); } * will be silently ignored. If you do not want any such attributes, return serverSession; } * be sure the <code>distributable</code> property of our associated } throw new IllegalStateException(msg); * Manager is set to <code>true</code>. } /** * /** * Return the session identifier for this session. /** * @param stream The output stream to write to * Called by context when request comes in so that accesses and Hashtable valuesClone = (Hashtable)values.clone(); */ * Return an <code>Enumeration</code> of <code>String</code> objects * * inactivities can be dealt with accordingly. public String getId() { * containing the names of the objects bound to this session. * @exception IOException if an input/output error occurs */ return (Enumeration)valuesClone.keys(); * */ } return (this.id); * @exception IllegalStateException if this method is called on an private void writeObject(ObjectOutputStream stream) throws IOException { * invalidated session // HTTP SESSION IMPLEMENTATION METHODS } */ // Write the scalar instance variables (except Manager) /** public Enumeration getAttributeNames() { stream.writeObject(new Long(creationTime)); public String getId() { * @deprecated stream.writeObject(id); if (valid) { */ /** return (attributes.keys()); stream.writeObject(new Long(lastAccessedTime)); return id; * Set the session identifier for this session. stream.writeObject(new Integer(maxInactiveInterval)); } else { public void removeValue(String name) { * } stream.writeObject(new Boolean(isNew)); String msg = sm.getString("applicationSession.session.ise"); removeAttribute(name); * @param id The new session identifier stream.writeObject(new Boolean(isValid)); } */ throw new IllegalStateException(msg); public void setId(String id) { /** // Accumulate the names of serializable attributes } public void removeAttribute(String name) { * Return the object bound with the specified name in this session, or Vector results = new Vector(); } if (! valid) { if ((this.id != null) && (manager != null) && * <code>null</code> if no object is bound with that name. Enumeration attrs = getAttributeNames(); String msg = sm.getString("applicationSession.session.ise"); (manager instanceof ManagerBase)) * while (attrs.hasMoreElements()) { public long getCreationTime() { ((ManagerBase) manager).remove(this); * @param name Name of the value to be returned String attr = (String) attrs.nextElement(); if (valid) { throw new IllegalStateException(msg); * Object value = attributes.get(attr); return creationTime; } this.id = id; * @exception IllegalStateException if this method is called on an if (value instanceof Serializable) } else { * invalidated session results.addElement(attr); localized implementations String msg = sm.getString("applicationSession.session.ise"); if (name == null) { if ((manager != null) && (manager instanceof ManagerBase)) * } String msg = sm.getString("applicationSession.value.iae"); ((ManagerBase) manager).add(this); * @deprecated As of Version 2.2, this method is replaced by throw new IllegalStateException(msg); * <code>getAttribute()</code> // Serialize the attribute count and the attribute values } throw new IllegalArgumentException(msg); } */ stream.writeObject(new Integer(results.size())); } } public Object getValue(String name) { Enumeration names = results.elements(); while (names.hasMoreElements()) { /** Object o = values.get(name); /** return (getAttribute(name)); String name = (String) names.nextElement(); * * Return descriptive information about this Session implementation and stream.writeObject(name); * @deprecated if (o instanceof HttpSessionBindingListener) { * the corresponding version number, in the format } stream.writeObject(attributes.get(name)); */ HttpSessionBindingEvent e = * <code>&lt;description&gt;/&lt;version&gt;</code>. } new HttpSessionBindingEvent(this,name); */ public HttpSessionContext getSessionContext() { public String getInfo() { /** return new SessionContextImpl(); ((HttpSessionBindingListener)o).valueUnbound(e); * Return the set of names of objects bound to this session. If there } } } return (this.info); * are no such objects, a zero-length array is returned. * crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | values.remove(name); } * @exception IllegalStateException if this method is called on an long getCreationTime() | } * invalidated session Object getAttribute(String) | /** * Enumeration getAttributeNames() | public void setMaxInactiveInterval(int interval) { * Return the Manager within which this Session is valid. * @deprecated As of Version 2.2, this method is replaced by String[] getValueNames() | if (! valid) { */ * <code>getAttributeNames()</code> void invalidate() | String msg = sm.getString("applicationSession.session.ise"); public Manager getManager() { */ boolean isNew() | public String[] getValueNames() { void removeAttribute(String) | throw new IllegalStateException(msg); return (this.manager); void setAttribute(String, Object)); } Vector results = new Vector(); } Enumeration attrs = getAttributeNames(); static advice(StandardSession s): invalidate(s) { inactiveInterval = interval; while (attrs.hasMoreElements()) { before { } String attr = (String) attrs.nextElement(); if (!s.isValid()) /** results.addElement(attr); throw new IllegalStateException public int getMaxInactiveInterval() { * Set the Manager within which this Session is valid. } (s.sm.getString("standardSession." if (! valid) { * String names[] = new String[results.size()]; + thisJoinPoint.methodName String msg = sm.getString("applicationSession.session.ise"); * @param manager The new Manager for (int i = 0; i < names.length; i++) + ".ise")); */ names[i] = (String) results.elementAt(i); } throw new IllegalStateException(msg); public void setManager(Manager manager) { return (names); } } this.manager = manager; } of CCCs. return inactiveInterval; } } } /** } * Invalidates this session and unbinds any objects bound to it. /** * //----------------------------------------------------------------------- * Return the maximum time interval, in seconds, between client requests * @exception IllegalStateException if this method is called on // -------------------------------------------------------------- Private Class * before the servlet container will invalidate the session. A negative * an invalidated session * time indicates that the session should never time out. */ * public void invalidate() { /** * @exception IllegalStateException if this method is called on * This class is a dummy implementation of the <code>HttpSessionContext</code> * an invalidated session // Cause this session to expire * interface, to conform to the requirement that such an object be returned */ expire(); * when <code>HttpSession.getSessionContext()</code> is called. public int getMaxInactiveInterval() { * } * @author Craig R. McClanahan return (this.maxInactiveInterval); * * @deprecated As of Java Servlet API 2.1 with no replacement. The /** * interface will be removed in a future version of this API. * Return <code>true</code> if the client does not yet know about the */ * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client final class StandardSessionContext implements HttpSessionContext { * has disabled the use of cookies, then a session would be new on each * request. * private Vector dummy = new Vector(); * @exception IllegalStateException if this method is called on an * invalidated session /** */ * Return the session identifiers of all sessions defined public boolean isNew() { * within this context. * return (this.isNew); * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> } * and will be removed in a future version of the API. */ public Enumeration getIds() { return (dummy.elements()); } /** * Return the <code>HttpSession</code> associated with the * specified session identifier. * * @param id Session identifier for which to look up a session * * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return null and will be removed in a * future version of the API. */ public HttpSession getSession(String id) { return (null); } } • Pointcuts select (join) points in the program where a CCC applies. package org.apache.tomcat.session; ynchronized void invalidate() { Enumeration enum = appSessions.keys(); import org.apache.tomcat.core.*; import org.apache.tomcat.util.StringManager; while (enum.hasMoreElements()) { import java.io.*; Object key = enum.nextElement(); import java.net.*; ApplicationSession appSession = import java.util.*; (ApplicationSession)appSessions.get(key); import javax.servlet.*; import javax.servlet.http.*; appSession.invalidate(); } /** } * Core implementation of a server session * public void putValue(String name, Object value) { * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * @author James Todd [gonzo@eng.sun.com] String msg = sm.getString("serverSession.value.iae"); */ throw new IllegalArgumentException(msg); public class ServerSession { } private StringManager sm = removeValue(name); // remove any existing binding StringManager.getManager("org.apache.tomcat.session"); values.put(name, value); private Hashtable values = new Hashtable(); } private Hashtable appSessions = new Hashtable(); private String id; public Object getValue(String name) { private long creationTime = System.currentTimeMillis();; if (name == null) { private long thisAccessTime = creationTime; String msg = sm.getString("serverSession.value.iae"); private long lastAccessed = creationTime; private int inactiveInterval = -1; throw new IllegalArgumentException(msg); } ServerSession(String id) { this.id = id; return values.get(name); } } public String getId() { public Enumeration getValueNames() { return id; return values.keys(); } } public long getCreationTime() { public void removeValue(String name) { return creationTime; values.remove(name); } } public long getLastAccessedTime() { public void setMaxInactiveInterval(int interval) { return lastAccessed; inactiveInterval = interval; } } public ApplicationSession getApplicationSession(Context context, public int getMaxInactiveInterval() { boolean create) { return inactiveInterval; ApplicationSession appSession = } (ApplicationSession)appSessions.get(context); // XXX if (appSession == null && create) { // sync'd for safty -- no other thread should be getting something // from this while we are reaping. This isn't the most optimal // XXX // solution for this, but we'll determine something else later. // sync to ensure valid? synchronized void reap() { appSession = new ApplicationSession(id, this, context); Enumeration enum = appSessions.keys(); appSessions.put(context, appSession); } while (enum.hasMoreElements()) { Object key = enum.nextElement(); // XXX ApplicationSession appSession = // make sure that we haven't gone over the end of our (ApplicationSession)appSessions.get(key); // inactive interval -- if so, invalidate and create // a new appSession appSession.validate(); } return appSession; } } } void removeApplicationSession(Context context) { appSessions.remove(context); } /** * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. */ void validate() private long lastAccessed = creationTime; if (inactiveInterval != -1) { private int inactiveInterval = -1; int thisInterval = (int)(System.currentTimeMillis() - lastAccessed) / 1000; void accessed() { // set last accessed to thisAccessTime as it will be left over if (thisInterval > inactiveInterval) { // from the previous access invalidate(); lastAccessed = thisAccessTime; thisAccessTime = System.currentTimeMillis(); ServerSessionManager ssm = ServerSessionManager.getManager(); validate(); } ssm.removeSession(this); } void validate() { } // if we have an inactive interval, check to see if we've exceeded it } if (inactiveInterval != -1) { int thisInterval = private long lastAccessedTime = creationTime; (int)(System.currentTimeMillis() - lastAccessed) / 1000; if (thisInterval > inactiveInterval) { invalidate(); /** } * 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() { */ if (valid) { public long getLastAccessedTime() { return lastAccessed; } else { return (this.lastAccessedTime); String msg = sm.getString("applicationSession.session.ise"); } throw new IllegalStateException(msg); } } this.lastAccessedTime = time; public long getLastAccessedTime() { return lastAccessed; } private long lastAccessed = creationTime; void accessed() { // set last accessed to thisAccessTime as it will be left over // from the previous access lastAccessed = thisAccessTime; thisAccessTime = System.currentTimeMillis(); } 11
  • 40. Aspect-Oriented Programming /* public void invalidate() { ; * Remove the object bound with the specified name from this session. If * ==================================================================== serverSession.removeApplicationSession(context); /** * the session does not have an object bound with this name, this method * * Perform the internal processing required to invalidate this session, * does nothing. * The Apache Software License, Version 1.1 // remove everything in the session /** * without triggering an exception if the session has already expired. * <p> * * Standard implementation of the <b>Session</b> interface. This object is */ * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred public void expire() { * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> // Remove this session from our manager's active sessions * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the if ((manager != null) && (manager instanceof ManagerBase)) * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. ((ManagerBase) manager).remove(this); * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an // Unbind any objects associated with this session * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. Vector results = new Vector(); */ * notice, this list of conditions and the following disclaimer. * Enumeration attrs = getAttributeNames(); public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan while (attrs.hasMoreElements()) { * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ String attr = (String) attrs.nextElement(); synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ results.addElement(attr); Object object = attributes.get(name); * the documentation and/or other materials provided with the } if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession Enumeration names = results.elements(); return; * } implements HttpSession, Session { while (names.hasMoreElements()) { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if String name = (String) names.nextElement(); // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { removeAttribute(name); if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors } ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; // Mark this session as invalid } itself, } /** setValid(false); } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. * * } } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated * Foundation" must not be used to endorse or promote products /** */ * Bind an object to this session, using the specified name. If an object derived * @deprecated public StandardSession(Manager manager) { /** * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ * replaced. * permission, please contact apache@apache.org. super(); } * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } /** * <code>valueBound()</code> on the object. * permission of the Apache Group. * Set the <code>isNew</code> flag for this session. * * public void setAttribute(String name, Object value) { * * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED if (! valid) { /** * @param isNew The new value for the <code>isNew</code> flag * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. */ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ void setNew(boolean isNew) { * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } this.isNew = isNew; * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** } */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; /** if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } * Set the <code>isValid</code> flag for this session. !(value instanceof Serializable)) • * SUCH DAMAGE. * throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** * @param isValid The new value for the <code>isValid</code> flag (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before */ * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time void setValid(boolean isValid) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ this.isValid = isValid; attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } (new HttpSessionBindingEvent((HttpSession) this, name)); * /** // ------------------------------------------------- HttpSession Properties } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } private boolean isNew = true; /** Aspect-Oriented /** * Return the time when this session was created, in milliseconds since package org.apache.tomcat.session; * @deprecated * midnight, January 1, 1970 GMT. // -------------------------------------------- HttpSession Private Methods */ /** * import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. * @exception IllegalStateException if this method is called on an import org.apache.tomcat.util.StringManager; return getAttribute(name); */ * invalidated session /** import java.io.*; } private boolean isValid = false; */ * Read a serialized version of this session object from the specified import java.net.*; public long getCreationTime() { * object input stream. import java.util.*; public Object getAttribute(String name) { * <p> import javax.servlet.*; if (! valid) { /** return (this.creationTime); * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager import javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * is not restored by this method, and must be set explicitly. */ } * /** throw new IllegalStateException(msg); private StringManager sm = * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * /** * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * Return the session context with which this session is associated. * @exception IOException if an input/output error occurs * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** * */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. * @deprecated As of Version 2.1, this method is deprecated and has no private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ * replacement. It will be removed in a future version of the throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; * Java Servlet API. public class ApplicationSession implements HttpSession { */ // Deserialize the scalar instance variables (except Manager) return values.get(name); public HttpSessionContext getSessionContext() { creationTime = ((Long) stream.readObject()). private StringManager sm = } /** isValid = ((Boolean) stream.readObject()).booleanValue(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. if (sessionContext == null) private Hashtable values = new Hashtable(); /** */ sessionContext = new StandardSessionContext(); // Deserialize the attribute count and attribute values private String id; * @deprecated private long thisAccessedTime = creationTime; return (sessionContext); int n = ((Integer) stream.readObject()).intValue(); private ServerSession serverSession; */ for (int i = 0; i < n; i++) { private Context context; public String[] getValueNames() { } String name = (String) stream.readObject(); private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); Object value = (Object) stream.readObject(); private long thisAccessTime = creationTime; Vector names = new Vector(); attributes.put(name, value); private boolean valid = true; // ----------------------------------------------------- Session Properties // ----------------------------------------------HttpSession Public Methods } while (e.hasMoreElements()) { ApplicationSession(String id, ServerSession serverSession, names.addElement(e.nextElement()); } Context context) { } /** /** this.serverSession = serverSession; * Set the creation time for this session. This method is called by the * Return the object bound with the specified name in this session, or this.context = context; String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * <code>null</code> if no object is bound with that name. /** Programming enables this.id = id; * * * Write a serialized version of this session object to the specified names.copyInto(valueNames); * @param time The new creation time * @param name Name of the attribute to be returned * object output stream. this.inactiveInterval = context.getSessionTimeOut(); */ * * <p> return valueNames; public void setCreationTime(long time) { * @exception IllegalStateException if this method is called on an * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored if (this.inactiveInterval != -1) { * invalidated session * in the serialized representation of this Session. After calling this.inactiveInterval *= 60; } this.creationTime = time; */ * <code>readObject()</code>, you must set the associated Manager } this.lastAccessedTime = time; public Object getAttribute(String name) { * explicitly. } public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <p> if (! valid) { return (attributes.get(name)); * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable ServerSession getServerSession() { String msg = sm.getString("applicationSession.session.ise"); } * will be silently ignored. If you do not want any such attributes, return serverSession; } * be sure the <code>distributable</code> property of our associated } throw new IllegalStateException(msg); * Manager is set to <code>true</code>. } /** * /** * Return the session identifier for this session. /** * @param stream The output stream to write to * Called by context when request comes in so that accesses and Hashtable valuesClone = (Hashtable)values.clone(); */ * Return an <code>Enumeration</code> of <code>String</code> objects * * inactivities can be dealt with accordingly. public String getId() { * containing the names of the objects bound to this session. * @exception IOException if an input/output error occurs */ return (Enumeration)valuesClone.keys(); * */ } return (this.id); * @exception IllegalStateException if this method is called on an private void writeObject(ObjectOutputStream stream) throws IOException { * invalidated session // HTTP SESSION IMPLEMENTATION METHODS } */ // Write the scalar instance variables (except Manager) /** public Enumeration getAttributeNames() { stream.writeObject(new Long(creationTime)); public String getId() { * @deprecated stream.writeObject(id); if (valid) { */ /** return (attributes.keys()); stream.writeObject(new Long(lastAccessedTime)); return id; * Set the session identifier for this session. stream.writeObject(new Integer(maxInactiveInterval)); } else { public void removeValue(String name) { * } stream.writeObject(new Boolean(isNew)); String msg = sm.getString("applicationSession.session.ise"); removeAttribute(name); * @param id The new session identifier stream.writeObject(new Boolean(isValid)); } */ throw new IllegalStateException(msg); public void setId(String id) { /** // Accumulate the names of serializable attributes } public void removeAttribute(String name) { * Return the object bound with the specified name in this session, or Vector results = new Vector(); } if (! valid) { if ((this.id != null) && (manager != null) && * <code>null</code> if no object is bound with that name. Enumeration attrs = getAttributeNames(); String msg = sm.getString("applicationSession.session.ise"); (manager instanceof ManagerBase)) * while (attrs.hasMoreElements()) { public long getCreationTime() { ((ManagerBase) manager).remove(this); * @param name Name of the value to be returned String attr = (String) attrs.nextElement(); if (valid) { throw new IllegalStateException(msg); * Object value = attributes.get(attr); return creationTime; } this.id = id; * @exception IllegalStateException if this method is called on an if (value instanceof Serializable) } else { * invalidated session results.addElement(attr); localized implementations String msg = sm.getString("applicationSession.session.ise"); if (name == null) { if ((manager != null) && (manager instanceof ManagerBase)) * } String msg = sm.getString("applicationSession.value.iae"); ((ManagerBase) manager).add(this); * @deprecated As of Version 2.2, this method is replaced by throw new IllegalStateException(msg); * <code>getAttribute()</code> // Serialize the attribute count and the attribute values } throw new IllegalArgumentException(msg); } */ stream.writeObject(new Integer(results.size())); } } public Object getValue(String name) { Enumeration names = results.elements(); while (names.hasMoreElements()) { /** Object o = values.get(name); /** return (getAttribute(name)); String name = (String) names.nextElement(); * * Return descriptive information about this Session implementation and stream.writeObject(name); * @deprecated if (o instanceof HttpSessionBindingListener) { * the corresponding version number, in the format } stream.writeObject(attributes.get(name)); */ HttpSessionBindingEvent e = * <code>&lt;description&gt;/&lt;version&gt;</code>. } new HttpSessionBindingEvent(this,name); */ public HttpSessionContext getSessionContext() { public String getInfo() { /** return new SessionContextImpl(); ((HttpSessionBindingListener)o).valueUnbound(e); * Return the set of names of objects bound to this session. If there } } } return (this.info); * are no such objects, a zero-length array is returned. * crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | values.remove(name); } * @exception IllegalStateException if this method is called on an long getCreationTime() | } * invalidated session Object getAttribute(String) | /** * Enumeration getAttributeNames() | public void setMaxInactiveInterval(int interval) { * Return the Manager within which this Session is valid. * @deprecated As of Version 2.2, this method is replaced by String[] getValueNames() | if (! valid) { */ * <code>getAttributeNames()</code> void invalidate() | String msg = sm.getString("applicationSession.session.ise"); public Manager getManager() { */ boolean isNew() | public String[] getValueNames() { void removeAttribute(String) | throw new IllegalStateException(msg); return (this.manager); void setAttribute(String, Object)); } Vector results = new Vector(); } Enumeration attrs = getAttributeNames(); static advice(StandardSession s): invalidate(s) { inactiveInterval = interval; while (attrs.hasMoreElements()) { before { } String attr = (String) attrs.nextElement(); if (!s.isValid()) /** results.addElement(attr); throw new IllegalStateException public int getMaxInactiveInterval() { * Set the Manager within which this Session is valid. } (s.sm.getString("standardSession." if (! valid) { * String names[] = new String[results.size()]; + thisJoinPoint.methodName String msg = sm.getString("applicationSession.session.ise"); * @param manager The new Manager for (int i = 0; i < names.length; i++) + ".ise")); */ names[i] = (String) results.elementAt(i); } throw new IllegalStateException(msg); public void setManager(Manager manager) { return (names); } } this.manager = manager; } of CCCs. return inactiveInterval; } } } /** } * Invalidates this session and unbinds any objects bound to it. /** * //----------------------------------------------------------------------- * Return the maximum time interval, in seconds, between client requests * @exception IllegalStateException if this method is called on // -------------------------------------------------------------- Private Class * before the servlet container will invalidate the session. A negative * an invalidated session * time indicates that the session should never time out. */ * public void invalidate() { /** * @exception IllegalStateException if this method is called on * This class is a dummy implementation of the <code>HttpSessionContext</code> * an invalidated session // Cause this session to expire * interface, to conform to the requirement that such an object be returned */ expire(); * when <code>HttpSession.getSessionContext()</code> is called. public int getMaxInactiveInterval() { * } * @author Craig R. McClanahan return (this.maxInactiveInterval); * * @deprecated As of Java Servlet API 2.1 with no replacement. The /** * interface will be removed in a future version of this API. * Return <code>true</code> if the client does not yet know about the */ * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client final class StandardSessionContext implements HttpSessionContext { * has disabled the use of cookies, then a session would be new on each * request. * private Vector dummy = new Vector(); * @exception IllegalStateException if this method is called on an * invalidated session /** */ * Return the session identifiers of all sessions defined public boolean isNew() { * within this context. * return (this.isNew); * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> } * and will be removed in a future version of the API. */ public Enumeration getIds() { return (dummy.elements()); } /** * Return the <code>HttpSession</code> associated with the * specified session identifier. * * @param id Session identifier for which to look up a session * * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return null and will be removed in a * future version of the API. */ public HttpSession getSession(String id) { return (null); } } • Pointcuts select (join) points in the program where a CCC applies. package org.apache.tomcat.session; ynchronized void invalidate() { Enumeration enum = appSessions.keys(); import org.apache.tomcat.core.*; import org.apache.tomcat.util.StringManager; while (enum.hasMoreElements()) { import java.io.*; Object key = enum.nextElement(); import java.net.*; ApplicationSession appSession = import java.util.*; (ApplicationSession)appSessions.get(key); import javax.servlet.*; import javax.servlet.http.*; appSession.invalidate(); } /** } * Core implementation of a server session * public void putValue(String name, Object value) { * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * @author James Todd [gonzo@eng.sun.com] String msg = sm.getString("serverSession.value.iae"); */ throw new IllegalArgumentException(msg); public class ServerSession { } private StringManager sm = removeValue(name); // remove any existing binding StringManager.getManager("org.apache.tomcat.session"); values.put(name, value); private Hashtable values = new Hashtable(); } private Hashtable appSessions = new Hashtable(); private String id; public Object getValue(String name) { private long creationTime = System.currentTimeMillis();; if (name == null) { private long thisAccessTime = creationTime; String msg = sm.getString("serverSession.value.iae"); private long lastAccessed = creationTime; private int inactiveInterval = -1; throw new IllegalArgumentException(msg); } ServerSession(String id) { this.id = id; return values.get(name); } } public String getId() { public Enumeration getValueNames() { return id; return values.keys(); } } public long getCreationTime() { public void removeValue(String name) { return creationTime; values.remove(name); } } public long getLastAccessedTime() { public void setMaxInactiveInterval(int interval) { return lastAccessed; inactiveInterval = interval; } } public ApplicationSession getApplicationSession(Context context, public int getMaxInactiveInterval() { boolean create) { return inactiveInterval; ApplicationSession appSession = } (ApplicationSession)appSessions.get(context); // XXX if (appSession == null && create) { // sync'd for safty -- no other thread should be getting something // from this while we are reaping. This isn't the most optimal • // XXX // solution for this, but we'll determine something else later. // sync to ensure valid? synchronized void reap() { appSession = new ApplicationSession(id, this, context); Enumeration enum = appSessions.keys(); appSessions.put(context, appSession); } while (enum.hasMoreElements()) { Object key = enum.nextElement(); // XXX ApplicationSession appSession = // make sure that we haven't gone over the end of our (ApplicationSession)appSessions.get(key); // inactive interval -- if so, invalidate and create // a new appSession appSession.validate(); } Code (advice) is implicitly return appSession; } } } void removeApplicationSession(Context context) { appSessions.remove(context); } /** * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. */ void validate() executed at those points. private long lastAccessed = creationTime; if (inactiveInterval != -1) { private int inactiveInterval = -1; int thisInterval = (int)(System.currentTimeMillis() - lastAccessed) / 1000; void accessed() { // set last accessed to thisAccessTime as it will be left over if (thisInterval > inactiveInterval) { // from the previous access invalidate(); lastAccessed = thisAccessTime; thisAccessTime = System.currentTimeMillis(); ServerSessionManager ssm = ServerSessionManager.getManager(); validate(); } ssm.removeSession(this); } void validate() { } // if we have an inactive interval, check to see if we've exceeded it } if (inactiveInterval != -1) { int thisInterval = private long lastAccessedTime = creationTime; (int)(System.currentTimeMillis() - lastAccessed) / 1000; if (thisInterval > inactiveInterval) { invalidate(); /** } * 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() { */ if (valid) { public long getLastAccessedTime() { return lastAccessed; } else { return (this.lastAccessedTime); String msg = sm.getString("applicationSession.session.ise"); } throw new IllegalStateException(msg); } } this.lastAccessedTime = time; public long getLastAccessedTime() { return lastAccessed; } private long lastAccessed = creationTime; void accessed() { // set last accessed to thisAccessTime as it will be left over // from the previous access lastAccessed = thisAccessTime; thisAccessTime = System.currentTimeMillis(); } 11
  • 41. Aspect-Oriented Programming /* public void invalidate() { ; * Remove the object bound with the specified name from this session. If * ==================================================================== serverSession.removeApplicationSession(context); /** * the session does not have an object bound with this name, this method * * Perform the internal processing required to invalidate this session, * does nothing. * The Apache Software License, Version 1.1 // remove everything in the session /** * without triggering an exception if the session has already expired. * <p> * * Standard implementation of the <b>Session</b> interface. This object is */ * After this method executes, and if the object implements * Copyright (c) 1999 The Apache Software Foundation. All rights Enumeration enum = values.keys(); * serializable, so that it can be stored in persistent storage or transferred public void expire() { * <code>HttpSessionBindingListener</code>, the container calls * reserved. while (enum.hasMoreElements()) { * to a different JVM for distributable session support. * <code>valueUnbound()</code> on the object. * String name = (String)enum.nextElement(); * <p> // Remove this session from our manager's active sessions * * Redistribution and use in source and binary forms, with or without removeValue(name); * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the if ((manager != null) && (manager instanceof ManagerBase)) * @param name Name of the object to remove from this session. * modification, are permitted provided that the following conditions } * internal (Session) and application level (HttpSession) view of the session. ((ManagerBase) manager).remove(this); * * are met: * However, because the class itself is not declared public, Java logic outside * @exception IllegalStateException if this method is called on an * valid = false; * of the <code>org.apache.tomcat.session</code> package cannot cast an // Unbind any objects associated with this session * invalidated session * 1. Redistributions of source code must retain the above copyright } * HttpSession view of this instance back to a Session view. Vector results = new Vector(); */ * notice, this list of conditions and the following disclaimer. * Enumeration attrs = getAttributeNames(); public void removeAttribute(String name) { * public boolean isNew() { * @author Craig R. McClanahan while (attrs.hasMoreElements()) { * 2. Redistributions in binary form must reproduce the above copyright if (! valid) { * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ String attr = (String) attrs.nextElement(); synchronized (attributes) { * notice, this list of conditions and the following disclaimer in String msg = sm.getString("applicationSession.session.ise"); */ results.addElement(attr); Object object = attributes.get(name); * the documentation and/or other materials provided with the } if (object == null) * distribution. throw new IllegalStateException(msg); final class StandardSession Enumeration names = results.elements(); return; * } implements HttpSession, Session { while (names.hasMoreElements()) { attributes.remove(name); * 3. The end-user documentation included with the redistribution, if String name = (String) names.nextElement(); // System.out.println( "Removing attribute " + name ); * any, must include the following acknowledgment: if (thisAccessTime == creationTime) { removeAttribute(name); if (object instanceof HttpSessionBindingListener) { * "This product includes software developed by the return true; // ----------------------------------------------------------- Constructors } ((HttpSessionBindingListener) object).valueUnbound * Apache Software Foundation (http://www.apache.org/)." } else { (new HttpSessionBindingEvent((HttpSession) this, name)); * Alternately, this acknowledgment may appear in the software return false; // Mark this session as invalid } itself, } /** setValid(false); } * if and wherever such third-party acknowledgments normally appear. } * Construct a new Session associated with the specified Manager. * * } } * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * @param manager The manager with which this Session is associated * Foundation" must not be used to endorse or promote products /** */ * Bind an object to this session, using the specified name. If an object derived * @deprecated public StandardSession(Manager manager) { /** * of the same name is already bound to this session, the object is * from this software without prior written permission. For written */ * replaced. * permission, please contact apache@apache.org. super(); } * <p> * public void putValue(String name, Object value) { this.manager = manager; * After this method executes, and if the object implements * 5. Products derived from this software may not be called "Apache" setAttribute(name, value); * <code>HttpSessionBindingListener</code>, the container calls * nor may "Apache" appear in their names without prior written } } /** * <code>valueBound()</code> on the object. * permission of the Apache Group. * Set the <code>isNew</code> flag for this session. * * public void setAttribute(String name, Object value) { * * @param name Name to which the object is bound, cannot be null * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED if (! valid) { /** * @param isNew The new value for the <code>isNew</code> flag * @param value Object to be bound, cannot be null * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES String msg = sm.getString("applicationSession.session.ise"); * The last accessed time for this Session. */ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ void setNew(boolean isNew) { * @exception IllegalArgumentException if an attempt is made to add a * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR throw new IllegalStateException(msg); private long lastAccessedTime = creationTime; * non-serializable object in an environment marked distributable. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, } this.isNew = isNew; * @exception IllegalStateException if this method is called on an * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * invalidated session * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF if (name == null) { /** } */ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND String msg = sm.getString("applicationSession.value.iae"); * The Manager with which this Session is associated. public void setAttribute(String name, Object value) { * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT throw new IllegalArgumentException(msg); private Manager manager = null; /** if ((manager != null) && manager.getDistributable() && * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF } * Set the <code>isValid</code> flag for this session. !(value instanceof Serializable)) • * SUCH DAMAGE. * throw new IllegalArgumentException * ==================================================================== removeValue(name); // remove any existing binding /** * @param isValid The new value for the <code>isValid</code> flag (sm.getString("standardSession.setAttribute.iae")); * * The maximum time interval, in seconds, between client requests before */ * This software consists of voluntary contributions made by many if (value != null && value instanceof HttpSessionBindingListener) { * the servlet container may invalidate this session. A negative time void setValid(boolean isValid) { synchronized (attributes) { * individuals on behalf of the Apache Software Foundation. For more HttpSessionBindingEvent e = * indicates that the session should never time out. removeAttribute(name); * information on the Apache Software Foundation, please see new HttpSessionBindingEvent(this, name); */ this.isValid = isValid; attributes.put(name, value); * <http://www.apache.org/>. private int maxInactiveInterval = -1; } if (value instanceof HttpSessionBindingListener) * ((HttpSessionBindingListener)value).valueBound(e); ((HttpSessionBindingListener) value).valueBound * [Additional notices, if required by prior licensing conditions] } (new HttpSessionBindingEvent((HttpSession) this, name)); * /** // ------------------------------------------------- HttpSession Properties } */ values.put(name, value); * Flag indicating whether this session is new or not. } */ } private boolean isNew = true; /** Aspect-Oriented /** * Return the time when this session was created, in milliseconds since package org.apache.tomcat.session; * @deprecated * midnight, January 1, 1970 GMT. // -------------------------------------------- HttpSession Private Methods */ /** * import org.apache.tomcat.core.*; public Object getValue(String name) { * Flag indicating whether this session is valid or not. * @exception IllegalStateException if this method is called on an import org.apache.tomcat.util.StringManager; return getAttribute(name); */ * invalidated session /** import java.io.*; } private boolean isValid = false; */ * Read a serialized version of this session object from the specified import java.net.*; public long getCreationTime() { * object input stream. import java.util.*; public Object getAttribute(String name) { * <p> import javax.servlet.*; if (! valid) { /** return (this.creationTime); * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager import javax.servlet.http.*; String msg = sm.getString("applicationSession.session.ise"); * The string manager for this package. * is not restored by this method, and must be set explicitly. */ } * /** throw new IllegalStateException(msg); private StringManager sm = * @param stream The input stream to read from * Core implementation of an application level session } StringManager.getManager("org.apache.tomcat.session"); * * /** * @exception ClassNotFoundException if an unknown class is specified * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * Return the session context with which this session is associated. * @exception IOException if an input/output error occurs * @author Jason Hunter [jch@eng.sun.com] String msg = sm.getString("applicationSession.value.iae"); /** * */ * @author James Todd [gonzo@eng.sun.com] * The HTTP session context associated with this session. * @deprecated As of Version 2.1, this method is deprecated and has no private void readObject(ObjectInputStream stream) */ throw new IllegalArgumentException(msg); */ * replacement. It will be removed in a future version of the throws ClassNotFoundException, IOException { } private static HttpSessionContext sessionContext = null; * Java Servlet API. public class ApplicationSession implements HttpSession { */ // Deserialize the scalar instance variables (except Manager) return values.get(name); public HttpSessionContext getSessionContext() { creationTime = ((Long) stream.readObject()). private StringManager sm = } /** isValid = ((Boolean) stream.readObject()).booleanValue(); StringManager.getManager("org.apache.tomcat.session"); * The current accessed time for this session. if (sessionContext == null) private Hashtable values = new Hashtable(); /** */ sessionContext = new StandardSessionContext(); // Deserialize the attribute count and attribute values private String id; * @deprecated private long thisAccessedTime = creationTime; return (sessionContext); int n = ((Integer) stream.readObject()).intValue(); private ServerSession serverSession; */ for (int i = 0; i < n; i++) { private Context context; public String[] getValueNames() { } String name = (String) stream.readObject(); private long creationTime = System.currentTimeMillis();; Enumeration e = getAttributeNames(); Object value = (Object) stream.readObject(); private long thisAccessTime = creationTime; Vector names = new Vector(); attributes.put(name, value); private boolean valid = true; // ----------------------------------------------------- Session Properties // ----------------------------------------------HttpSession Public Methods } while (e.hasMoreElements()) { ApplicationSession(String id, ServerSession serverSession, names.addElement(e.nextElement()); } Context context) { } /** /** this.serverSession = serverSession; * Set the creation time for this session. This method is called by the * Return the object bound with the specified name in this session, or this.context = context; String[] valueNames = new String[names.size()]; * Manager when an existing Session instance is reused. * <code>null</code> if no object is bound with that name. /** Programming enables this.id = id; * * * Write a serialized version of this session object to the specified names.copyInto(valueNames); * @param time The new creation time * @param name Name of the attribute to be returned * object output stream. this.inactiveInterval = context.getSessionTimeOut(); */ * * <p> return valueNames; public void setCreationTime(long time) { * @exception IllegalStateException if this method is called on an * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored if (this.inactiveInterval != -1) { * invalidated session * in the serialized representation of this Session. After calling this.inactiveInterval *= 60; } this.creationTime = time; */ * <code>readObject()</code>, you must set the associated Manager } this.lastAccessedTime = time; public Object getAttribute(String name) { * explicitly. } public Enumeration getAttributeNames() { this.thisAccessedTime = time; * <p> if (! valid) { return (attributes.get(name)); * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable ServerSession getServerSession() { String msg = sm.getString("applicationSession.session.ise"); } * will be silently ignored. If you do not want any such attributes, return serverSession; } * be sure the <code>distributable</code> property of our associated } throw new IllegalStateException(msg); * Manager is set to <code>true</code>. } /** * /** * Return the session identifier for this session. /** * @param stream The output stream to write to * Called by context when request comes in so that accesses and Hashtable valuesClone = (Hashtable)values.clone(); */ * Return an <code>Enumeration</code> of <code>String</code> objects * * inactivities can be dealt with accordingly. public String getId() { * containing the names of the objects bound to this session. * @exception IOException if an input/output error occurs */ return (Enumeration)valuesClone.keys(); * */ } return (this.id); * @exception IllegalStateException if this method is called on an private void writeObject(ObjectOutputStream stream) throws IOException { * invalidated session // HTTP SESSION IMPLEMENTATION METHODS } */ // Write the scalar instance variables (except Manager) /** public Enumeration getAttributeNames() { stream.writeObject(new Long(creationTime)); public String getId() { * @deprecated stream.writeObject(id); if (valid) { */ /** return (attributes.keys()); stream.writeObject(new Long(lastAccessedTime)); return id; * Set the session identifier for this session. stream.writeObject(new Integer(maxInactiveInterval)); } else { public void removeValue(String name) { * } stream.writeObject(new Boolean(isNew)); String msg = sm.getString("applicationSession.session.ise"); removeAttribute(name); * @param id The new session identifier stream.writeObject(new Boolean(isValid)); } */ throw new IllegalStateException(msg); public void setId(String id) { /** // Accumulate the names of serializable attributes } public void removeAttribute(String name) { * Return the object bound with the specified name in this session, or Vector results = new Vector(); } if (! valid) { if ((this.id != null) && (manager != null) && * <code>null</code> if no object is bound with that name. Enumeration attrs = getAttributeNames(); String msg = sm.getString("applicationSession.session.ise"); (manager instanceof ManagerBase)) * while (attrs.hasMoreElements()) { public long getCreationTime() { ((ManagerBase) manager).remove(this); * @param name Name of the value to be returned String attr = (String) attrs.nextElement(); if (valid) { throw new IllegalStateException(msg); * Object value = attributes.get(attr); return creationTime; } this.id = id; * @exception IllegalStateException if this method is called on an if (value instanceof Serializable) } else { * invalidated session results.addElement(attr); localized implementations String msg = sm.getString("applicationSession.session.ise"); if (name == null) { if ((manager != null) && (manager instanceof ManagerBase)) * } String msg = sm.getString("applicationSession.value.iae"); ((ManagerBase) manager).add(this); * @deprecated As of Version 2.2, this method is replaced by throw new IllegalStateException(msg); * <code>getAttribute()</code> // Serialize the attribute count and the attribute values } throw new IllegalArgumentException(msg); } */ stream.writeObject(new Integer(results.size())); } } public Object getValue(String name) { Enumeration names = results.elements(); while (names.hasMoreElements()) { /** Object o = values.get(name); /** return (getAttribute(name)); String name = (String) names.nextElement(); * * Return descriptive information about this Session implementation and stream.writeObject(name); * @deprecated if (o instanceof HttpSessionBindingListener) { * the corresponding version number, in the format } stream.writeObject(attributes.get(name)); */ HttpSessionBindingEvent e = * <code>&lt;description&gt;/&lt;version&gt;</code>. } new HttpSessionBindingEvent(this,name); */ public HttpSessionContext getSessionContext() { public String getInfo() { /** return new SessionContextImpl(); ((HttpSessionBindingListener)o).valueUnbound(e); * Return the set of names of objects bound to this session. If there } } } return (this.info); * are no such objects, a zero-length array is returned. * crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | values.remove(name); } * @exception IllegalStateException if this method is called on an long getCreationTime() | } * invalidated session Object getAttribute(String) | /** * Enumeration getAttributeNames() | public void setMaxInactiveInterval(int interval) { * Return the Manager within which this Session is valid. * @deprecated As of Version 2.2, this method is replaced by String[] getValueNames() | if (! valid) { */ * <code>getAttributeNames()</code> void invalidate() | String msg = sm.getString("applicationSession.session.ise"); public Manager getManager() { */ boolean isNew() | public String[] getValueNames() { void removeAttribute(String) | throw new IllegalStateException(msg); return (this.manager); void setAttribute(String, Object)); } Vector results = new Vector(); } Enumeration attrs = getAttributeNames(); static advice(StandardSession s): invalidate(s) { inactiveInterval = interval; while (attrs.hasMoreElements()) { before { } String attr = (String) attrs.nextElement(); if (!s.isValid()) /** results.addElement(attr); throw new IllegalStateException public int getMaxInactiveInterval() { * Set the Manager within which this Session is valid. } (s.sm.getString("standardSession." if (! valid) { * String names[] = new String[results.size()]; + thisJoinPoint.methodName String msg = sm.getString("applicationSession.session.ise"); * @param manager The new Manager for (int i = 0; i < names.length; i++) + ".ise")); */ names[i] = (String) results.elementAt(i); } throw new IllegalStateException(msg); public void setManager(Manager manager) { return (names); } } this.manager = manager; } of CCCs. return inactiveInterval; } } } /** } * Invalidates this session and unbinds any objects bound to it. /** * //----------------------------------------------------------------------- * Return the maximum time interval, in seconds, between client requests * @exception IllegalStateException if this method is called on // -------------------------------------------------------------- Private Class * before the servlet container will invalidate the session. A negative * an invalidated session * time indicates that the session should never time out. */ * public void invalidate() { /** * @exception IllegalStateException if this method is called on * This class is a dummy implementation of the <code>HttpSessionContext</code> * an invalidated session // Cause this session to expire * interface, to conform to the requirement that such an object be returned */ expire(); * when <code>HttpSession.getSessionContext()</code> is called. public int getMaxInactiveInterval() { * } * @author Craig R. McClanahan return (this.maxInactiveInterval); * * @deprecated As of Java Servlet API 2.1 with no replacement. The /** * interface will be removed in a future version of this API. * Return <code>true</code> if the client does not yet know about the */ * session, or if the client chooses not to join the session. For * example, if the server used only cookie-based sessions, and the client final class StandardSessionContext implements HttpSessionContext { * has disabled the use of cookies, then a session would be new on each * request. * private Vector dummy = new Vector(); * @exception IllegalStateException if this method is called on an * invalidated session /** */ * Return the session identifiers of all sessions defined public boolean isNew() { * within this context. * return (this.isNew); * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return an empty <code>Enumeration</code> } * and will be removed in a future version of the API. */ public Enumeration getIds() { return (dummy.elements()); } /** * Return the <code>HttpSession</code> associated with the * specified session identifier. * * @param id Session identifier for which to look up a session * * @deprecated As of Java Servlet API 2.1 with no replacement. * This method must return null and will be removed in a * future version of the API. */ public HttpSession getSession(String id) { return (null); } } • Pointcuts select (join) Aspects points in the program allow code to be where a CCC applies. localized into a package org.apache.tomcat.session; ynchronized void invalidate() { Enumeration enum = appSessions.keys(); import org.apache.tomcat.core.*; import org.apache.tomcat.util.StringManager; while (enum.hasMoreElements()) { import java.io.*; Object key = enum.nextElement(); import java.net.*; ApplicationSession appSession = import java.util.*; (ApplicationSession)appSessions.get(key); import javax.servlet.*; import javax.servlet.http.*; appSession.invalidate(); } /** } * Core implementation of a server session * public void putValue(String name, Object value) { * @author James Duncan Davidson [duncan@eng.sun.com] if (name == null) { * @author James Todd [gonzo@eng.sun.com] String msg = sm.getString("serverSession.value.iae"); */ throw new IllegalArgumentException(msg); public class ServerSession { } private StringManager sm = removeValue(name); // remove any existing binding StringManager.getManager("org.apache.tomcat.session"); values.put(name, value); private Hashtable values = new Hashtable(); } private Hashtable appSessions = new Hashtable(); private String id; public Object getValue(String name) { private long creationTime = System.currentTimeMillis();; if (name == null) { private long thisAccessTime = creationTime; String msg = sm.getString("serverSession.value.iae"); private long lastAccessed = creationTime; private int inactiveInterval = -1; throw new IllegalArgumentException(msg); } ServerSession(String id) { this.id = id; return values.get(name); } } public String getId() { public Enumeration getValueNames() { return id; return values.keys(); } } public long getCreationTime() { public void removeValue(String name) { single module return creationTime; values.remove(name); } } public long getLastAccessedTime() { public void setMaxInactiveInterval(int interval) { return lastAccessed; inactiveInterval = interval; } } public ApplicationSession getApplicationSession(Context context, public int getMaxInactiveInterval() { boolean create) { return inactiveInterval; ApplicationSession appSession = } (ApplicationSession)appSessions.get(context); // XXX if (appSession == null && create) { // sync'd for safty -- no other thread should be getting something // from this while we are reaping. This isn't the most optimal • // XXX // solution for this, but we'll determine something else later. // sync to ensure valid? synchronized void reap() { appSession = new ApplicationSession(id, this, context); Enumeration enum = appSessions.keys(); appSessions.put(context, appSession); } while (enum.hasMoreElements()) { Object key = enum.nextElement(); // XXX ApplicationSession appSession = // make sure that we haven't gone over the end of our (ApplicationSession)appSessions.get(key); // inactive interval -- if so, invalidate and create // a new appSession appSession.validate(); } Code (advice) is implicitly return appSession; } } } void removeApplicationSession(Context context) { appSessions.remove(context); } /** * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. */ void validate() executed at those points. private long lastAccessed = creationTime; if (inactiveInterval != -1) { private int inactiveInterval = -1; int thisInterval = (int)(System.currentTimeMillis() - lastAccessed) / 1000; void accessed() { // set last accessed to thisAccessTime as it will be left over if (thisInterval > inactiveInterval) { // from the previous access invalidate(); lastAccessed = thisAccessTime; thisAccessTime = System.currentTimeMillis(); ServerSessionManager ssm = ServerSessionManager.getManager(); validate(); } ssm.removeSession(this); } void validate() { } // if we have an inactive interval, check to see if we've exceeded it } if (inactiveInterval != -1) { int thisInterval = private long lastAccessedTime = creationTime; (int)(System.currentTimeMillis() - lastAccessed) / 1000; if (thisInterval > inactiveInterval) { invalidate(); /** } * 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() { */ if (valid) { public long getLastAccessedTime() { return lastAccessed; } else { return (this.lastAccessedTime); String msg = sm.getString("applicationSession.session.ise"); } throw new IllegalStateException(msg); } } this.lastAccessedTime = time; public long getLastAccessedTime() { return lastAccessed; } private long lastAccessed = creationTime; void accessed() { // set last accessed to thisAccessTime as it will be left over // from the previous access lastAccessed = thisAccessTime; thisAccessTime = System.currentTimeMillis(); } 11
  • 43. Message Encryption Example messageSent(): execution(* send*(..)) 12
  • 44. Message Encryption Example messageSent(): execution(* send*(..)) The execution of all methods whose name begins with “send” must have their messages encrypted. 12
  • 46. Fragile Pointcut Problem • A pointcut is robust iff it continues to select points where the CCC applies in subsequent base-code versions without textual modification. 13
  • 47. Fragile Pointcut Problem • A pointcut is robust iff it continues to select points where the CCC applies in subsequent base-code versions without textual modification. • Otherwise, a pointcut is fragile. 13
  • 48. Fragile Pointcut Problem • A pointcut is robust iff it continues to select points where the CCC applies in subsequent base-code versions without textual modification. • Otherwise, a pointcut is fragile. • Fragile pointcuts can cause software to silently malfunction! 13
  • 50. Pointcut fragility Example • Suppose a subsequent version, a new method is added that sends messages but whose name begins with “transmit?” 14
  • 51. Pointcut fragility Example • Suppose a subsequent version, a new method is added that sends messages but whose name begins with “transmit?” • Our pointcut breaks as a result. 14
  • 52. Pointcut fragility Example • Suppose a subsequent version, a new method is added that sends messages but whose name begins with “transmit?” • Our pointcut breaks as a result. • Thus, messageSent() is a fragile pointcut. 14
  • 53. My Approach to the Fragile Pointcut Problem 15
  • 54. My Approach to the Fragile Pointcut Problem • Developed an approach that mechanically aids developers in suitably updating pointcuts upon changes to the base-code. 15
  • 55. My Approach to the Fragile Pointcut Problem • Developed an approach that mechanically aids developers in suitably updating pointcuts upon changes to the base-code. • The approach analyzes arbitrarily deep structural commonalities between program elements associated with pointcuts in a particular software version. 15
  • 56. My Approach to the Fragile Pointcut Problem • Developed an approach that mechanically aids developers in suitably updating pointcuts upon changes to the base-code. • The approach analyzes 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. 15
  • 58. Contributions • Commonality identification: • Developed an open source Eclipse IDE plug-in called REJUVENATE POINTCUT that finds new join points exhibiting structural properties similar to those already selected by a pointcut. 16
  • 59. Contributions • Commonality identification: • Developed an open source Eclipse IDE plug-in called REJUVENATE POINTCUT that finds new join points exhibiting structural properties similar to those already selected by a pointcut. • Correlation analysis: • Empirically establish that join points selected by a single pointcut typically portray a significant amount of unique structural commonality on multiple fronts. 16
  • 60. Contributions • Commonality identification: • Developed an open source Eclipse IDE plug-in called REJUVENATE POINTCUT that finds new join points exhibiting structural properties similar to those already selected by a pointcut. • Correlation analysis: • Empirically establish that join points selected by a single pointcut typically portray a significant amount of unique structural commonality on multiple fronts. • Expression recovery: • Evaluated usefulness by rejuvenating pointcuts in multiple versions of three open source AO projects. 16
  • 61. Abstract Example Base Code package p; class A { int f; void m1() { int a = f + 1; } void m2() { int b = f + 2; } void n() { f = 3; } } 17
  • 62. Abstract Example Base Code package p; class A { int f; void m1() { int a = f + 1; } void m2() { int b = f + 2; } void n() { f = 3; } } 17
  • 63. Abstract Example Base Code package p; class A { • Two methods whose int f; name begins with the character m. void m1 m1() { int a = f + 1; } void m2 m2() { int b = f + 2; } void n() { f = 3; } } 17
  • 64. Abstract Example Base Code package p; class A { • Two methods whose int f; name begins with the character m. void m1() { int a = f + 1; • One method whose name } does not begin with the character m. void m2() { int b = f + 2; } void n n() { f = 3; } } 17
  • 65. Abstract Example Base Code package p; class A { • Two methods whose int f; f name begins with the character m. void m1() { int a = f + 1; • One method whose name } does not begin with the character m. void m2() { int b = f + 2; • Method bodies of m1 and } m2 read from a field f. void n() { f = 3; } } 17
  • 66. Abstract Example Base Code package p; class A { • Two methods whose int f; f name begins with the character m. void m1() { int a = f + 1; • One method whose name } does not begin with the character m. void m2() { int b = f + 2; • Method bodies of m1 and } m2 read from a field f. void n() { f = 3; • Method body of n writes } to field f. } 17
  • 67. Pointcut Example pointcut mayBeFragile() : execution(* m*(..)); 18
  • 68. Pointcut Example pointcut mayBeFragile() : execution(* m*(..)); • Selects m1() and m2() but not n(). 18
  • 69. Pointcut Example pointcut mayBeFragile() : execution(* m*(..)); • Selects m1() and m2() but not n(). • Assume that correct join points are selected. 18
  • 70. Pointcut Example pointcut mayBeFragile() : execution(* m*(..)); • Selects m1() and m2() but not n(). • Assume that correct join points are selected. CCC applies to m1 and m2 but not p. 18
  • 71. 19
  • 72. void p() { int d = f + 4; A new method } is added to the base code 19
  • 73. void p() { int d = f + 4; } pointcut mayBeFragile() : execution(* m*(..)); W ha ta po bo int ut cu th t? e 19
  • 74. void p() { int d = f + 4; } pointcut mayBeFragile() : execution(* m*(..)); • Same pointcut selects m1() and m2() but not n() and p(). 19
  • 75. void p() { int d = f + 4; } pointcut mayBeFragile() : execution(* m*(..)); • Same pointcut selects m1() and m2() but not n() and p(). • Assume CCC applies to p(). 19
  • 76. void p() { int d = f + 4; } pointcut mayBeFragile() : execution(* m*(..)); • Same pointcut selects m1() and m2() but not n() and p(). • Assume CCC applies to p(). • mayBeFragile() is fragile! 19
  • 77. void p() { int d = f + 4; } pointcut mayBeFragile() : execution(* m*(..)); • Same pointcut selects m1() and m2() but not n() and p(). • Assume CCC applies to p(). • mayBeFragile() is fragile! • p() silently fall out of pointcut’s scope. 19
  • 78. void p() { int d = f + 4; } pointcut mayBeFragile() : execution(* m*(..)); • Same pointcut selects m1() and m2() but not n() and p(). • Assume CCC applies to p(). • mayBeFragile() is fragile! • p() silently fall out of pointcut’s scope. • May be difficult to identify in large base codes. 19
  • 79. Phase I: Leverage Structural Commonality 20
  • 80. Phase I: Leverage Structural Commonality • Build a Concern Graph [Robillard, Murphy ’02]. m1 gets declares f gets m2 declares A sets declares n 20
  • 81. Phase I: Leverage Structural Commonality • Build a Concern Graph [Robillard, Murphy ’02]. • Extract commonalities between currently selected join points. m1 gets declares f gets m2 declares A sets declares n 20
  • 82. Phase I: Leverage Structural Commonality • Build a Concern Graph [Robillard, Murphy ’02]. • Extract commonalities between currently selected join points. • Find common sinks and sources in the graph. m1 gets (A,declares,?) declares f (?,gets, f) gets m2 declares A sets declares n 20
  • 83. Evaluating Patterns [Dagenais, Breu, Warr, Robillard ’07] (?,gets, f) (A,declares,?) m1 gets declares f gets m2 declares A sets declares n 21
  • 84. Evaluating Patterns [Dagenais, Breu, Warr, Robillard ’07] (?,gets, f) (A,declares,?) {m1,m2} m1 gets declares f gets m2 declares A sets declares n 21
  • 85. Evaluating Patterns [Dagenais, Breu, Warr, Robillard ’07] (?,gets, f) (A,declares,?) 100% confidence! {m1,m2} m1 gets declares f gets m2 declares A sets declares n 21
  • 86. Evaluating Patterns [Dagenais, Breu, Warr, Robillard ’07] (?,gets, f) (A,declares,?) 100% confidence! {m1,m2} {m1,m2,n} m1 gets declares f gets m2 declares A sets declares n 21
  • 87. Evaluating Patterns [Dagenais, Breu, Warr, Robillard ’07] (?,gets, f) (A,declares,?) 100% 66% confidence! confidence {m1,m2} {m1,m2,n} m1 gets declares f gets m2 declares A sets declares n 21
  • 88. Storing patterns for Phase II (?,gets, f) (A,declares,?) 100% 66% confidence! confidence XML 22
  • 89. Storing patterns for Phase II XML 22
  • 90. It’s a little more complicated ... 23
  • 91. It’s a little more complicated ... • Pattern evaluation is done on several other different levels. 23
  • 92. It’s a little more complicated ... • Pattern evaluation is done on several other different levels. • Previously illustrated the α evaluation: 23
  • 93. It’s a little more complicated ... • Pattern evaluation is done on several other different levels. • Previously illustrated the α evaluation: • Considers the strength of the structural relationships between elements produced by the pattern and those selected by the pointcut. 23
  • 94. It’s a little more complicated ... • Pattern evaluation is done on several other different levels. • Previously illustrated the α evaluation: • Considers the strength of the structural relationships between elements produced by the pattern and those selected by the pointcut. • Another dimension is the β evaluation: 23
  • 95. It’s a little more complicated ... • Pattern evaluation is done on several other different levels. • Previously illustrated the α evaluation: • Considers the strength of the structural relationships between elements produced by the pattern and those selected by the pointcut. • Another dimension is the β evaluation: • Considers the completeness of the structural relationship expressed by the pattern compared to relationships expressed by the pointcut. 23
  • 96. It’s a little more complicated ... • Pattern evaluation is done on several other different levels. • Previously illustrated the α evaluation: • Considers the strength of the structural relationships between elements produced by the pattern and those selected by the pointcut. • Another dimension is the β evaluation: • Considers the completeness of the structural relationship expressed by the pattern compared to relationships expressed by the pointcut. • Lastly, there is an abstractness evaluation: 23
  • 97. It’s a little more complicated ... • Pattern evaluation is done on several other different levels. • Previously illustrated the α evaluation: • Considers the strength of the structural relationships between elements produced by the pattern and those selected by the pointcut. • Another dimension is the β evaluation: • Considers the completeness of the structural relationship expressed by the pattern compared to relationships expressed by the pointcut. • Lastly, there is an abstractness evaluation: • Considers the ratio of wild-cards (?) to concrete elements in the pattern as patterns can be arbitrarily deep. 23
  • 98. It’s a little more complicated ... • Pattern evaluation is done on several other different levels. • Previously illustrated the α evaluation: • Considers the strength of the structural relationships between elements produced by the pattern and those selected by the pointcut. • Another dimension is the β evaluation: • Considers the completeness of the structural relationship expressed by the pattern compared to relationships expressed by the pointcut. • Lastly, there is an abstractness evaluation: • Considers the ratio of wild-cards (?) to concrete elements in the pattern as patterns can be arbitrarily deep. • All three dimensions are combined to produce a patterns confidence value. 23
  • 99. SACTIONS OF SOFTWARE ENGINEERING, VOL. X, NO. Y, Z 20AB  0 if |Match(ˆ , Paths(CG + ))| = 0 π err α (ˆ , PCE) π = |PCE ∩ Match(ˆ , Paths(CG + ))| π 1 − + otherwise |Match(ˆ , Paths(CG ))| π  1 if |PCE| = 0 err β (ˆ , PCE) π = |PCE ∩ Match(ˆ , Paths(CG + ))| π 1 − otherwise |PCE|  1 if |ˆ | = 0 π abs(ˆ ) π = |ˆ | − |W(ˆ )| π π 1 − otherwise |ˆ | π conf (ˆ , PCE) π = 1 − [err α (ˆ , PCE)(1 − abs(ˆ )) + err β (ˆ , PCE)abs(ˆ )] π π π π Pattern attribute equations. allSpeed). Thus, the err α rate for this pattern projection of wild card elements contained e PCE found on line 3 of Figure 2, which selects π . Likewise, |W(ˆ )| represents the number o ˆ π ution of methods DieselEngine.increase(Fuel) and elements contained within pattern π . Then, t ˆ 24
  • 100. 25 25
  • 103. All join points Pointcut Pattern 25 25
  • 104. All join points Pointcut Pattern α 25 25
  • 105. All join points Pointcut β Pattern α 25 25
  • 106. All join points Pointcut β Pattern α A ? ? ? ? 25 25
  • 107. All join points Pointcut β Pattern α A ? ? ? ? abs 25 25
  • 108. Phase II: Expression Recovery 26
  • 109. Phase II: Expression Recovery void p() { int d = f + 4; A new method } is added to the base code 26
  • 110. Phase II: Expression Recovery void p() { int d = f + 4; A new method } is added to the base code m1 gets declares f gets m2 declares A sets declares gets n declares p 26
  • 111. Phase II: Expression Recovery void p() { int d = f + 4; A new method } is added to the base code m1 (?,gets, f) gets (A,declares,?) declares f gets m2 declares A sets declares gets n declares XML p 26
  • 112. 27 27
  • 113. (?,gets, f) 27 27
  • 115. (?,gets, f) 100% confidence! {m1,m2,p} 27 27
  • 116. (?,gets, f) execution(* m*(..)) 100% confidence! {m1,m2,p} 27 27
  • 117. (?,gets, f) execution(* m*(..)) 100% confidence! {m1,m2,p} {m1,m2} 27 27
  • 118. (?,gets, f) execution(* m*(..)) 100% confidence! {m1,m2,p} {m1,m2} = {p} 27 27
  • 119. (?,gets, f) execution(* m*(..)) 100% confidence! {m1,m2,p} {m1,m2} = {p} (A,declares,?) 27 27
  • 120. (?,gets, f) execution(* m*(..)) 100% confidence! {m1,m2,p} {m1,m2} = {p} (A,declares,?) {m1,m2,n,p} 27 27
  • 121. (?,gets, f) execution(* m*(..)) 100% confidence! {m1,m2,p} {m1,m2} = {p} (A,declares,?) 66% confidence {m1,m2,n,p} 27 27
  • 122. (?,gets, f) execution(* m*(..)) 100% confidence! {m1,m2,p} {m1,m2} = {p} (A,declares,?) execution(* m*(..)) 66% confidence {m1,m2,n,p} 27 27
  • 123. (?,gets, f) execution(* m*(..)) 100% confidence! {m1,m2,p} {m1,m2} = {p} (A,declares,?) execution(* m*(..)) 66% confidence {m1,m2,n,p} {m1,m2} 27 27
  • 124. (?,gets, f) execution(* m*(..)) 100% confidence! {m1,m2,p} {m1,m2} = {p} (A,declares,?) execution(* m*(..)) 66% confidence {m1,m2,n,p} {m1,m2} = {n,p} 27 27
  • 125. (?,gets, f) execution(* m*(..)) 100% confidence! {m1,m2,p} {m1,m2} = {p} (A,declares,?) execution(* m*(..)) 66% confidence {m1,m2,n,p} {m1,m2} = {n,p} p is suggested with (100 + 66) / 2 ≈ 83% confidence 27 27
  • 126. (?,gets, f) execution(* m*(..)) 100% confidence! {m1,m2,p} {m1,m2} = {p} (A,declares,?) execution(* m*(..)) 66% confidence {m1,m2,n,p} {m1,m2} = {n,p} p is suggested with (100 + 66) / 2 ≈ 83% confidence n is suggested with 66% confidence 27 27
  • 127. (?,gets, f) execution(* m*(..)) 100% confidence! {m1,m2,p} {m1,m2} = {p} (A,declares,?) execution(* m*(..)) 66% confidence {m1,m2,n,p} {m1,m2} = {n,p} p is suggested with (100 + 66) / 2 ≈ 83% confidence n is suggested with 66% confidence execution(* m*(..)) || execution (* p()) 27 27
  • 128. (?,gets, f) execution(* m*(..)) 100% confidence! {m1,m2,p} {m1,m2} = {p} (A,declares,?) execution(* m*(..)) 66% confidence {m1,m2,n,p} {m1,m2} = {n,p} p is suggested with (100 + 66) / 2 ≈ 83% Suggestions confidence n is suggested with 66% confidence sorted by confidence in IDE execution(* m*(..)) || execution (* p()) 27 27
  • 129. mplementation Implementation 28
  • 130. Evaluation: Phase I subject KL. cls. PC shd. KP. α β t (s) AJHotDraw 21.8 298 32 90 3.36 0.32 0.06 101 Ants 1.57 33 22 297 1.25 0.15 0.23 43 Bean 0.12 2 2 4 0.02 0.24 0.23 4 Contract4J 10.7 199 15 350 1.80 0.26 0.44 115 DCM 1.68 29 8 343 2.47 0.15 0.45 4 Figure 0.10 5 1 6 0.02 0.11 0.45 8 Glassbox 26.0 430 55 208 2.62 0.1 0.29 228 HealthWatcher 5.72 76 27 122 1.00 0.21 0.16 22 Cactus 7.57 93 4 222 2.15 0.21 0.52 8 LoD 1.59 29 5 164 0.54 0.15 0.41 46 MobilePhoto 3.80 52 25 25 0.78 0.23 0.00 11 MySQLa 44.0 187 2 3016 17.6 0.12 0.58 379 NullCheck 1.47 27 1 112 0.10 0.17 0.55 293 N-Version 0.55 15 4 9 0.08 0.19 0.24 1 Quicksort 0.07 3 4 7 0.06 0.19 0.15 3 RacerAJ 0.58 13 4 9 0.02 0.23 0.09 5 RecoveryCache 0.22 3 4 14 0.07 0.11 0.21 6 Spacewar 1.42 21 9 58 0.23 0.15 0.22 37 StarJ-Pool 38.2 511 1 3 0.07 0.25 0.00 75 Telecom 0.28 10 4 5 0.03 0.21 0.02 7 Tetris 1.04 8 18 27 0.50 0.16 0.01 14 TollSystem 5.20 88 35 85 1.68 0.26 0.06 20 Tracing 0.37 5 16 132 0.68 0.17 0.4 1 Totals: 174 2137 298 5308 37.1 0.18 0.16 1431 29
  • 131. Evaluation: Phase I subject KL. cls. PC shd. KP. α β t (s) AJHotDraw 21.8 298 32 90 3.36 0.32 0.06 101 Ants 1.57 33 22 297 1.25 0.15 0.23 43 Bean 0.12 2 2 4 0.02 0.24 0.23 4 Contract4J 10.7 199 15 350 1.80 0.26 0.44 115 DCM 1.68 29 8 343 2.47 0.15 0.45 4 Figure 0.10 5 1 6 0.02 0.11 0.45 8 Glassbox 26.0 430 55 208 2.62 0.1 0.29 228 HealthWatcher 5.72 76 27 122 1.00 0.21 0.16 22 Cactus 7.57 93 4 222 2.15 0.21 0.52 8 LoD 1.59 29 5 164 0.54 0.15 0.41 46 MobilePhoto 3.80 52 25 25 0.78 0.23 0.00 11 MySQLa 44.0 187 2 3016 17.6 0.12 0.58 379 NullCheck 1.47 27 1 112 0.10 0.17 0.55 293 N-Version 0.55 15 4 9 0.08 0.19 0.24 1 Quicksort 0.07 3 4 7 0.06 0.19 0.15 3 RacerAJ 0.58 13 4 9 0.02 0.23 0.09 5 RecoveryCache 0.22 3 4 14 0.07 0.11 0.21 6 Spacewar 1.42 21 9 58 0.23 0.15 0.22 37 StarJ-Pool 38.2 511 1 3 0.07 0.25 0.00 75 Telecom 0.28 10 4 5 0.03 0.21 0.02 7 Tetris 1.04 8 18 27 0.50 0.16 0.01 14 TollSystem 5.20 88 35 85 1.68 0.26 0.06 20 Tracing 0.37 5 16 132 0.68 0.17 0.4 1 Totals: 174 2137 298 5308 37.1 0.18 0.16 1431 29
  • 132. Evaluation: Phase I subject KL. cls. PC shd. KP. α β t (s) AJHotDraw 21.8 298 32 90 3.36 0.32 0.06 101 Ants 1.57 33 22 297 1.25 0.15 0.23 43 Bean 0.12 2 2 4 0.02 0.24 0.23 4 Contract4J 10.7 199 15 350 1.80 0.26 0.44 115 DCM 1.68 29 8 343 2.47 0.15 0.45 4 Figure 0.10 5 1 6 0.02 0.11 0.45 8 Glassbox 26.0 430 55 208 2.62 0.1 0.29 228 HealthWatcher 5.72 76 27 122 1.00 0.21 0.16 22 Cactus 7.57 93 4 222 2.15 0.21 0.52 8 LoD 1.59 29 5 164 0.54 0.15 0.41 46 MobilePhoto 3.80 52 25 25 0.78 0.23 0.00 11 MySQLa 44.0 187 2 3016 17.6 0.12 0.58 379 NullCheck 1.47 27 1 112 0.10 0.17 0.55 293 N-Version 0.55 15 4 9 0.08 0.19 0.24 1 Quicksort 0.07 3 4 7 0.06 0.19 0.15 3 RacerAJ 0.58 13 4 9 0.02 0.23 0.09 5 4.8 secs per RecoveryCache Spacewar 0.22 1.42 3 21 4 9 14 0.07 0.11 0.21 58 0.23 0.15 0.22 6 37 pointcut StarJ-Pool Telecom 38.2 511 0.28 10 1 4 3 0.07 0.25 0.00 5 0.03 0.21 0.02 75 7 Tetris 1.04 8 18 27 0.50 0.16 0.01 14 TollSystem 5.20 88 35 85 1.68 0.26 0.06 20 Tracing 0.37 5 16 132 0.68 0.17 0.4 1 Totals: 174 2137 298 5308 37.1 0.18 0.16 1431 29
  • 134. Evaluation: Phase 2 • Applied to 3 multi-versioned AspectJ projects. 30
  • 135. Evaluation: Phase 2 • Applied to 3 multi-versioned AspectJ projects. • Rejuvenated pointcuts (49 in total) over major releases (20 in total). 30
  • 136. Evaluation: Phase 2 • Applied to 3 multi-versioned AspectJ projects. • Rejuvenated pointcuts (49 in total) over major releases (20 in total). • Maximum pattern length set to 2 edges. 30
  • 137. Evaluation: Phase 2 • Applied to 3 multi-versioned AspectJ projects. • Rejuvenated pointcuts (49 in total) over major releases (20 in total). • Maximum pattern length set to 2 edges. • Able to identify 93% of new shadows introduced in later versions that were not selected by previous pointcut representations. 30
  • 138. Evaluation: Phase 2 • Applied to 3 multi-versioned AspectJ projects. • Rejuvenated pointcuts (49 in total) over major releases (20 in total). • Maximum pattern length set to 2 edges. • Able to identify 93% of new shadows introduced in later versions that were not selected by previous pointcut representations. • On average, 3.97 suggestions appeared before true positives. 30
  • 139. Evaluation: Phase 2 • Applied to 3 multi-versioned AspectJ projects. • Rejuvenated pointcuts (49 in total) over major releases (20 in total). • Maximum pattern length set to 2 edges. • Able to identify 93% of new shadows introduced in later versions that were not selected by previous pointcut representations. • On average, 3.97 suggestions appeared before true positives. • On average, 10.95 secs. required to rejuvenate a pointcut. 30
  • 141. Related Work • Wloka et al. [AOSD 08] automatically modify PCEs upon automated base code refactoring. 31
  • 142. Related Work • Wloka et al. [AOSD 08] automatically modify PCEs upon automated base code refactoring. • Base code changes must only be administered by automated refactoring. 31
  • 143. Related Work • Wloka et al. [AOSD 08] automatically modify PCEs upon automated base code refactoring. • Base code changes must only be administered by automated refactoring. RP works with arbitrary changes 31
  • 144. Related Work • Wloka et al. [AOSD 08] automatically modify PCEs upon automated base code refactoring. • Base code changes must only be administered by automated refactoring. • Adding new base code also breaks pointcuts. 31
  • 145. Related Work • Wloka et al. [AOSD 08] automatically modify PCEs upon automated base code refactoring. • Base code changes must only be administered by automated refactoring. • Adding new base code also breaks pointcuts. • AspectJ Development Tools (AJDT) and Ye and Volder [AOSD 08] display join points that are currently and almost selected by a pointcut. 31
  • 146. Related Work • Wloka et al. [AOSD 08] automatically modify PCEs upon automated base code refactoring. • Base code changes must only be administered by automated refactoring. • Adding new base code also breaks pointcuts. • AspectJ Development Tools (AJDT) and Ye and Volder [AOSD 08] display join points that are currently and almost selected by a pointcut. • Do not analyze the differences exhibited by join points between base code versions. 31
  • 147. Related Work • Wloka et al. [AOSD 08] automatically modify PCEs upon automated base code refactoring. • Base code changes must only be administered by automated refactoring. • Adding new base code also breaks pointcuts. • AspectJ Development Tools (AJDT) and Ye and Volder [AOSD 08] display join points that are currently and almost selected by a pointcut. • Do not analyze the differences exhibited by join points between base code versions. • Pointcut Doctor uses heuristics general to all AO systems. 31
  • 148. Related Work • Wloka et al. [AOSD 08] automatically modify PCEs upon automated base code refactoring. • Base code changes must only be administered by automated refactoring. • Adding new base code also breaks pointcuts. • AspectJ Development Tools (AJDT) and Ye and Volder [AOSD 08] display join points thatuses RP are currently and almost selected by a pointcut. heuristics customized to a •Do not analyze the differences exhibited by join particular system points between base code versions. • Pointcut Doctor uses heuristics general to all AO systems. 31
  • 149. Conclusion 32
  • 150. Conclusion • Aspect-Oriented Programming localize implementations of CCCs that would otherwise be scattered throughout the system and tangled with unrelated code. 32
  • 151. Conclusion • Aspect-Oriented Programming localize implementations of CCCs that would otherwise be scattered throughout the system and tangled with unrelated code. • Evolving Aspect-Oriented programs requires some special consideration, especially regarding pointcut fragility. 32
  • 152. Conclusion • Aspect-Oriented Programming localize implementations of CCCs that would otherwise be scattered throughout the system and tangled with unrelated code. • Evolving Aspect-Oriented programs requires some special consideration, especially regarding pointcut fragility. • Rejuvenating pointcuts can be non-trivial in large systems. 32
  • 153. Conclusion • Aspect-Oriented Programming localize implementations of CCCs that would otherwise be scattered throughout the system and tangled with unrelated code. • Evolving Aspect-Oriented programs requires some special consideration, especially regarding pointcut fragility. • Rejuvenating pointcuts can be non-trivial in large systems. • Mechanical assistance that leverages structural commonality can ease the evolution process. 32
  • 155. Java 5 Enums • Java 5 introduced a rich set of new features such as generics, metadata annotations, boxing/unboxing, and type-safe enumerations.
  • 156. Java 5 Enums • Java 5 introduced a rich set of new features such as generics, metadata annotations, boxing/unboxing, and type-safe enumerations. • Using enums increases:
  • 157. Java 5 Enums • Java 5 introduced a rich set of new features such as generics, metadata annotations, boxing/unboxing, and type-safe enumerations. • Using enums increases: • Type-safety.
  • 158. Java 5 Enums • Java 5 introduced a rich set of new features such as generics, metadata annotations, boxing/unboxing, and type-safe enumerations. • Using enums increases: • Type-safety. • Code comprehension.
  • 159. Java 5 Enums • Java 5 introduced a rich set of new features such as generics, metadata annotations, boxing/unboxing, and type-safe enumerations. • Using enums increases: • Type-safety. • Code comprehension. • Code simplicity.
  • 160. Java 5 Enums • Java 5 introduced a rich set of new features such as generics, metadata annotations, boxing/unboxing, and type-safe enumerations. • Using enums increases: • Type-safety. • Code comprehension. • Code simplicity. • Resiliency related to separate compilation.
  • 161. Java 5 Enums • Java 5 introduced a rich set of new features such as generics, metadata annotations, boxing/unboxing, and type-safe enumerations. • Using enums increases: • Type-safety. • Code comprehension. • Code simplicity. • Resiliency related to separate compilation. • Enums replaced a variety of coding patterns used to compensate for their absence in legacy software.
  • 162. Java 5 Enums • Java 5 introduced a rich set of new features such as generics, metadata annotations, boxing/unboxing, and type-safe enumerations. • Using enums increases: • Type-safety. • Code comprehension. • Code simplicity. • Resiliency related to separate compilation. • Enums replaced a variety of coding patterns used to compensate for their absence in legacy software. • Leaves a large body of code to be manually upgraded.
  • 163. Motivating Example class TrafficSignal { public static final int RED = 0; public static final int YELLOW = 1; public static final int GREEN = 2; /∗ Current color of the traffic signal, initially red by default ∗/ private int color = RED; /∗ Accessor for the light’s current color ∗/ public int getColor() {return this.color;}} class Automobile { private static final int IDLE = 0; private static final int INCREASE_SPEED = 1; private static final int DECREASE_SPEED = 2; private static final int STOP = 3; 34
  • 164. Motivating Example Weak Enum Pattern class TrafficSignal { public static final int RED = 0; public static final int YELLOW = 1; public static final int GREEN = 2; /∗ Current color of the traffic signal, initially red by default ∗/ private int color = RED; /∗ Accessor for the light’s current color ∗/ public int getColor() {return this.color;}} class Automobile { private static final int IDLE = 0; private static final int INCREASE_SPEED = 1; private static final int DECREASE_SPEED = 2; private static final int STOP = 3; 34
  • 165. Motivating Example class TrafficSignal { public static final int RED = 0; public static final int YELLOW = 1; public static final int GREEN = 2; /∗ Current color of the traffic signal, initially red by default ∗/ private int color = RED; /∗ Accessor for the light’s current color ∗/ public int getColor() {return this.color;}} class Automobile { Type Safety private static final int IDLE = 0; private static final int INCREASE_SPEED = 1; private static final int DECREASE_SPEED = 2; private static final int STOP = 3; 34
  • 166. Motivating Example class TrafficSignal { public static final int RED = 0; public static final int YELLOW = 1; public static final int GREEN = 2; /∗ Current color of the traffic signal, initially red by default ∗/ Manual private int color = RED; Enumeration /∗ Accessor for the light’s current color ∗/ public int getColor() {return this.color;}} class Automobile { private static final int IDLE = 0; private static final int INCREASE_SPEED = 1; private static final int DECREASE_SPEED = 2; private static final int STOP = 3; 34
  • 167. Motivating Example class TrafficSignal { public static final int RED = 0; public static final int YELLOW = 1; public static final int GREEN = 2; /∗ Current color of the traffic signal, initially red by default ∗/ private int color = RED; /∗ Accessor for the light’s current color ∗/ Namespacing public int getColor() {return this.color;}} class Automobile { private static final int IDLE = 0; private static final int INCREASE_SPEED = 1; private static final int DECREASE_SPEED = 2; private static final int STOP = 3; 34
  • 168. Motivating Example class TrafficSignal { public static final int RED = 0; public static final int YELLOW = 1; public static final int GREEN = 2; /∗ Current color of the traffic signal, initially red by default ∗/ private int color = RED; Brittle /∗ Accessor for the light’s current color ∗/ public int getColor() {return this.color;}} class Automobile { private static final int IDLE = 0; private static final int INCREASE_SPEED = 1; private static final int DECREASE_SPEED = 2; private static final int STOP = 3; 34
  • 169. Motivating Example class TrafficSignal { public static final int RED = 0; public static final int YELLOW = 1; public static final int GREEN = 2; /∗ Current color of the traffic signal, initially red by default ∗/ private int color = RED; /∗ Accessor for the light’s current color ∗/ public int getColor() {return this.color;}} class Automobile { private static final int IDLE = 0; private static final int INCREASE_SPEED = 1; private static final int DECREASE_SPEED = 2; private static final int STOP = 3; 34
  • 170. Motivating Example Revisited class TrafficSignal { public static final int RED = 0; public static final int YELLOW = 1; public static final int GREEN = 2; /∗ Current color of the traffic signal, initially red by default ∗/ private int color = RED; /∗ Accessor for the light’s current color ∗/ public int getColor() {return this.color;}} class Automobile { private static final int IDLE = 0; private static final int INCREASE_SPEED = 1; private static final int DECREASE_SPEED = 2; private static final int STOP = 3; 35
  • 171. Motivating Example Revisited class TrafficSignal {{ TrafficSignal public enum Color {RED, RED = 0; public static final int YELLOW, public static final int YELLOW = 1; GREEN}; public static final int GREEN = 2; /∗ Current color of the traffic signal, initially red byby default ∗/ /* Current color of the traffic signal, initially red default */ private Color color= =RED; private int color Color.RED; /∗ Accessor for the light’s current color */∗/ /* Accessor for the light’s current color public Color getColor(){return this.color;}} public int getColor() {return this.color;}} class Automobile { class Automobile { private enum Action {IDLE,IDLE = 0; private static final int INCREASE_SPEED, private static final int INCREASE_SPEED = 1; DECREASE_SPEED, private static final int DECREASE_SPEED = 2; STOP}; private static final int MAX_SPEED = 140; private static final int STOP = 3; 35
  • 172. Motivating Example Revisited class TrafficSignal {{ class TrafficSignal public enum Color {RED, RED = 0; public static final int YELLOW, public static final int YELLOW = 1; GREEN}; public static final int GREEN = 2; /∗ Current color of the traffic signal, initially red byby default ∗/ /* Current color of the traffic signal, initially red default */ private Color color= =RED; private int color Color.RED; /∗ Accessor for the light’s current color */∗/ /* Accessor for the light’s current color public Color getColor(){return this.color;}} public int getColor() {return this.color;}} class Automobile { class Automobile { private enum Action {IDLE,IDLE = 0; private static final int INCREASE_SPEED, private static final int INCREASE_SPEED = 1; DECREASE_SPEED, private static final int DECREASE_SPEED = 2; STOP}; private static final int MAX_SPEED = 140; private static final int STOP = 3; 35
  • 173. Motivating Example Revisited class TrafficSignal {{ TrafficSignal class TrafficSignal { public enum Color {RED, RED = 0; public static final int public enum Color {RED, YELLOW, public static final int YELLOW = 1; YELLOW, GREEN}; public static final int GREEN = 2; GREEN}; /∗ Current color of the traffic signal, initially red byby default ∗/ /* Current color of the traffic signal, initially red by default */ /* Current color of the traffic signal, initially red default */ private Color color= =RED; private Color color = Color.RED; private int color Color.RED; /∗ Accessor for the light’s current color */∗/ /* Accessor for the light’s current color */ /* Accessor for the light’s current color public Color getColor(){return this.color;}} public Color getColor() {return this.color;}} int getColor() {return this.color;}} class Automobile { class Automobile { class Automobile { private enum Action {IDLE,IDLE = 0; private enum Action {IDLE, private static final int INCREASE_SPEED, INCREASE_SPEED, private static final int INCREASE_SPEED = 1; DECREASE_SPEED, DECREASE_SPEED, private static final int DECREASE_SPEED = 2; STOP}; STOP}; static final int STOP = 3; private static final int MAX_SPEED = 140; private 35
  • 174. Motivating Example Revisited class TrafficSignal {{ TrafficSignal class TrafficSignal { public enum Color {RED, RED = 0; public static final int public enum Color {RED, YELLOW, public static final int YELLOW = 1; YELLOW, GREEN}; public static final int GREEN = 2; GREEN}; /∗ Current color of the traffic signal, initially red byby default ∗/ /* Current color of the traffic signal, initially red by default */ /* Current color of the traffic signal, initially red default */ private Color color= =RED; private Color color = Color.RED; private int color Color.RED; /∗ Accessor for the light’s current color */∗/ /* Accessor for the light’s current color */ /* Accessor for the light’s current color public Color getColor(){return this.color;}} public Color getColor() {return this.color;}} int getColor() {return this.color;}} class Automobile { class Automobile { class Automobile { private enum Action {IDLE,IDLE = 0; private enum Action {IDLE, private static final int INCREASE_SPEED, INCREASE_SPEED, private static final int INCREASE_SPEED = 1; DECREASE_SPEED, DECREASE_SPEED, private static final int DECREASE_SPEED = 2; STOP}; STOP}; static final int STOP = 3; private static final int MAX_SPEED = 140; private 36
  • 175. Motivating Example Revisited Language Enum class TrafficSignal {{ TrafficSignal class TrafficSignal { public enum Color {RED, RED = 0; public static final int public enum Color {RED, YELLOW, public static final int YELLOW = 1; YELLOW, GREEN}; public static final int GREEN = 2; GREEN}; /∗ Current color of the traffic signal, initially red byby default ∗/ /* Current color of the traffic signal, initially red by default */ /* Current color of the traffic signal, initially red default */ private Color color= =RED; private Color color = Color.RED; private int color Color.RED; /∗ Accessor for the light’s current color */∗/ /* Accessor for the light’s current color */ /* Accessor for the light’s current color public Color getColor(){return this.color;}} public Color getColor() {return this.color;}} int getColor() {return this.color;}} class Automobile { class Automobile { class Automobile { private enum Action {IDLE,IDLE = 0; private enum Action {IDLE, private static final int INCREASE_SPEED, INCREASE_SPEED, private static final int INCREASE_SPEED = 1; DECREASE_SPEED, DECREASE_SPEED, private static final int DECREASE_SPEED = 2; STOP}; STOP}; static final int STOP = 3; private static final int MAX_SPEED = 140; private 36
  • 176. Motivating Example Revisited class TrafficSignal {{ TrafficSignal class TrafficSignal { public enum Color {RED, RED = 0; public static final int public enum Color {RED, YELLOW, public static final int YELLOW = 1; YELLOW, GREEN}; public static final int GREEN = 2; GREEN}; /∗ Current color of the traffic signal, initially red byby default ∗/ /* Current color of the traffic signal, initially red by default */ /* Current color of the traffic signal, initially red default */ private Color color= =RED; private Color color = Color.RED; private int color Color.RED; /∗ Accessor for the light’s current color */∗/ /* Accessor for the light’s current color */ /* Accessor for the light’s current color public Color getColor(){return this.color;}} public Color getColor() {return this.color;}} int getColor() {return this.color;}} class Automobile { class Automobile { class Automobile { Type Safety private enum Action {IDLE,IDLE = 0; private enum Action {IDLE, private static final int INCREASE_SPEED, INCREASE_SPEED, private static final int INCREASE_SPEED = 1; DECREASE_SPEED, DECREASE_SPEED, private static final int DECREASE_SPEED = 2; STOP}; STOP}; static final int STOP = 3; private static final int MAX_SPEED = 140; private 36
  • 177. Motivating Example Revisited class TrafficSignal {{ TrafficSignal class TrafficSignal { public enum Color {RED, RED = 0; public static final int public enum Color {RED, YELLOW, public static final int YELLOW = 1; YELLOW, GREEN}; public static final int GREEN = 2; GREEN}; Singletons in initially red by default */ /∗ Current color of the traffic signal, initially red byby default ∗/ /* Current color of the traffic signal, initially red default */ /* Current color of the traffic signal, colorOrder private ColorNatural = =RED; private Color color = Color.RED; private int color Color.RED; /∗ Accessor for the light’s current color */∗/ /* Accessor for the light’s current color */ /* Accessor for the light’s current color public Color getColor(){return this.color;}} public Color getColor() {return this.color;}} int getColor() {return this.color;}} class Automobile { class Automobile { class Automobile { private enum Action {IDLE,IDLE = 0; private enum Action {IDLE, private static final int INCREASE_SPEED, INCREASE_SPEED, private static final int INCREASE_SPEED = 1; DECREASE_SPEED, DECREASE_SPEED, private static final int DECREASE_SPEED = 2; STOP}; STOP}; static final int STOP = 3; private static final int MAX_SPEED = 140; private 36
  • 178. Motivating Example Revisited class TrafficSignal {{ TrafficSignal class TrafficSignal { public enum Color {RED, RED = 0; public static final int public enum Color {RED, YELLOW, public static final int YELLOW = 1; YELLOW, GREEN}; public static final int GREEN = 2; GREEN}; /∗ Current color of the traffic signal, initially red byby default ∗/ /* Current color of the traffic signal, initially red by default */ /* Current color of the traffic signal, initially red default */ private Color color= =RED; private Color color = Color.RED; private int color Color.RED; /∗ Accessor for the light’s current color */∗/ /* Accessor for the light’s current color */ /* Accessor for the light’s current color public Color getColor(){return Prefixed public Color getColor() {return this.color;}} int getColor() {return this.color;}} this.color;}} class Automobile { class Automobile { class Automobile { private enum Action {IDLE,IDLE = 0; private enum Action {IDLE, private static final int INCREASE_SPEED, INCREASE_SPEED, private static final int INCREASE_SPEED = 1; DECREASE_SPEED, DECREASE_SPEED, private static final int DECREASE_SPEED = 2; STOP}; STOP}; static final int STOP = 3; private static final int MAX_SPEED = 140; private 36
  • 179. Motivating Example Revisited Supports Separate Compilation class TrafficSignal {{ TrafficSignal class TrafficSignal { public enum Color {RED, RED = 0; public static final int public enum Color {RED, YELLOW, public static final int YELLOW = 1; YELLOW, GREEN}; public static final int GREEN = 2; GREEN}; /∗ Current color of the traffic signal, initially red byby default ∗/ /* Current color of the traffic signal, initially red by default */ /* Current color of the traffic signal, initially red default */ private Color color= =RED; private Color color = Color.RED; private int color Color.RED; /∗ Accessor for the light’s current color */∗/ /* Accessor for the light’s current color */ /* Accessor for the light’s current color public Color getColor(){return this.color;}} public Color getColor() {return this.color;}} int getColor() {return this.color;}} class Automobile { class Automobile { class Automobile { private enum Action {IDLE,IDLE = 0; private enum Action {IDLE, private static final int INCREASE_SPEED, INCREASE_SPEED, private static final int INCREASE_SPEED = 1; DECREASE_SPEED, DECREASE_SPEED, private static final int DECREASE_SPEED = 2; STOP}; STOP}; static final int STOP = 3; private static final int MAX_SPEED = 140; private 36
  • 180. Motivating Example Revisited class TrafficSignal {{ TrafficSignal class TrafficSignal { public enum Color {RED, RED = 0; public static final int public enum Color {RED, YELLOW, public static final int YELLOW = 1; YELLOW, GREEN}; public static final int GREEN = 2; GREEN}; /∗ Current color of the traffic signal, initially red byby default ∗/ /* Current color of the traffic signal, initially red by default */ /* Current color of the traffic signal, initially red default */ private Color color= =RED; private Color color = Color.RED; private int color Color.RED; /∗ Accessor for the light’s current color */∗/ /* Accessor for the light’s current color */ /* Accessor for the light’s current color public Color getColor(){return this.color;}} public Color getColor() {return this.color;}} int getColor() {return this.color;}} class Automobile { class Automobile { class Automobile { private enum Action {IDLE,IDLE = 0; private enum Action {IDLE, private static final int INCREASE_SPEED, INCREASE_SPEED, private static final int INCREASE_SPEED = 1; DECREASE_SPEED, DECREASE_SPEED, private static final int DECREASE_SPEED = 2; STOP}; STOP}; static final int STOP = 3; private static final int MAX_SPEED = 140; private 36
  • 181. this.currentAction && private int color = RED; 38 (reacti INCREASE_SPEED ||automobile is currently performing, idle by default ∗/ /∗ The action this private for currentAction = tSpeed <= MAX_SPEED)) Traffic Signal Client /∗ Accessorintthe light’s current color ∗/IDLE; 39 this.c public intspeed of the automobile, initially 540 getColor() {return this.color;}} this. /∗ The current rmAction(reaction);} mph. ∗/ 41 private int currentSpeed = 5; 42 private void rmAction(int action) { class Automobile {...}} (b) Im private int react(TrafficSignal 0; static final int IDLE = signal) { eger constants for static final int INCREASE_SPEED = 1; private enumerated types. switch(signal.getColor()) { private static final int DECREASE_SPEED = 2; case TrafficSignal.RED: return STOP; Figure 1. Running example: STOP = 3; private static final int a hypothetical drive-by-w case TrafficSignal.YELLOW: private decide whether to stop or go // static final int MAX_SPEED = 140; /∗ The action (this.shouldGo()) performing, idle by default ∗/ if this automobile is currently ch machinery.int currentAction = IDLE; example, in which private return Third, INCREASE_SPEED; the weak enum /∗ The to manually enumerate initially 5 mph.language enum ogrammercurrent speed of theSTOP; the else return automobile, by ∗/ ts, whichcaseint currentSpeed = of // no changeAutomobile. private TrafficSignal.GREEN: increases the likelihood 5; and return this.currentAction; different enumint react(TrafficSignal signal) of these ne private constants may be unin- ations { default: throw new IllegalArgumentException he same internal value. Finally, the ("Invalid traffic color");}}through compile-tim switch(signal.getColor()) { // required case TrafficSignal.RED: return STOP; rittle public voidthe values {are com- [?]:case TrafficSignal.YELLOW: since drive() between the named at compile time they are to stop or=go... ; ated values. It is als TrafficSignal aSignal into // decide whether inlined new constants(this.shouldGo()) int if are added in between reaction = this.react(aSignal); Action, whic is an 37
  • 182. this.currentAction && private int color = RED; 38 (reacti INCREASE_SPEED ||automobile is currently performing, idle by default ∗/ /∗ The action this private for currentAction = tSpeed <= MAX_SPEED)) Traffic Signal Client /∗ Accessorintthe light’s current color ∗/IDLE; 39 this.c public intspeed of the automobile, initially 540 getColor() {return this.color;}} this. /∗ The current rmAction(reaction);} mph. ∗/ 41 private int currentSpeed = 5; 42 private void rmAction(int action) { class Automobile {...}} (b) Im private int react(TrafficSignal 0; static final int IDLE = signal) { eger constants for static final int INCREASE_SPEED = 1; private enumerated types. switch(signal.getColor()) { private static final int DECREASE_SPEED = 2; case TrafficSignal.RED: return STOP; Figure 1. Running example: STOP = 3; private static final int a hypothetical drive-by-w case TrafficSignal.YELLOW: private decide whether to stop or go // static final int MAX_SPEED = 140; /∗ The action (this.shouldGo()) performing, idle by default ∗/ if this automobile is currently ch machinery.int currentAction = IDLE; example, in which private return Third, INCREASE_SPEED; the weak enum /∗ The to manually enumerate initially 5 mph.language enum ogrammercurrent speed of theSTOP; the else return automobile, by ∗/ ts, whichcaseint currentSpeed = of // no changeAutomobile. private TrafficSignal.GREEN: increases the likelihood 5; and return this.currentAction; different enumint react(TrafficSignal signal) of these ne private constants may be unin- ations { default: throw new IllegalArgumentException he same internal value. Finally, the ("Invalid traffic color");}}through compile-tim switch(signal.getColor()) { // required case TrafficSignal.RED: return STOP; rittle public voidthe values {are com- [?]:case TrafficSignal.YELLOW: since drive() between the named at compile time they are to stop or=go... ; ated values. It is als TrafficSignal aSignal into // decide whether inlined new constants(this.shouldGo()) int if are added in between reaction = this.react(aSignal); Action, whic is an 37
  • 183. this.currentAction && private int color = RED; 38 (reacti INCREASE_SPEED ||automobile is currently performing, idle by default ∗/ /∗ The action this private for currentAction = tSpeed <= MAX_SPEED)) Traffic Signal Client /∗ Accessorintthe light’s current color ∗/IDLE; 39 this.c public intspeed of the automobile, initially 540 getColor() {return this.color;}} this. /∗ The current rmAction(reaction);} mph. ∗/ 41 private int currentSpeed = 5; 42 private void rmAction(int action) { class Automobile {...}} (b) Im private int react(TrafficSignal 0; static final int IDLE = signal) { eger constants for static final int INCREASE_SPEED = 1; private enumerated types. switch(signal.getColor()) { private static final int DECREASE_SPEED = 2; case TrafficSignal.RED: return STOP; Figure 1. Running example: STOP = 3; private static final int a hypothetical drive-by-w case TrafficSignal.YELLOW: private decide whether to stop or go // static final int MAX_SPEED = 140; /∗ The action (this.shouldGo()) performing, idle by default ∗/ if this automobile is currently ch machinery.int currentAction = IDLE; example, in which private return Third, INCREASE_SPEED; the weak enum /∗ The to manually enumerate initially 5 mph.language enum ogrammercurrent speed of theSTOP; the else return automobile, by ∗/ ts, whichcaseint currentSpeed = of // no changeAutomobile. private TrafficSignal.GREEN: increases the likelihood 5; and return this.currentAction; different enumint react(TrafficSignal signal) of these ne private constants may be unin- ations { default: throw new IllegalArgumentException he same internal value. Finally, the ("Invalid traffic color");}}through compile-tim switch(signal.getColor()) { // required case TrafficSignal.RED: return STOP; rittle public voidthe values {are com- [?]:case TrafficSignal.YELLOW: since drive() between the named at compile time they are to stop or=go... ; ated values. It is als TrafficSignal aSignal into // decide whether inlined new constants(this.shouldGo()) int if are added in between reaction = this.react(aSignal); Action, whic is an 37
  • 184. this.currentAction && private int color = RED; 38 (reacti INCREASE_SPEED ||automobile is currently performing, idle by default ∗/ /∗ The action this private for currentAction = tSpeed <= MAX_SPEED)) Traffic Signal Client /∗ Accessorintthe light’s current color ∗/IDLE; 39 this.c public intspeed of the automobile, initially 540 getColor() {return this.color;}} this. /∗ The current rmAction(reaction);} mph. ∗/ 41 private int currentSpeed = 5; 42 private void rmAction(int action) { class Automobile {...}} (b) Im private int react(TrafficSignal 0; static final int IDLE = signal) { eger constants for static final int INCREASE_SPEED = 1; private enumerated types. switch(signal.getColor()) { private static final int DECREASE_SPEED = 2; case TrafficSignal.RED: return STOP; Figure 1. Running example: STOP = 3; private static final int a hypothetical drive-by-w case TrafficSignal.YELLOW: private decide whether to stop or go // static final int MAX_SPEED = 140; /∗ The action (this.shouldGo()) performing, idle by default ∗/ if this automobile is currently ch machinery.int currentAction = IDLE; example, in which private return Third, INCREASE_SPEED; the weak enum /∗ The to manually enumerate initially 5 mph.language enum ogrammercurrent speed of theSTOP; the else return automobile, by ∗/ ts, whichcaseint currentSpeed = of // no changeAutomobile. private TrafficSignal.GREEN: increases the likelihood 5; and return this.currentAction; different enumint react(TrafficSignal signal) of these ne private constants may be unin- ations { default: throw new IllegalArgumentException he same internal value. Finally, the ("Invalid traffic color");}}through compile-tim switch(signal.getColor()) { // required case TrafficSignal.RED: return STOP; rittle public voidthe values {are com- [?]:case TrafficSignal.YELLOW: since drive() between the named at compile time they are to stop or=go... ; ated values. It is als TrafficSignal aSignal into // decide whether inlined new constants(this.shouldGo()) int if are added in between reaction = this.react(aSignal); Action, whic is an 37
  • 185. this.currentAction && private int color = RED; int color = RED; 38 (reacti INCREASE_SPEED || /∗ Accessor for the light’s current color ∗/ Accessor for the light’s current color ∗/ tSpeed <= MAX_SPEED)) Traffic Signal Client 39 this.c public int getColor() {return this.color;}} int getColor() {return this.color;}} rmAction(reaction);} 40 Automobile this. 41 Action Enum 42 private void rmAction(int action) { class Automobile {...}} Automobile { (b) Im private static final int IDLE == 0; static final int IDLE 0; eger constants for static final int INCREASE_SPEED ==1; enumerated types. private static final int INCREASE_SPEED private 1; private static final int DECREASE_SPEED ==2; private static final int DECREASE_SPEED 2; Figure 1. Running example: STOP == 3; private static final int a hypothetical drive-by-w private static final int STOP 3; private static final int MAX_SPEED == 140; private static final int MAX_SPEED 140; /∗ The action this automobile is currently performing, idle by default ∗/ /∗ The action Third, the weak enumperforming, idle by default ∗/ this automobile is currently ch machinery.int currentAction = IDLE; example, in which private int currentAction = IDLE; private /∗ The current speed of the automobile,initially 55by language enum ogrammercurrent speed of the automobile,the /∗ The to manually enumerate initially mph. ∗/ mph. ∗/ private int currentSpeed = 5; ts, which increases the likelihood of private int currentSpeed = 5; and Automobile. different enumint react(TrafficSignal signal) of these ne constants may be unin- ations private int react(TrafficSignal signal) {{ private he same internal value. Finally, the{ switch(signal.getColor()) { switch(signal.getColor()) through compile-tim case TrafficSignal.RED: return STOP; rittle [?]:case TrafficSignal.YELLOW: case TrafficSignal.RED: return STOP; the named since the values are com- between case TrafficSignal.YELLOW: at compile time they are to stop or go // decide whether inlined into // decide whether to stop or go ated values. It is als new constants(this.shouldGo()) if are added in between is an Action, whic 37
  • 186. this.currentAction && private int color = RED; int color = RED; 38 (reacti INCREASE_SPEED || /∗ Accessor for the light’s current color ∗/ Accessor for the light’s current color ∗/ tSpeed <= MAX_SPEED)) Traffic Signal Client 39 this.c public int getColor() {return this.color;}} int getColor() {return this.color;}}40 this. rmAction(reaction);} 41 42 private void rmAction(int action) { class Automobile {...}} Automobile { (b) Im private static final int IDLE == 0; static final int IDLE 0; eger constants for static final int INCREASE_SPEED ==1; enumerated types. private static final int INCREASE_SPEED private 1; private static final int DECREASE_SPEED ==2; private static final int DECREASE_SPEED 2; Figure 1. Running example: STOP == 3; private static final int a hypothetical drive-by-w private static final int STOP 3; private static final int MAX_SPEED == 140; private static final int MAX_SPEED 140; /∗ The action this automobile is currently performing, idle by default ∗/ /∗ The action Third, the weak enumperforming, idle by default ∗/ this automobile is currently ch machinery.int currentAction = IDLE; example, in which private int currentAction = IDLE; private /∗ The to manually enumerate initially mph. Named- /∗ The current speed of the automobile,initially 55by language enum ogrammercurrent speed of the automobile,the ∗/ mph. ∗/ private int currentSpeed = of ts, which increases the likelihood 5; private int currentSpeed = 5; Constant and Automobile. different enumint react(TrafficSignal signal) of these ne constants may be unin- ations private int react(TrafficSignal signal) {{ private he same internal value. Finally, the{ switch(signal.getColor()) { switch(signal.getColor()) through compile-tim case TrafficSignal.RED: return STOP; rittle [?]:case TrafficSignal.YELLOW: case TrafficSignal.RED: return STOP; the named since the values are com- between case TrafficSignal.YELLOW: at compile time they are to stop or go // decide whether inlined into // decide whether to stop or go ated values. It is als new constants(this.shouldGo()) if are added in between is an Action, whic 37
  • 187. this.currentAction && private int color = RED; int color = RED; 38 (reacti INCREASE_SPEED || /∗ Accessor for the light’s current color ∗/ Accessor for the light’s current color ∗/ tSpeed <= MAX_SPEED)) Traffic Signal Client 39 this.c public int getColor() {return this.color;}} int getColor() {return this.color;}}40 this. rmAction(reaction);} 41 42 private void rmAction(int action) { class Automobile {...}} Automobile { (b) Im private static final int IDLE == 0; static final int IDLE 0; eger constants for static final int INCREASE_SPEED ==1; enumerated types. private static final int INCREASE_SPEED private 1; private static final int DECREASE_SPEED ==2; private static final int DECREASE_SPEED 2; Figure 1. Running example: STOP == 3; private static final int a hypothetical drive-by-w private static final int STOP 3; private static final int MAX_SPEED == 140; private static final int MAX_SPEED Promising... 140; /∗ The action this automobile is currently performing, idle by default ∗/ /∗ The action Third, the weak enumperforming, idle by default ∗/ this automobile is currently ch machinery.int currentAction = IDLE; example, in which private int currentAction = IDLE; private /∗ The current speed of the automobile,initially 55by language enum ogrammercurrent speed of the automobile,the /∗ The to manually enumerate initially mph. ∗/ mph. ∗/ private int currentSpeed = 5; ts, which increases the likelihood of private int currentSpeed = 5; and Automobile. different enumint react(TrafficSignal signal) of these ne constants may be unin- ations private int react(TrafficSignal signal) {{ private he same internal value. Finally, the{ switch(signal.getColor()) { switch(signal.getColor()) through compile-tim case TrafficSignal.RED: return STOP; rittle [?]:case TrafficSignal.YELLOW: case TrafficSignal.RED: return STOP; the named since the values are com- between case TrafficSignal.YELLOW: at compile time they are to stop or go // decide whether inlined into // decide whether to stop or go ated values. It is als new constants(this.shouldGo()) if are added in between is an Action, whic 37
  • 188. this.currentAction && private int color = RED; int color = RED; 38 (reacti INCREASE_SPEED || /∗ Accessor for the light’s current color ∗/ Accessor for the light’s current color ∗/ tSpeed <= MAX_SPEED)) Traffic Signal Client 39 this.c public int getColor() {return this.color;}} int getColor() {return this.color;}}40 this. rmAction(reaction);} 41 42 private void rmAction(int action) { class Automobile {...}} Automobile { (b) Im private static final int IDLE == 0; static final int IDLE 0; eger constants for static final int INCREASE_SPEED ==1; enumerated types. private static final int INCREASE_SPEED private 1; private static final int DECREASE_SPEED ==2; private static final int DECREASE_SPEED 2; Figure 1. Running example: STOP == 3; private static final int a hypothetical drive-by-w private static final int STOP 3; private static final int MAX_SPEED == 140; private static final int MAX_SPEED 140; /∗ The action this automobile is currently performing, idle by default ∗/ /∗ The action Third, the weak enumperforming, idle by default ∗/ this automobile is currently ch machinery.int currentAction = IDLE; example, in which private int currentAction = IDLE; private /∗ The current speed of the automobile,initially 55by language enum ogrammercurrent speed of the automobile,the /∗ The to manually enumerate initially mph. ∗/ mph. ∗/ private int currentSpeed = 5; ts, which increases the likelihood of private int currentSpeed = 5; and Automobile. different enumint react(TrafficSignal signal) of these ne constants may be unin- ations private int react(TrafficSignal signal) {{ private not Definitely he same internal value. Finally, the{ switch(signal.getColor()) { switch(signal.getColor()) through compile-tim enumerizable case TrafficSignal.RED: return STOP; rittle [?]:case TrafficSignal.YELLOW: case TrafficSignal.RED: return STOP; the named since the values are com- between case TrafficSignal.YELLOW: at compile time they are to stop or go // decide whether inlined into // decide whether to stop or go ated values. It is als new constants(this.shouldGo()) if are added in between is an Action, whic 37
  • 189. this.currentAction && private int color = RED; 38 (reacti INCREASE_SPEED ||automobile is currently performing, idle by default ∗/ /∗ The action this private for currentAction = tSpeed <= MAX_SPEED)) Traffic Signal Client /∗ Accessorintthe light’s current color ∗/IDLE; 39 this.c public intspeed of the automobile, initially 540 getColor() {return this.color;}} this. /∗ The current rmAction(reaction);} mph. ∗/ 41 private int currentSpeed = 5; 42 private void rmAction(int action) { class Automobile {...}} (b) Im private int react(TrafficSignal 0; static final int IDLE = signal) { eger constants for static final int INCREASE_SPEED = 1; private enumerated types. switch(signal.getColor()) { private static final int DECREASE_SPEED = 2; case TrafficSignal.RED: return STOP; Figure 1. Running example: STOP = 3; private static final int a hypothetical drive-by-w case TrafficSignal.YELLOW: private decide whether to stop or go // static final int MAX_SPEED = 140; /∗ The action (this.shouldGo()) performing, idle by default ∗/ if this automobile is currently ch machinery.int currentAction = IDLE; example, in which private return Third, INCREASE_SPEED; the weak enum /∗ The to manually enumerate initially 5 mph.language enum ogrammercurrent speed of theSTOP; the else return automobile, by ∗/ ts, whichcaseint currentSpeed = of // no changeAutomobile. private TrafficSignal.GREEN: increases the likelihood 5; and return this.currentAction; different enumint react(TrafficSignal signal) of these ne private constants may be unin- ations { default: throw new IllegalArgumentException he same internal value. Finally, the ("Invalid traffic color");}}through compile-tim switch(signal.getColor()) { // required case TrafficSignal.RED: return STOP; rittle public voidthe values {are com- [?]:case TrafficSignal.YELLOW: since drive() between the named at compile time they are to stop or=go... ; ated values. It is als TrafficSignal aSignal into // decide whether inlined new constants(this.shouldGo()) int if are added in between reaction = this.react(aSignal); Action, whic is an 37
  • 190. this.currentAction && private int color = RED; 38 (reacti INCREASE_SPEED ||automobile is currently performing, idle by default ∗/ /∗ The action this private for currentAction = tSpeed <= MAX_SPEED)) Traffic Signal Client /∗ Accessorintthe light’s current color ∗/IDLE; 39 this.c public intspeed of the automobile, initially 540 getColor() {return this.color;}} this. /∗ The current rmAction(reaction);} mph. ∗/ 41 private int currentSpeed = 5; 42 private void rmAction(int action) { class Automobile {...}} (b) Im private int react(TrafficSignal 0; static final int IDLE = signal) { eger constants for static final int INCREASE_SPEED = 1; private enumerated types. switch(signal.getColor()) { private static final int DECREASE_SPEED = 2; case TrafficSignal.RED: return STOP; Figure 1. Running example: STOP = 3; private static final int a hypothetical drive-by-w case TrafficSignal.YELLOW: private decide whether to stop or go // static final int MAX_SPEED = 140; /∗ The action (this.shouldGo()) performing, idle by default ∗/ if this automobile is currently ch machinery.int currentAction = IDLE; example, in which private return Third, INCREASE_SPEED; the weak enum /∗ The to manually enumerate initially 5 mph.language enum ogrammercurrent speed of theSTOP; the else return automobile, by ∗/ ts, whichcaseint currentSpeed = of // no changeAutomobile. private TrafficSignal.GREEN: increases the likelihood 5; and return this.currentAction; different enumint react(TrafficSignal signal) of these ne private constants may be unin- ations { default: throw new IllegalArgumentException he same internal value. Finally, the ("Invalid traffic color");}}through compile-tim switch(signal.getColor()) { // required case TrafficSignal.RED: return STOP; rittle public voidthe values {are com- [?]:case TrafficSignal.YELLOW: since drive() between the named at compile time they are to stop or=go... ; ated values. It is als TrafficSignal aSignal into // decide whether inlined new constants(this.shouldGo()) int if are added in between reaction = this.react(aSignal); Action, whic is an 37
  • 191. this.currentAction && private int color = RED; 38 (reacti INCREASE_SPEED ||automobile is currently performing, idle by default ∗/ /∗ The action this private for currentAction = tSpeed <= MAX_SPEED)) Traffic Signal Client /∗ Accessorintthe light’s current color ∗/IDLE; 39 this.c public intspeed of the automobile, initially 540 getColor() {return this.color;}} this. /∗ The current rmAction(reaction);} mph. ∗/ 41 private int currentSpeed = 5; 42 private void rmAction(int action) { class Automobile {...}} (b) Im private int react(TrafficSignal 0; static final int IDLE = signal) { eger constants for static final int INCREASE_SPEED = 1; private enumerated types. switch(signal.getColor()) { private static final int DECREASE_SPEED = 2; case TrafficSignal.RED: return STOP; Figure 1. Running example: STOP = 3; private static final int a hypothetical drive-by-w case TrafficSignal.YELLOW: private decide whether to stop or go // static final int MAX_SPEED = 140; /∗ The action (this.shouldGo()) performing, idle by default ∗/ if this automobile is currently ch machinery.int currentAction = IDLE; example, in which private return Third, INCREASE_SPEED; the weak enum /∗ The to manually enumerate initially 5 mph.language enum ogrammercurrent speed of theSTOP; the else return automobile, by ∗/ ts, whichcaseint currentSpeed = of // no changeAutomobile. private TrafficSignal.GREEN: increases the likelihood 5; and return this.currentAction; different enumint react(TrafficSignal signal) of these ne private constants may be unin- ations { default: throw new IllegalArgumentException he same internal value. Finally, the ("Invalid traffic color");}}through compile-tim switch(signal.getColor()) { // required case TrafficSignal.RED: return STOP; rittle public voidthe values {are com- [?]:case TrafficSignal.YELLOW: since drive() between the named at compile time they are to stop or=go... ; ated values. It is als TrafficSignal aSignal into // decide whether inlined new constants(this.shouldGo()) int if are added in between reaction = this.react(aSignal); Action, whic is an 37
  • 192. this.currentAction && /∗ The action this color = RED; 38 (reacti private int automobile is currently performing, idle by default */ /* idle by default ∗/ INCREASE_SPEED || /∗ Accessor Action currentAction = Action.IDLE; Client Traffic Signal this.c private intthe light’s current color ∗/IDLE; 39 for currentAction = tSpeed <= MAX_SPEED)) public intspeed of the automobile, initially 540 getColor() {return this.color;}} this. /∗ The current /* rmAction(reaction);} mph. */ ∗/ 41 private int currentSpeed = 5; 42 private void rmAction(int action) { class Automobile {...}} (b) Im private int react(TrafficSignal 0; signal) { static final int IDLE = signal) { Action react(TrafficSignal eger constants for static final int INCREASE_SPEED = 1; private enumerated types. switch(signal.getColor()) { private static final int DECREASE_SPEED = 2; case TrafficSignal.RED: return Action.STOP; STOP; Figure 1. Running example: STOP = 3; private static final int a hypothetical drive-by-w case TrafficSignal.YELLOW: private decide whether to stop or go // static final int MAX_SPEED = 140; /∗ The action (this.shouldGo()) performing, idle by default ∗/ if this automobile is currently ch machinery.int currentAction = IDLE; example, in which Third, INCREASE_SPEED; the weak enum private return Action.INCREASE_SPEED; /∗ The to manually enumerate initially 5 mph.language enum ogrammercurrent speed of theSTOP; the automobile, else return Action.STOP; by ∗/ ts, whichcaseint currentSpeed = of // no changeAutomobile. private TrafficSignal.GREEN: increases the likelihood 5; and return this.currentAction; different enumint react(TrafficSignal signal) of these ne private constants may be unin- ations { default: throw new IllegalArgumentException he same internal value. Finally, the ("Invalid traffic color");}}through compile-tim switch(signal.getColor()) { // required case TrafficSignal.RED: return STOP; rittle public voidthe values {are com- [?]:case TrafficSignal.YELLOW: since drive() between the named at compile time they are to stop or=go... ; ated values. It is als TrafficSignal aSignal into // decide whether inlined new constants(this.shouldGo()) int if reactionthis.react(aSignal); Action, whic Action are added in between reaction = = this.react(aSignal);is an 38
  • 193. this.currentAction && /∗ The action this color = RED; 38 (reacti private int automobile is currently performing, idle by default */ /* idle by default ∗/ INCREASE_SPEED || /∗ Accessor Action currentAction = Action.IDLE; Client Traffic Signal this.c private intthe light’s current color ∗/IDLE; 39 for currentAction = tSpeed <= MAX_SPEED)) public intspeed of the automobile, initially 540 getColor() {return this.color;}} this. /∗ The current /* rmAction(reaction);} mph. */ ∗/ 41 private int currentSpeed = 5; 42 private void rmAction(int action) { class Automobile {...}} (b) Im private int react(TrafficSignal 0; signal) { static final int IDLE = signal) { Action react(TrafficSignal eger constants for static final int INCREASE_SPEED = 1; private enumerated types. switch(signal.getColor()) { private static final int DECREASE_SPEED = 2; case TrafficSignal.RED: return Action.STOP; STOP; Figure 1. Running example: STOP = 3; private static final int a hypothetical drive-by-w case TrafficSignal.YELLOW: private decide whether to stop or go // static final int MAX_SPEED = 140; /∗ The action (this.shouldGo()) performing, idle by default ∗/ if this automobile is currently ch machinery.int currentAction = IDLE; example, in which Third, INCREASE_SPEED; the weak enum private return Action.INCREASE_SPEED; /∗ The to manually enumerate initially 5 mph.language enum ogrammercurrent speed of theSTOP; the automobile, else return Action.STOP; by ∗/ ts, whichcaseint currentSpeed = of // no changeAutomobile. private TrafficSignal.GREEN: increases the likelihood 5; and return this.currentAction; different enumint react(TrafficSignal signal) of these ne private constants may be unin- ations { default: throw new IllegalArgumentException he same internal value. Finally, the ("Invalid traffic color");}}through compile-tim switch(signal.getColor()) { // required case TrafficSignal.RED: return STOP; rittle public voidthe values {are com- [?]:case TrafficSignal.YELLOW: since drive() between the named at compile time they are to stop or=go... ; ated values. It is als TrafficSignal aSignal into // decide whether inlined new constants(this.shouldGo()) int if reactionthis.react(aSignal); Action, whic Action are added in between reaction = = this.react(aSignal);is an 38
  • 194. this.currentAction && /∗ The action this color = RED; 38 (reacti private int automobile is currently performing, idle by default */ /* idle by default ∗/ INCREASE_SPEED || /∗ Accessor Action currentAction = Action.IDLE; Client Traffic Signal this.c private intthe light’s current color ∗/IDLE; 39 for currentAction = tSpeed <= MAX_SPEED)) public intspeed of the automobile, initially 540 getColor() {return this.color;}} this. /∗ The current /* rmAction(reaction);} mph. */ ∗/ 41 private int currentSpeed = 5; 42 private void rmAction(int action) { class Automobile {...}} (b) Im private int react(TrafficSignal 0; signal) { static final int IDLE = signal) { Action react(TrafficSignal eger constants for static final int INCREASE_SPEED = 1; private enumerated types. switch(signal.getColor()) { private static final int DECREASE_SPEED = 2; case TrafficSignal.RED: return Action.STOP; STOP; Figure 1. Running example: STOP = 3; private static final int a hypothetical drive-by-w case TrafficSignal.YELLOW: private decide whether to stop or go // static final int MAX_SPEED = 140; /∗ The action (this.shouldGo()) performing, idle by default ∗/ if this automobile is currently ch machinery.int currentAction = IDLE; example, in which Third, INCREASE_SPEED; the weak enum private return Action.INCREASE_SPEED; /∗ The to manually enumerate initially 5 mph.language enum ogrammercurrent speed of theSTOP; the automobile, else return Action.STOP; by ∗/ ts, whichcaseint currentSpeed = of // no changeAutomobile. private TrafficSignal.GREEN: increases the likelihood 5; and return this.currentAction; different enumint react(TrafficSignal signal) of these ne private constants may be unin- ations { default: throw new IllegalArgumentException he same internal value. Finally, the ("Invalid traffic color");}}through compile-tim switch(signal.getColor()) { // required case TrafficSignal.RED: return STOP; rittle public voidthe values {are com- [?]:case TrafficSignal.YELLOW: since drive() between the named at compile time they are to stop or=go... ; ated values. It is als TrafficSignal aSignal into // decide whether inlined new constants(this.shouldGo()) int if reactionthis.react(aSignal); Action, whic Action are added in between reaction = = this.react(aSignal);is an 38
  • 195. this.currentAction && /∗ The action this color = RED; 38 (reacti private int automobile is currently performing, idle by default */ /* idle by default ∗/ INCREASE_SPEED || /∗ Accessor Action currentAction = Action.IDLE; Client Traffic Signal this.c private intthe light’s current color ∗/IDLE; 39 for currentAction = tSpeed <= MAX_SPEED)) public intspeed of the automobile, initially 540 getColor() {return this.color;}} this. /∗ The current /* rmAction(reaction);} mph. */ ∗/ 41 private int currentSpeed = 5; 42 private void rmAction(int action) { class Automobile {...}} (b) Im private int react(TrafficSignal 0; signal) { static final int IDLE = signal) { Action react(TrafficSignal eger constants for static final int INCREASE_SPEED = 1; private enumerated types. switch(signal.getColor()) { private static final int DECREASE_SPEED = 2; case TrafficSignal.RED: return Action.STOP; STOP; Figure 1. Running example: STOP = 3; private static final int a hypothetical drive-by-w case TrafficSignal.YELLOW: private decide whether to stop or go // static final int MAX_SPEED = 140; /∗ The action (this.shouldGo()) performing, idle by default ∗/ if this automobile is currently ch machinery.int currentAction = IDLE; example, in which Third, INCREASE_SPEED; the weak enum private return Action.INCREASE_SPEED; /∗ The to manually enumerate initially 5 mph.language enum ogrammercurrent speed of theSTOP; the automobile, else return Action.STOP; by ∗/ ts, whichcaseint currentSpeed = of // no changeAutomobile. private TrafficSignal.GREEN: increases the likelihood 5; and return this.currentAction; different enumint react(TrafficSignal signal) of these ne private constants may be unin- ations { default: throw new IllegalArgumentException he same internal value. Finally, the ("Invalid traffic color");}}through compile-tim switch(signal.getColor()) { // required case TrafficSignal.RED: return STOP; rittle public voidthe values {are com- [?]:case TrafficSignal.YELLOW: since drive() between the named at compile time they are to stop or=go... ; ated values. It is als TrafficSignal aSignal into // decide whether inlined new constants(this.shouldGo()) int if reactionthis.react(aSignal); Action, whic Action are added in between reaction = = this.react(aSignal);is an 38
  • 196. this.currentAction && /∗ The action this color = RED; 38 (reacti private int automobile is currently performing, idle by default */ /* idle by default ∗/ INCREASE_SPEED || /∗ Accessor Action currentAction = Action.IDLE; Client Traffic Signal this.c private intthe light’s current color ∗/IDLE; 39 for currentAction = tSpeed <= MAX_SPEED)) public intspeed of the automobile, initially 540 getColor() {return this.color;}} this. /∗ The current /* rmAction(reaction);} mph. */ ∗/ 41 private int currentSpeed = 5; 42 private void rmAction(int action) { class Automobile {...}} (b) Im private int react(TrafficSignal 0; signal) { static final int IDLE = signal) { Action react(TrafficSignal eger constants for static final int INCREASE_SPEED = 1; private enumerated types. switch(signal.getColor()) { private static final int DECREASE_SPEED = 2; case TrafficSignal.RED: return Action.STOP; STOP; Figure 1. Running example: STOP = 3; private static final int a hypothetical drive-by-w case TrafficSignal.YELLOW: private decide whether to stop or go // static final int MAX_SPEED = 140; /∗ The action (this.shouldGo()) performing, idle by default ∗/ if this automobile is currently ch machinery.int currentAction = IDLE; example, in which Third, INCREASE_SPEED; the weak enum private return Action.INCREASE_SPEED; /∗ The to manually enumerate initially 5 mph.language enum ogrammercurrent speed of theSTOP; the automobile, else return Action.STOP; by ∗/ ts, whichcaseint currentSpeed = of // no changeAutomobile. private TrafficSignal.GREEN: increases the likelihood 5; and return this.currentAction; different enumint react(TrafficSignal signal) of these ne private constants may be unin- ations { default: throw new IllegalArgumentException he same internal value. Finally, the ("Invalid traffic color");}}through compile-tim switch(signal.getColor()) { // required case TrafficSignal.RED: return STOP; rittle public voidthe values {are com- [?]:case TrafficSignal.YELLOW: since drive() between the named at compile time they are to stop or=go... ; ated values. It is als TrafficSignal aSignal into // decide whether inlined new constants(this.shouldGo()) int if reactionthis.react(aSignal); Action, whic Action are added in between reaction = = this.react(aSignal);is an 38
  • 197. My Approach to Refactoring to Enums 39
  • 198. My Approach to Refactoring to Enums • Developed a semantics preserving, declarative type inferencing algorithm that migrates legacy Java code to use enums. 39
  • 199. My Approach to Refactoring to Enums • Developed a semantics preserving, declarative type inferencing algorithm that migrates legacy Java code to use enums. • Algorithm: 39
  • 200. My Approach to Refactoring to Enums • Developed a semantics preserving, declarative type inferencing algorithm that migrates legacy Java code to use enums. • Algorithm: • Infers fields that are possibly being used to simulate enumerated types. 39
  • 201. My Approach to Refactoring to Enums • Developed a semantics preserving, declarative type inferencing algorithm that migrates legacy Java code to use enums. • Algorithm: • Infers fields that are possibly being used to simulate enumerated types. • Identifies all code changes required to introduce the inferred enum type. 39
  • 203. Contributions • Developed an open source Eclipse IDE plug-in called CONVERT CONSTANTS TO ENUM that: • Automatically refactors code to use enums. • Provides a developer-friendly graphical user interface with preview pane, constant selection, etc. • Proposed as a Google Summer of Code (GSoC) project in 2009 and 2010. • In progress to be included with the standard distribution of Eclipse, proposed by IBM. 40
  • 204. Contributions • Developed an open source Eclipse IDE plug-in called CONVERT CONSTANTS TO ENUM that: • Automatically refactors code to use enums. • Provides a developer-friendly graphical user interface with preview pane, constant selection, etc. • Proposed as a Google Summer of Code (GSoC) project in 2009 and 2010. • In progress to be included with the standard distribution of Eclipse, proposed by IBM. • Evaluated plug-in on 17 open source applications: • Analysis and transformation costs are practical. • Enum-absence compensation patterns are widely used. • Large percentage of fields can be automatically refactored. 40
  • 205. α '%2"%,&)/ !)&-/ 1)!0#- αctxt 30"+$5+ "$ 40"+0 α 1%. Enumerization Approach #++(2 !"#$%& '( !)%*+,"-* .)/+/").( function Enumerizable(C)P) .',/&4$'& Enumerize(F, R ← Enumerizable(F ) 1: >AW ← C /* seed the worklist with the input constants */ 2: QAN ← ∅ /* the non-enumerizable set ∩ Consistent(R) */ R ← U nique(R) ∩ Distinct(R) list, initially empty 3: GAfor all c T ∈ R 4, 5,' *22 ∈ C do T ransf orm(T ) 4: RA MakeSet(c) /* init the union-find data structure */ ?A &#4 5,' 5: end for 6: while W = ∅ do !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*( 7: /* remove an element from the worklist */ α ← e | ∈ %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+% 2)9%+!#2"$37 eM)W 8: W ← W {α} "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. - 9: 6)$-)$! 62#32%1 Contexts(α, P) do 10: for all αctxt ∈ )$!"!")*7 O0"* %**(16!"#$ +#(&- ,) "$'% 11: ¬isEnumerizableContext (α, αctxt ) then -%!)-if!02#(30 !0) (*) #9 2)")+!"#$ %$- +(*!#1 +&%** &#%-)41
  • 206. α '%2"%,&)/ !)&-/ 1)!0#- αctxt 30"+$5+ "$ 40"+0 α 1%. Enumerization Approach #++(2 !"#$%& '( !)%*+,"-* .)/+/").( Subset of static function Enumerizable(C)P) .',/&4$'& Enumerize(F, final fields R ← Enumerizable(F ) 1: >AW ← C /* seed the worklist with the input constants */ 2: QAN ← ∅ /* the non-enumerizable set ∩ Consistent(R) */ R ← U nique(R) ∩ Distinct(R) list, initially empty 3: GAfor all c T ∈ R 4, 5,' *22 ∈ C do T ransf orm(T ) 4: RA MakeSet(c) /* init the union-find data structure */ ?A &#4 5,' 5: end for 6: while W = ∅ do !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*( 7: /* remove an element from the worklist */ α ← e | ∈ %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+% 2)9%+!#2"$37 eM)W 8: W ← W {α} "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. - 9: 6)$-)$! 62#32%1 Contexts(α, P) do 10: for all αctxt ∈ )$!"!")*7 O0"* %**(16!"#$ +#(&- ,) "$'% 11: ¬isEnumerizableContext (α, αctxt ) then -%!)-if!02#(30 !0) (*) #9 2)")+!"#$ %$- +(*!#1 +&%** &#%-)41
  • 207. α '%2"%,&)/ !)&-/ 1)!0#- αctxt 30"+$5+ "$ 40"+0 α 1%. Enumerization Approach #++(2 !"#$%& '( !)%*+,"-* .)/+/").( function Enumerizable(C)P) Abstract Syntax Tree (AST) .',/&4$'& Enumerize(F, R ← Enumerizable(F ) 1: >AW ← C /* seed the worklist with the input constants */ 2: QAN ← ∅ /* the non-enumerizable set ∩ Consistent(R) */ R ← U nique(R) ∩ Distinct(R) list, initially empty 3: GAfor all c T ∈ R 4, 5,' *22 ∈ C do T ransf orm(T ) 4: RA MakeSet(c) /* init the union-find data structure */ ?A &#4 5,' 5: end for 6: while W = ∅ do !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*( 7: /* remove an element from the worklist */ α ← e | ∈ %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+% 2)9%+!#2"$37 eM)W 8: W ← W {α} "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. - 9: 6)$-)$! 62#32%1 Contexts(α, P) do 10: for all αctxt ∈ )$!"!")*7 O0"* %**(16!"#$ +#(&- ,) "$'% 11: ¬isEnumerizableContext (α, αctxt ) then -%!)-if!02#(30 !0) (*) #9 2)")+!"#$ %$- +(*!#1 +&%** &#%-)41
  • 208. α '%2"%,&)/ !)&-/ 1)!0#- αctxt 30"+$5+ "$ 40"+0 α 1%. Enumerization Approach #++(2 !"#$%& '( !)%*+,"-* .)/+/").( function Enumerizable(C)P) .',/&4$'& Enumerize(F, Output: C /* seed the worklist with the input constants */ R← 1: >AW ← Enumerizable(F ) 2: QAN ← ∅ /* the non-enumerizable set ∩ Consistent(R) */ R ← U nique(R) ∩ Distinct(R) list, initially empty 3: GAfor all c T ∈ R 4, 5,' *22 ∈ C do T ransf orm(T ) 4: RA MakeSet(c) /* init the union-find data structure */ ?A &#4 5,' 5: end for 6: while W = ∅ do !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*( 7: /* remove an element from the worklist */ α ← e | ∈ %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+% 2)9%+!#2"$37 eM)W 8: W ← W {α} "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. - 9: 6)$-)$! 62#32%1 Contexts(α, P) do 10: for all αctxt ∈ )$!"!")*7 O0"* %**(16!"#$ +#(&- ,) "$'% 11: ¬isEnumerizableContext (α, αctxt ) then -%!)-if!02#(30 !0) (*) #9 2)")+!"#$ %$- +(*!#1 +&%** &#%-)41
  • 209. α '%2"%,&)/ !)&-/ 1)!0#- αctxt 30"+$5+ "$ 40"+0 α 1%. Enumerization Approach #++(2 !"#$%& '( !)%*+,"-* .)/+/").( function Enumerizable(C)P) .',/&4$'& Enumerize(F, Output: C /* seed the worklist with the input constants */ R← 1: >AW ← Enumerizable(F ) •2: QAN ← ∅U nique(R) ∩ Distinct(R) ∩ Consistent(R) */ Partitioning of program entities: list, initially empty R ← /* the non-enumerizable set 3: GAfor all c T ∈ R 4, 5,' *22 ∈ C do • Fields T ransf orm(T ) 4: RA MakeSet(c) /* init the union-find data structure */ 5: • end for declarations (return types) ?A Method &#4 5,' 6:• while W = ∅ do (including formal parameters) Local variables !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*( 7: /* remove an element from the worklist */ α ← e | ∈ %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+% 2)9%+!#2"$37 eM)W 8: W ← W {α} "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. - 9: 6)$-)$! 62#32%1 Contexts(α, P) do 10: for all αctxt ∈ )$!"!")*7 O0"* %**(16!"#$ +#(&- ,) "$'% 11: ¬isEnumerizableContext (α, αctxt ) then -%!)-if!02#(30 !0) (*) #9 2)")+!"#$ %$- +(*!#1 +&%** &#%-)41
  • 210. α '%2"%,&)/ !)&-/ 1)!0#- αctxt 30"+$5+ "$ 40"+0 α 1%. Enumerization Approach #++(2 !"#$%& '( !)%*+,"-* .)/+/").( function Enumerizable(C)P) .',/&4$'& Enumerize(F, Output: C /* seed the worklist with the input constants */ R← 1: >AW ← Enumerizable(F ) •2: QAN ← ∅U nique(R) ∩ Distinct(R) ∩ Consistent(R) */ Partitioning of program entities: list, initially empty R ← /* the non-enumerizable set 3: GAfor all c T ∈ R 4, 5,' *22 ∈ C do • Fields T ransf orm(T ) 4: RA MakeSet(c) /* init the union-find data structure */ 5: • end for declarations (return types) ?A Method &#4 5,' 6:• while W = ∅ do (including formal parameters) Local variables !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*( /* remove an element from the worklist */ • Each partition contains elements that: 7: α ← e | ∈ %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+% 2)9%+!#2"$37 eM)W 8: • Transitively type-dependent upon one another W ← W {α} "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. - 9: 10:• Are all αctxt ∈ Contexts(α, P) do 6)$-)$!safe for enum type transformation +#(&- ,) "$'% for 62#32%1 )$!"!")*7 O0"* %**(16!"#$ 11: ¬isEnumerizableContext (α, αctxt ) then -%!)-if!02#(30 !0) (*) #9 2)")+!"#$ %$- +(*!#1 +&%** &#%-) 41
  • 211. 42
  • 212. DECREASE_SPEED IDLE STOP INCREASE_SPEED GREEN RED YELLOW MAX_SPEED 42
  • 213. DECREASE_SPEED IDLE STOP INCREASE_SPEED GREEN RED class 1 YELLOW TrafficSignal { MAX_SPEED 2 public enum Color {RED, 3 YELLOW, 4 GREEN}; 5 /* Current color of the traffic signal, initially red by default */ 6 private Color color = Color.RED; 7 /* Accessor for the light’s current color */ 8 public Color getColor() {return this.color; 9 42 10 class Automobile {
  • 214. DECREASE_SPEED IDLE STOP INCREASE_SPEED GREEN RED color class 1 YELLOW TrafficSignal { MAX_SPEED 2 public enum Color {RED, 3 YELLOW, 4 GREEN}; 5 /* Current color of the traffic signal, initially red by default */ 6 private Color color = Color.RED; 7 /* Accessor for the light’s current color */ 8 public Color getColor() {return this.color; 9 42 10 class Automobile {
  • 215. DECREASE_SPEED IDLE STOP INCREASE_SPEED GREEN RED 1 class TrafficSignal color { 2 public enum Color {RED, 3 YELLOW, YELLOW MAX_SPEED 4 GREEN}; 5 /* Current color of the traffic signal, initially red by default */ 6 private Color color = Color.RED; 7 /* Accessor for the light’s current color */ 8 public Color getColor() {return this.color;}} 9 0 class Automobile { 1 private enum Action {IDLE, 42 2 INCREASE_SPEED,
  • 216. DECREASE_SPEED IDLE STOP INCREASE_SPEED GREEN RED 1 class TrafficSignal color { 2 public enum Color {RED, 3 YELLOW, YELLOW MAX_SPEED getColor 4 GREEN}; 5 /* Current color of the traffic signal, initially red by default */ 6 private Color color = Color.RED; 7 /* Accessor for the light’s current color */ 8 public Color getColor() {return this.color;}} 9 0 class Automobile { 1 private enum Action {IDLE, 42 2 INCREASE_SPEED,
  • 217. 78 private int the light’s current color ∗/ /∗ Accessor for color = RED; 89 /∗ Accessorintthe light’s current {return this.color;}} public for getColor() color ∗/ IDLE STOP DECREASE_SPEED 910 public int getColor() {return this.color;}} 1011 class Automobile { 1112 class Automobile {final int IDLE = 0; private static 1213 private static final int IDLE INCREASE_SPEED= 1; private static final int INCREASE_SPEED = 0; 1314 private static final int INCREASE_SPEED ==1; GREENprivate static final int DECREASE_SPEED 2; 1415 private static RED private staticfinal int DECREASE_SPEED = 2; final int STOP = 3; 1516 private static final int STOP = 3; = 140; private static final int MAX_SPEED 1617 private static final int MAX_SPEED = 140; defa /∗ The action this automobile is currently performing, idle by 1718 private color /∗ The action int automobile is currently performing, idle by defaul this currentAction = IDLE; 1819 private intspeed of the automobile, initially 5 mph. ∗/ /∗ The current currentAction = IDLE; YELLOW MAX_SPEED 1920 /∗ The current speedgetColor private int currentSpeed =initially 5 mph. ∗/ of the automobile, 5; 2021 private int currentSpeed = 5; 2122 private int react(TrafficSignal signal) { 2223 private int react(TrafficSignal signal) { switch(signal.getColor()) { 2324 switch(signal.getColor()) {return STOP; case TrafficSignal.RED: 2425 case TrafficSignal.RED: return STOP; case TrafficSignal.YELLOW: 2526 case decide whether to stop or go // TrafficSignal.YELLOW: 2627 // if (this.shouldGo()) decide whether to stop or go 2728 if (this.shouldGo()) return INCREASE_SPEED; 42
  • 218. 78 private int the light’s current color ∗/ /∗ Accessor for color = RED; 89 /∗ Accessorintthe light’s current {return this.color;}} public for getColor() color ∗/ IDLE STOP DECREASE_SPEED 910 public int getColor() {return this.color;}} 1011 class Automobile { 1112 class Automobile {final int IDLE = 0; private static 1213 private static final int IDLE INCREASE_SPEED= 1; private static final int INCREASE_SPEED YELLOW = 0; 1314 private static final int INCREASE_SPEED ==1; GREENprivate static final int DECREASE_SPEED 2; 1415 private static RED private staticfinal int DECREASE_SPEED = 2; final int STOP = 3; 1516 private static final int STOP = 3; = 140; private static final int MAX_SPEED 1617 private static final int MAX_SPEED = 140; defa /∗ The action this automobile is currently performing, idle by 1718 private color /∗ The action int automobile is currently performing, idle by defaul this currentAction = IDLE; 1819 private intspeed of the automobile, initially 5 mph. ∗/ /∗ The current currentAction = IDLE; MAX_SPEED 1920 /∗ The current speedgetColor private int currentSpeed =initially 5 mph. ∗/ of the automobile, 5; 2021 private int currentSpeed = 5; 2122 private int react(TrafficSignal signal) { 2223 private int react(TrafficSignal signal) { switch(signal.getColor()) { 2324 switch(signal.getColor()) {return STOP; case TrafficSignal.RED: 2425 case TrafficSignal.RED: return STOP; case TrafficSignal.YELLOW: 2526 case decide whether to stop or go // TrafficSignal.YELLOW: 2627 // if (this.shouldGo()) decide whether to stop or go 2728 if (this.shouldGo()) return INCREASE_SPEED; 42
  • 219. 7 13private int static = RED; int INCREASE_SPEED = private color final 8 14 /∗ Accessor for the light’s current color ∗/ DECREASE_SPEED = private static final int IDLE STOP DECREASE_SPEED 9 15 public int getColor() {return this.color;}} private static final int STOP = 3; 10 16 private static final int MAX_SPEED = 140; 11 class /∗ The action this automobile is currently performing, idle by d 17 Automobile { 12 18 private static final int IDLE = IDLE; private int currentAction INCREASE_SPEED YELLOW = 0; 13 19 private static final int INCREASE_SPEED = ∗/ GREEN /∗ The current speed of the automobile, initially 5 mph. 1; 14 20 private static RED private int final int DECREASE_SPEED = 2; currentSpeed = 5; 15 21 private static final int STOP = 3; 16 22 private static final int MAX_SPEED = 140; private int react(TrafficSignal signal) { 17 23 color /∗ The action this automobile is currently performing, idle by defaul switch(signal.getColor()) { 18 24 private case currentAction = IDLE; int TrafficSignal.RED: return STOP; MAX_SPEED 19 25 /∗ The current speedgetColor case TrafficSignal.YELLOW: mph. ∗/ of the automobile, initially 5 20 26 private intdecide whether to stop or go // currentSpeed = 5; 21 27 if (this.shouldGo()) 22 28 private int return INCREASE_SPEED; react(TrafficSignal signal) { 23 29 switch(signal.getColor()) { else return STOP; 24 30 case TrafficSignal.RED: return no change case TrafficSignal.GREEN: // STOP; 25 31 case TrafficSignal.YELLOW: return this.currentAction; 26 32 // decide whether to stop new IllegalArgumentExce default: throw or go 27 33 if (this.shouldGo()) color");}} // required ("Invalid traffic 42
  • 220. 7 13private int static = RED; int INCREASE_SPEED = private color final 8 14 /∗ Accessor for the light’s current color ∗/ DECREASE_SPEED = private static final int IDLE STOP DECREASE_SPEED 9 15 public int getColor() {return this.color;}} private static final int STOP = 3; 10 16 private static final int MAX_SPEED = 140; 11 class /∗ The action this automobile is currently performing, idle by d 17 Automobile { 12 18 private static final int IDLE = IDLE; private int currentAction INCREASE_SPEED YELLOW = 0; 13 19 private static final int INCREASE_SPEED = ∗/ /∗ The current speed of the automobile, initially 5 mph. 1; 14 20 private static RED private int final int DECREASE_SPEED = 2; currentSpeed = 5; 15 21 private static final int STOP = 3; 16 22 private static final int MAX_SPEED = 140; private int react(TrafficSignal signal) { GREEN 17 23 color /∗ The action this automobile is currently performing, idle by defaul switch(signal.getColor()) { 18 24 private case currentAction = IDLE; int TrafficSignal.RED: return STOP; MAX_SPEED 19 25 /∗ The current speedgetColor case TrafficSignal.YELLOW: mph. ∗/ of the automobile, initially 5 20 26 private intdecide whether to stop or go // currentSpeed = 5; 21 27 if (this.shouldGo()) 22 28 private int return INCREASE_SPEED; react(TrafficSignal signal) { 23 29 switch(signal.getColor()) { else return STOP; 24 30 case TrafficSignal.RED: return no change case TrafficSignal.GREEN: // STOP; 25 31 case TrafficSignal.YELLOW: return this.currentAction; 26 32 // decide whether to stop new IllegalArgumentExce default: throw or go 27 33 if (this.shouldGo()) color");}} // required ("Invalid traffic 42
  • 221. 2 public static final int RED = 0; DECREASE_SPEED static final int RED_YELLOW = 1; 3 public IDLE STOP 4 public static final int YELLOW = 2; 5 public static final int GREEN = 3; 6 /∗ Current color of the traffic signal, initially red by default ∗/ YELLOW = RED; INCREASE_SPEED 7 private int color 8 /∗ Accessor for the light’s current color ∗/ 9 RED public int getColor() {return this.color;}} 10 11 class Automobile { GREEN color 12 private static final int IDLE = 0; 13 private static final int INCREASE_SPEED = 1 MAX_SPEED getColor 14 private static final int DECREASE_SPEED = 2 15 private static final int STOP = 3; 16 private static final int MAX_SPEED = 140; 17 /∗ The action this automobile is currently performing, idle by de 18 private int currentAction = IDLE; 19 /∗ The current speed of the automobile, initially 5 mph. ∗/ 20 private int currentSpeed = 5; 21 42
  • 222. 2 public static final int RED = 0; DECREASE_SPEED static final int RED_YELLOW = 1; 3 public IDLE currentAction STOP 4 public static final int YELLOW = 2; 5 public static final int GREEN = 3; 6 /∗ Current color of the traffic signal, initially red by default ∗/ YELLOW = RED; INCREASE_SPEED 7 private int color 8 /∗ Accessor for the light’s current color ∗/ 9 RED public int getColor() {return this.color;}} 10 11 class Automobile { GREEN color 12 private static final int IDLE = 0; 13 private static final int INCREASE_SPEED = 1 MAX_SPEED getColor 14 private static final int DECREASE_SPEED = 2 15 private static final int STOP = 3; 16 private static final int MAX_SPEED = 140; 17 /∗ The action this automobile is currently performing, idle by de 18 private int currentAction = IDLE; 19 /∗ The current speed of the automobile, initially 5 mph. ∗/ 20 private int currentSpeed = 5; 21 42
  • 223. l RED; signal) { 23 25 case TrafficSignal.RE public int getColor() {return this.color;}} privateorC // decide whether to stop 6 turn STOP; 7class Automobile color = RED; private int { 22 switch(signal.getColor( 24 26 7 /* Accessor f case (this.shouldGo() if TrafficSignal.YE urrent colorAccessor for thefinal currentIDLE ∗/ 0; // decide whether to stop or 8 /∗ ∗/ private static light’s int color currentAction 23 IDLE 25 = casereturn Action.INC TrafficSignal.RE STOP turnDECREASE_SPEED{ STOP; lass Automobile 27 8 public Co () private static final int {return case (this.shouldGo() {return this.color;}} 24 9 private static final int 26 INCREASE_SPEED = 1; Action. public int getColor()28 if TrafficSignal.YE this.color;}} IDLE = 0; else return to stop or 25 9 // decide whether 10 private static final int 27 DECREASE_SPEED = 2; private static final int 29 casereturn Action.INC TrafficSignal.GR class Autom INCREASE_SPEED(this.shouldGo() 10 = 1; // no private static final int STOP = 3; if change 26 else return Action. 11 private static final int 28 class Automobile { 30 return this.current n; int IDLE = 0; l private static final int 27 return private e DECREASE_SPEED = 2; Action.INC 11 INCREASE_SPEED private static final 31 // no change ArgumentException YELLOW 12 private static final int 29 MAX_SPEED 0; 12int IDLE case TrafficSignal.GR = 140; STOP = 3; default: throwAction. = else return INCREAS new Il l intThe action this automobile 1; 28 13 private static final= int 32 INCREASE_SPEED /∗ //private static final 30 return this.current is currentlyINCREASE_SPEEDdefault ∗/ int performing, idle by =traffic c ("Invalid 1; n; );}} required MAX_SPEED case 13 29 = 140; throw new Il default: DECREAS TrafficSignal.GR 14 /∗ Theprivate automobile = currently = DECREASE_SPEED = 2; l int DECREASE_SPEED final 31 ArgumentException static is 2; 33 performing, returndefault ∗/ // no private int currentAction change action this 3; RED int IDLE; idle by this.current 30 14 STOP}; n; intThe current static final 34 l /∗ required = STOP 32 ("Invalid traffic c 15 private int speed of the automobile, initially default:drive()new Il );}} //private currentAction31= IDLE; = mph. ∗/ throw { public void int STOP 5 3; 15 private s 33 16 /∗ Theprivate GREEN 140; color initially 5 mph. ∗/ = 140;traffic c ArgumentException = l int MAX_SPEEDcurrentSpeed = 5; TrafficSignal aSignal = static final 35 private int of the automobile, int MAX_SPEED 16 drive() { ; current speed );}} ///∗ The action this automobile is ∗/ required 32 34 public("Invalid /* The this. void action 17 private performing, idle by defaultcurrently performing, idle by default ∗/ A e is currently 36 Action reaction = ignal); Action && IDLE; = int currentSpeed 33 5; = 35 37 ; private int react(TrafficSignal signal) drive() { if (reaction private = 17 TrafficSignal!= this.cu aSignal Actionprivate int currentAction = IDLE;void { /* The this. public (reaction != curren 18 34 36 Action 18 MAX_SPEED=Action reaction automobile,The currentmph. ∗/ the automobile, initially 5 mph. ∗/ aSignal = EED ||/∗ initially 5 speed of ignal); 38 getColor switch(signal.getColor()) { TrafficSignal!= this.cu 19 private int react(TrafficSignal signal) { 35 ; 37 39 if (reaction private i 19 this.currentSpeed X_SPEED))5; TrafficSignal.RED: = 5; Speed =case Actionprivate int currentSpeed return STOP; 20 && 36 Action 20 (reaction !==Action reaction this. EED switch(signal.getColor()) { ignal); 38 40 this.performActio 21 || case TrafficSignal.YELLOW: if (reaction != this.cu ction);} 37 Action && TrafficSignal.RED: return STOP; case 39 41 this.currentSpeedA 21 private X_SPEED)) // decide whether to stop or go rafficSignal signal) { 22 EED || private int react(TrafficSignal (reaction{!= Action 38 40 signal) case{ TrafficSignal.YELLOW: privatethis.currentSpeed 42 this.performActio 22 switch( void performActio ction);} {...}} Color()) if (this.shouldGo()) 23action)// decide whether to stop or go X_SPEED)) switch(signal.getColor()) { 39 41 (b) Improvements afte 23 case nal.RED: return STOP; ction);}if case TrafficSignal.RED: 24 (this.shouldGo()) 40 42 private this.performActio return INCREASE_SPEED; return 24STOP; void performActiocase oraction) {...}} enumerated types. nal.YELLOW: (b) Improvements // de afte 25 else return STOP; 41 case TrafficSignal.YELLOW: return INCREASE_SPEED; private void performActio 25 o stop or gocase //TrafficSignal.GREEN: // no change oraction)else return STOP; stop or go 26 enumerated types. {...}} decide whether to 42 if ldGo()) example: a hypothetical drive-by-wire applica unning return this.currentAction; (b) Improvements afte 26 27 if (this.shouldGo())// no change 27 case TrafficSignal.GREEN: 42 r
  • 224. l RED; signal) { 23 25 case TrafficSignal.RE public int getColor() {return this.color;}} privateorC // decide whether to stop 6 turn STOP; 7class Automobile color = RED; private int { 22 switch(signal.getColor( 24 26 7 /* Accessor f case (this.shouldGo() if TrafficSignal.YE urrent colorAccessor for thefinal currentIDLE ∗/ 0; // decide whether to stop or 8 /∗ ∗/ private static light’s int color currentAction 23 IDLE 25 = casereturn Action.INC TrafficSignal.RE STOP turnDECREASE_SPEED{ STOP; lass Automobile 27 8 public Co () private static final int {return case (this.shouldGo() {return this.color;}} 24 9 private static final int 26 INCREASE_SPEED = 1; Action. public int getColor()28 if TrafficSignal.YE this.color;}} IDLE = 0; else return to stop or 25 9 // decide whether 10 private static final int 27 DECREASE_SPEED = 2; private static final int 29 casereturn Action.INC TrafficSignal.GR class Autom INCREASE_SPEED(this.shouldGo() 10 = 1; // no private static final int STOP = 3; if change 26 else return Action. 11 private static final int 28 class Automobile { 30 return this.current n; int IDLE = 0; l private static final int 27 return private e DECREASE_SPEED = 2; Action.INC 11 INCREASE_SPEED private static final 31 // no change ArgumentException YELLOW 12 private static final int 29 MAX_SPEED 0; 12int IDLE case TrafficSignal.GR = 140; STOP = 3; default: throwAction. = else return INCREAS new Il l intThe action this automobile 1; 28 13 private static final= int 32 INCREASE_SPEED /∗ //private static final 30 return this.current is currentlyINCREASE_SPEEDdefault ∗/ int performing, idle by =traffic c ("Invalid 1; n; );}} required MAX_SPEED case 13 29 = 140; throw new Il default: DECREAS TrafficSignal.GR 14 /∗ Theprivate automobile = currently = DECREASE_SPEED = 2; l int DECREASE_SPEED final 31 ArgumentException static is 2; 33 performing, returndefault ∗/ // no private int currentAction change action this 3; RED int IDLE; idle by this.current 30 14 STOP}; n; intThe current static final 34 l /∗ required = STOP 32 ("Invalid traffic c 15 private int speed of the automobile, initially default:drive()new Il );}} //private currentAction31= IDLE; = mph. ∗/ throw { public void int STOP 5 3; 15 private s 33 16 /∗ Theprivate GREEN 140; color initially 5 mph. ∗/ = 140;traffic c ArgumentException = l int MAX_SPEEDcurrentSpeed = 5; TrafficSignal aSignal = static final 35 private int of the automobile, int MAX_SPEED 16 drive() { ; current speed );}} ///∗ The action this automobile is ∗/ required 32 34 public("Invalid /* The this. void action 17 private performing, idle by defaultcurrently performing, idle by default ∗/ A e is currently 36 Action reaction = ignal); Action && IDLE; = int currentSpeed 33 5; = 35 37 ; private int react(TrafficSignal signal) drive() { if (reaction private = 17 TrafficSignal!= this.cu aSignal Actionprivate int currentAction = IDLE;void { /* The this. public (reaction != curren 18 34 36 Action 18 MAX_SPEED=Action reaction automobile,The currentmph. ∗/ the automobile, initially 5 mph. ∗/ aSignal = EED ||/∗ initially 5 speed of ignal); 38 getColor switch(signal.getColor()) { TrafficSignal!= this.cu 19 private int react(TrafficSignal signal) { 35 ; 37 39 if (reaction private i 19 this.currentSpeed X_SPEED))5; TrafficSignal.RED: = 5; Speed =case Actionprivate int currentSpeed return STOP; 20 && 36 Action 20 (reaction !==Action reaction this. EED switch(signal.getColor()) { ignal); 38 40 this.performActio 21 || case TrafficSignal.YELLOW: if (reaction != this.cu ction);} 37 Action && TrafficSignal.RED: return STOP; case 39 41 this.currentSpeedA 21 private X_SPEED)) // decide whether to stop or go rafficSignal signal) { 22 EED || private int react(TrafficSignal (reaction{!= Action 38 40 signal) case{ TrafficSignal.YELLOW: privatethis.currentSpeed 42 this.performActio 22 switch( void performActio ction);} {...}} Color()) if (this.shouldGo()) 23action)// decide whether to stop or go X_SPEED)) switch(signal.getColor()) { 39 41 (b) Improvements afte 23 case nal.RED: return STOP; ction);}if case TrafficSignal.RED: 24 (this.shouldGo()) 40 42 private this.performActio return INCREASE_SPEED; return 24STOP; void performActiocase oraction) {...}} enumerated types. nal.YELLOW: (b) Improvements // de afte 25 else return STOP; 41 case TrafficSignal.YELLOW: return INCREASE_SPEED; private void performActio 25 o stop or gocase //TrafficSignal.GREEN: // no change oraction)else return STOP; stop or go 26 enumerated types. {...}} decide whether to 42 if ldGo()) example: a hypothetical drive-by-wire applica unning return this.currentAction; (b) Improvements afte 26 27 if (this.shouldGo())// no change 27 case TrafficSignal.GREEN: 42 r
  • 225. l RED; signal) { 23 25 case TrafficSignal.RE public int getColor() {return this.color;}} privateorC // decide whether to stop 6 turn STOP; 7class Automobile color = RED; private int { 22 switch(signal.getColor( 24 26 7 /* Accessor f case (this.shouldGo() if TrafficSignal.YE urrent colorAccessor for thefinal currentIDLE ∗/ 0; // decide whether to stop or 8 /∗ ∗/ private static light’s int color currentAction 23 IDLE 25 = casereturn Action.INC TrafficSignal.RE turnDECREASE_SPEED{ lass STOP; this.color;}} 27 Automobile 8 public Co () private static final int {return case (this.shouldGo() {return int getColor()24 9 private static final int 26 INCREASE_SPEED = 1; Action. public if TrafficSignal.YE this.color;}} IDLE = 0; else return to stop or 28 9 private static final int 27 DECREASE_SPEED whether 25 // decide STOP casereturn 2; Action.INC 10 private static final int 29 INCREASE_SPEED 10 = = TrafficSignal.GR class Autom 1; // no private static final int STOP = 3; if (this.shouldGo() change 26 else return Action. 11 private static final int 28 class Automobile { 30 return this.current n; int IDLE = 0; l private static final int 27 return private e DECREASE_SPEED = 2; Action.INC 11 INCREASE_SPEED private static final 31 // no change ArgumentException YELLOW 12 private static final int 29 MAX_SPEED 0; 12int IDLE case TrafficSignal.GR = 140; STOP = 3; default: throwAction. = else return INCREAS new Il l intThe action this automobile 1; 28 13 private static final= int 32 INCREASE_SPEED /∗ //private static final 30 return this.current is currentlyINCREASE_SPEEDdefault ∗/ int performing, idle by =traffic c ("Invalid 1; n; );}} required MAX_SPEED case 13 29 = 140; throw new Il default: DECREAS TrafficSignal.GR 14 /∗ Theprivate automobile = currently = DECREASE_SPEED = 2; l int DECREASE_SPEED final 31 ArgumentException static is 2; 33 performing, returndefault ∗/ // no private int currentAction change action this 3; RED int IDLE; idle by this.current 30 14 STOP}; n; intThe current static final 34 l /∗ required = STOP 32 ("Invalid traffic c 15 private int speed of the automobile, initially default:drive()new Il );}} //private currentAction31= IDLE; = mph. ∗/ throw { public void int STOP 5 3; 15 private s 33 16 /∗ Theprivate GREEN 140; color initially 5 mph. ∗/ = 140;traffic c ArgumentException = l int MAX_SPEEDcurrentSpeed = 5; TrafficSignal aSignal = static final 35 private int of the automobile, int MAX_SPEED 16 drive() { ; current speed );}} ///∗ The action this automobile is ∗/ required 32 34 public("Invalid /* The this. void action 17 private performing, idle by defaultcurrently performing, idle by default ∗/ A e is currently 36 Action reaction = ignal); Action && IDLE; = int currentSpeed 33 5; = 35 37 ; private int react(TrafficSignal signal) drive() { if (reaction private = 17 TrafficSignal!= this.cu aSignal Actionprivate int currentAction = IDLE;void { /* The this. public (reaction != curren 18 34 36 Action 18 MAX_SPEED=Action reaction automobile,The currentmph. ∗/ the automobile, initially 5 mph. ∗/ aSignal = EED ||/∗ initially 5 speed of ignal); 38 getColor switch(signal.getColor()) { TrafficSignal!= this.cu 19 private int react(TrafficSignal signal) { 35 ; 37 39 if (reaction private i 19 this.currentSpeed X_SPEED))5; TrafficSignal.RED: = 5; Speed =case Actionprivate int currentSpeed return STOP; 20 && 36 Action 20 (reaction !==Action reaction this. EED switch(signal.getColor()) { ignal); 38 40 this.performActio 21 || case TrafficSignal.YELLOW: if (reaction != this.cu ction);} 37 Action && TrafficSignal.RED: return STOP; case 39 41 this.currentSpeedA 21 private X_SPEED)) // decide whether to stop or go rafficSignal signal) { 22 EED || private int react(TrafficSignal (reaction{!= Action 38 40 signal) case{ TrafficSignal.YELLOW: privatethis.currentSpeed 42 this.performActio 22 switch( void performActio ction);} {...}} Color()) if (this.shouldGo()) 23action)// decide whether to stop or go X_SPEED)) switch(signal.getColor()) { 39 41 (b) Improvements afte 23 case nal.RED: return STOP; ction);}if case TrafficSignal.RED: 24 (this.shouldGo()) 40 42 private this.performActio return INCREASE_SPEED; return 24STOP; void performActiocase oraction) {...}} enumerated types. nal.YELLOW: (b) Improvements // de afte 25 else return STOP; 41 case TrafficSignal.YELLOW: return INCREASE_SPEED; private void performActio 25 o stop or gocase //TrafficSignal.GREEN: // no change oraction)else return STOP; stop or go 26 enumerated types. {...}} decide whether to 42 if ldGo()) example: a hypothetical drive-by-wire applica unning return this.currentAction; (b) Improvements afte 26 27 if (this.shouldGo())// no change 27 case TrafficSignal.GREEN: 42 r
  • 226. l RED; signal) { 23 25 case TrafficSignal.RE public int getColor() {return this.color;}} privateorC // decide whether to stop 6 turn STOP; 7class Automobile color = RED; private int { 22 switch(signal.getColor( 24 26 7 /* Accessor f case (this.shouldGo() if TrafficSignal.YE urrent colorAccessor for thefinal currentIDLE ∗/ 0; // decide whether to stop or 8 /∗ ∗/ private static light’s int color currentAction 23 IDLE 25 = casereturn Action.INC TrafficSignal.RE turnDECREASE_SPEED{ lass STOP; this.color;}} 27 Automobile 8 public Co () private static final int {return case (this.shouldGo() {return int getColor()24 9 private static final int 26 INCREASE_SPEED = 1; Action. public if TrafficSignal.YE this.color;}} IDLE = 0; else return to stop or 28 9 private static final int 27 DECREASE_SPEED whether 25 // decide STOP casereturn 2; Action.INC 10 private static final int 29 INCREASE_SPEED 10 = = TrafficSignal.GR class Autom 1; // no private static final int STOP = 3; if (this.shouldGo() change 26 else return Action. 11 private static final int 28 class Automobile { 30 return this.current n; int IDLE = 0; l private static final int 27 return private e DECREASE_SPEED = 2; Action.INC 11 INCREASE_SPEED private static final 31 // no change ArgumentException YELLOW 12 private static final int 29 MAX_SPEED 0; 12int IDLE case TrafficSignal.GR = 140; STOP = 3; default: throwAction. = else return INCREAS new Il l intThe action this automobile 1; 28 13 private static final= int 32 INCREASE_SPEED /∗ //private static final 30 return this.current is currentlyINCREASE_SPEEDdefault ∗/ int performing, idle by =traffic c ("Invalid 1; n; );}} required MAX_SPEED case 13 react DECREAS 29 = 140; TrafficSignal.GR default: throw new Il 14 /∗ Theprivate automobile = currently = DECREASE_SPEED = 2; l int DECREASE_SPEED final 33 static is 2; 30 performing, returndefault ∗/ // no private int currentAction change 31 ArgumentException action this 3; RED int IDLE; idle by this.current 14 STOP}; n; intThe current static final 34 l /∗ required = STOP 32 ("Invalid traffic c 15 private int speed of the automobile, initially default:drive()new Il );}} //private currentAction31= IDLE; = mph. ∗/ throw { public void int STOP 5 3; 15 private s 33 16 /∗ Theprivate GREEN 140; color initially 5 mph. ∗/ = 140;traffic c ArgumentException = l int MAX_SPEEDcurrentSpeed = 5; TrafficSignal aSignal = static final 35 private int of the automobile, int MAX_SPEED 16 drive() { ; current speed );}} ///∗ The action this automobile is ∗/ required 32 34 public("Invalid /* The this. void action 17 private performing, idle by defaultcurrently performing, idle by default ∗/ A e is currently 36 Action reaction = ignal); Action && IDLE; = int currentSpeed 33 5; = 35 37 ; private int react(TrafficSignal signal) drive() { if (reaction private = 17 TrafficSignal!= this.cu aSignal Actionprivate int currentAction = IDLE;void { /* The this. public (reaction != curren 18 34 36 Action 18 MAX_SPEED=Action reaction automobile,The currentmph. ∗/ the automobile, initially 5 mph. ∗/ aSignal = EED ||/∗ initially 5 speed of ignal); 38 getColor switch(signal.getColor()) { TrafficSignal!= this.cu 19 private int react(TrafficSignal signal) { 35 ; 37 39 if (reaction private i 19 this.currentSpeed X_SPEED))5; TrafficSignal.RED: = 5; Speed =case Actionprivate int currentSpeed return STOP; 20 && 36 Action 20 (reaction !==Action reaction this. EED switch(signal.getColor()) { ignal); 38 40 this.performActio 21 || case TrafficSignal.YELLOW: if (reaction != this.cu ction);} 37 Action && TrafficSignal.RED: return STOP; case 39 41 this.currentSpeedA 21 private X_SPEED)) // decide whether to stop or go rafficSignal signal) { 22 EED || private int react(TrafficSignal (reaction{!= Action 38 40 signal) case{ TrafficSignal.YELLOW: privatethis.currentSpeed 42 this.performActio 22 switch( void performActio ction);} {...}} Color()) if (this.shouldGo()) 23action)// decide whether to stop or go X_SPEED)) switch(signal.getColor()) { 39 41 (b) Improvements afte 23 case nal.RED: return STOP; ction);}if case TrafficSignal.RED: 24 (this.shouldGo()) 40 42 private this.performActio return INCREASE_SPEED; return 24STOP; void performActiocase oraction) {...}} enumerated types. nal.YELLOW: (b) Improvements // de afte 25 else return STOP; 41 case TrafficSignal.YELLOW: return INCREASE_SPEED; private void performActio 25 o stop or gocase //TrafficSignal.GREEN: // no change oraction)else return STOP; stop or go 26 enumerated types. {...}} decide whether to 42 if ldGo()) example: a hypothetical drive-by-wire applica unning return this.currentAction; (b) Improvements afte 26 27 if (this.shouldGo())// no change 27 case TrafficSignal.GREEN: 42 r
  • 227. l RED; signal) { 23 25 case TrafficSignal.RE public int getColor() {return this.color;}} privateorC // decide whether to stop 6 turn STOP; 7class Automobile color = RED; private int { 22 switch(signal.getColor( 24 26 7 /* Accessor f case (this.shouldGo() if TrafficSignal.YE urrent colorAccessor for thefinal currentIDLE ∗/ 0; // decide whether to stop or 8 /∗ ∗/ private static light’s int color = casereturn Action.INC 23 25 TrafficSignal.RE turnDECREASE_SPEED{ lass STOP; this.color;}} 27 Automobile 8 IDLEpublic Co () private static final int {return case (this.shouldGo() {return int getColor()24 9 private static final int 26 INCREASE_SPEED = 1; Action. public if TrafficSignal.YE this.color;}} IDLE = 0; else return to stop or 28 9 private static final int 27 DECREASE_SPEED whether 25 // decide STOP casereturn 2; Action.INC 10 private static final int 29 INCREASE_SPEED 10 = = TrafficSignal.GR class Autom 1; // no private static final int STOP = 3; if (this.shouldGo() change 26 else return Action. 11 private static final int 28 class Automobile { 30 return this.current n; int IDLE = 0; l private static final int 27 return private e DECREASE_SPEED = 2; Action.INC 11 INCREASE_SPEED private static final 31 // no change ArgumentException YELLOW int IDLE case TrafficSignal.GR 12 private static final int 29 MAX_SPEED 0; 12 = 140; STOP = 3; default: throwAction. = else return INCREAS new Il l intThe action this automobile 1; 28 13 private static final= int 32 INCREASE_SPEED /∗ //private static final 30 return this.current is currentlyINCREASE_SPEEDdefault ∗/ int performing, idle by =traffic c ("Invalid 1; n; );}} required MAX_SPEED case 13 react DECREAS 29 = 140; TrafficSignal.GR default: throw new Il 14 /∗ Theprivate automobile = currently = DECREASE_SPEED = 2; l int DECREASE_SPEED final 33 static is 2; 30 performing, returndefault ∗/ // no private int currentAction change 31 ArgumentException action this 3; RED int IDLE; idle by this.current 14 STOP}; n; intThe current static final 34 l /∗ required = STOP 32 ("Invalid traffic c 15 private int speed of the automobile, initially default:drive()new Il );}} //private currentAction31= IDLE; = mph. ∗/ throw { public void int STOP 5 3; 15currentAction private s 33 16 /∗ Theprivate GREEN 140; color initially 5 mph. ∗/ = 140;traffic c ArgumentException = l int MAX_SPEEDcurrentSpeed = 5; TrafficSignal aSignal = static final 35 private int of the automobile, int MAX_SPEED 16 drive() { ; current speed );}} ///∗ The action this automobile is ∗/ required 32 34 public("Invalid /* The this. void action 17 private performing, idle by defaultcurrently performing, idle by default ∗/ A e is currently 36 Action reaction = ignal); Action && IDLE; = int currentSpeed 33 5; = 35 37 ; private int react(TrafficSignal signal) drive() { if (reaction private = 17 TrafficSignal!= this.cu aSignal Actionprivate int currentAction = IDLE;void { /* The this. public (reaction != curren 18 34 36 Action 18 MAX_SPEED=Action reaction automobile,The currentmph. ∗/ the automobile, initially 5 mph. ∗/ aSignal = EED ||/∗ initially 5 speed of ignal); 38 getColor switch(signal.getColor()) { TrafficSignal!= this.cu 19 private int react(TrafficSignal signal) {35 ; 37 39 if (reaction private i 19 this.currentSpeed X_SPEED))5; TrafficSignal.RED: = 5; Speed =case Actionprivate int currentSpeed return STOP; 20 && 36 Action 20 (reaction !==Action reaction this. EED switch(signal.getColor()) { ignal); 38 40 this.performActio 21 || case TrafficSignal.YELLOW: if (reaction != this.cu ction);} 37 Action && TrafficSignal.RED: return STOP; case 39 41 this.currentSpeedA 21 private X_SPEED)) // decide whether to stop or go rafficSignal signal) { 22 EED || private int react(TrafficSignal (reaction{!= Action 38 40 signal) case{ TrafficSignal.YELLOW: privatethis.currentSpeed 42 this.performActio 22 switch( void performActio ction);} {...}} Color()) if (this.shouldGo()) 23action)// decide whether to stop or go X_SPEED)) switch(signal.getColor()) { 39 41 (b) Improvements afte 23 case nal.RED: return STOP; ction);}if case TrafficSignal.RED: 24 (this.shouldGo()) 40 42 private this.performActio return INCREASE_SPEED; return 24STOP; void performActiocase oraction) {...}} enumerated types. nal.YELLOW: (b) Improvements // de afte 25 else return STOP; 41 case TrafficSignal.YELLOW: return INCREASE_SPEED; private void performActio 25 o stop or gocase //TrafficSignal.GREEN: // no change oraction)else return STOP; stop or go 26 enumerated types. {...}} decide whether to 42 if ldGo()) example: a hypothetical drive-by-wire applica unning return this.currentAction; (b) Improvements afte 26 27 if (this.shouldGo())// no change 27 case TrafficSignal.GREEN: 42 r
  • 228. Identifiers Array access/creation expressions Identifiers Conditional expressions Identifiers Array access/creation expressions Identifiers Conditional expressions function XA(α,ID) function XA(α, E XP1 [E XP2 ]) function EA(α,ID) function EA(α, E XP1 ? E XP2 : E XP3 ) function XA(α,ID) function XA(α, E XP1 [E XP2 ]) function EA(α,ID) function EA(α, E XP1 ? E XP2 : E XP3 ) return XA(α, P arent(ID)) 1: 1: return EA(α, P arent(ID)) 1: return XA(α, P arent(ID)) 1: if contains(E XP2 , α) then 1: if contains(E XP2 , α) ∨ contains (E XP3 , α) then 1: if contains(E XP2 , α) then 1: return EA(α, P arent(ID)) 1: if contains(E XP2 , α) ∨ contains (E XP3 , α) then Parenthesized expressions Parenthesized expressions return EA(α, P arent(E XP1 ? E XP2 : E XP3 )) Parenthesized expressions 2: return ∅ Parenthesized expressions 2: return EA(α, P arent(E XP1 ? E XP2 : XA(α,(ID)) 2: return ∅ 2: function E XP3 )) 3: else function EA(α,(ID)) 3: else function XA(α,(ID)) 3: else function EA(α,(ID)) 3: else 1: return XA(α, P arent(ID)) 4: return XA(α, P arent(E XP1 )) 1: return EA(α, P arent(ID)) 4: return true 1: return XA(α, P arent(ID)) 4: return XA(α, P arent(E XP1 )) 1: return EA(α, P arent(ID)) 4: return true 5: end if 5: end if Cast expressions 5: end if Cast expressions 5: end if Cast expressions Cast expressions Array access/creation expressions function XA(α, (T YPE)E XP) Array initialization expressions function EA(α, (T YPE)E XP) Array access/creation expressions function XA(α, (T YPE)E XP) Array initialization expressions function EA(α, (T YPE)E XP) function EA(α, E XP1 [E XP2 ]) 1: return ∅ function XA(α, {E XP1 , . . . , E XPn }) 1: return false function EA(α, E XP1 [E XP2 ]) 1: return ∅ function XA(α, {E XP1 , . . . , E XPn }) 1: return false Field access expressions 1: R ← ∅ 1: if contains(E XP2 , α) then 1: R ← ∅ Field access expressions 1: if contains(E XP2 , α) then Field access expressions 2: for E XPi , 1 ≤ i ≤ n do Field access expressions 2: return false function XA(α, E XP.ID) 2: for E XPi , 1 ≤ i ≤ n do function EA(α, E XP.ID) 2: return false function XA(α, E XP.ID) R ← R ∪ XD(E XPi ) function EA(α, E XP.ID) 3: else 1: return XA(α, P arent(E XP)) 3: 3: R ← R ∪ XD(E XPi ) 1: return EA(α, P arent(E XP)) 3: else 1: return XA(α, P arent(E XP)) 4: end for 1: return EA(α, P arent(E XP)) return EA(α, P arent(E XP1 )) 4: end for 4: return EA(α, P arent(E XP1 )) Assignment expressions 5: return R Assignment expressions 5: end if 4: Assignment expressions Assignment expressions function XA(α,E XP1 = E XP2 ) 5: return R function EA(α,E XP1 = E XP2 ) 5: end if function XA(α,E XP1 = E XP2 ) function EA(α,E XP1 = E XP2 ) Array initialization expressions Return statements Array initialization expressions 1: return XD(E XP1 ) ∪ XD(E XP2 ) Return statements 1: return ED(E XP1 ) ∧ ED(E XP2 ) function EA(α, {E XP1 , . . . , E XPn }) 1: return XD(E XP1 ) ∪ XD(E XP2 ) function XA(α,return E XP) 1: return ED(E XP1 ) ∧ ED(E XP2 ) Subtract assignment expressions function EA(α, {E XP1 , . . . , E XPn }) function XA(α,return E XP) Subtract assignment expressions Subtract assignment expressions 1: return XD(M ethodDecl(return E XP )) Subtract assignment expressions 1: let ie = true function XA(α,E XP1 -= E XP2 ) 1: return XD(M ethodDecl(return E XP )) function EA(α,E XP1 -= E XP2 ) 1: let ie = true function XA(α,E XP1 -= E XP2 ) function EA(α,E XP1 -= E XP2 ) 2: for E XPi , 1 ≤ i ≤ n do Method declaration statements 2: for E XPi , 1 ≤ i ≤ n do 1: return ∅ Method declaration statements 1: return false 3: ie ← ie ∧ ED(E XPi ) 1: return ∅ function XA(α,ID(P 1 , . . . ,P n )) 1: return false 3: ie ← ie ∧ ED(E XPi ) Divide assignment expressions function XA(α,ID(P 1 , . . . ,P n )) Divide assignment expressions 4: end for Divide assignment expressions 1: R ← ∅ Divide assignment expressions 4: end for function XA(α,E XP1 /= E XP2 ) 1: R ← ∅ function EA(α,E XP1 /= E XP2 ) 5: return ie function XA(α,E XP1 /= E XP2 ) 2: for all return E XPr ∈ returnStmts(ID(P 1, . . . , P n )) do function EA(α,E XP1 /= E XP2 ) 5: return ie 2: for all return E XPr ∈ returnStmts(ID(P 1, . . . , P n )) do 1: return ∅ R ← R ∪ XD(E XPr ) 1: return false Return statements 1: return ∅ 3: R ← R ∪ XD(E XPr ) 1: return false Return statements Infix addition expressions 3: function EA(α,return E XP) 4: end for Infix addition expressions function EA(α,return E XP) Infix addition expressions 4: end for Infix addition expressions function XA(α,E XP1 + E XP2 ) 5: return R function EA(α,E XP1 + E XP2 ) 1: return true function XA(α,E XP1 + E XP2 ) 5: return R function EA(α,E XP1 + E XP2 ) 1: return true 1: return ∅ Formal parameters 1: return false Method declaration statements 1: return ∅ Formal parameters 1: return false Method declaration statements Infix multiplication expressions function XA(α,P i ) function EA(α,ID(P 1 , . . . ,P n )) function XA(α,P i ) Infix multiplication expressions Infix multiplication expressions function EA(α,ID(P 1 , . . . ,P n )) function XA(α,Emultiplication expressions Infix XP1 * E XP2 ) 1: R ← ∅ function EA(α,E XP1 * E XP2 ) 1: let re = true function XA(α,E XP1 * E XP2 ) 1: R ← ∅ function EA(α,E XP1 * E XP2 ) 1: let re = true 1: return ∅ 2: /*extract the ith argument of each invocation of the declaring 1: return false 2: for all return E XPr ∈ returnStmts(ID(P 1, . . . , P n )) do 1: return ∅ 2: /*extract the ith argument of each invocation of the declaring 1: return false 2: for all return E XPr ∈ returnStmts(ID(P 1, . . . , P n )) do method*/ 3: re ← re ∧ ED(E XPr ) Prefix unary minus expressions method*/ Prefix unary minus expressions 3: re ← re ∧ ED(E XPr ) Prefix unary minus expressions 3: let α = M ethodDecl(P i ) ˆ Prefix unary minus expressions 4: end for function XA(α,-E XP) 3: let α = M ethodDecl(P i ) ˆ function EA(α,-E XP) 4: end for function XA(α,-E XP) 4: for all αctxt ∈ Invocations(α, P) do ˆ ˆ function EA(α,-E XP) 5: return re 1: return ∅ 4: for all αctxt ∈ Invocations(α, P) do ˆ ˆ 1: return false 5: return re 1: return ∅ 5: R ← R ∪ XD(Arg(αctxt, i)) ˆ 1: return false Formal parameters R ← R ∪ XD(Arg(αctxt, i)) ˆ Postfix increment expressions 5: Postfix increment expressions Formal parameters Postfix increment expressions 6: end for Postfix increment expressions function EA(α,P i ) function XA(α,E XP ++) 6: end for function EA(α,E XP ++) function EA(α,P i ) function XA(α,E XP ++) 7: return R function EA(α,E XP ++) 7: return R 1: let ae = true 1: return ∅ 1: return false 1: let ae = true 1: return ∅ Method invocation expressions 1: return false 2: /*check the ith argument of each invocation of the declaring Equality expressions Method invocation expressions Equality expressions 2: /*check the ith argument of each invocation of the declaring Equality expressions function XA(α,ID(E XP1 , . . . , E XPn )) Equality expressions method*/ function XA(α,E XP1 == E XP2 ) function XA(α,ID(E XP1 , . . . , E XPn )) function EA(α,E XP1 == E XP2 ) method*/ function XA(α,E XP1 == E XP2 ) 1: R ← ∅ function EA(α,E XP1 == E XP2 ) 3: let α = M ethodDecl(P i ) ˆ 1: R ← ∅ 3: let α = M ethodDecl(P i ) ˆ 1: return XD(E XP2 ) ∪ XD(E XP1 ) 2: for E XPi , 1 ≤ i ≤ n do 1: return ED(E XP1 ) ∧ ED(E XP2 ) 4: for all αctxt ∈ Invocations(α, P) do ˆ ˆ 1: return XD(E XP2 ) ∪ XD(E XP1 ) 2: for E XPi , 1 ≤ i ≤ n do 1: return ED(E XP1 ) ∧ ED(E XP2 ) 4: for all αctxt ∈ Invocations(α,Inequality expressions ˆ ˆ P) do Inequality expressions Inequality expressions 3: if contains(E XPi , α) then Inequality expressions 5: ae ← ae ∧ ED(Arg(αctxt, i)) ˆ 3: if contains(E XPi , α) then 5: ae ← ae ∧ ED(Arg(αctxt, i))function XA(α,E XP1 != E XP2 ) ˆ 4: R ← R ∪ XD(E XP1 ) function EA(α,E XP1 != E XP2 ) 6: end for function XA(α,E XP1 != E XP2 ) 4: R ← R ∪ XD(E XP1 ) function EA(α,E XP1 != E XP2 ) 6: end for 1: return XD(E XP1 ) ∪ XD(E XP2 ) 5: end if 1: return ED(E XP1 ) ∧ ED(E XP2 ) 7: return ae 1: return XD(E XP1 ) ∪ XD(E XP2 ) 5: end if 1: return ED(E XP1 ) ∧ ED(E XP2 ) 7: return ae 6: end for Method invocation expressions Switch statements 6: end for Switch statements Method invocation expressions Switch statements 7: if R = ∅ then Switch statements function XA(α, switch(E XP)) 7: if R = ∅ then function EA(α, switch(E EA(α, switch(E XP)) XP)) function EA(α,ID(E XP1 , . . . , E XPn )) function XA(α, switch(E XP)) function function EA(α,ID(E XP1 , . . . , E XPn )) R ← XD(E XP) 8: return R 1: for E XPi , 1 ≤ i ≤ n do 1: 1: R ← XD(E XP) 8: return R 1: let se = ED(E XP) 9: else 1: let se = ED(E XP) 1: for E XPi , 1 ≤ i ≤ n do 2: for all case E XP c ∈ cases(switch(E XP )) do 9: else 2: let ce = true 2: if contains(E XPiif α) then , contains(E XP , α) then 2: for all case E XP c ∈ cases(switch(E XP )) do 10: return XA(α, P arent(ID(E XP1 , . . . , E XPn ))) 2: let ce = true 2: i 3: R ← XD(E XPc ) 10: return XA(α, P arent(ID(E XP1 , . . . , E XPn ))) 3: for all case E XP c ∈ cases(switch(E XP )) do 3: return true3: return true 3: R ← XD(E XPc ) 11: end if 3: for all case E XP c ∈ cases(switch(E XP )) do 4: end for 11: end if 4: ce ← ce ∧ ED(Ece ← ce ∧ ED(E XP ) XPc ) 4: end if end if 4: end for 4: c 4: 5: return R General statements 5: end for 5: end for 5: return R General statements 5: end for 5: end for function XA(α,S MT ) 6: return se ∧ ce 6: return EA(α, P arent(ID(E XP1 , . . . , E XPn ))) Switch case statements function XA(α,S MT ) 6: return se ∧ ce 6: return EA(α, P arent(ID(E XP1 , . . . , E XPnSwitch case statements ))) 1: R ← ∅ General statements function XA(α,case E XP) 1: R ← ∅ Switch case statements case statements General statements function XA(α,case E XP) 2: for E XP ∈ Children(S MT) do Switch 1: return XA(α, switchStmt(case E XP )) 2: for E XP ∈ Children(S MT) do function EA(α,case E XP) EA(α,case E XP) function XA(α,Sfunction XA(α,S MT ) MT ) 1: return XA(α, switchStmt(case E XP )) function 3: R ← R ∪ XD(E XP) 1: return EA(α, switchStmt(case E XP )) 1: let se = true Conditional expressions 3: R ← R ∪ XD(E XP) 1: let se = true Conditional expressions 4: end for 1: return EA(α, switchStmt(case E XP )) 4: end for 2: for E XP ∈ Children(S MT) do function XA(α, E XP1 ? E XP2 : E XP3 ) 2: for E XP ∈ Children(S MT) do function XA(α, E XP1 ? E XP2 : E XP3 ) 5: return R 1: if contains(E XP2 , α) ∨ contains (E XP3 , α) then 5: return R 3: se ← se ∨ED(E XP)← se ∨ED(E XP) se 3: 1: if contains(E XP2 , α) ∨ contains (E XP3 , α) then 4: end for 2: return XA(α, P arent(E XP1 ? E XP2 : E XP3 )) 4: end for 2: return XA(α, P arent(E XP1 ? E XP2 : E XP3 )) 5: return se 3: else 5: return se 3: else 4: return ∅ Figure 7. EnumerizableEnumerizable ascender. return ∅ Figure 7. ascender. 4: 5: end if 12 12 5: end if 10 10 Figure 9. Extraction ascender. Figure 9. Extraction ascender. 43
  • 229. this.currentAction && case TrafficSignal.YELLOW: private int color = RED; 38 (reacti INCREASE_SPEED || /∗ Accessor for the light’s current or go ∗/ Enums vs. Constants // decide whether toDistinction: Algorithmic stop color tSpeed <= MAX_SPEED)) 39 this.c publicif (this.shouldGo()) int getColor() {return this.color;}} 40 this. rmAction(reaction);} return INCREASE_SPEED; 41 else return STOP; 42 private void rmAction(int action) { class Automobile {...}} casestatic final int IDLE = no change TrafficSignal.GREEN: // 0; (b) Im private eger constants for static final int INCREASE_SPEED = 1; private enumerated types. return this.currentAction; default: throw new IllegalArgumentException private static final int DECREASE_SPEED = 2; Figure 1. Running example:color");}} // required ("Invalid traffic a hypothetical drive-by-w private static final int STOP = 3; private static final int MAX_SPEED = 140; public void drive() is currently performing, idle by default ∗/ /∗ The action this automobile { ch machinery.int currentAction = IDLE; example, in which TrafficSignal the weak enum ; private Third, aSignal = ... /∗ The to manually enumerate initially 5 mph.language enum ogrammercurrent speed of the automobile,the int reaction = this.react(aSignal); ∗/ by if (reaction != this.currentAction && ts, which increases the likelihood 5; private int currentSpeed = of (reaction != INCREASE_SPEED || and Automobile. different enumint react(TrafficSignal signal) of these ne privatethis.currentSpeed unin- constants may be <= MAX_SPEED)) { ations he same internal value. Finally, the this.performAction(reaction);} switch(signal.getColor()) { through compile-tim case TrafficSignal.RED: return STOP; rittle private void performAction(int action) {...}}named [?]:case TrafficSignal.YELLOW: since the values are com- between the at compile time they are to stop or go // decide whether inlined into ated values. It is als new constants if(a)are added in constants for enumerated types., whic Using integer (this.shouldGo()) between is an Action 44
  • 230. this.currentAction && case TrafficSignal.YELLOW: private int color = RED; 38 (reacti INCREASE_SPEED || /∗ Accessor for the light’s current or go ∗/ Enums vs. Constants // decide whether toDistinction: Algorithmic stop color tSpeed <= MAX_SPEED)) 39 this.c publicif (this.shouldGo()) int getColor() {return this.color;}} 40 this. rmAction(reaction);} return INCREASE_SPEED; 41 else return STOP; 42 private void rmAction(int action) { class Automobile {...}} casestatic final int IDLE = no change TrafficSignal.GREEN: // 0; (b) Im private eger constants for static final int INCREASE_SPEED = 1; private enumerated types. return this.currentAction; default: throw new IllegalArgumentException private static final int DECREASE_SPEED = 2; Figure 1. Running example:color");}} // required ("Invalid traffic a hypothetical drive-by-w private static final int STOP = 3; private static final int MAX_SPEED = 140; public void drive() is currently performing, idle by default ∗/ /∗ The action this automobile { ch machinery.int currentAction = IDLE; example, in which TrafficSignal the weak enum ; private Third, aSignal = ... /∗ The to manually enumerate initially 5 mph.language enum ogrammercurrent speed of the automobile,the int reaction = this.react(aSignal); ∗/ by if (reaction != this.currentAction && ts, which increases the likelihood 5; private int currentSpeed = of (reaction != INCREASE_SPEED || and Automobile. different enumint react(TrafficSignal signal) of these ne privatethis.currentSpeed unin- constants may be <= MAX_SPEED)) { ations he same internal value. Finally, the this.performAction(reaction);} switch(signal.getColor()) { through compile-tim case TrafficSignal.RED: return STOP; rittle private void performAction(int action) {...}}named [?]:case TrafficSignal.YELLOW: since the values are com- between the at compile time they are to stop or go // decide whether inlined into ated values. It is als new constants if(a)are added in constants for enumerated types., whic Using integer (this.shouldGo()) between is an Action 44
  • 231. this.currentAction && case TrafficSignal.YELLOW: private int color = RED; 38 (reacti INCREASE_SPEED || /∗ Accessor for the light’s current or go ∗/ Enums vs. Constants // decide whether toDistinction: Algorithmic stop color tSpeed <= MAX_SPEED)) 39 this.c publicif (this.shouldGo()) int getColor() {return this.color;}} 40 this. rmAction(reaction);} return INCREASE_SPEED; 41 else return STOP; 42 private void rmAction(int action) { class Automobile {...}} casestatic final int IDLE = no change TrafficSignal.GREEN: // 0; (b) Im private eger constants for static final int INCREASE_SPEED = 1; private enumerated types. return this.currentAction; default: throw new IllegalArgumentException private static final int DECREASE_SPEED = 2; Figure 1. Running example:color");}} // required ("Invalid traffic a hypothetical drive-by-w private static final int STOP = 3; private static final int MAX_SPEED = 140; public void drive() is currently performing, idle by default ∗/ /∗ The action this automobile { ch machinery.int currentAction = IDLE; example, in which TrafficSignal the weak enum ; private Third, aSignal = ... /∗ The to manually enumerate initially 5 mph.language enum ogrammercurrent speed of the automobile,the int reaction = this.react(aSignal); ∗/ by if (reaction != this.currentAction && ts, which increases the likelihood 5; private int currentSpeed = of (reaction != INCREASE_SPEED || and Automobile. different enumint react(TrafficSignal signal) of these ne privatethis.currentSpeed unin- constants may be <= MAX_SPEED)) { ations he same internal value. Finally, the this.performAction(reaction);} switch(signal.getColor()) { through compile-tim case TrafficSignal.RED: return STOP; rittle private void performAction(int action) {...}}named [?]:case TrafficSignal.YELLOW: since the values are com- between the at compile time they are to stop or go // decide whether inlined into ated values. It is als new constants if(a)are added in constants for enumerated types., whic Using integer (this.shouldGo()) between is an Action 44
  • 232. this.currentAction && case TrafficSignal.YELLOW: private int color = RED; 38 (reacti INCREASE_SPEED || /∗ Accessor for the light’s current or go ∗/ Enums vs. Constants // decide whether toDistinction: Algorithmic stop color tSpeed <= MAX_SPEED)) 39 this.c publicif (this.shouldGo()) int getColor() {return this.color;}} 40 this. rmAction(reaction);} return INCREASE_SPEED; 41 else return STOP; 42 private void rmAction(int action) { class Automobile {...}} casestatic final int IDLE = no change TrafficSignal.GREEN: // 0; (b) Im private eger constants for static final int INCREASE_SPEED = 1; private enumerated types. return this.currentAction; default: throw new IllegalArgumentException private static final int DECREASE_SPEED = 2; Figure 1. Running example:color");}} // required ("Invalid traffic a hypothetical drive-by-w private static final int STOP = 3; private static final int MAX_SPEED = 140; public void drive() is currently performing, idle by default ∗/ /∗ The action this automobile { ch machinery.int currentAction = IDLE; example, in which TrafficSignal the weak enum ; private Third, aSignal = ... /∗ The to manually enumerate initially 5 mph.language enum ogrammercurrent speed of the automobile,the int reaction = this.react(aSignal); ∗/ by if (reaction != this.currentAction && ts, which increases the likelihood 5; private int currentSpeed = of (reaction != INCREASE_SPEED || and Automobile. different enumint react(TrafficSignal signal) of these ne privatethis.currentSpeed unin- constants may be <= MAX_SPEED)) { ations he same internal value. Finally, the this.performAction(reaction);} switch(signal.getColor()) { through compile-tim case TrafficSignal.RED: return STOP; rittle private void performAction(int action) {...}}named [?]:case TrafficSignal.YELLOW: since the values are com- between the at compile time they are to stop or go // decide whether inlined into ated values. It is als new constants if(a)are added in constants for enumerated types., whic Using integer (this.shouldGo()) between is an Action 44
  • 233. this.currentAction && case TrafficSignal.YELLOW: private int color = RED; class Automobile { 38 (reacti INCREASE_SPEED || /∗ Accessor static final int go ∗/ Enums vs. Constants private Algorithmic Distinction: = 0; // decide whether current or for the light’s to stop color tSpeed <= MAX_SPEED)) IDLE 39 this.c publicif static final int INCREASE_SPEED = 1; this. (this.shouldGo()) 40 int getColor() {return this.color;}} rmAction(reaction);} private return INCREASE_SPEED; 41 private static final int DECREASE_SPEED = 2; void 42 private else return STOP; rmAction(int action) { class Automobile {...}} int STOP = 3; private static final (b) Im casestatic final int IDLE = no change TrafficSignal.GREEN: // 0; private static final int MAX_SPEED = 140; private enumerated types. eger constants for static final int INCREASE_SPEED = 1; private return this.currentAction; /∗ The action this automobile is currently performing, idle by default ∗/ default: throw new IllegalArgumentException private static final int DECREASE_SPEED = 2; private int currentAction = IDLE; // required Figure 1. current speed oftraffic color");}} mph. ∗/ drive-by-w private static example: STOP = 3; /∗ The Running final int a hypothetical ("Invalid the automobile, initially 5 private static final int MAX_SPEED = 140; privatevoid drive() { public int currentSpeed = 5; /∗ The action this automobile is currently performing, idle by default ∗/ ch machinery.int currentAction = IDLE; example, in which TrafficSignal the weak enum ; private Third, aSignal = ... private int react(TrafficSignal signal) { ogrammercurrent speed of the automobile,the{ 5 mph.language enum /∗ The to manually enumerate initially by ∗/ int reaction = this.react(aSignal); switch(signal.getColor()) if (reaction != this.currentAction && ts, whichcaseint currentSpeed = ofreturn STOP; privateincreases the likelihood 5; TrafficSignal.RED: (reaction != INCREASE_SPEED || and Automobile. different enumint react(TrafficSignal signal) of these ne case constants may be unin- private TrafficSignal.YELLOW: this.currentSpeed <= MAX_SPEED)) { ations // decide whether to stop or go { he same internal value. Finally, the this.performAction(reaction);} switch(signal.getColor()) if (this.shouldGo()) through compile-tim case TrafficSignal.RED: return STOP; rittle private void performAction(int action) {...}}named [?]:case returnvalues are com- since the INCREASE_SPEED; between the TrafficSignal.YELLOW: at compile time they are to stop or go // decide whether STOP; into else return inlined ated values. It is als if(a)are added in constants for enumerated types., whic Using integer TrafficSignal.GREEN: // no change case (this.shouldGo()) new constants between is an Action 44
  • 234. this.currentAction && case TrafficSignal.YELLOW: private int color = RED; private int color = RED; class Automobile { 38 (reacti INCREASE_SPEED || /∗ Accessor static final int go ∗/ Enums vs. Constants private // decide whether toDistinction: Algorithmiccurrentcolor ∗/ Accessor for the light’s current or IDLE = 0; for the light’s stop color tSpeed <= MAX_SPEED)) 39 this.c publicif static final int INCREASE_SPEED = 1; this. (this.shouldGo()) public int getColor() {return this.color;}} 40 int getColor() {return this.color;}} rmAction(reaction);} private return INCREASE_SPEED; 41 private static final int DECREASE_SPEED = 2; void 42 private else return STOP; Automobile final rmAction(int action) { { class Automobile {...}} int STOP = 3; private static (b) Im casestatic final int IDLE ==no change TrafficSignal.GREEN: // 0; private static final int IDLE private static final int MAX_SPEED = 140; 0; private enumerated types. eger constants for static final int INCREASE_SPEED ==1; return this.currentAction; private static final isint INCREASE_SPEED by default ∗/ private this automobile currently performing, idle 1; /∗ The action default: throw new IllegalArgumentException private static final int DECREASE_SPEED ==2; private int currentActionDECREASE_SPEED private static final int = IDLE; // required 2; Figure 1. current speed oftraffic color");}} mph. ∗/ drive-by-w private static example: STOP == 3; private static final int a hypothetical /∗ The Running final int STOP 3; ("Invalid the automobile, initially 5 private static final int MAX_SPEED == 140; private int currentSpeed MAX_SPEED privatevoid drive() { int = 5; public static final 140; /∗ The action this automobile is currently performing, idle by default ∗/∗/ action Third, the weak enumperforming, idle by in which this automobile is currently default ch machinery.int currentAction == IDLE; example, private int currentAction ... ; TrafficSignal aSignal = private int react(TrafficSignal signal) { IDLE; private ogrammercurrent speed of the automobile,the{ 55mph.language enum /∗ The current speed of the automobile,initially by ∗/ /∗ The to manually enumerate initially mph. ∗/ int reaction = this.react(aSignal); switch(signal.getColor()) if (reaction != this.currentAction && ts, whichcaseint currentSpeed == ofreturn STOP; private int currentSpeed 5; increases the likelihood private TrafficSignal.RED:5; (reaction != INCREASE_SPEED || and Automobile. different enumint react(TrafficSignal signal) of these ne case constants may be unin- TrafficSignal.YELLOW: this.currentSpeed <= MAX_SPEED)) {{ private int react(TrafficSignal signal) private decide whether to stop or go ations // this.performAction(reaction);} he same internal value. Finally, the{ switch(signal.getColor()) { switch(signal.getColor()) if (this.shouldGo()) through compile-tim case TrafficSignal.RED: return STOP; rittle private void performAction(int action) {...}}named [?]:case returnvalues are com-return STOP; the since the INCREASE_SPEED; between case TrafficSignal.RED: case TrafficSignal.YELLOW: TrafficSignal.YELLOW: at compile time return to stop or go // decide whether STOP; into else they are to stop or go // decide whether inlined ated values. It is als if(a)are added in constants for enumerated types., whic Using integer TrafficSignal.GREEN: // no change case (this.shouldGo()) new constants (this.shouldGo()) if between is an Action 44
  • 235. this.currentAction && case TrafficSignal.YELLOW: private int color = RED; private int color = RED; class Automobile { 38 (reacti INCREASE_SPEED || class Automobile final int go ∗/ Enums vs. Constants Accessor for the light’s toDistinction: private Algorithmic stop color /∗ Accessor static { current or IDLE = 0; // decide whether currentcolor ∗/ for the light’s tSpeed <= MAX_SPEED)) 39 this.c publicif static final int IDLE this.color;}}1; this. (this.shouldGo()) public int getColor() int INCREASE_SPEED =40 int getColor() {return this.color;}} private static rmAction(reaction);} final private {return = 0; return INCREASE_SPEED; 41 private static final int INCREASE_SPEED = 1; void private static final int DECREASE_SPEED = 2; 42 private else return STOP; Automobile final rmAction(int action) { { class Automobile {...}} int DECREASE_SPEED = 2; ? private static final int STOP = 3; private static (b) Im casestatic final int IDLE ==no change TrafficSignal.GREEN: // 0; private static final int IDLE private static final int STOP 0; 3; private enumerated types. MAX_SPEED = 140; eger constants for static final int INCREASE_SPEED ==1; return this.currentAction; private static final isint INCREASE_SPEED by default ∗/ private this automobile currently performing, idle MAX_SPEED = 140; 1; /∗ The action default: throw new currently performing, idle /∗ The action this automobile int IllegalArgumentException private static final isint DECREASE_SPEED ==2; private int currentActionDECREASE_SPEED by default ∗/ static final private = IDLE; // required 2; Figure 1. current speed oftraffic color");}} mph. ∗/ drive-by-w private static example: STOPIDLE; Running final int a =initially3; ("Invalid final int hypothetical private int currentActionSTOP == 3; /∗ The static the automobile, 5 private static of the automobile, initially 5 mph.140; private int currentSpeed MAX_SPEED == 140; /∗ The current speed final int MAX_SPEED privatevoid drive() { int = 5; static final public int automobile is currently5; ∗/ /∗ The action this currentSpeed = performing, idle by default ∗/∗/ private Third, the weak enumperforming, idle by in which action this automobile is currently default ch machinery.int currentAction == IDLE; example, private int currentAction ... ; TrafficSignal aSignal = private int react(TrafficSignal signal) { IDLE; private /∗ The current speed of the automobile,initially 5by language enum ogrammercurrent speed of the automobile,the{ 5signal) { /∗ The to manually enumerate initially mph. ∗/ int reaction = this.react(aSignal); ∗/ private int react(TrafficSignal switch(signal.getColor()) mph. if (reaction != this.currentAction && ts, whichcaseint currentSpeed == ofreturn STOP; private int currentSpeed 5;{ increases the likelihood private TrafficSignal.RED:5; switch(signal.getColor()) (reaction != INCREASE_SPEED || and Automobile. case constants may be unin-return STOP; these ne TrafficSignal.RED: different enum int react(TrafficSignal signal){{ caseint react(TrafficSignal signal) of TrafficSignal.YELLOW: ations this.currentSpeed <= MAX_SPEED)) private TrafficSignal.YELLOW: private decide whether to stop or go case // this.performAction(reaction);} he same internal value. to stop or go {{ // decide whether Finally, the switch(signal.getColor()) switch(signal.getColor()) if (this.shouldGo()) through compile-tim case TrafficSignal.RED: return STOP; rittle private void performAction(int action) {...}}named [?]:case returnvalues are com-return STOP; the since the INCREASE_SPEED; between case TrafficSignal.RED: if (this.shouldGo()) TrafficSignal.YELLOW: casereturn INCREASE_SPEED; TrafficSignal.YELLOW: at compile time return to stop or go // decide whether STOP; into else they are to stop or go inlined // decide whether STOP; ated values. It is als else Using integer constants for enumerated types. (a) return if TrafficSignal.GREEN: // nois an Action, whic case (this.shouldGo()) change new constants (this.shouldGo()) if are added in between 44
  • 236. this.currentAction && { class case int color = RED; Automobile private TrafficSignal.YELLOW: private int color = RED; class Automobile { INCREASE_SPEED || 38 (reacti private decide whether toDistinction: Enums vs. Constants static final int IDLE = 0; // Algorithmiccurrentor go ∗/ Accessor for the light’s stop color for the light’s this.c /∗ Accessor static { current color ∗/ class Automobile final int IDLE = 0; private static 39 tSpeed <= MAX_SPEED)) final int INCREASE_SPEED = 1; privateint getColor() {return this.color;}} this. publicif static final int IDLE this.color;}}1; (this.shouldGo()) private static final 40 public int getColor() int INCREASE_SPEED = {return = 0; rmAction(reaction);} final int DECREASE_SPEED = 2; private static private return INCREASE_SPEED; 41 private static final int INCREASE_SPEED = 1; void private static final int DECREASE_SPEED = 2; private static { STOP; final int STOP = 3; 42 private else return Automobile { class Automobile final int STOP = 3; ? rmAction(int action) {...}} int DECREASE_SPEED = 2; private static final int MAX_SPEED = 140; private static final private static final int IDLE ==no change static case static final int IDLE // 0; TrafficSignal.GREEN: (b) Im private static final int STOP private 0; 3; private enumerated types. currently performing, idle by default ∗/ MAX_SPEED = 140; eger constantsaction this automobile isint INCREASE_SPEED ==1; /∗ The for static final int INCREASE_SPEED return this.currentAction; private static final is currently performing, idle by default ∗/ private this automobile MAX_SPEED = 140; 1; /∗ The action private static final int DECREASE_SPEED default: currentAction = IDLE; int throw new IllegalArgumentException private static final isint DECREASE_SPEED ==2; private int currentAction = IDLE; 2; /∗ The action this automobile currently performing, idle by default ∗/ private private static of the automobile,hypothetical /∗ The current speed example: STOP == 3; mph. ∗/ initially 5 Figure 1. current speed oftraffic color");}} mph. ∗/ drive-by-w Running final int a =initially3; // required ("Invalid final int STOP private int currentAction static the automobile, IDLE; /∗ The private static final int MAX_SPEED == 140; int currentSpeed MAX_SPEED= 5; 5 private static of the automobile, initially 5 mph.140; private int currentSpeed = 5; /∗ The current speed final int ∗/ privatevoid drive() { public int automobile is currently5; /∗ The action this currentSpeed = performing, idle by default ∗/∗/ private int react(TrafficSignal signal) by in which action Third, the weak enumperforming, idle default this automobile is currently ch machinery.int currentAction == IDLE; example, private private int currentAction ... ; TrafficSignal aSignal = private int react(TrafficSignal signal) { IDLE; { private /∗ The current speed of the automobile,initially 5by language enum ogrammercurrent speed of the automobile,the{ 5signal) { int to manually enumerate initially mph. ∗/ switch(signal.getColor()) { /∗ The reaction = this.react(aSignal); ∗/ private int react(TrafficSignal switch(signal.getColor()) mph. if caseint currentSpeed = 5;return STOP; TrafficSignal.RED:5; (reaction != this.currentAction && private int currentSpeed = of{ ts, whichcase TrafficSignal.RED: return STOP; privateincreases the likelihood switch(signal.getColor()) case TrafficSignal.YELLOW: (reaction != INCREASE_SPEED || and Automobile. case constants may beor go return STOP; these ne TrafficSignal.RED: different enum int react(TrafficSignal signal){{ caseint react(TrafficSignal signal) of //this.currentSpeed unin- TrafficSignal.YELLOW: decide whether to stop <= MAX_SPEED)) ations private TrafficSignal.YELLOW: private decide whether to stop or go case (this.shouldGo()) // this.performAction(reaction);} if he same internal value. to stop or go {{ // decide whether Finally, the switch(signal.getColor()) switch(signal.getColor()) if TrafficSignal.RED: return STOP; (this.shouldGo()) through compile-tim case return INCREASE_SPEED; rittle private void performAction(int action) {...}}named [?]:case returnvalues are com-return STOP; the since the INCREASE_SPEED; between case TrafficSignal.RED: if (this.shouldGo()) else return STOP; TrafficSignal.YELLOW: casereturn INCREASE_SPEED; TrafficSignal.YELLOW: at compile timeTrafficSignal.GREEN: // noated values. It is als else they are to stop or go case return STOP; into inlined // decide whether to stop or go // decide whether STOP; change else Using integer constants for enumerated types. (a) return if TrafficSignal.GREEN: // nois an Action, whic return this.currentAction; change case (this.shouldGo()) new constants (this.shouldGo()) if are added in between 44
  • 237. this.currentAction && { class case int color = RED; Automobile private TrafficSignal.YELLOW: private int color = RED; class Automobile { INCREASE_SPEED || 38 (reacti private decide whether toDistinction: Enums vs. Constants static final int IDLE = 0; // Algorithmiccurrentor go ∗/ Accessor for the light’s stop color for the light’s this.c /∗ Accessor static { current color ∗/ class Automobile final int IDLE = 0; private static 39 tSpeed <= MAX_SPEED)) final int INCREASE_SPEED = 1; privateint getColor() {return this.color;}} this. publicif static final int IDLE this.color;}}1; (this.shouldGo()) private static final 40 public int getColor() int INCREASE_SPEED = {return = 0; rmAction(reaction);} final int DECREASE_SPEED = 2; private static private return INCREASE_SPEED; 41 private static final int INCREASE_SPEED = 1; void private static final int DECREASE_SPEED = 2; private static { STOP; final int STOP = 3; 42 private else return Automobile { class Automobile final int STOP = 3; rmAction(int action) {...}} int DECREASE_SPEED = 2; private static final int MAX_SPEED = 140; private static final private static final int IDLE ==no change static (b) Im case static final int IDLE // 0; private TrafficSignal.GREEN: private static final int STOP 0; 3; private enumerated types. currently performing, idle by default ∗/ MAX_SPEED = 140; eger constantsaction this automobile isint INCREASE_SPEED ==1; /∗ The for static final int INCREASE_SPEED return this.currentAction; private static final is currently performing, idle by default ∗/ private this automobile MAX_SPEED = 140; 1; /∗ The action private static final int DECREASE_SPEED default: currentAction = IDLE; int throw new IllegalArgumentException private static final isint DECREASE_SPEED ==2; private int currentAction = IDLE; 2; /∗ The action this automobile currently performing, idle by default ∗/ private private static of the automobile,hypothetical /∗ The current speed example: STOP == 3; mph. ∗/ initially 5 Figure 1. current speed oftraffic color");}} mph. ∗/ drive-by-w Running final int a =initially3; // required ("Invalid final int STOP private int currentAction static the automobile, IDLE; /∗ The private static final int MAX_SPEED == 140; int currentSpeed MAX_SPEED= 5; 5 private static of the automobile, initially 5 mph.140; private int currentSpeed = 5; /∗ The current speed final int ∗/ privatevoid drive() { public int automobile is currently5; /∗ The action this currentSpeed = performing, idle by default ∗/∗/ private int react(TrafficSignal signal) by in which action Third, the weak enumperforming, idle default this automobile is currently ch machinery.int currentAction == IDLE; example, private private int currentAction ... ; TrafficSignal aSignal = private int react(TrafficSignal signal) { IDLE; { private /∗ The current speed of the automobile,initially 5by language enum ogrammercurrent speed of the automobile,the{ 5signal) { int to manually enumerate initially mph. ∗/ switch(signal.getColor()) { /∗ The reaction = this.react(aSignal); ∗/ private int react(TrafficSignal switch(signal.getColor()) mph. if caseint currentSpeed = 5;return STOP; TrafficSignal.RED:5; (reaction != this.currentAction && private int currentSpeed = of{ ts, whichcase TrafficSignal.RED: return STOP; privateincreases the likelihood switch(signal.getColor()) case TrafficSignal.YELLOW: (reaction != INCREASE_SPEED || and Automobile. case constants may beor go return STOP; these ne TrafficSignal.RED: different enum int react(TrafficSignal signal){{ caseint react(TrafficSignal signal) of //this.currentSpeed unin- TrafficSignal.YELLOW: decide whether to stop <= MAX_SPEED)) ations private TrafficSignal.YELLOW: private decide whether to stop or go case (this.shouldGo()) // this.performAction(reaction);} if he same internal value. to stop or go {{ // decide whether Finally, the switch(signal.getColor()) switch(signal.getColor()) if TrafficSignal.RED: return STOP; (this.shouldGo()) through compile-tim case return INCREASE_SPEED; rittle private void performAction(int action) {...}}named [?]:case returnvalues are com-return STOP; the since the INCREASE_SPEED; between case TrafficSignal.RED: if (this.shouldGo()) else return STOP; TrafficSignal.YELLOW: casereturn INCREASE_SPEED; TrafficSignal.YELLOW: at compile timeTrafficSignal.GREEN: // noated values. It is als else they are to stop or go case return STOP; into inlined // decide whether to stop or go // decide whether STOP; change else Using integer constants for enumerated types. (a) return if TrafficSignal.GREEN: // nois an Action, whic return this.currentAction; change case (this.shouldGo()) new constants (this.shouldGo()) if are added in between 44
  • 238. µ(P) {m | m "* % 1)!0#- "$ P} υ(P) Top-level Enumerization Algorithm {l | l "* % '%2"%,&) "$ P} α '%2"%,&)/ !)&-/ 1)!0#- αctxt 30"+$5+ "$ 40"+0 α 1%. #++(2 !"#$%& '( !)%*+,"-* .)/+/").( .',/&4$'& Enumerize(F, P) >A R ← Enumerizable(F ) QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R) GA 5,' *22 T ∈ R 4, RA T ransf orm(T ) ?A &#4 5,' !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*( 2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+ "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. 45
  • 239. µ(P) {m | m "* % 1)!0#- "$ P} υ(P) Top-level Enumerization Algorithm {l | l "* % '%2"%,&) "$ P} α '%2"%,&)/ !)&-/ 1)!0#- ic αctxt 30"+$5+ "$ 40"+0 α 1%. #++(2 at of st ds et l fiel bs a !"#$%& '( !)%*+,"-* .)/+/").( Su in .',/&4$'& Enumerize(F, P) f >A R ← Enumerizable(F ) QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R) GA 5,' *22 T ∈ R 4, RA T ransf orm(T ) ?A &#4 5,' !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*( 2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+ "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. 45
  • 240. µ(P) {m | m "* % 1)!0#- "$ P} υ(P) Top-level Enumerization Algorithm {l | l "* % '%2"%,&) "$ P} α '%2"%,&)/ !)&-/ 1)!0#- αctxt 30"+$5+ "$ 40"+0 α 1%. #++(2 Orig inal P !"#$%&g '( !)%*+,"-* .)/+/").( ro ra .',/&4$'& Enumerize(F, m P) >A R ← Enumerizable(F ) QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R) GA 5,' *22 T ∈ R 4, RA T ransf orm(T ) ?A &#4 5,' !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*( 2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+ "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. 45
  • 241. µ(P) {m | m "* % 1)!0#- "$ P} υ(P) Top-level Enumerization Algorithm {l | l "* % '%2"%,&) "$ P} α '%2"%,&)/ !)&-/ 1)!0#- αctxt 30"+$5+ "$ 40"+0 α 1%. #++(2Infers which !"#$%& '( !)%*+,"-* .)/+/").( being candidate fields are .',/&4$'& Enumerize(F, P) used as enums >A R ← Enumerizable(F ) QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R) GA 5,' *22 T ∈ R 4, RA T ransf orm(T ) ?A &#4 5,' !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*( 2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+ "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. 45
  • 242. µ(P) {m | m "* % 1)!0#- "$ P} υ(P) Top-level Enumerization Algorithm {l | l "* % '%2"%,&) "$ P} α '%2"%,&)/ !)&-/ 1)!0#- αctxt 30"+$5+ "$ 40"+0 α 1%. #++(2 !"#$%& '( !)%*+,"-* .)/+/").( .',/&4$'& Enumerize(F, P) >A R ← Enumerizable(F ) QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R) GA 5,' *22 T ∈ R 4, RA T ransf orm(T ) Groups ?A &#4 5,' them into minimal sets !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*( 2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+ "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. 45
  • 243. µ(P) {m | m "* % 1)!0#- "$ P} υ(P) Top-level Enumerization Algorithm {l | l "* % '%2"%,&) "$ P} α '%2"%,&)/ !)&-/ 1)!0#- αctxt 30"+$5+ "$ 40"+0 α 1%. #++(2 !"#$%& '( !)%*+,"-* .)/+/").( .',/&4$'& Enumerize(F, P) >A R ← Enumerizable(F ) QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R) GA 5,' *22 T ∈ R 4, RA T ransf orm(T ) ?A &#4 5,' !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*( 2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+ "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. 45
  • 244. µ(P) {m | m "* % 1)!0#- "$ P} υ(P) Top-level Enumerization Algorithm {l | l "* % '%2"%,&) "$ P} α '%2"%,&)/ !)&-/ 1)!0#- αctxt 30"+$5+ "$ 40"+0 α 1%. #++(2 !"#$%& '( !)%*+,"-* .)/+/").( .',/&4$'& Enumerize(F, P) >A R ← Enumerizable(F ) QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R) GA 5,' *22 T ∈ R 4, RA T ransf orm(T ) ?A &#4 5,' !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*( 2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+ "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. 45
  • 245. µ(P) {m | m "* % 1)!0#- "$ P} υ(P) Top-level Enumerization Algorithm {l | l "* % '%2"%,&) "$ P} α '%2"%,&)/ !)&-/ 1)!0#- αctxt 30"+$5+ "$ 40"+0 α 1%. #++(2 !"#$%& '( !)%*+,"-* .)/+/").( .',/&4$'& Enumerize(F, P) >A R ← Enumerizable(F ) QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R) GA 5,' *22 T ∈ R 4, RA T ransf orm(T ) ?A &#4 5,' !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*( 2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+ "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. 45
  • 246. µ(P) {m | m "* % 1)!0#- "$ P} υ(P) Top-level Enumerization Algorithm {l | l "* % '%2"%,&) "$ P} α '%2"%,&)/ !)&-/ 1)!0#- αctxt 30"+$5+ "$ 40"+0 α 1%. #++(2 !"#$%& '( !)%*+,"-* .)/+/").( .',/&4$'& Enumerize(F, P) >A R ← Enumerizable(F ) QA R ← U nique(R) ∩ Distinct(R) ∩ Consistent(R) GA 5,' *22 T ∈ R 4, RA T ransf orm(T ) ?A &#4 5,' !"#$%& 0( 1)23,&4&, &.$*&%"5+/"). +,#)%"/6*( Natural ordering 2)9%+!#2"$37 M) %&*# %**(1) !0%! 4) %2) %,&) !# *!%!"+ "-)$!"9. %&& 2)9)2)$+)* !# +%$-"-%!) !)&-* %$- !2%$*"!"')&. 45
  • 247. Empirical Evaluation Benchmark KLOC Classes Sites Time (s) ArtOfIllusion 75 378 111 207 Azureus 272 1894 635 1269 java5 180 1586 572 760 JavaCup 6 41 3 19 jdepend 3 28 1 1 JFlex 10 46 27 75 JFreeChart 71 420 43 128 jGap 6 137 5 7 jgraph 14 91 6 11 JHotDraw 29 496 24 14 junit 8 271 3 1 jwps 20 155 102 60 sablecc 29 237 10 9 tomcat6 153 1164 400 346 verbos 5 41 15 3 VietPad 11 84 22 8 Violet 7 73 20 9 Totals 899 7142 1999 2227 46
  • 248. Empirical Evaluation Benchmark KLOC Classes Sites Time (s) ArtOfIllusion 75 378 111 207 Azureus 272 1894 635 1269 java5 180 1586 572 760 JavaCup 6 41 3 19 jdepend 3 28 1 1 JFlex 10 46 27 75 JFreeChart 71 420 43 128 jGap 6 137 5 7 jgraph 14 91 6 11 JHotDraw 29 496 24 14 junit 8 271 3 1 jwps 20 155 102 60 sablecc 29 237 10 9 tomcat6 153 1164 400 346 verbos 5 41 15 3 VietPad 11 84 2.4 / KLOC 22 8 Violet 7 73 20 9 Totals 899 7142 1999 2227 46
  • 249. Empirical Evaluation Benchmark KLOC Classes Sites Time (s) ArtOfIllusion 75 378 111 207 Azureus 272 1894 635 1269 java5 180 384 sites / 1586 572 760 JavaCup 6 Benchmark 41 3 19 jdepend 3 28 1 1 JFlex 10 46 27 75 JFreeChart 71 420 43 128 jGap 6 137 5 7 jgraph 14 91 6 11 JHotDraw 29 496 24 14 junit 8 271 3 1 jwps 20 155 102 60 sablecc 29 237 10 9 tomcat6 153 1164 400 346 verbos 5 41 15 3 VietPad 11 84 22 8 Violet 7 73 20 9 Totals 899 7142 1999 2227 46
  • 251. Filtered Contexts • Certain fields cannot be refactored. 47
  • 252. Filtered Contexts • Certain fields cannot be refactored. • Program semantics preservation depends on the actual values of these fields. 47
  • 253. Filtered Contexts • Certain fields cannot be refactored. • Program semantics preservation depends on the actual values of these fields. • For example, named-constants (used in mathematical calculations). 47
  • 254. Filtered Contexts • Certain fields cannot be refactored. • Program semantics preservation depends on the actual values of these fields. • For example, named-constants (used in mathematical calculations). • Transitive dependency of an element outside available source code. 47
  • 255. Filtered Contexts • Certain fields cannot be refactored. • Program semantics preservation depends on the actual values of these fields. • For example, named-constants (used in mathematical calculations). • Transitive dependency of an element outside available source code. • Language constraints prohibit enumerization. 47
  • 256. Filtered Contexts • Certain fields cannot be refactored. • Program semantics preservation depends on the actual values of these fields. • For example, named-constants (used in mathematical calculations). • Transitive dependency of an element outside available source code. • Language constraints prohibit enumerization. • Remaining fields denoted as candidates. 47
  • 257. Filtered Contexts • Certain fields cannot be refactored. • Program semantics preservation depends on the actual values of these fields. • For example, named-constants (used in mathematical calculations). • Transitive dependency of an element outside arr[RED] available source code. • Language constraints prohibit enumerization. • Remaining fields denoted as candidates. 47
  • 258. Filtered Contexts • Certain fields cannot be refactored. • Program semantics preservation depends on the actual values of these fields. • For example, named-constants (used in mathematical calculations). • Transitive dependency of an element outside available source code. • Language constraints prohibit enumerization. • Remaining fields denoted as candidates. 47
  • 260. Enum Identification Effectiveness 0 140 280 420 560 ArtOfIllusion Azureus java5 JavaCup jdepend JFlex JFreeChart jGap jgraph JHotDraw junit jwps sablecc tomcat6 verbos VietPad Violet cands enum 48
  • 261. Enum Identification Effectiveness 0 140 280 420 560 ArtOfIllusion Azureus java5 JavaCup jdepend JFlex JFreeChart jGap jgraph Refactored JHotDraw junit 87% jwps sablecc tomcat6 verbos VietPad Violet cands enum 48
  • 263. Result Summary • 37% of all primitive constant fields identified as candidates. 49
  • 264. Result Summary • 37% of all primitive constant fields identified as candidates. • 87% of candidate fields found safe for refactoring. 49
  • 265. Result Summary • 37% of all primitive constant fields identified as candidates. • 87% of candidate fields found safe for refactoring. • Remaining 13% required more sophisticated analysis: 49
  • 266. Result Summary • 37% of all primitive constant fields identified as candidates. • 87% of candidate fields found safe for refactoring. • Remaining 13% required more sophisticated analysis: • Explicit primitive conversion analysis (casts). 49
  • 267. Result Summary • 37% of all primitive constant fields identified as candidates. • 87% of candidate fields found safe for refactoring. • Remaining 13% required more sophisticated analysis: • Explicit primitive conversion analysis (casts). • Native array copying method usage. 49
  • 269. Related Work • Fowler [99] and Kerievsky [04] present a RE- PLACE TYPE CODE WITH CLASS refactoring. 50
  • 270. Related to a Manual, not Work language enum type, and no inference • Fowler [99] and Kerievsky [04] present a RE- PLACE TYPE CODE WITH CLASS refactoring. 50
  • 271. Related Work • Fowler [99] and Kerievsky [04] present a RE- PLACE TYPE CODE WITH CLASS refactoring. • Deursen and Moonen [IWPC 99] identify enumerated types in COBOL. 50
  • 272. Related Work Different semantics • preservation Fowler [99] and Kerievsky [04] present a RE- PLACE Tconstraints WITH CLASS refactoring. YPE CODE • Deursen and Moonen [IWPC 99] identify enumerated types in COBOL. 50
  • 273. Related Work • Fowler [99] and Kerievsky [04] present a RE- PLACE TYPE CODE WITH CLASS refactoring. • Deursen and Moonen [IWPC 99] identify enumerated types in COBOL. • Gravley and Lakhotia [WCRE 96] identify enumerated types in C. 50
  • 274. Related Work • Fowler [99] and Kerievsky [04] present a RE- PLACE TYPE CODE WITH CLASS refactoring. • Deursen and Moonen [IWPC 99] identify No transitivity enumerated types in COBOL. • Gravley and Lakhotia [WCRE 96] identify enumerated types in C. 50
  • 275. Related Work • Fowler [99] and Kerievsky [04] present a RE- PLACE TYPE CODE WITH CLASS refactoring. • Deursen and Moonen [IWPC 99] identify enumerated types in COBOL. • Gravley and Lakhotia [WCRE 96] identify enumerated types in C. • Lawal and Lo [ASE 10] also identify enumerated types in C, specifically, in Linux kernel. 50
  • 276. Related Work • Fowler [99] and Kerievsky [04] present a RE- PLACE TYPE CODE WITH CLASS refactoring. • Deursen and Moonen [IWPC 99] identify enumerated types in COBOL. • Gravley and Lakhotia [WCRE 96] identify enumerated types in C. • Lawal and Lo [ASE 10] also identify enumerated types in C, specifically, in Linux kernel. Intra- procedural 50
  • 277. Conclusions 51
  • 278. Conclusions • Semantics preserving, declarative type inferencing algorithm migrating legacy Java code to the enum language construct introduced in Java 5. 51
  • 279. Conclusions • Semantics preserving, declarative type inferencing algorithm migrating legacy Java code to the enum language construct introduced in Java 5. • Implemented algorithm as a plug-in for the Eclipse IDE and evaluated it on 17 open source applications: 51
  • 280. Conclusions • Semantics preserving, declarative type inferencing algorithm migrating legacy Java code to the enum language construct introduced in Java 5. • Implemented algorithm as a plug-in for the Eclipse IDE and evaluated it on 17 open source applications: • Analysis cost is practical. 51
  • 281. Conclusions • Semantics preserving, declarative type inferencing algorithm migrating legacy Java code to the enum language construct introduced in Java 5. • Implemented algorithm as a plug-in for the Eclipse IDE and evaluated it on 17 open source applications: • Analysis cost is practical. • Weak enum pattern is commonly used in legacy Java software. 51
  • 282. Conclusions • Semantics preserving, declarative type inferencing algorithm migrating legacy Java code to the enum language construct introduced in Java 5. • Implemented algorithm as a plug-in for the Eclipse IDE and evaluated it on 17 open source applications: • Analysis cost is practical. • Weak enum pattern is commonly used in legacy Java software. • Proposal successfully refactors a large number of static final fields into enumerated types. 51
  • 283. Reasoning about Evolving AO Programs 52
  • 284. Reasoning about Evolving AO Programs • AOP enables modular implementation of CCCs. 52
  • 285. Reasoning about Evolving AO Programs • AOP enables modular implementation of CCCs. • Both formal and informal reasoning about AOP presents unique challenges especially in respect to evolution. 52
  • 286. Reasoning about Evolving AO Programs • AOP enables modular implementation of CCCs. • Both formal and informal reasoning about AOP presents unique challenges especially in respect to evolution. • As components enter, exit, and re-enter software, conclusions about behavior of components may be invalidated. 52
  • 287. C 53
  • 288. A C 53
  • 289. A C 53
  • 290. A C 53
  • 291. A C Behavior of C+A 53
  • 294. C Behavior of C+A 53
  • 295. C 53
  • 297. The Invasiveness of AOP • Desire a compositional reasoning approach, however the invasive nature of AOP makes this difficult. 54
  • 298. The Invasiveness of AOP • Desire a compositional reasoning approach, however the invasive nature of AOP makes this difficult. • In the worst case, changes made to a single component require reexamining the entire program. 54
  • 300. Research Questions • Can we draw meaningful conclusions about component code without considering the actual advice code? 55
  • 301. Research Questions • Can we draw meaningful conclusions about component code without considering the actual advice code? • Can we specify the behavior of components without any particular advice in mind? 55
  • 302. Research Questions • Can we draw meaningful conclusions about component code without considering the actual advice code? • Can we specify the behavior of components without any particular advice in mind? • Can we parameterize specifications over all possibly applicable aspects? 55
  • 303. Research Questions • Can we draw meaningful conclusions about component code without considering the actual advice code? • Can we specify the behavior of components without any particular advice in mind? • Can we parameterize specifications over all possibly applicable aspects? • Can we suitably constrain the behavior of aspects as the software evolves? 55
  • 305. Hiding Behind Interfaces • Using interface is one answer (e.g., XPIs [Griswold ’06], Open Modules [Aldrich ’05]) 56
  • 306. Hiding Behind Interfaces • Using interface is one answer (e.g., XPIs [Griswold ’06], Open Modules [Aldrich ’05]) • But it would be nice to have a way to derive the enriched behavior of the base plus the aspects at compile time. 56
  • 308. Contributions • Developed an approach to specify the behavior of aspects so that: 57
  • 309. Contributions • Developed an approach to specify the behavior of aspects so that: • They can be combined with the behavior of the base- code to arrive at the overall system behavior 57
  • 310. Contributions • Developed an approach to specify the behavior of aspects so that: • They can be combined with the behavior of the base- code to arrive at the overall system behavior • Are not invalidated upon evolution. 57
  • 311. Contributions • Developed an approach to specify the behavior of aspects so that: • They can be combined with the behavior of the base- code to arrive at the overall system behavior • Are not invalidated upon evolution. • Inspired subsequent work by Bagherzadeh et al. [AOSD 11]. 57
  • 312. Proposal 58
  • 313. Proposal • AO programs inherently enjoy plug-n-play capabilities [Laddad ’03] 58
  • 314. Proposal • AO programs inherently enjoy plug-n-play capabilities [Laddad ’03] • Crosscutting features can be plugged-in to enrich the behavior of advised components. 58
  • 315. Proposal • AO programs inherently enjoy plug-n-play capabilities [Laddad ’03] • Crosscutting features can be plugged-in to enrich the behavior of advised components. • My proposal involves developing an reasoning technique that enables developers to specify components so that their behaviors can be derive in a similar fashion. 58
  • 316. C
  • 320. Spec(C) A1 C A2
  • 321. Spec(C) Spec(A1 ) Spec(A2 ) A1 C A2
  • 322. Spec(A1 ) Spec(C) Spec(A2 )
  • 323. Spec(A1 ) Spec(C) Spec(A2 ) Compose Behavior of C+A1
  • 324. Spec(A1 ) Spec(C) Spec(A2 ) Compose Compose Behavior of C+A1 Behavior of C+A2
  • 325. Spec(A1 ) Spec(C) Spec(A2 ) Compose Compose Compose Behavior of C+A1 Behavior of C+A1+A2 Behavior of C+A2
  • 326. Obstacles 60
  • 328. Obstacles • Usefulness • Is it possible to draw meaningful conclusions from such incomplete information? 60
  • 329. Obstacles • Usefulness • Is it possible to draw meaningful conclusions from such incomplete information? • Obliviousness 60
  • 330. Obstacles • Usefulness • Is it possible to draw meaningful conclusions from such incomplete information? • Obliviousness • Specifications contain “slots” for applications of crosscutting concerns. 60
  • 331. Obstacles 61
  • 333. Obstacles • Abstraction • Competing forces: 61
  • 334. Obstacles • Abstraction • Competing forces: • Specs abstract internal details components, aspects directly manipulate them. 61
  • 335. Obstacles • Abstraction • Competing forces: • Specs abstract internal details components, aspects directly manipulate them. • Composition 61
  • 336. Obstacles • Abstraction • Competing forces: • Specs abstract internal details components, aspects directly manipulate them. • Composition • Which pegs go into which holes? 61
  • 337. Obstacles • Abstraction • Competing forces: • Specs abstract internal details components, aspects directly manipulate them. • Composition • Which pegs go into which holes? • How to deal with dynamic and lexical pointcuts? 61
  • 338. Obstacles • Abstraction • Competing forces: • Specs abstract internal details components, aspects directly manipulate them. • Composition • Which pegs go into which holes? • How to deal with dynamic and lexical pointcuts? • Complexity 61
  • 339. Obstacles • Abstraction • Competing forces: • Specs abstract internal details components, aspects directly manipulate them. • Composition • Which pegs go into which holes? • How to deal with dynamic and lexical pointcuts? • Complexity • What if no advice is applicable? 61
  • 341. Tackling Specification Complexity • May need to make assumptions about the behavior of evolving components. 62
  • 342. Tackling Specification Complexity • May need to make assumptions about the behavior of evolving components. • Specification pointcuts 62
  • 343. Tackling Specification Complexity • May need to make assumptions about the behavior of evolving components. • Specification pointcuts • Pointcut interfaces [Gudmundson ’01] annotated with behavioral specifications. 62
  • 344. Tackling Specification Complexity • May need to make assumptions about the behavior of evolving components. • Specification pointcuts • Pointcut interfaces [Gudmundson ’01] annotated with behavioral specifications. • “Exported” internal semantic events within the component. 62
  • 345. Tackling Specification Complexity • May need to make assumptions about the behavior of evolving components. • Specification pointcuts • Pointcut interfaces [Gudmundson ’01] annotated with behavioral specifications. • “Exported” internal semantic events within the component. • Adopt a rely-guarantee approach [Xu ’97] from concurrent programming to constrain the behavior of all possibly applicable advice using a rely clause. 62
  • 346. Tackling Specification Complexity • May need to make assumptions about the behavior of evolving components. • Specification pointcuts • Pointcut interfaces [Gudmundson ’01] annotated with behavioral specifications. • “Exported” internal semantic events within the component. • Adopt a rely-guarantee approach [Xu ’97] from concurrent programming to constrain the behavior of all possibly applicable advice using a rely clause. • A guar clause may be used to constrain components. 62
  • 347. Review of R/G for AOP [Khatchadourian07, Soundarajan07] the set of all variables of σ the program states in which each σi , σj , ... variable has a particular value 63
  • 348. 64
  • 350. 64
  • 352. !1 Aspect !2' !3
  • 353. 66
  • 354. !a Aspect !b 66
  • 355. The state at a point in the execution of a component is σa. !a Aspect !b 66
  • 356. The state at a point in the execution of a component is σa. !a Aspect !b The state when the class gets control back from an aspect is σb. 66
  • 357. The state at a point in the execution of a component is σa. !a Aspect rely(σa, σb) !b The state when the class gets control back from an aspect is σb. 66
  • 358. Rely() Example rely(σ, σ ) ≡ (σ = σ ) 67
  • 359. Rely() Example The entire state of C rely(σ, σ ) ≡ (σ = σ ) 67
  • 360. Rely() Example rely(σ, σ ) ≡ (σ = σ ) le y ab an lic g pp kin e! a a ny m stat s a om he id fr rb e t o ic F v in d ang es a ch 67
  • 361. Rely() Example This is “Harmless”[DW POPL’06] rely(σ, σ ) ≡ (σ = σ ) 67
  • 363. Deriving Effective Behavior • Constraining parameterized behavior reduces complexity, but ... 68
  • 364. Deriving Effective Behavior • Constraining parameterized behavior reduces complexity, but ... • How are formal parameters expressed? 68
  • 365. Deriving Effective Behavior • Constraining parameterized behavior reduces complexity, but ... • How are formal parameters expressed? • How are actual parameters deduced? 68
  • 366. Deriving Effective Behavior • Constraining parameterized behavior reduces complexity, but ... • How are formal parameters expressed? • How are actual parameters deduced? • How are the specifications composed? 68
  • 367. Deriving Effective Behavior • Constraining parameterized behavior reduces complexity, but ... • How are formal parameters expressed? • How are actual parameters deduced? • How are the specifications composed? • Aspects are typically used to enrich the behavior of the an underlying component. 68
  • 368. Deriving Effective Behavior • Constraining parameterized behavior reduces complexity, but ... • How are formal parameters expressed? • How are actual parameters deduced? • How are the specifications composed? • Aspects are typically used to enrich the behavior of the an underlying component. • Thus, desire to derive the actual behavior of components combined with the aspects. 68
  • 370. Join Point Traces • A Join Point Trace (JPT) variable is introduced to track the flow-of-control through various join points within a component. 69
  • 371. Join Point Traces • A Join Point Trace (JPT) variable is introduced to track the flow-of-control through various join points within a component. • A JPT is used as a parameter over the actions of all possibly applicable aspects. 69
  • 372. Join Point Traces • A Join Point Trace (JPT) variable is introduced to track the flow-of-control through various join points within a component. • A JPT is used as a parameter over the actions of all possibly applicable aspects. • Method post-conditions will references to the JPT. 69
  • 373. Join Point Traces • A Join Point Trace (JPT) variable is introduced to track the flow-of-control through various join points within a component. • A JPT is used as a parameter over the actions of all possibly applicable aspects. • Method post-conditions will references to the JPT. • Informally, a JPT is used to refer to the actions and resulting values taken by advice at certain join point. 69
  • 374. Elements of the JPT 70
  • 375. Elements of the JPT • The JPT is composed of several components that are associated with each join point. 70
  • 376. Elements of the JPT • The JPT is composed of several components that are associated with each join point. • Just as there are different kinds of join points (e.g., call, execution), there different kinds of JPT entries. 70
  • 377. JPT Method Call Completion Element (oid , mid , aid , args, res, σ, σ ) 71
  • 378. JPT Method Call Completion Element (oid , mid , aid , args, res, σ, σ ) Called Object 71
  • 379. JPT Method Call Completion Element Called Method (oid , mid , aid , args, res, σ, σ ) Called Object 71
  • 380. JPT Method Call Completion Element Called Method (oid , mid , aid , args, res, σ, σ ) Applicable Called Object Aspect 71
  • 381. JPT Method Call Completion Element Called Argument Method Values (oid , mid , aid , args, res, σ, σ ) Applicable Called Object Aspect 71
  • 382. JPT Method Call Completion Element Called Argument Method Values (oid , mid , aid , args, res, σ, σ ) Applicable Method Called Object Return Value Aspect 71
  • 383. JPT Method Call Completion Element σ, σ 71
  • 384. JPT Method Call Completion Element State Vectors σ, σ 71
  • 385. JPT Method Call Completion Element State Vectors σ, σ σ[oid] State of object oid after completion of method mid 71
  • 386. JPT Method Call Completion Element State Vectors σ, σ σ[oid] State of object oid after completion of method mid σ [oid] State of object oid after completion of aspect aid 71
  • 387. JPT Method Call Completion Element State Vectors σ, σ σ[oid] State of object oid after completion of method mid σ [oid] State of object oid after completion of aspect aid No applicable advice =⇒ σ = σ 71
  • 388. Rule for method specification 72
  • 389. Rule for method specification Normal pre-condition 72
  • 390. Rule for method specification Post-condition, may include references to portions of JPT 72
  • 391. Rule for method specification R/G Clauses 72
  • 392. Rule for method specification 72
  • 393. Rule for method specification 73
  • 394. Rule for method specification Invocation of C.m on the local JPT 73
  • 395. Rule for method specification 73
  • 396. Rule for method specification 74
  • 397. Rule for method specification Classic Hoare Triple 74
  • 398. Rule for method specification 74
  • 399. Rule for method specification 75
  • 400. Rule for method specification Don’t forget about the guarantee 75
  • 401. Rule for method specification 75
  • 402. Rule for method specification 76
  • 403. Rule for method specification If when q holds and applicable advice behaves properly implies that ... 76
  • 404. Rule for method specification 76
  • 405. Rule for method specification 77
  • 406. Rule for method specification ... our post- condition holds with a a new entry in the local JPT 77
  • 407. Rule for method specification Not sure which aspect is applicable yet, so we’ll leave this blank 77
  • 408. Rule for method specification Replace all occurrences of σ with σ’ 77
  • 409. Rule for Method Calls 78
  • 410. Rule for Method Calls 79
  • 411. Rule for Method Calls Substitute actuals for formals 79
  • 412. Rule for Method Calls 79
  • 413. Rule for Method Calls 80
  • 414. Rule for Method Calls Local JPT for caller 80
  • 415. Rule for Method Calls Local JPT for callee 80
  • 416. Rule for Method Calls Substitute formals for actuals 80
  • 417. Rule for Aspect Application (Simple) 81
  • 418. Rule for Aspect Application (Simple) Base-code plus an aspect 81
  • 419. Rule for Aspect Application (Simple) Base-code pre-condition 81
  • 420. Rule for Aspect Application (Simple) Aspect pre- condition 81
  • 421. Rule for Aspect Application (Simple) Base-code post-condition 81
  • 422. Rule for Aspect Application (Simple) Aspect post- condition 81
  • 423. Rule for Aspect Application (Simple) 82
  • 424. Rule for Aspect Application (Simple) Base-code satisfies guar 82
  • 425. Rule for Aspect Application (Simple) Advice body 82
  • 426. Rule for Aspect Application (Simple) State vector immediately prior to the execution of the advice 82
  • 427. Rule for Aspect Application (Simple) 83
  • 428. Future Work 84
  • 429. Future Work 84
  • 430. Future Work • (More) Complete axiomatic proof system. 84
  • 431. Future Work • (More) Complete axiomatic proof system. • Develop for a core calculus, expand as necessarily. 84
  • 432. Future Work • (More) Complete axiomatic proof system. • Develop for a core calculus, expand as necessarily. • Advice advising other advice. 84
  • 433. Future Work • (More) Complete axiomatic proof system. • Develop for a core calculus, expand as necessarily. • Advice advising other advice. • Multiple advice acting on a single join point. 84
  • 434. Future Work • (More) Complete axiomatic proof system. • Develop for a core calculus, expand as necessarily. • Advice advising other advice. • Multiple advice acting on a single join point. • Dealing with object aliasing. 84
  • 435. Future Work • (More) Complete axiomatic proof system. • Develop for a core calculus, expand as necessarily. • Advice advising other advice. • Multiple advice acting on a single join point. • Dealing with object aliasing. • Separation Logic [Ishtiaq, O’Hearn ’01] may help. 84
  • 436. Future Work 85
  • 437. Future Work • Curbing complexity: 85
  • 438. Future Work • Curbing complexity: • Specifications may (easily!) become unwieldy. 85
  • 439. Future Work • Curbing complexity: • Specifications may (easily!) become unwieldy. • Find suitable restrictions on aspects. 85
  • 440. Future Work • Curbing complexity: • Specifications may (easily!) become unwieldy. • Find suitable restrictions on aspects. • Module “sealing” ([Aldrich ’05]) 85
  • 441. Future Work • Curbing complexity: • Specifications may (easily!) become unwieldy. • Find suitable restrictions on aspects. • Module “sealing” ([Aldrich ’05]) • Advice not applicable to internal join points. 85
  • 442. Future Work • Curbing complexity: • Specifications may (easily!) become unwieldy. • Find suitable restrictions on aspects. • Module “sealing” ([Aldrich ’05]) • Advice not applicable to internal join points. • Semi-automation: 85
  • 443. Future Work • Curbing complexity: • Specifications may (easily!) become unwieldy. • Find suitable restrictions on aspects. • Module “sealing” ([Aldrich ’05]) • Advice not applicable to internal join points. • Semi-automation: • Integration with IDE/theorem provers, AJDT. 85
  • 444. Future Work • Curbing complexity: • Specifications may (easily!) become unwieldy. • Find suitable restrictions on aspects. • Module “sealing” ([Aldrich ’05]) • Advice not applicable to internal join points. • Semi-automation: • Integration with IDE/theorem provers, AJDT. • Extend specification languages (e.g., JML, Pipa) 85
  • 445. Conclusion 86
  • 447. Conclusion • Presented techniques to: 1. Mechanically alleviate burden of fragile pointcuts in Aspect-Oriented software. 86
  • 448. Conclusion • Presented techniques to: 1. Mechanically alleviate burden of fragile pointcuts in Aspect-Oriented software. 2.Automatically refactor legacy Java software to language enumerated (enum) types. 86
  • 449. Conclusion • Presented techniques to: 1. Mechanically alleviate burden of fragile pointcuts in Aspect-Oriented software. 2.Automatically refactor legacy Java software to language enumerated (enum) types. 3.Robustly specify evolving Aspect-Oriented software components. 86