Aspect Oriented Programming Aspect Oriented Software Development AOSD
- Slides: 22
Aspect Oriented Programming
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 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 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 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 shows relevant lines of code nicely fits in one box 6
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 – – – 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 /* * ================================== * * 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> ; </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> ; </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 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 /* * ================================== * * 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> ; </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> ; </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 – 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 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 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() { 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)) || 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) { 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. 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 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 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 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. html n Mailing list: http: //aosd. net/ 22
- Aspect oriented programming
- La structure de la phrase descriptive
- Object oriented sdlc
- Be next frontier software development
- Trade oriented sales promotion
- What is a column row db
- Vba object oriented
- Functional programming vs object oriented
- Java and c++ difference
- What is polymorphism in oop
- Java oop exercises
- C# object oriented programming
- Structured vs object oriented programming
- Tony albrecht
- Object oriented programming flowchart
- Khanacademy java
- Common business oriented language
- Actor oriented programming
- Object oriented programming slideshare
- Oops in systemverilog
- Oop lab
- Modularity in object oriented programming
- Counterfeit object oriented programming