Aspect Oriented Programming Aspect Oriented Software Development AOSD

  • Slides: 22
Download presentation
Aspect Oriented Programming

Aspect Oriented Programming

Aspect Oriented Software Development (AOSD) Emerging technologies that seek new modularizations of software systems

Aspect Oriented Software Development (AOSD) Emerging technologies that seek new modularizations of software systems n Modularization is an important theme in software engineering n “Separation and Localization of concerns” n Traditional engineering : decompose system into units of core functionality n 2

Concerns Core concerns vs. crosscutting concerns (eg. security). n AOP – programming with multiple

Concerns Core concerns vs. crosscutting concerns (eg. security). n AOP – programming with multiple crosscutting concerns or aspects. n Express each concerns in its own module. n 3

Terminology (1) Concern – is a particular goal, concept, or area of interest. An

Terminology (1) Concern – is a particular goal, concept, or area of interest. An engineering process deals with many concerns. High level vs. low level, localized vs. system wide. n Crosscutting concerns – concerns that in conventional implementations cannot be implemented without scattering code. n 4

Terminology (2) Code tangling – in conventional environments, implementing crosscutting concerns is scattered in

Terminology (2) Code tangling – in conventional environments, implementing crosscutting concerns is scattered in many modules. n Code scattering n – Duplicated code blocks – Complementary code blocks 5

good modularity XML parsing n XML parsing in org. apache. tomcat – – red

good modularity XML parsing n XML parsing in org. apache. tomcat – – red shows relevant lines of code nicely fits in one box 6

good modularity URL pattern matching n URL pattern matching in org. apache. tomcat –

good modularity URL pattern matching n URL pattern matching in org. apache. tomcat – – red shows relevant lines of code nicely fits in two boxes (using inheritance) 7

logging is not modularized… n where is logging in org. apache. tomcat – –

logging is not modularized… n where is logging in org. apache. tomcat – – – red shows lines of code that handle logging not in just one place not even in a small number of places 8

session expiration is not modularized… Standard. Session Application. Session /* * ================================== * *

session expiration is not modularized… Standard. Session Application. Session /* * ================================== * * The Apache Software License, Version 1. 1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement : * "This product includes software developed by the * Apache Software Foundation (http: //www. apache. org/). " * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache. org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http: //www. apache. org/>. * * [Additional notices, if required by prior licensing conditions] * */ public void invalidate() { server. Session. remove. Application. Session(context package org. apache. tomcat. session; // remove everything in the session Enumeration enum = values. keys(); while ( enum. has. More. Elements ()) { String name = ( String)enum. next. Element (); remove. Value(name ); } valid = false; } public boolean is. New () { if (! valid) { String msg = sm. get. String("application. Session. session. ise "); throw new Illegal. State. Exception(msg ); } if ( this. Access. Time == creation. Time ) { return true; } else { return false; } } /** * @deprecated */ public void put. Value(String name, Object value) { set. Attribute(name , value); } public void set. Attribute(String name, Object value) { if (! valid) { String msg = sm. get. String("application. Session. session. ise "); throw new Illegal. State. Exception(msg ); } if (name == null) { String msg = sm. get. String("application. Session. value. iae import org. apache. tomcat. core. *; import org. apache. tomcat. util. String. Manager ; import java. io. *; import java. net. *; import java. util. *; import javax. servlet. http. *; ; /** * Standard implementation of the <b>Session</b> interface. This object is * serializable , so that it can be stored in persistent storage or transferred * to a different JVM for distributable session support. * <p> * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * internal (Session) and application level (Http. Session ) view of the session. * However, because the class itself is not declared public, Java logic outside * of the <code>org. apache. tomcat. session</code> package cannot cast an * Http. Session view of this instance back to a Session view. * * @author Craig R. Mc. Clanahan * @version $Revision: 1. 2 $ $Date: 2000/05/15 17: 54: 10 $ */ // ----------------------------- Constructors (( Http. Session. Binding. Listener)value). value. Bound(e } ); values. put(name, value); } /** * Construct a new Session associated with the specified Manager. * * @ param manager The manager with which this Session is associated */ public Standard. Session(Manager manager) { super(); this. manager = manager; "); throw new Illegal. Argument. Exception(msg ); } return values. get(name); } /** * The collection of user data attributes associated with this Session. */ private Hashtable attributes = new Hashtable (); /** * The time this session was created, in milliseconds since midnight, * January 1, 1970 GMT. */ private long creation. Time = 0 L; /** * The session identifier of this Session. */ private String id = null; /** * @deprecated */ public String[] get. Value. Names () { Enumeration e = get. Attribute. Names (); Vector names = new Vector(); /** * Descriptive information describing this Session implementation. */ private static final String info = "Standard. Session/1. 0"; while ( e. has. More. Elements ()) { names. add. Element(e. next. Element ()); } String[] value. Names = new String[names. size()]; names. copy. Into(value. Names ); /** * The last accessed time for this Session. */ private long last. Accessed. Time = creation. Time ; return value. Names ; } if ( this. inactive. Interval != -1) { this. inactive. Interval *= 60; } } public Enumeration get. Attribute. Names () { if (! valid) { String msg = sm. get. String("application. Session. session. ise Server. Session get. Server. Session () { return server. Session ; } "); throw new Illegal. State. Exception(msg ); } /** * The Manager with which this Session is associated. */ private Manager manager = null; Hashtable values. Clone = ( Hashtable)values. clone (); /** * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. */ validate(); } void validate() { // if we have an inactive interval, check to see if we've exceeded it if ( inactive. Interval != -1) { int this. Interval = ( int)(System. current. Time. Millis () - last. Accessed ) / 1000; if ( this. Interval > inactive. Interval ) { invalidate(); } } // HTTP SESSION IMPLEMENTATION METHODS public String get. Id () { if (valid) { return id; } else { String msg = sm. get. String("application. Session. session. ise public void remove. Value(String name) { remove. Attribute(name ); } public void remove. Attribute(String name) { if (! valid) { String msg = sm. get. String("application. Session. session. ise "); throw new Illegal. State. Exception(msg ); } "); /** * Flag indicating whether this session is new or not. */ private boolean is. New = true; /** * Flag indicating whether this session is valid or not. */ private boolean is. Valid = false; throw new Illegal. Argument. Exception(msg ); } /** * The string manager for this package. */ private String. Manager sm = String. Manager. get. Manager("org. apache. tomcat. se ssion "); Object o = values. get(name); if (o instanceof Http. Session. Binding. Listener ) { Http. Session. Binding. Event e = new Http. Session. Binding. Event(this, name ); "); (( Http. Session. Binding. Listener)o). value. Unbound(e } public void set. Max. Inactive. Interval(int interval) { if (! valid) { String msg = sm. get. String("application. Session. session. ise "); /** * The HTTP session context associated with this session. */ private static Http. Session. Context session. Context = null; "); /** * The current accessed time for this session. */ private long this. Accessed. Time = creation. Time ; throw new Illegal. State. Exception(msg ); } inactive. Interval = interval; } public int get. Max. Inactive. Interval () { if (! valid) { String msg = sm. get. String("application. Session. session. ise "); throw new Illegal. State. Exception(msg ); } return inactive. Interval ; } } //-----------------------------------"); this. last. Accessed. Time = this. Accessed. Time ; this. Accessed. Time = System. current. Time. Millis (); this. New =false; } /** * Perform the internal processing required to invalidate this session, * without triggering an exception if the session has already expired. */ public void expire() { // Remove this session from our manager's active sessions if ((manager != null) && (manager instanceof Manager. Base )) (( Manager. Base ) manager). remove(this); // Unbind any objects associated with this session Vector results = new Vector(); Enumeration attrs = get. Attribute. Names (); while ( attrs. has. More. Elements ()) { String attr = (String) attrs. next. Element (); results. add. Element(attr ); } Enumeration names = results. elements(); while ( names. has. More. Elements ()) { String name = (String) names. next. Element (); remove. Attribute(name ); } // Mark this session as invalid set. Valid(false ); /** * Release all object references, and initialize instance variables, in * preparation for reuse of this object. */ public void recycle() { // Reset the instance variables associated with this Session attributes. clear(); creation. Time = 0 L; id = null; last. Accessed. Time = 0 L; manager = null; max. Inactive. Interval = -1; is. New = true; is. Valid = false; // Tell our Manager that this Session has been recycled if ((manager != null) && (manager instanceof Manager. Base )) (( Manager. Base ) manager). recycle(this); } // ------------------------ Session Package Methods /** * Return the <code> is. Valid </code> flag for this session. */ boolean is. Valid () { return ( this. Valid ); } /** * Set the <code> is. New </code> flag for this session. * * @ param is. New The new value for the <code> is. New </code> flag */ void set. New(boolean is. New ) { // -------------------------- Session Properties /** * Set the creation time for this session. This method is called by the * Manager when an existing Session instance is reused. * * @ param time The new creation time */ public void set. Creation. Time(long time) { throw new Illegal. State. Exception(msg ); } } this. creation. Time = time; this. last. Accessed. Time = time; this. Accessed. Time = time; } /** * Return the session identifier for this session. */ public String get. Id () { /** * Bind an object to this session, using the specified name. If an object * of the same name is already bound to this session, the object is * replaced. * <p> * After this method executes, and if the object implements * <code> Http. Session. Binding. Listener </code>, the container calls * <code> value. Bound ()</code> on the object. * * @ param name Name to which the object is bound, cannot be null * @ param value Object to be bound, cannot be null * * @exception Illegal. State. Exception if this method is called on an * invalidated session * * @deprecated As of Version 2. 2, this method is replaced by * <code> set. Attribute ()</code> */ public void put. Value(String name, Object value) { set. Attribute(name , value); } /** * Remove the object bound with the specified name from this session. If * the session does not have an object bound with this name, this method * does nothing. * <p> * After this method executes, and if the object implements * <code> Http. Session. Binding. Listener </code>, the container calls * <code> value. Unbound ()</code> on the object. * * @ param name Name of the object to remove from this session. * * @exception Illegal. State. Exception if this method is called on an * invalidated session */ public void remove. Attribute(String name) { synchronized (attributes) { Object object = attributes. get(name); if (object == null) return; attributes. remove(name); // System. out. println ( "Removing attribute " + name ); if (object instanceof Http. Session. Binding. Listener ) { (( Http. Session. Binding. Listener ) object). value. Unbound (new Http. Session. Binding. Event((Http. Session ) this, name)); } } /** * Remove the object bound with the specified name from this session. If * the session does not have an object bound with this name, this method * does nothing. * <p> * After this method executes, and if the object implements * <code> Http. Session. Binding. Listener </code>, the container calls * <code> value. Unbound ()</code> on the object. * * @ param name Name of the object to remove from this session. * * @exception Illegal. State. Exception if this method is called on an * invalidated session * * @deprecated As of Version 2. 2, this method is replaced by * <code> remove. Attribute ()</code> */ public void remove. Value(String name) { remove. Attribute(name ); /** * Bind an object to this session, using the specified name. If an object * of the same name is already bound to this session, the object is * replaced. * <p> * After this method executes, and if the object implements * <code> Http. Session. Binding. Listener </code>, the container calls * <code> value. Bound ()</code> on the object. * * @ param name Name to which the object is bound, cannot be null * @ param value Object to be bound, cannot be null * * @exception Illegal. Argument. Exception if an attempt is made to add a * non- serializable object in an environment marked distributable. * @exception Illegal. State. Exception if this method is called on an * invalidated session */ public void set. Attribute(String name, Object value) { /** * Read a serialized version of this session object from the specified * object input stream. * <p> * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager * is not restored by this method, and must be set explicitly. * * @ param stream The input stream to read from * * @exception Class. Not. Found. Exception if an unknown class is specified * @exception IOException if an input/output error occurs */ private void read. Object(Object. Input. Stream stream) throws Class. Not. Found. Exception , IOException { this. Valid = is. Valid ; } // ------------------------- Http. Session Properties /** * Return the time when this session was created, in milliseconds since * midnight, January 1, 1970 GMT. * * @exception Illegal. State. Exception if this method is called on an * invalidated session */ public long get. Creation. Time () { return ( this. creation. Time ); } Http. Session Private Methods // Deserialize the scalar instance variables (except Manager) creation. Time = ((Long) stream. read. Object()). long. Value (); id = (String) stream. read. Object (); last. Accessed. Time = ((Long) stream. read. Object()). long. Value (); max. Inactive. Interval = ((Integer) stream. read. Object()). int. Value (); is. New = ((Boolean) stream. read. Object()). boolean. Value (); is. Valid = ((Boolean) stream. read. Object()). boolean. Value (); public final class Standard. Manager extends Manager. Base implements Lifecycle, Runnable { // --------------------------- Instance Variables // Deserialize the attribute count and attribute values int n = ((Integer) stream. read. Object()). int. Value (); for ( int i = 0; i < n; i++) { String name = (String) stream. read. Object (); Object value = (Object) stream. read. Object (); attributes. put(name, value); } /** * The interval (in seconds) between checks for expired sessions. */ private int check. Interval = 60; /** * Has this component been configured yet? */ private boolean configured = false; } /** * Return the session context with which this session is associated. * * @deprecated As of Version 2. 1, this method is deprecated and has no * replacement. It will be removed in a future version of the * Java Servlet API. */ public Http. Session. Context get. Session. Context () { if ( session. Context == null) session. Context = new Standard. Session. Context (); return ( session. Context ); } // -----------------------Http. Session Public Methods /** * Return the object bound with the specified name in this session, or * <code>null</code> if no object is bound with that name. * * @ param name Name of the attribute to be returned * * @exception Illegal. State. Exception if this method is called on an * invalidated session */ public Object get. Attribute(String name) { return (attributes. get(name)); return (this. id); } if ((this. id != null) && (manager != null) && (manager instanceof Manager. Base )) (( Manager. Base ) manager). remove(this); /** * Return an <code>Enumeration</code> of <code>String</code> objects * containing the names of the objects bound to this session. * * @exception Illegal. State. Exception if this method is called on an * invalidated session */ public Enumeration get. Attribute. Names () { this. id = id; return (attributes. keys()); if ((manager != null) && (manager instanceof Manager. Base )) (( Manager. Base ) manager). add(this); } Server. Sess on } /** * Return descriptive information about this Session implementation and * the corresponding version number, in the format * <code>& lt; description> /< version&gt ; </code>. */ public String get. Info () { return (this. info); /** * Return the object bound with the specified name in this session, or * <code>null</code> if no object is bound with that name. * * @ param name Name of the value to be returned * * @exception Illegal. State. Exception if this method is called on an * invalidated session * * @deprecated As of Version 2. 2, this method is replaced by * <code> get. Attribute ()</code> */ public Object get. Value(String name) { } return ( get. Attribute(name )); /** * 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 get. Last. Accessed. Time () { /** * The string manager for this package. */ private String. Manager sm = String. Manager. get. Manager("org. apache. tomcat. session return ( this. last. Accessed. Time ); } /** * Return the Manager within which this Session is valid. */ public Manager get. Manager () { return (this. manager); } /** * Set the Manager within which this Session is valid. * * @ param manager The new Manager */ public void set. Manager(Manager manager) { this. manager = manager; } /** * Return the maximum time interval, in seconds, between client requests * before the servlet container will invalidate the session. A negative * time indicates that the session should never time out. * * @exception Illegal. State. Exception if this method is called on * an invalidated session */ public int get. Max. Inactive. Interval () { return ( this. max. Inactive. Interval ); } /** * Set the maximum time interval, in seconds, between client requests * before the servlet container will invalidate the session. A negative * time indicates that the session should never time out. * * @ param interval The new maximum interval */ public void set. Max. Inactive. Interval(int interval) { private Vector dummy = new Vector(); /** * Return the session identifiers of all sessions defined * 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. */ public Enumeration get. Ids () { } return (dummy. elements()); /** * Invalidates this session and unbinds any objects bound to it. * * @exception Illegal. State. Exception if this method is called on * 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 Illegal. State. Exception if this method is called on an * invalidated session */ public boolean is. New () { return ( this. New ); } } /** * Return the <code> Http. Session </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 Http. Session get. Session(String id) { ")); import org. apache. tomcat. core. Session. Manager ; import org. apache. tomcat. util. Session. Util ; /** * Mark the specified session's last accessed time. This should be * called for each request by a Request. Interceptor. * * @ param session The session to be marked */ public void accessed(Context ctx, Request req, String id) { Http. Session session= find. Session(ctx , id); if( session == null) return; /** * <p> if (session instanceof Session) * <p> // Parse and process our configuration parameters if (!(" Manager". equals(parameters. get. Node. Name ()))) return; Named. Node. Map attributes = parameters. get. Attributes (); Node node = null; node = attributes. get. Named. Item("check. Interval "); if (node != null) { try { set. Check. Interval(Integer. parse. Int(node. get. Node. Value } catch ( Throwable t) { ; // XXX - Throw exception? } // cache the Http. Session - avoid another find req. set. Session ( session ); * XXX - At present, use of <code> Standard. Manager </code> is hard coded, } * and lifecycle configuration is not supported. // XXX should we throw exception or just return null ? ? * <b>IMPLEMENTATION NOTE</b>: Once we commit to the new Manager/Session public Http. Session find. Session ( Context ctx, String id ) { * paradigm, I would suggest moving the logic implemented here back into try { * the core level. The Tomcat. Next "Manager" interface acts more like a Session session = manager. find. Session(id ); * collection class, and has minimal knowledge of the detailed request if(session!=null) * processing semantics of handling sessions. return session. get. Session (); * <p> } catch ( IOException e) { * XXX - At present, there is no way (via the Session. Manager interface) } for ())); node = attributes. get. Named. Item("max. Active. Sessions "); if (node != null) { try { set. Max. Active. Sessions(Integer. parse. Int(node. get. Node. Value } catch ( Throwable t) { ; // XXX - Throw exception? } return (null); * a Context to tell the Manager that we create what the default session * timeout for this web application (specified in the deployment descriptor) * should be. ())); * * @author Craig R. Mc. Clanahan } public Http. Session create. Session(Context ctx) { return manager. create. Session(). get. Session (); } */ /** node = attributes. get. Named. Item("max. Inactive. Interval "); if (node != null) { try { set. Max. Inactive. Interval(Integer. parse. Int(node. get. Node. Value } catch ( Throwable t) { ; // XXX - Throw exception? } public final class Standard. Session. Manager implements Session. Manager { * Remove all sessions because our associated Context is being shut down. * ())); /** * Prepare for the beginning of active use of the public methods of this * component. This method should be called after <code>configure()</code>, * and before any of the public methods of the component are utilized. * * @exception Illegal. State. Exception if this component has not yet been * configured (if required for this component) * @exception Illegal. State. Exception if this component has already been * started * @exception Lifecycle. Exception if this component detects a fatal error * that prevents this component from being used */ public void start() throws Lifecycle. Exception { * @ param ctx The context that is being shut down // ------------------------------ Constructors */ public void remove. Sessions(Context ctx) { // Start the background reaper thread thread. Start (); /** * The background thread completion semaphore. */ private boolean thread. Done = false; manager = new Standard. Manager (); if (manager instanceof Lifecycle) { try { ((Lifecycle) manager). configure(null); } catch ( Lifecycle. Exception e) { throw new Illegal. State. Exception ("" + e); } ((Lifecycle) manager). start(); } catch ( Lifecycle. Exception e) { } throw new Illegal. State. Exception ("" + e); } /** * Used by context to configure the session manager's inactivity timeout. * * The Session. Manager may have some default session time out, the * Context on the other hand has it's timeout set by the deployment * descriptor ( web. xml ). This method lets the Context conforgure the // --------------------------- Instance * session manager according to this value. Variables // ------------------------------- Properties /** * Gracefully terminate the active use of the public methods of this * component. This method should be the last one called on a given * instance of this component. * * @exception Illegal. State. Exception if this component has not been started * @exception Illegal. State. Exception if this component has already * been stopped * @exception Lifecycle. Exception if this component detects a fatal error * that needs to be reported */ public void stop() throws Lifecycle. Exception { /** * Return the check interval (in seconds) for this Manager. */ public int get. Check. Interval () { // Validate and update our current component state if (!started) throw new Lifecycle. Exception ( sm. get. String("standard. Manager. not. Started ")); started = false; /** * Name to register for the background thread. */ private String thread. Name = "Standard. Manager "; // contexts, we just want to remove the sessions of ctx! * Create a new Session. Manager that adapts to the corresponding // The manager will still run after that ( i. e. keep database Manager // connection open * implementation. if (manager instanceof Lifecycle) { */ try { public Standard. Session. Manager () { ((Lifecycle) manager). stop(); } } * * @ param minutes The session inactivity timeout in minutes. /** * The Manager implementation we are actually using. */ private Manager manager = null; */ public void set. Session. Time. Out(int minutes) { if(-1 != minutes) { // The manager works with seconds. . . manager. set. Max. Inactive. Interval(minutes * 60); } } } // Stop the background reaper thread thread. Stop (); return ( this. check. Interval ); } Server. Session. Manager // ------------------------------- Private Class Vector results = new Vector(); Enumeration attrs = get. Attribute. Names (); while ( attrs. has. More. Elements ()) { String attr = (String) attrs. next. Element (); results. add. Element(attr ); } String names[] = new String[results. size()]; for ( int i = 0; i < names. length; i++) names[i] = (String) results. element. At(i ); return (names); import org. apache. tomcat. core. Response; ((Session) session). access(); * Specialized implementation of org. apache. tomcat. core. Session. Manager // Validate and update our current component state if (!configured) throw new Lifecycle. Exception ( sm. get. String("standard. Manager. not. Configured ")); if (started) throw new Lifecycle. Exception ( sm. get. String("standard. Manager. already. Started ")); started = true; /** * The background thread. */ private Thread thread = null; // Serialize the attribute count and the attribute values stream. write. Object(new Integer(results. size())); Enumeration names = results. elements(); while ( names. has. More. Elements ()) { String name = (String) names. next. Element (); stream. write. Object(name ); stream. write. Object(attributes. get(name )); } final class Standard. Session. Context implements Http. Session. Context { import org. apache. tomcat. core. Request; * that adapts to the new component-based Manager implementation. "); /** * Has this component been started yet? */ private boolean started = false; // Accumulate the names of serializable attributes Vector results = new Vector(); Enumeration attrs = get. Attribute. Names (); while ( attrs. has. More. Elements ()) { String attr = (String) attrs. next. Element (); Object value = attributes. get(attr ); if (value instanceof Serializable ) results. add. Element(attr ); } /** * This class is a dummy implementation of the <code> Http. Session. Context </code> * interface, to conform to the requirement that such an object be returned * when <code> Http. Session. get. Session. Context ()</code> is called. * * @author Craig R. Mc. Clanahan * * @deprecated As of Java Servlet API 2. 1 with no replacement. The * interface will be removed in a future version of this API. */ import org. apache. tomcat. catalina. *; import org. apache. tomcat. core. Context; /** * The maximum number of active Sessions allowed, or -1 for no limit. */ protected int max. Active. Sessions = -1; } /** * Return the set of names of objects bound to this session. If there * are no such objects, a zero-length array is returned. * * @exception Illegal. State. Exception if this method is called on an * invalidated session * * @deprecated As of Version 2. 2, this method is replaced by * <code> get. Attribute. Names ()</code> */ public String[] get. Value. Names () { // Validate and update our current component state if (configured) throw new Lifecycle. Exception ( sm. get. String("standard. Manager. already. Configured configured = true; if (parameters == null) return; import javax. servlet. http. Cookie ; import javax. servlet. http. Http. Session ; // XXX a manager may be shared by multiple /** * The descriptive information about this implementation. */ private static final String info = "Standard. Manager/1. 0"; // Write the scalar instance variables (except Manager) stream. write. Object(new Long(creation. Time )); stream. write. Object(id ); stream. write. Object(new Long(last. Accessed. Time )); stream. write. Object(new Integer(max. Inactive. Interval )); stream. write. Object(new Boolean(is. New )); stream. write. Object(new Boolean(is. Valid )); } crosscut invalidate(Standard. Session s): s & ( int get. Max. Inactive. Interval () | long get. Creation. Time () | Object get. Attribute(String ) | Enumeration get. Attribute. Names () | String[] get. Value. Names () | void invalidate() | boolean is. New () | void remove. Attribute(String ) | void set. Attribute(String , Object)); static advice(Standard. Session s): invalidate(s) { before { if (! s. is. Valid ()) throw new Illegal. State. Exception ( s. sm. get. String("standard. Session. " + this. Join. Point. method. Name + ". ise")); } } } /** * Configure this component, based on the specified configuration * parameters. This method should be called immediately after the * component instance is created, and before <code>start()</code> * is called. * * @ parameters Configuration parameters for this component * (<B>FIXME: What object type should this really be? ) * * @exception Illegal. State. Exception if this component has already been * configured and/or started * @exception Lifecycle. Exception if this component detects a fatal error * in the configuration parameters it was given */ public void configure(Node parameters) throws Lifecycle. Exception { } /** * Write a serialized version of this session object to the specified * object output stream. * <p> * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored * in the serialized representation of this Session. After calling * <code> read. Object ()</code>, you must set the associated Manager * explicitly. * <p> * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable * will be silently ignored. If you do not want any such attributes, * be sure the <code>distributable</code> property of our associated * Manager is set to <code>true</code>. * * @ param stream The output stream to write to * * @exception IOException if an input/output error occurs */ private void write. Object(Object. Output. Stream stream) throws IOException { } /** * Set the session identifier for this session. * * @ param id The new session identifier */ public void set. Id(String id) { // ----------------------------- Public Methods import java. io. IOException ; /** * Standard implementation of the <b>Manager</b> interface that provides * no session persistence or distributable capabilities, but does support * an optional, configurable, maximum number of active sessions allowed. * <p> * Lifecycle configuration of this component assumes an XML node * in the following format: * <code> * & lt; Manager class. Name ="org. apache. tomcat. session. Standard. Manager " * check. Interval ="60" max. Active. Sessions ="-1" * max. Inactive. Interval ="-1" /> * </code> * where you can adjust the following parameters, with default values * in square brackets: * <ul> * <li><b>check. Interval </b> - The interval (in seconds) between background * thread checks for expired sessions. [60] * <li><b>max. Active. Sessions </b> - The maximum number of sessions allowed to * be active at once, or -1 for no limit. [-1] * <li><b>max. Inactive. Interval </b> - The default maximum number of seconds of * inactivity before which the servlet container is allowed to time out * a session, or -1 for no limit. This value should be overridden from * the default session timeout specified in the web application deployment * descriptor, if any. [-1] * </ ul> * * @author Craig R. Mc. Clanahan * @version $Revision: 1. 1 $ $Date: 2000/05/02 21: 28: 30 $ */ this. New = is. New ; /** * Set the <code> is. Valid </code> flag for this session. * * @ param is. Valid The new value for the <code> is. Valid </code> flag */ void set. Valid(boolean is. Valid ) { package org. apache. tomcat. session; // --------------------------- Lifecycle Methods synchronized (attributes) { remove. Attribute(name ); attributes. put(name, value); if (value instanceof Http. Session. Binding. Listener ) (( Http. Session. Binding. Listener ) value). value. Bound (new Http. Session. Binding. Event((Http. Session ) this, name)); } // ---------------------- Standard. Session. Manager package org. apache. tomcat. session; import java. io. IOException ; import java. util. Enumeration; import java. util. Hashtable ; import java. util. Vector; import org. apache. tomcat. catalina. *; import javax. servlet. http. Cookie ; import javax. servlet. http. Http. Session ; import org. apache. tomcat. util. String. Manager ; import org. w 3 c. dom. Named. Node. Map; import org. w 3 c. dom. Node; if ((manager != null) && manager. get. Distributable () && !(value instanceof Serializable )) throw new Illegal. Argument. Exception ( sm. get. String("standard. Session. set. Attribute. iae ")); } Standard. Manager Sess on n ercep or } } ); values. remove(name); } throw new Illegal. State. Exception(msg ); } } /** * * @deprecated */ public Http. Session. Context get. Session. Context () { return new Session. Context. Impl (); } public long get. Last. Accessed. Time () { if (valid) { return last. Accessed ; } else { String msg = sm. get. String("application. Session. session. ise /** * @deprecated */ if (name == null) { String msg = sm. get. String("application. Session. value. iae throw new Illegal. State. Exception(msg ); } } public long get. Creation. Time () { if (valid) { return creation. Time ; } else { String msg = sm. get. String("application. Session. session. ise /** * The maximum time interval, in seconds, between client requests before * the servlet container may invalidate this session. A negative time * indicates that the session should never time out. */ private int max. Inactive. Interval = -1; return ( Enumeration)values. Clone. keys (); } void accessed() { // set last accessed to this. Access. Time as it will be left over // from the previous access last. Accessed = this. Access. Time ; this. Access. Time = System. current. Time. Millis (); /** * Update the accessed time information for this session. This method * should be called by the context when a request comes in for a particular * session, even if the application does not reference it. */ public void access() { } // -------------------------- Instance Variables if (name == null) { String msg = sm. get. String("application. Session. value. iae this. inactive. Interval = context. get. Session. Time. Out (); // ------------------------- Session Public Methods } throw new Illegal. State. Exception(msg ); } Application. Session(String id, Server. Session server. Session , Context context) { this. server. Session = server. Session ; this. context = context; this. id = id; } final class Standard. Session implements Http. Session , Session { public class Application. Session implements Http. Session { private String. Manager sm = String. Manager. get. Manager("org. apache. tomcat. session "); private Hashtable values = new Hashtable (); private String id; private Server. Session server. Session ; private Context context; private long creation. Time = System. current. Time. Millis (); ; private long this. Access. Time = creation. Time ; private long last. Accessed = creation. Time ; private int inactive. Interval = -1; private boolean valid = true; return (( Http. Session ) this); remove. Value(name ); // remove any existing binding if (value != null && value instanceof Http. Session. Binding. Listener ) { Http. Session. Binding. Event e = new Http. Session. Binding. Event(this , name); public Object get. Attribute(String name) { if (! valid) { String msg = sm. get. String("application. Session. session. ise /** * Core implementation of an application level session * * @author James Duncan Davidson [ duncan@eng. sun. com ] * @author Jason Hunter [ jch@eng. sun. com ] * @author James Todd [gonzo@eng. sun. com] */ import java. io. IOException ; import java. io. Object. Input. Stream ; import java. io. Object. Output. Stream ; import java. io. Serializable ; import java. util. Enumeration; import java. util. Hashtable ; import java. util. Vector; import javax. servlet. Servlet. Exception ; import javax. servlet. http. Http. Session. Binding. Event ; import javax. servlet. http. Http. Session. Binding. Listener import javax. servlet. http. Http. Session. Context ; import org. apache. tomcat. catalina. *; import org. apache. tomcat. util. String. Manager ; "); throw new Illegal. Argument. Exception(msg ); } /** * @deprecated */ public Object get. Value(String name) { return get. Attribute(name ); } package org. apache. tomcat. session; /** * Return the <code> Http. Session </code> for which this object * is the facade. */ public Http. Session get. Session () { ); /** * Set the check interval (in seconds) for this Manager. * * @ param check. Interval The new check interval */ public void set. Check. Interval(int check. Interval ) { // Expire all active sessions Session sessions[] = find. Sessions (); for ( int i = 0; i < sessions. length; i++) { Standard. Session session = ( Standard. Session ) sessions[i]; if (! session. is. Valid ()) continue; session. expire(); } this. check. Interval = check. Interval ; } } // ---------------------------- Private Methods /** * Return descriptive information about this Manager implementation and * the corresponding version number, in the format * <code>& lt; description> /< version&gt ; </code>. */ public String get. Info () { package org. apache. tomcat. session; import org. apache. tomcat. util. *; import org. apache. tomcat. core. *; import java. io. *; import java. net. *; import java. util. *; import javax. servlet. http. *; /** * * @author James Duncan Davidson [ duncan@eng. sun. com ] * @author Jason Hunter [ jch@eng. sun. com ] * @author James Todd [gonzo@eng. sun. com] */ public class Server. Session. Manager implements Session. Manager { private String. Manager sm = String. Manager. get. Manager("org. apache. tomcat. session "); private static Server. Session. Manager manager; // = new Server. Session. Manager (); // 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. synchronized void reap() { Enumeration enum = sessions. keys(); while ( enum. has. More. Elements ()) { Object key = enum. next. Element (); Server. Session session = ( Server. Session)sessions. get(key ); session. reap(); session. validate(); } } synchronized void remove. Session(Server. Session session) { String id = session. get. Id (); session. invalidate(); sessions. remove(id); } static { manager = new Server. Session. Manager (); } public static Server. Session. Manager get. Manager () { return manager; } private Hashtable sessions = new Hashtable (); private Reaper reaper; private Server. Session. Manager () { reaper = Reaper. get. Reaper (); reaper. set. Server. Session. Manager(this ); reaper. start(); } return (null); public void accessed( Context ctx, Request req, String id ) { Application. Session ap. S=(Application. Session)find. Session ( ctx, id); if( ap. S==null) return; } Server. Session serv. S =ap. S. get. Server. Session (); serv. S. accessed (); ap. S. accessed (); // cache it - no need to compute it again req. set. Session ( ap. S ); } public Http. Session create. Session(Context ctx) { String session. Id = Session. Id. Generator. generate. Id (); Server. Session session = new Server. Session(session. Id ); sessions. put(session. Id , session); if(-1 != inactive. Interval ) { session. set. Max. Inactive. Interval(inactive. Interval ); } return session. get. Application. Session ( ctx, true ); } public Http. Session find. Session(Context ctx, String id) { Server. Session s. Session =(Server. Session)sessions. get(id ); if(s. Session ==null) return null; this. max. Inactive. Interval = interval; return s. Session. get. Application. Session(ctx , false); } } } /** * Return the maximum number of active Sessions allowed, or -1 for * no limit. */ public int get. Max. Active. Sessions () { return ( this. max. Active. Sessions ); } /** * Set the maximum number of actives Sessions allowed, or -1 for * no limit. * * @ param max The new maximum number of sessions */ public void set. Max. Active. Sessions(int max) { public void remove. Sessions(Context context) { Enumera for ( int i = 0; i < sessions. length; i++) { Standard. Session session = ( Standard. Session ) sessions[i]; if (! session. is. Valid ()) continue; int max. Inactive. Interval = session. get. Max. Inactive. Interval (); if ( max. Inactive. Interval < 0) continue; int time. Idle = // Truncate, do not round up ( int) (( time. Now - session. get. Last. Accessed. Time ()) / 1000 L); if ( time. Idle >= max. Inactive. Interval ) session. expire(); } } /** * Sleep for the duration specified by the <code> * property. */ private void thread. Sleep () { check. Interval </code> try { Thread. sleep(check. Interval * 1000 L); } catch ( Interrupted. Exception e) { ; } this. max. Active. Sessions = max; protected int inactive. Interval = -1; /** * Invalidate all sessions that have expired. */ private void process. Expires () { long time. Now = System. current. Time. Millis (); Session sessions[] = find. Sessions (); return (this. info); } // ----------------------------- Public Methods } /** * Construct and return a new session object, based on the default * settings specified by this Manager's properties. The session * id will be assigned by this method, and available via the get. Id () * method of the returned session. If a new session cannot be created * for any reason, return <code>null</code>. * * @exception Illegal. State. Exception if a new session cannot be * instantiated for any reason */ public Session create. Session () { /** * Start the background thread that will periodically check for * session timeouts. */ private void thread. Start () { if (( max. Active. Sessions >= 0) && (sessions. size() >= max. Active. Sessions )) throw new Illegal. State. Exception ( sm. get. String("standard. Manager. create. Session. ise return ( super. create. Session ()); } if (thread != null) return; thread. Done = false; thread = new Thread(this, thread. Name ); thread. set. Daemon(true ); thread. start(); } ")); /** * Stop the background thread that is periodically checking for * session timeouts. */ private void thread. Stop () { if (thread == null) return; thread. Done = true; thread. interrupt(); try { thread. join(); } catch ( Interrupted. Exception e) { ; } thread = null; } // --------------------------- Background Thread /** * The background thread that checks for session timeouts and shutdown. */ public void run() { // Loop until the termination semaphore is set while (! thread. Done ) { thread. Sleep (); process. Expires (); } } } 9

Implications of Non-modularization n Redundant code n Difficult to reason about n Difficult to

Implications of Non-modularization n Redundant code n Difficult to reason about n Difficult to change – same fragment of code in many places – non-explicit structure – the big picture of the tangling isn’t clear – have to find all the code involved – and be sure to change it consistently – and be sure not to break it by accident 10

If we just could… App ca on. Sess on Application. Session /* * ==================================

If we just could… App ca on. Sess on Application. Session /* * ================================== * * The Apache Software License, Version 1. 1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement : * "This product includes software developed by the * Apache Software Foundation (http: //www. apache. org/). " * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache. org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http: //www. apache. org/>. * * [Additional notices, if required by prior licensing conditions] * */ Standard. Session S andard. Sess on public void invalidate() { server. Session. remove. Application. Session (context); package org. apache. tomcat. session; // remove everything in the session import java. io. IOException ; import java. io. Object. Input. Stream ; import java. io. Object. Output. Stream ; import java. io. Serializable ; import java. util. Enumeration; import java. util. Hashtable ; import java. util. Vector; import javax. servlet. Servlet. Exception ; import javax. servlet. http. Http. Session. Binding. Event ; import javax. servlet. http. Http. Session. Binding. Listener ; import javax. servlet. http. Http. Session. Context ; import org. apache. tomcat. catalina. *; import org. apache. tomcat. util. String. Manager ; Enumeration enum = values. keys(); while ( enum. has. More. Elements ()) { String name = (String) enum. next. Element (); remove. Value (name); } valid = false; } public boolean is. New () { if (! valid) { String msg = sm. get. String ("application. Session. session. ise"); throw new Illegal. State. Exception (msg); } if ( this. Access. Time == creation. Time ) { return true; } else { return false; } } /** * @deprecated */ public void put. Value (String name, Object value) { set. Attribute (name, value); } public void set. Attribute (String name, Object value) { if (! valid) { String msg = sm. get. String ("application. Session. session. ise"); throw new Illegal. State. Exception (msg); } if (name == null) { String msg = sm. get. String ("application. Session. value. iae"); import org. apache. tomcat. core. *; import org. apache. tomcat. util. String. Manager ; import java. io. *; import java. net. *; import java. util. *; import javax. servlet. http. *; remove. Value (name); // remove any existing binding if (value != null && value instanceof Http. Session. Binding. Listener ) { Http. Session. Binding. Event e = new Http. Session. Binding. Event (this, name); (( Http. Session. Binding. Listener )value). value. Bound (e); } values. put(name, value); } if (name == null) { String msg = sm. get. String("application. Session. value. iae "); throw new Illegal. Argument. Exception(msg ); } return values. get(name); } /** * The collection of user data attributes associated with this Session. */ private Hashtable attributes = new Hashtable (); /** * The time this session was created, in milliseconds since midnight, * January 1, 1970 GMT. */ private long creation. Time = 0 L; /** * The session identifier of this Session. */ private String id = null; /** * @deprecated */ public String[] get. Value. Names () { Enumeration e = get. Attribute. Names (); Vector names = new Vector(); /** * Descriptive information describing this Session implementation. */ private static final String info = "Standard. Session/1. 0"; while ( e. has. More. Elements ()) { names. add. Element(e. next. Element ()); } String[] value. Names = new String[names. size()]; names. copy. Into(value. Names ); /** * The last accessed time for this Session. */ private long last. Accessed. Time = creation. Time ; return value. Names ; } this. inactive. Interval = context. get. Session. Time. Out (); if ( this. inactive. Interval != -1) { this. inactive. Interval *= 60; } } public Enumeration get. Attribute. Names () { if (! valid) { String msg = sm. get. String("application. Session. session. ise Server. Session get. Server. Session () { return server. Session ; } "); throw new Illegal. State. Exception(msg ); } /** * The Manager with which this Session is associated. */ private Manager manager = null; Hashtable values. Clone = ( Hashtable)values. clone (); /** * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. */ validate(); } void validate() { // if we have an inactive interval, check to see if we've exceeded it if ( inactive. Interval != -1) { int this. Interval = ( int)(System. current. Time. Millis () - last. Accessed ) / 1000; if ( this. Interval > inactive. Interval ) { invalidate(); } } // HTTP SESSION IMPLEMENTATION METHODS public String get. Id () { if (valid) { return id; } else { String msg = sm. get. String("application. Session. session. ise public void remove. Value(String name) { remove. Attribute(name ); } public void remove. Attribute(String name) { if (! valid) { String msg = sm. get. String("application. Session. session. ise "); throw new Illegal. State. Exception(msg ); } "); /** * Flag indicating whether this session is new or not. */ private boolean is. New = true; /** * Flag indicating whether this session is valid or not. */ private boolean is. Valid = false; throw new Illegal. Argument. Exception(msg ); } /** * The string manager for this package. */ private String. Manager sm = String. Manager. get. Manager("org. apache. tomcat. se ssion "); Object o = values. get(name); if (o instanceof Http. Session. Binding. Listener ) { Http. Session. Binding. Event e = new Http. Session. Binding. Event(this, name ); "); (( Http. Session. Binding. Listener)o). value. Unbound(e } public void set. Max. Inactive. Interval(int interval) { if (! valid) { String msg = sm. get. String("application. Session. session. ise "); /** * The HTTP session context associated with this session. */ private static Http. Session. Context session. Context = null; "); /** * The current accessed time for this session. */ private long this. Accessed. Time = creation. Time ; throw new Illegal. State. Exception(msg ); } inactive. Interval = interval; } public int get. Max. Inactive. Interval () { if (! valid) { String msg = sm. get. String("application. Session. session. ise "); throw new Illegal. State. Exception(msg ); } return inactive. Interval ; } } //-----------------------------------"); // ------------------------- Session Public Methods /** * Update the accessed time information for this session. This method * should be called by the context when a request comes in for a particular * session, even if the application does not reference it. */ public void access() { this. last. Accessed. Time = this. Accessed. Time ; this. Accessed. Time = System. current. Time. Millis (); this. New =false; } /** * Perform the internal processing required to invalidate this session, * without triggering an exception if the session has already expired. */ public void expire() { // Remove this session from our manager's active sessions if ((manager != null) && (manager instanceof Manager. Base )) (( Manager. Base ) manager). remove(this); // Unbind any objects associated with this session Vector results = new Vector(); Enumeration attrs = get. Attribute. Names (); while ( attrs. has. More. Elements ()) { String attr = (String) attrs. next. Element (); results. add. Element (attr); } Enumeration names = results. elements(); while (names. has. More. Elements ()) { String name = (String) names. next. Element (); remove. Attribute (name); } // Mark this session as invalid set. Valid (false); /** * Release all object references, and initialize instance variables, in * preparation for reuse of this object. */ public void recycle() { // Reset the instance variables associated with this Session attributes. clear(); creation. Time = 0 L; id = null; last. Accessed. Time = 0 L; manager = null; max. Inactive. Interval = -1; is. New = true; is. Valid = false; // Tell our Manager that this Session has been recycled if ((manager != null) && (manager instanceof Manager. Base )) (( Manager. Base ) manager). recycle(this); } // ------------------------ Session Package Methods /** * Return the <code> is. Valid </code> flag for this session. */ boolean is. Valid () { return ( this. Valid ); } /** * Set the <code> is. New </code> flag for this session. * * @ param is. New The new value for the <code> is. New </code> flag */ void set. New(boolean is. New ) { // -------------------------- Session Properties /** * Set the creation time for this session. This method is called by the * Manager when an existing Session instance is reused. * * @ param time The new creation time */ public void set. Creation. Time(long time) { throw new Illegal. State. Exception(msg ); } } this. creation. Time = time; this. last. Accessed. Time = time; this. Accessed. Time = time; } /** * Return the session identifier for this session. */ public String get. Id () { /** * Bind an object to this session, using the specified name. If an object * of the same name is already bound to this session, the object is * replaced. * <p> * After this method executes, and if the object implements * <code> Http. Session. Binding. Listener </code>, the container calls * <code> value. Bound ()</code> on the object. * * @ param name Name to which the object is bound, cannot be null * @ param value Object to be bound, cannot be null * * @exception Illegal. State. Exception if this method is called on an * invalidated session * * @deprecated As of Version 2. 2, this method is replaced by * <code> set. Attribute ()</code> */ public void put. Value (String name, Object value) { set. Attribute (name, value); } /** * Remove the object bound with the specified name from this session. If * the session does not have an object bound with this name, this method * does nothing. * <p> * After this method executes, and if the object implements * <code> Http. Session. Binding. Listener </code>, the container calls * <code> value. Unbound ()</code> on the object. * * @ param name Name of the object to remove from this session. * * @exception Illegal. State. Exception if this method is called on an * invalidated session */ public void remove. Attribute (String name) { synchronized (attributes) { Object object = attributes. get(name); if (object == null) return; attributes. remove(name); // System. out. println ( "Removing attribute " + name ); if (object instanceof Http. Session. Binding. Listener ) { (( Http. Session. Binding. Listener ) object). value. Unbound (new Http. Session. Binding. Event((Http. Session ) this, name)); } } /** * Remove the object bound with the specified name from this session. If * the session does not have an object bound with this name, this method * does nothing. * <p> * After this method executes, and if the object implements * <code> Http. Session. Binding. Listener </code>, the container calls * <code> value. Unbound ()</code> on the object. * * @ param name Name of the object to remove from this session. * * @exception Illegal. State. Exception if this method is called on an * invalidated session * * @deprecated As of Version 2. 2, this method is replaced by * <code> remove. Attribute ()</code> */ public void remove. Value(String name) { remove. Attribute(name ); /** * Bind an object to this session, using the specified name. If an object * of the same name is already bound to this session, the object is * replaced. * <p> * After this method executes, and if the object implements * <code> Http. Session. Binding. Listener </code>, the container calls * <code> value. Bound ()</code> on the object. * * @ param name Name to which the object is bound, cannot be null * @ param value Object to be bound, cannot be null * * @exception Illegal. Argument. Exception if an attempt is made to add a * non- serializable object in an environment marked distributable. * @exception Illegal. State. Exception if this method is called on an * invalidated session */ public void set. Attribute(String name, Object value) { /** * Read a serialized version of this session object from the specified * object input stream. * <p> * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager * is not restored by this method, and must be set explicitly. * * @ param stream The input stream to read from * * @exception Class. Not. Found. Exception if an unknown class is specified * @exception IOException if an input/output error occurs */ private void read. Object(Object. Input. Stream stream) throws Class. Not. Found. Exception , IOException { this. Valid = is. Valid ; } // ------------------------- Http. Session Properties /** * Return the time when this session was created, in milliseconds since * midnight, January 1, 1970 GMT. * * @exception Illegal. State. Exception if this method is called on an * invalidated session */ public long get. Creation. Time () { return ( this. creation. Time ); } Http. Session Private Methods // Deserialize the scalar instance variables (except Manager) creation. Time = ((Long) stream. read. Object()). long. Value (); id = (String) stream. read. Object (); last. Accessed. Time = ((Long) stream. read. Object()). long. Value (); max. Inactive. Interval = ((Integer) stream. read. Object()). int. Value (); is. New = ((Boolean) stream. read. Object()). boolean. Value (); is. Valid = ((Boolean) stream. read. Object()). boolean. Value (); public final class Standard. Manager extends Manager. Base implements Lifecycle, Runnable { // --------------------------- Instance Variables // Deserialize the attribute count and attribute values int n = ((Integer) stream. read. Object()). int. Value (); for ( int i = 0; i < n; i++) { String name = (String) stream. read. Object (); Object value = (Object) stream. read. Object (); attributes. put(name, value); } /** * The interval (in seconds) between checks for expired sessions. */ private int check. Interval = 60; /** * Has this component been configured yet? */ private boolean configured = false; } /** * Return the session context with which this session is associated. * * @deprecated As of Version 2. 1, this method is deprecated and has no * replacement. It will be removed in a future version of the * Java Servlet API. */ public Http. Session. Context get. Session. Context () { if ( session. Context == null) session. Context = new Standard. Session. Context (); return ( session. Context ); } // -----------------------Http. Session Public Methods /** * Return the object bound with the specified name in this session, or * <code>null</code> if no object is bound with that name. * * @ param name Name of the attribute to be returned * * @exception Illegal. State. Exception if this method is called on an * invalidated session */ public Object get. Attribute(String name) { return (attributes. get(name)); return (this. id); } import java. io. IOException ; /** * Standard implementation of the <b>Manager</b> interface that provides * no session persistence or distributable capabilities, but does support * an optional, configurable, maximum number of active sessions allowed. * <p> * Lifecycle configuration of this component assumes an XML node * in the following format: * <code> * & lt; Manager class. Name ="org. apache. tomcat. session. Standard. Manager " * check. Interval ="60" max. Active. Sessions ="-1" * max. Inactive. Interval ="-1" /> * </code> * where you can adjust the following parameters, with default values * in square brackets: * <ul> * <li><b>check. Interval </b> - The interval (in seconds) between background * thread checks for expired sessions. [60] * <li><b>max. Active. Sessions </b> - The maximum number of sessions allowed to * be active at once, or -1 for no limit. [-1] * <li><b>max. Inactive. Interval </b> - The default maximum number of seconds of * inactivity before which the servlet container is allowed to time out * a session, or -1 for no limit. This value should be overridden from * the default session timeout specified in the web application deployment * descriptor, if any. [-1] * </ ul> * * @author Craig R. Mc. Clanahan * @version $Revision: 1. 1 $ $Date: 2000/05/02 21: 28: 30 $ */ this. New = is. New ; /** * Set the <code> is. Valid </code> flag for this session. * * @ param is. Valid The new value for the <code> is. Valid </code> flag */ void set. Valid(boolean is. Valid ) { if ((this. id != null) && (manager != null) && (manager instanceof Manager. Base )) (( Manager. Base ) manager). remove(this); /** * Return an <code>Enumeration</code> of <code>String</code> objects * containing the names of the objects bound to this session. * * @exception Illegal. State. Exception if this method is called on an * invalidated session */ public Enumeration get. Attribute. Names () { this. id = id; return (attributes. keys()); if ((manager != null) && (manager instanceof Manager. Base )) (( Manager. Base ) manager). add(this); } Server. Sess on } /** * Return descriptive information about this Session implementation and * the corresponding version number, in the format * <code>& lt; description> /< version&gt ; </code>. */ public String get. Info () { return (this. info); /** * Return the object bound with the specified name in this session, or * <code>null</code> if no object is bound with that name. * * @ param name Name of the value to be returned * * @exception Illegal. State. Exception if this method is called on an * invalidated session * * @deprecated As of Version 2. 2, this method is replaced by * <code> get. Attribute ()</code> */ public Object get. Value(String name) { } return ( get. Attribute(name )); /** * 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 get. Last. Accessed. Time () { /** * The string manager for this package. */ private String. Manager sm = String. Manager. get. Manager("org. apache. tomcat. session return ( this. last. Accessed. Time ); } /** * Return the Manager within which this Session is valid. */ public Manager get. Manager () { return (this. manager); } /** * Set the Manager within which this Session is valid. * * @ param manager The new Manager */ public void set. Manager(Manager manager) { this. manager = manager; } /** * Return the maximum time interval, in seconds, between client requests * before the servlet container will invalidate the session. A negative * time indicates that the session should never time out. * * @exception Illegal. State. Exception if this method is called on * an invalidated session */ public int get. Max. Inactive. Interval () { return ( this. max. Inactive. Interval ); } /** * Set the maximum time interval, in seconds, between client requests * before the servlet container will invalidate the session. A negative * time indicates that the session should never time out. * * @ param interval The new maximum interval */ public void set. Max. Inactive. Interval(int interval) { private Vector dummy = new Vector(); /** * Return the session identifiers of all sessions defined * 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. */ public Enumeration get. Ids () { } return (dummy. elements()); /** * Invalidates this session and unbinds any objects bound to it. * * @exception Illegal. State. Exception if this method is called on * 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 Illegal. State. Exception if this method is called on an * invalidated session */ public boolean is. New () { return ( this. New ); } } /** * Return the <code> Http. Session </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 Http. Session get. Session(String id) { * Mark the specified session's last accessed time. This should be * called for each request by a Request. Interceptor. * import org. apache. tomcat. core. Request; * @ param session The session to be marked import org. apache. tomcat. core. Response; */ import org. apache. tomcat. core. Session. Manager ; public void accessed(Context ctx, Request req, String id) { import org. apache. tomcat. util. Session. Util ; Http. Session session= find. Session (ctx, id); if( session == null) return; if (session instanceof Session) /** * Specialized implementation of org. apache. tomcat. core. ((Session) session). access(); Session. Manager * that adapts to the new component-based Manager implementation. * <p> // cache the Http. Session - avoid another find req. set. Session ( session ); * XXX - At present, use of <code> Standard. Manager </code> is hard coded, } * and lifecycle configuration is not supported. * <p> // XXX should we throw exception or just return null ? ? * <b>IMPLEMENTATION NOTE</b>: Once we commit to the new Manager/Session public Http. Session find. Session ( Context ctx, String id ) { * paradigm, I would suggest moving the logic implemented here back into try { * the core level. The Tomcat. Next "Manager" interface acts more like a Session session = manager. find. Session (id); * collection class, and has minimal knowledge of the detailed request if(session!=null) * processing semantics of handling sessions. return session. get. Session (); * <p> } catch ( IOException e) { * XXX - At present, there is no way (via the Session. Manager interface) } for return (null); * a Context to tell the Manager that we create what the default session * timeout for this web application (specified in the deployment descriptor) * should be. * * @author Craig R. Mc. Clanahan } public Http. Session create. Session (Context ctx) { return manager. create. Session (). get. Session (); } */ /** node = attributes. get. Named. Item ("max. Inactive. Interval "); if (node != null) { try { set. Max. Inactive. Interval (Integer. parse. Int (node. get. Node. Value ())); } catch ( Throwable t) { ; // XXX - Throw exception? } /** * Prepare for the beginning of active use of the public methods of this * component. This method should be called after <code>configure()</code>, * and before any of the public methods of the component are utilized. * * @exception Illegal. State. Exception if this component has not yet been * configured (if required for this component) * @exception Illegal. State. Exception if this component has already been * started * @exception Lifecycle. Exception if this component detects a fatal error * that prevents this component from being used */ public void start() throws Lifecycle. Exception { public final class Standard. Session. Manager implements Session. Manager { * Remove all sessions because our associated Context is being shut down. * * @ param ctx The context that is being shut down // ------------------------------ Constructors */ public void remove. Sessions (Context ctx) { // Start the background reaper thread thread. Start (); /** * The background thread completion semaphore. */ private boolean thread. Done = false; manager = new Standard. Manager (); if (manager instanceof Lifecycle) { try { ((Lifecycle) manager). configure(null); } catch ( Lifecycle. Exception e) { throw new Illegal. State. Exception ("" + e); } ((Lifecycle) manager). start(); } catch ( Lifecycle. Exception e) { } throw new Illegal. State. Exception ("" + e); } /** * Used by context to configure the session manager's inactivity timeout. * * The Session. Manager may have some default session time out, the * Context on the other hand has it's timeout set by the deployment * descriptor (web. xml). This method lets the Context conforgure the // --------------------------- Instance * session manager according to this value. Variables // ------------------------------- Properties /** * Gracefully terminate the active use of the public methods of this * component. This method should be the last one called on a given * instance of this component. * * @exception Illegal. State. Exception if this component has not been started * @exception Illegal. State. Exception if this component has already * been stopped * @exception Lifecycle. Exception if this component detects a fatal error * that needs to be reported */ public void stop() throws Lifecycle. Exception { /** * Return the check interval (in seconds) for this Manager. */ public int get. Check. Interval () { // Validate and update our current component state if (!started) throw new Lifecycle. Exception (sm. get. String ("standard. Manager. not. Started ")); started = false; /** * Name to register for the background thread. */ private String thread. Name = "Standard. Manager "; // contexts, we just want to remove the sessions of ctx! * Create a new Session. Manager that adapts to the corresponding // The manager will still run after that ( i. e. keep database Manager // connection open * implementation. if (manager instanceof Lifecycle) { */ try { public Standard. Session. Manager () { ((Lifecycle) manager). stop(); } } * * @ param minutes The session inactivity timeout in minutes. /** * The Manager implementation we are actually using. */ private Manager manager = null; */ public void set. Session. Time. Out (int minutes) { if(-1 != minutes) { // The manager works with seconds. . . manager. set. Max. Inactive. Interval (minutes * 60); } } } // Stop the background reaper thread thread. Stop (); return ( this. check. Interval ); } Server. Session. Manager Server. Sess on. Manager // ------------------------------- Private Class Vector results = new Vector(); Enumeration attrs = get. Attribute. Names (); while ( attrs. has. More. Elements ()) { String attr = (String) attrs. next. Element (); results. add. Element(attr ); } String names[] = new String[results. size()]; for ( int i = 0; i < names. length; i++) names[i] = (String) results. element. At(i ); return (names); node = attributes. get. Named. Item ("max. Active. Sessions "); if (node != null) { try { set. Max. Active. Sessions (Integer. parse. Int (node. get. Node. Value ())); } catch ( Throwable t) { ; // XXX - Throw exception? } // Validate and update our current component state if (!configured) throw new Lifecycle. Exception (sm. get. String ("standard. Manager. not. Configured ")); if (started) throw new Lifecycle. Exception (sm. get. String ("standard. Manager. already. Started ")); started = true; /** * The background thread. */ private Thread thread = null; // Serialize the attribute count and the attribute values stream. write. Object(new Integer(results. size())); Enumeration names = results. elements(); while ( names. has. More. Elements ()) { String name = (String) names. next. Element (); stream. write. Object(name ); stream. write. Object(attributes. get(name )); } final class Standard. Session. Context implements Http. Session. Context { node = attributes. get. Named. Item ("check. Interval "); if (node != null) { try { set. Check. Interval (Integer. parse. Int (node. get. Node. Value ())); } catch ( Throwable t) { ; // XXX - Throw exception? } "); /** * Has this component been started yet? */ private boolean started = false; // Accumulate the names of serializable attributes Vector results = new Vector(); Enumeration attrs = get. Attribute. Names (); while ( attrs. has. More. Elements ()) { String attr = (String) attrs. next. Element (); Object value = attributes. get(attr ); if (value instanceof Serializable ) results. add. Element(attr ); } /** * This class is a dummy implementation of the <code> Http. Session. Context </code> * interface, to conform to the requirement that such an object be returned * when <code> Http. Session. get. Session. Context ()</code> is called. * * @author Craig R. Mc. Clanahan * * @deprecated As of Java Servlet API 2. 1 with no replacement. The * interface will be removed in a future version of this API. */ // Parse and process our configuration parameters if (!("Manager". equals(parameters. get. Node. Name ()))) return; Named. Node. Map attributes = parameters. get. Attributes (); Node node = null; /** import org. apache. tomcat. catalina. *; import org. apache. tomcat. core. Context; /** * The maximum number of active Sessions allowed, or -1 for no limit. */ protected int max. Active. Sessions = -1; } /** * Return the set of names of objects bound to this session. If there * are no such objects, a zero-length array is returned. * * @exception Illegal. State. Exception if this method is called on an * invalidated session * * @deprecated As of Version 2. 2, this method is replaced by * <code> get. Attribute. Names ()</code> */ public String[] get. Value. Names () { // Validate and update our current component state if (configured) throw new Lifecycle. Exception (sm. get. String ("standard. Manager. already. Configured ")); configured = true; if (parameters == null) return; import javax. servlet. http. Cookie; import javax. servlet. http. Http. Session ; // XXX a manager may be shared by multiple /** * The descriptive information about this implementation. */ private static final String info = "Standard. Manager/1. 0"; // Write the scalar instance variables (except Manager) stream. write. Object(new Long(creation. Time )); stream. write. Object(id ); stream. write. Object(new Long(last. Accessed. Time )); stream. write. Object(new Integer(max. Inactive. Interval )); stream. write. Object(new Boolean(is. New )); stream. write. Object(new Boolean(is. Valid )); } crosscut invalidate(Standard. Session s): s & ( int get. Max. Inactive. Interval () | long get. Creation. Time () | Object get. Attribute(String ) | Enumeration get. Attribute. Names () | String[] get. Value. Names () | void invalidate() | boolean is. New () | void remove. Attribute(String ) | void set. Attribute(String , Object)); static advice(Standard. Session s): invalidate(s) { before { if (! s. is. Valid ()) throw new Illegal. State. Exception ( s. sm. get. String("standard. Session. " + this. Join. Point. method. Name + ". ise")); } } } /** * Configure this component, based on the specified configuration * parameters. This method should be called immediately after the * component instance is created, and before <code>start()</code> * is called. * * @ parameters Configuration parameters for this component * (<B>FIXME: What object type should this really be? ) * * @exception Illegal. State. Exception if this component has already been * configured and/or started * @exception Lifecycle. Exception if this component detects a fatal error * in the configuration parameters it was given */ public void configure(Node parameters) throws Lifecycle. Exception { } /** * Write a serialized version of this session object to the specified * object output stream. * <p> * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored * in the serialized representation of this Session. After calling * <code> read. Object ()</code>, you must set the associated Manager * explicitly. * <p> * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable * will be silently ignored. If you do not want any such attributes, * be sure the <code>distributable</code> property of our associated * Manager is set to <code>true</code>. * * @ param stream The output stream to write to * * @exception IOException if an input/output error occurs */ private void write. Object(Object. Output. Stream stream) throws IOException { } /** * Set the session identifier for this session. * * @ param id The new session identifier */ public void set. Id(String id) { // ----------------------------- Public Methods // --------------------------- Lifecycle Methods synchronized (attributes) { remove. Attribute(name ); attributes. put(name, value); if (value instanceof Http. Session. Binding. Listener ) (( Http. Session. Binding. Listener ) value). value. Bound (new Http. Session. Binding. Event((Http. Session ) this, name)); } // ---------------------- Standard. Session. Manager S andard. Sess on. Manager package org. apache. tomcat. session; import java. io. IOException ; import java. util. Enumeration; import java. util. Hashtable ; import java. util. Vector; import org. apache. tomcat. catalina. *; import javax. servlet. http. Cookie; import javax. servlet. http. Http. Session ; import org. apache. tomcat. util. String. Manager ; import org. w 3 c. dom. Named. Node. Map; import org. w 3 c. dom. Node; if ((manager != null) && manager. get. Distributable () && !(value instanceof Serializable )) throw new Illegal. Argument. Exception ( sm. get. String("standard. Session. set. Attribute. iae ")); } Standard. Manager Sess on n ercep or } } ); values. remove(name); } throw new Illegal. State. Exception(msg ); } } /** * * @deprecated */ public Http. Session. Context get. Session. Context () { return new Session. Context. Impl (); } public long get. Last. Accessed. Time () { if (valid) { return last. Accessed ; } else { String msg = sm. get. String("application. Session. session. ise /** * @deprecated */ if (name == null) { String msg = sm. get. String("application. Session. value. iae throw new Illegal. State. Exception(msg ); } } public long get. Creation. Time () { if (valid) { return creation. Time ; } else { String msg = sm. get. String("application. Session. session. ise /** * The maximum time interval, in seconds, between client requests before * the servlet container may invalidate this session. A negative time * indicates that the session should never time out. */ private int max. Inactive. Interval = -1; return ( Enumeration)values. Clone. keys (); } void accessed() { // set last accessed to this. Access. Time as it will be left over // from the previous access last. Accessed = this. Access. Time ; this. Access. Time = System. current. Time. Millis (); } } // -------------------------- Instance Variables throw new Illegal. State. Exception(msg ); } Application. Session(String id, Server. Session server. Session , Context context) { this. server. Session = server. Session ; this. context = context; this. id = id; return (( Http. Session ) this); } public class Application. Session implements Http. Session { private String. Manager sm = String. Manager. get. Manager("org. apache. tomcat. session "); private Hashtable values = new Hashtable (); private String id; private Server. Session server. Session ; private Context context; private long creation. Time = System. current. Time. Millis (); ; private long this. Access. Time = creation. Time ; private long last. Accessed = creation. Time ; private int inactive. Interval = -1; private boolean valid = true; /** * Construct a new Session associated with the specified Manager. * * @ param manager The manager with which this Session is associated */ public Standard. Session(Manager manager) { super(); this. manager = manager; public Object get. Attribute (String name) { if (! valid) { String msg = sm. get. String ("application. Session. session. ise"); /** * Core implementation of an application level session * * @author James Duncan Davidson [ duncan@eng. sun. com ] * @author Jason Hunter [ jch@eng. sun. com ] * @author James Todd [gonzo@eng. sun. com] */ final class Standard. Session implements Http. Session , Session { // ----------------------------- Constructors throw new Illegal. Argument. Exception (msg); } /** * @deprecated */ public Object get. Value (String name) { return get. Attribute (name); } package org. apache. tomcat. session; /** * Standard implementation of the <b>Session</b> interface. This object is * serializable , so that it can be stored in persistent storage or transferred * to a different JVM for distributable session support. * <p> * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * internal (Session) and application level (Http. Session ) view of the session. * However, because the class itself is not declared public, Java logic outside * of the <code>org. apache. tomcat. session</code> package cannot cast an * Http. Session view of this instance back to a Session view. * * @author Craig R. Mc. Clanahan * @version $Revision: 1. 2 $ $Date: 2000/05/15 17: 54: 10 $ */ /** * Return the <code> Http. Session </code> for which this object * is the facade. */ public Http. Session get. Session () { /** * Set the check interval (in seconds) for this Manager. * * @ param check. Interval The new check interval */ public void set. Check. Interval(int check. Interval ) { // Expire all active sessions Session sessions[] = find. Sessions (); for ( int i = 0; i < sessions. length; i++) { Standard. Session session = ( Standard. Session ) sessions[i]; if (! session. is. Valid ()) continue; session. expire(); } this. check. Interval = check. Interval ; } } // ---------------------------- Private Methods /** * Return descriptive information about this Manager implementation and * the corresponding version number, in the format * <code>& lt; description> /< version&gt ; </code>. */ public String get. Info () { package org. apache. tomcat. session; import org. apache. tomcat. util. *; import org. apache. tomcat. core. *; import java. io. *; import java. net. *; import java. util. *; import javax. servlet. http. *; /** * * @author James Duncan Davidson [ duncan @eng. sun. com] * @author Jason Hunter [ jch@eng. sun. com] * @author James Todd [gonzo@eng. sun. com] */ public class Server. Session. Manager implements Session. Manager { private String. Manager sm = String. Manager. get. Manager ("org. apache. tomcat. session"); private static Server. Session. Manager manager; // = new Server. Session. Manager (); // 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. synchronized void reap() { Enumeration enum = sessions. keys(); while ( enum. has. More. Elements ()) { Object key = enum. next. Element (); Server. Session session = ( Server. Session )sessions. get(key); session. reap(); session. validate(); } } synchronized void remove. Session (Server. Session session) { String id = session. get. Id (); session. invalidate(); sessions. remove(id); } static { manager = new Server. Session. Manager (); } public static Server. Session. Manager get. Manager () { return manager; } private Hashtable sessions = new Hashtable (); private Reaper reaper; private Server. Session. Manager () { reaper = Reaper. get. Reaper (); reaper. set. Server. Session. Manager (this); reaper. start(); } return (null); public void accessed( Context ctx, Request req, String id ) { Application. Session ap. S=(Application. Session )find. Session ( ctx, id); if( ap. S==null) return; } Server. Session serv. S =ap. S. get. Server. Session (); serv. S. accessed(); ap. S. accessed(); // cache it - no need to compute it again req. set. Session ( ap. S ); } public Http. Session create. Session (Context ctx) { String session. Id = Session. Id. Generator. generate. Id (); Server. Session session = new Server. Session (session. Id ); sessions. put( session. Id , session); if(-1 != inactive. Interval ) { session. set. Max. Inactive. Interval (inactive. Interval ); } return session. get. Application. Session ( ctx, true ); } public Http. Session find. Session (Context ctx, String id) { Server. Session s. Session =(Server. Session )sessions. get(id); if( s. Session ==null) return null; this. max. Inactive. Interval = interval; return s. Session. get. Application. Session (ctx, false); } } } /** * Return the maximum number of active Sessions allowed, or -1 for * no limit. */ public int get. Max. Active. Sessions () { return ( this. max. Active. Sessions ); } /** * Set the maximum number of actives Sessions allowed, or -1 for * no limit. * * @ param max The new maximum number of sessions */ public void set. Max. Active. Sessions(int max) { public void remove. Sessions (Context context) { Enumera for ( int i = 0; i < sessions. length; i++) { Standard. Session session = ( Standard. Session ) sessions[i]; if (! session. is. Valid ()) continue; int max. Inactive. Interval = session. get. Max. Inactive. Interval (); if ( max. Inactive. Interval < 0) continue; int time. Idle = // Truncate, do not round up ( int) (( time. Now - session. get. Last. Accessed. Time ()) / 1000 L); if ( time. Idle >= max. Inactive. Interval ) session. expire(); } } /** * Sleep for the duration specified by the <code> * property. */ private void thread. Sleep () { check. Interval </code> try { Thread. sleep(check. Interval * 1000 L); } catch ( Interrupted. Exception e) { ; } this. max. Active. Sessions = max; protected int inactive. Interval = -1; /** * Invalidate all sessions that have expired. */ private void process. Expires () { long time. Now = System. current. Time. Millis (); Session sessions[] = find. Sessions (); return (this. info); } // ----------------------------- Public Methods } /** * Construct and return a new session object, based on the default * settings specified by this Manager's properties. The session * id will be assigned by this method, and available via the get. Id () * method of the returned session. If a new session cannot be created * for any reason, return <code>null</code>. * * @exception Illegal. State. Exception if a new session cannot be * instantiated for any reason */ public Session create. Session () { /** * Start the background thread that will periodically check for * session timeouts. */ private void thread. Start () { if (( max. Active. Sessions >= 0) && (sessions. size() >= max. Active. Sessions )) throw new Illegal. State. Exception ( sm. get. String("standard. Manager. create. Session. ise return ( super. create. Session ()); } if (thread != null) return; thread. Done = false; thread = new Thread(this, thread. Name ); thread. set. Daemon(true ); thread. start(); } ")); /** * Stop the background thread that is periodically checking for * session timeouts. */ private void thread. Stop () { if (thread == null) return; thread. Done = true; thread. interrupt(); try { thread. join(); } catch ( Interrupted. Exception e) { ; } thread = null; } // --------------------------- Background Thread /** * The background thread that checks for session timeouts and shutdown. */ public void run() { // Loop until the termination semaphore is set while (! thread. Done ) { thread. Sleep (); process. Expires (); } } } 11

Aspect. J™ is… a small extension to Java n a general-purpose AO language n

Aspect. J™ is… a small extension to Java n a general-purpose AO language n – just as Java is a general-purpose OO language version 1. 2. 1 (Nov 04). 1. 5 pre-release. n The most mature of several approaches. n very active research community: conferences, Journal, books, software, . . . n 12

Terminology (3) Join Points – well defined places in the execution flow where additional

Terminology (3) Join Points – well defined places in the execution flow where additional behavior can be attached. n Advice – the behavior to execute at a join point (before/after/instead). n Pointcut designator – describes a set of join points. n 13

Terminology (4) Aspect – a modular unit designed to implement a concern. May include

Terminology (4) Aspect – a modular unit designed to implement a concern. May include code (called advice) and indication where, when and how to invoke it. n Weaving - the process of composing core functionality modules with aspects, yielding a working system. n 14

Example: logging pointcut method. Call(): call(void Line. *(. . )); before() : method. Call()

Example: logging pointcut method. Call(): call(void Line. *(. . )); before() : method. Call() { System. out. println(“entering “+ this. Join. Point); } after() returning: method. Call() { System. out. println(“exiting “+ this. Join. Point); } 15

Example: update display aspect Display. Updating { pointcut move(): call(void Line. set. P 1(Point))

Example: update display aspect Display. Updating { pointcut move(): call(void Line. set. P 1(Point)) || call(void Line. set. P 2(Point)); after() returning: move() { Display. update(); } } 16

Hello. World. java public class Hello. World { public static void say(String message) {

Hello. World. java public class Hello. World { public static void say(String message) { System. out. println(message); } public static void say. To. Person(String message, String name) { System. out. println(name + ", " + message); } } 17

Hello. World(2) Test. java public class Test { public static void main(String[] args) {

Hello. World(2) Test. java public class Test { public static void main(String[] args) { Hello. World. say(“Hello World”); Hello. World. say. To. Person(“Hello World”, “Ohad”); } } ajc Hello. World. java Test. java Ø java Test Hello World Ohad, Hello World Ø 18

Hello. World(3) Manners. Aspect. java public aspect Manners. Aspect { pointcut saying() : call(public

Hello. World(3) Manners. Aspect. java public aspect Manners. Aspect { pointcut saying() : call(public static void Hello. World. say*(. . )); before() : saying() { System. out. print("Good day! "); } after() : saying() { System. out. println("Thank you!"); } } Ø ajc Hello. World. java Manners. Aspect. java Test. java Ø java Test Good day! Hello World Thank you! Good day! Ohad, Hello World Thank you! 19

Hello. World(4) Hebrew. Salutation. Aspect. java public aspect Hebrew. Salutation. Aspect { pointcut Histahbekoot(String

Hello. World(4) Hebrew. Salutation. Aspect. java public aspect Hebrew. Salutation. Aspect { pointcut Histahbekoot(String person) : call(* void Hello. World. say. To. Person(String, String)) && args(String , person); void around (String Person) : Histahbekoot(person) { proceed(person + “-AHI”); } } Ø ajc Hello. World. java Manners. Aspect. java Hebrew. Salutation. Aspect. java Test. java Ø java Test Good day! Hello World Thank you! Good day! Ohad-AHI, Hello World 20 Thank you!

More AOP and Aspect. J n Book: Aspect. J in Action Practical Aspect. Oriented

More AOP and Aspect. J n Book: Aspect. J in Action Practical Aspect. Oriented Programming Ramnivas Laddad 21

More AOP and Aspect. J n Online Documentation: http: //dev. eclipse. org/viewcvs/indextech. cgi/~checkou t~/aspectj-home/doc/index.

More AOP and Aspect. J n Online Documentation: http: //dev. eclipse. org/viewcvs/indextech. cgi/~checkou t~/aspectj-home/doc/index. html n Mailing list: http: //aosd. net/ 22