© copyright 2003, gregor kiczales. all rights reserved. aosd 2003 the fun has just begun gregor...

64
© Copyright 2003, Gregor Kiczales. All rights reserved. the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003, Gregor Kiczales, except for slides explicitly marked with a different copyright. Permission is granted to use this presentation, in whole or in part for educational purposes, provided that every slide used is used in its entirety, with no changes, deletions or additions; and that the copyright notice is preserved on every slide used. software modularity group

Upload: cameron-cooper

Post on 27-Mar-2015

212 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

the fun has just begun

Gregor Kiczales

University of British Columbia

© Copyright 2003, Gregor Kiczales, except for slides explicitly marked with a different copyright.Permission is granted to use this presentation, in whole or in part for educational purposes, provided that every slide used is used in its entirety, with no changes, deletions or additions; and that the copyright notice is preserved on every slide used.

software modularity group

Page 2: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

talk timeline and level of abstraction

software models

conclusion

tangle, scatter, crosscut

join point mechanism

s

another

view

Page 3: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

© Copyright 2003, Gregor Kiczales. All rights reserved.

scattertangle

crosscutand

allthat

exploringsome of the terms we use

Page 4: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

bad modularity

/* * ==================================================================== * * 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 softwareitself, * 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 productsderived * from this software without prior written permission. For written * permission, please contact [email protected]. * * 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, INDIRECT, 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] * */

package org.apache.tomcat.session;

import org.apache.tomcat.core.*;import org.apache.tomcat.util.StringManager;import java.io.*;import java.net.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;

/** * Core implementation of an application level session * * @author James Duncan Davidson [[email protected]] * @author Jason Hunter [[email protected]] * @author James Todd [[email protected]] */

public class ApplicationSession implements HttpSession {

private StringManager sm = StringManager.getManager("org.apache.tomcat.session"); private Hashtable values = new Hashtable(); private String id; private ServerSession serverSession; private Context context; private long creationTime = System.currentTimeMillis();; private long thisAccessTime = creationTime; private long lastAccessed = creationTime; private int inactiveInterval = -1; private boolean valid = true;

ApplicationSession(String id, ServerSession serverSession, Context context) { this.serverSession = serverSession; this.context = context; this.id = id;

this.inactiveInterval = context.getSessionTimeOut();

if (this.inactiveInterval != -1) { this.inactiveInterval *= 60; } }

ServerSession getServerSession() { return serverSession; }

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

void accessed() { // set last accessed to thisAccessTime as it will be left over // from the previous access lastAccessed = thisAccessTime; thisAccessTime = System.currentTimeMillis();

validate(); }

void validate() { // if we have an inactive interval, check to see if we've exceeded it if (inactiveInterval != -1) { int thisInterval = (int)(System.currentTimeMillis() - lastAccessed) / 1000;

if (thisInterval > inactiveInterval) { invalidate(); } } } // HTTP SESSION IMPLEMENTATION METHODS public String getId() { if (valid) { return id; } else { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); } }

public long getCreationTime() { if (valid) { return creationTime; } else { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); } } /** * * @deprecated */

public HttpSessionContext getSessionContext() { return new SessionContextImpl(); } public long getLastAccessedTime() { if (valid) { return lastAccessed; } else { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); } }

public void invalidate() { serverSession.removeApplicationSession(context);

// remove everything in the session

Enumeration enum = values.keys(); while (enum.hasMoreElements()) { String name = (String)enum.nextElement(); removeValue(name); }

valid = false; }

public boolean isNew() { if (! valid) { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); }

if (thisAccessTime == creationTime) { return true; } else { return false; } } /** * @deprecated */

public void putValue(String name, Object value) { setAttribute(name, value); }

public void setAttribute(String name, Object value) { if (! valid) { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); }

if (name == null) { String msg = sm.getString("applicationSession.value.iae");

throw new IllegalArgumentException(msg); }

removeValue(name); // remove any existing binding

if (value != null && value instanceof HttpSessionBindingListener) { HttpSessionBindingEvent e = new HttpSessionBindingEvent(this, name);

((HttpSessionBindingListener)value).valueBound(e); }

values.put(name, value); }

/** * @deprecated */ public Object getValue(String name) { return getAttribute(name); }

public Object getAttribute(String name) { if (! valid) { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); }

if (name == null) { String msg = sm.getString("applicationSession.value.iae");

throw new IllegalArgumentException(msg); }

return values.get(name); }

/** * @deprecated */ public String[] getValueNames() { Enumeration e = getAttributeNames(); Vector names = new Vector();

while (e.hasMoreElements()) { names.addElement(e.nextElement()); }

String[] valueNames = new String[names.size()];

names.copyInto(valueNames);

return valueNames; }

public Enumeration getAttributeNames() { if (! valid) { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); }

Hashtable valuesClone = (Hashtable)values.clone();

return (Enumeration)valuesClone.keys(); }

/** * @deprecated */

public void removeValue(String name) { removeAttribute(name); }

public void removeAttribute(String name) { if (! valid) { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); }

if (name == null) { String msg = sm.getString("applicationSession.value.iae");

throw new IllegalArgumentException(msg); }

Object o = values.get(name);

if (o instanceof HttpSessionBindingListener) { HttpSessionBindingEvent e = new HttpSessionBindingEvent(this,name);

((HttpSessionBindingListener)o).valueUnbound(e); }

values.remove(name); }

public void setMaxInactiveInterval(int interval) { if (! valid) { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); }

inactiveInterval = interval; }

public int getMaxInactiveInterval() { if (! valid) { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); }

return inactiveInterval; }}

//-----------------------------------------------------------------------

package org.apache.tomcat.session;

import org.apache.tomcat.core.*;import org.apache.tomcat.util.StringManager;import java.io.*;import java.net.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;

/** * Core implementation of a server session * * @author James Duncan Davidson [[email protected]] * @author James Todd [[email protected]] */

public class ServerSession {

private StringManager sm = StringManager.getManager("org.apache.tomcat.session"); private Hashtable values = new Hashtable(); private Hashtable appSessions = new Hashtable(); private String id; private long creationTime = System.currentTimeMillis();; private long thisAccessTime = creationTime; private long lastAccessed = creationTime; private int inactiveInterval = -1; ServerSession(String id) { this.id = id; }

public String getId() { return id; }

public long getCreationTime() { return creationTime; }

public long getLastAccessedTime() { return lastAccessed; } public ApplicationSession getApplicationSession(Context context, boolean create) { ApplicationSession appSession = (ApplicationSession)appSessions.get(context);

if (appSession == null && create) {

// XXX // sync to ensure valid? appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); }

// XXX // make sure that we haven't gone over the end of our // inactive interval -- if so, invalidate and create // a new appSession return appSession; } void removeApplicationSession(Context context) { appSessions.remove(context); }

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

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

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

void validate()

void validate() { // if we have an inactive interval, check to see if // we've exceeded it

if (inactiveInterval != -1) { int thisInterval = (int)(System.currentTimeMillis() - lastAccessed) / 1000;

if (thisInterval > inactiveInterval) { invalidate();

ServerSessionManager ssm = ServerSessionManager.getManager();

ssm.removeSession(this); } } }

synchronized void invalidate() { Enumeration enum = appSessions.keys();

while (enum.hasMoreElements()) { Object key = enum.nextElement(); ApplicationSession appSession = (ApplicationSession)appSessions.get(key);

appSession.invalidate(); } } public void putValue(String name, Object value) { if (name == null) { String msg = sm.getString("serverSession.value.iae");

throw new IllegalArgumentException(msg); }

removeValue(name); // remove any existing binding values.put(name, value); }

public Object getValue(String name) { if (name == null) { String msg = sm.getString("serverSession.value.iae");

throw new IllegalArgumentException(msg); }

return values.get(name); }

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

public void removeValue(String name) { values.remove(name); }

public void setMaxInactiveInterval(int interval) { inactiveInterval = interval; }

public int getMaxInactiveInterval() { return inactiveInterval; }

// 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 = appSessions.keys();

while (enum.hasMoreElements()) { Object key = enum.nextElement(); ApplicationSession appSession = (ApplicationSession)appSessions.get(key);

appSession.validate(); } }}

scattering – spread around

tangling – code in one region addresses multiple concerns

scattering and tangling (S&T) tend to appear together; they describe different facets of the same problem

;

/** * 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 (HttpSession) 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 * HttpSession view of this instance back to a Session view. * * @author Craig R. McClanahan * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ */

final class StandardSession implements HttpSession, Session {

// ----------------------------------------------------------- Constructors

/** * Construct a new Session associated with the specified Manager. * * @param manager The manager with which this Session is associated */ public StandardSession(Manager manager) {

super(); this.manager = manager;

}

/** * The last accessed time for this Session. */ private long lastAccessedTime = creationTime;

/** * The Manager with which this Session is associated. */ private Manager manager = null;

/** * 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 maxInactiveInterval = -1;

/** * Flag indicating whether this session is new or not. */ private boolean isNew = true;

/** * Flag indicating whether this session is valid or not. */ private boolean isValid = false;

/** * The string manager for this package. */ private StringManager sm = StringManager.getManager("org.apache.tomcat.session");

/** * The HTTP session context associated with this session. */ private static HttpSessionContext sessionContext = null;

/** * The current accessed time for this session. */ private long thisAccessedTime = creationTime;

// ----------------------------------------------------- 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 setCreationTime(long time) {

this.creationTime = time; this.lastAccessedTime = time; this.thisAccessedTime = time;

}

/** * Return the session identifier for this session. */ public String getId() {

return (this.id);

}

/** * Set the session identifier for this session. * * @param id The new session identifier */ public void setId(String id) {

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

this.id = id;

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

}

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

return (this.info);

}

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

return (this.lastAccessedTime);

}

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

return (this.manager);

}

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

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 IllegalStateException if this method is called on * an invalidated session */ public int getMaxInactiveInterval() {

return (this.maxInactiveInterval);

/** * 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.lastAccessedTime = this.thisAccessedTime; this.thisAccessedTime = System.currentTimeMillis(); this.isNew=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 ManagerBase)) ((ManagerBase) manager).remove(this);

// Unbind any objects associated with this session Vector results = new Vector(); Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { String attr = (String) attrs.nextElement(); results.addElement(attr); } Enumeration names = results.elements(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); removeAttribute(name); }

// Mark this session as invalid setValid(false);

}

/**

}

/** * Set the <code>isNew</code> flag for this session. * * @param isNew The new value for the <code>isNew</code> flag */ void setNew(boolean isNew) {

this.isNew = isNew;

}

/** * Set the <code>isValid</code> flag for this session. * * @param isValid The new value for the <code>isValid</code> flag */ void setValid(boolean isValid) {

this.isValid = isValid; }

// ------------------------------------------------- HttpSession Properties

/** * Return the time when this session was created, in milliseconds since * midnight, January 1, 1970 GMT. * * @exception IllegalStateException if this method is called on an * invalidated session */ public long getCreationTime() {

return (this.creationTime);

}

/** * 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 HttpSessionContext getSessionContext() {

if (sessionContext == null) sessionContext = new StandardSessionContext(); return (sessionContext);

}

// ----------------------------------------------HttpSession 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 IllegalStateException if this method is called on an * invalidated session */ public Object getAttribute(String name) {

return (attributes.get(name));

}

/** * Return an <code>Enumeration</code> of <code>String</code> objects * containing the names of the objects bound to this session. * * @exception IllegalStateException if this method is called on an * invalidated session */ public Enumeration getAttributeNames() {

return (attributes.keys());

}

/** * 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 IllegalStateException if this method is called on an * invalidated session * * @deprecated As of Version 2.2, this method is replaced by * <code>getAttribute()</code> */ public Object getValue(String name) {

return (getAttribute(name));

}

/** * Return the set of names of objects bound to this session. If there * are no such objects, a zero-length array is returned. * * @exception IllegalStateException if this method is called on an * invalidated session * * @deprecated As of Version 2.2, this method is replaced by * <code>getAttributeNames()</code> */ public String[] getValueNames() {

Vector results = new Vector(); Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { String attr = (String) attrs.nextElement(); results.addElement(attr); } String names[] = new String[results.size()]; for (int i = 0; i < names.length; i++) names[i] = (String) results.elementAt(i); return (names);

}

/** * Invalidates this session and unbinds any objects bound to it. * * @exception IllegalStateException 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 IllegalStateException if this method is called on an * invalidated session */ public boolean isNew() {

return (this.isNew);

}

* 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>HttpSessionBindingListener</code>, the container calls * <code>valueUnbound()</code> on the object. * * @param name Name of the object to remove from this session. * * @exception IllegalStateException if this method is called on an * invalidated session */ public void removeAttribute(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 HttpSessionBindingListener) { ((HttpSessionBindingListener) object).valueUnbound (new HttpSessionBindingEvent((HttpSession) this, 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>HttpSessionBindingListener</code>, the container calls * <code>valueBound()</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 IllegalArgumentException if an attempt is made to add a * non-serializable object in an environment marked distributable. * @exception IllegalStateException if this method is called on an * invalidated session */ public void setAttribute(String name, Object value) {

if ((manager != null) && manager.getDistributable() && !(value instanceof Serializable)) throw new IllegalArgumentException (sm.getString("standardSession.setAttribute.iae"));

synchronized (attributes) { removeAttribute(name); attributes.put(name, value); if (value instanceof HttpSessionBindingListener) ((HttpSessionBindingListener) value).valueBound (new HttpSessionBindingEvent((HttpSession) this, name)); }

}

// -------------------------------------------- HttpSession Private Methods

/** * 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 ClassNotFoundException if an unknown class is specified * @exception IOException if an input/output error occurs */ private void readObject(ObjectInputStream stream) throws ClassNotFoundException, IOException {

// Deserialize the scalar instance variables (except Manager) creationTime = ((Long) stream.readObject()).longValue(); id = (String) stream.readObject(); lastAccessedTime = ((Long) stream.readObject()).longValue(); maxInactiveInterval = ((Integer) stream.readObject()).intValue(); isNew = ((Boolean) stream.readObject()).booleanValue(); isValid = ((Boolean) stream.readObject()).booleanValue();

// Deserialize the attribute count and attribute values int n = ((Integer) stream.readObject()).intValue(); for (int i = 0; i < n; i++) { String name = (String) stream.readObject(); Object value = (Object) stream.readObject(); attributes.put(name, value); }

}

/** * 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>readObject()</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 writeObject(ObjectOutputStream stream) throws IOException {

// Write the scalar instance variables (except Manager) stream.writeObject(new Long(creationTime)); stream.writeObject(id); stream.writeObject(new Long(lastAccessedTime)); stream.writeObject(new Integer(maxInactiveInterval)); stream.writeObject(new Boolean(isNew)); stream.writeObject(new Boolean(isValid));

// Accumulate the names of serializable attributes Vector results = new Vector(); Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { String attr = (String) attrs.nextElement(); Object value = attributes.get(attr); if (value instanceof Serializable) results.addElement(attr); }

// Serialize the attribute count and the attribute values stream.writeObject(new Integer(results.size())); Enumeration names = results.elements(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); stream.writeObject(name); stream.writeObject(attributes.get(name)); }

} crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | long getCreationTime() | Object getAttribute(String) | Enumeration getAttributeNames() | String[] getValueNames() | void invalidate() | boolean isNew() | void removeAttribute(String) | void setAttribute(String, Object)); static advice(StandardSession s): invalidate(s) { before { if (!s.isValid()) throw new IllegalStateException (s.sm.getString("standardSession." + thisJoinPoint.methodName + ".ise")); } } }

// -------------------------------------------------------------- Private Class

/** * This class is a dummy implementation of the <code>HttpSessionContext</code> * interface, to conform to the requirement that such an object be returned * when <code>HttpSession.getSessionContext()</code> is called. * * @author Craig R. McClanahan * * @deprecated As of Java Servlet API 2.1 with no replacement. The * interface will be removed in a future version of this API. */

final class StandardSessionContext implements HttpSessionContext {

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 getIds() {

return (dummy.elements());

}

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

return (null);

} }

Page 5: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

good modularity

private long lastAccessed = creationTime; private int inactiveInterval = -1;

void accessed() { // set last accessed to thisAccessTime as it will be left over // from the previous access lastAccessed = thisAccessTime; thisAccessTime = System.currentTimeMillis();

validate(); }

void validate() { // if we have an inactive interval, check to see if we've exceeded it if (inactiveInterval != -1) { int thisInterval = (int)(System.currentTimeMillis() - lastAccessed) / 1000;

if (thisInterval > inactiveInterval) { invalidate(); } } }

public long getLastAccessedTime() { if (valid) { return lastAccessed; } else { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); } }

public long getLastAccessedTime() { return lastAccessed; }

private long lastAccessed = creationTime;

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

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

if (inactiveInterval != -1) { int thisInterval = (int)(System.currentTimeMillis() - lastAccessed) / 1000;

if (thisInterval > inactiveInterval) { invalidate();

ServerSessionManager ssm = ServerSessionManager.getManager();

ssm.removeSession(this); } } }

private long lastAccessedTime = creationTime;

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

return (this.lastAccessedTime);

}

this.lastAccessedTime = time;

/* * ==================================================================== * * 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 softwareitself, * 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 productsderived * from this software without prior written permission. For written * permission, please contact [email protected]. * * 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, INDIRECT, 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] * */

package org.apache.tomcat.session;

import org.apache.tomcat.core.*;import org.apache.tomcat.util.StringManager;import java.io.*;import java.net.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;

/** * Core implementation of an application level session * * @author James Duncan Davidson [[email protected]] * @author Jason Hunter [[email protected]] * @author James Todd [[email protected]] */

public class ApplicationSession implements HttpSession {

private StringManager sm = StringManager.getManager("org.apache.tomcat.session"); private Hashtable values = new Hashtable(); private String id; private ServerSession serverSession; private Context context; private long creationTime = System.currentTimeMillis();; private long thisAccessTime = creationTime;private boolean valid = true;

ApplicationSession(String id, ServerSession serverSession, Context context) { this.serverSession = serverSession; this.context = context; this.id = id;

this.inactiveInterval = context.getSessionTimeOut();

if (this.inactiveInterval != -1) { this.inactiveInterval *= 60; } }

ServerSession getServerSession() { return serverSession; }

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

// HTTP SESSION IMPLEMENTATION METHODS public String getId() { if (valid) { return id; } else { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); } }

public long getCreationTime() { if (valid) { return creationTime; } else { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); } } /** * * @deprecated */

public HttpSessionContext getSessionContext() { return new SessionContextImpl(); }

public void invalidate() { serverSession.removeApplicationSession(context);

// remove everything in the session

Enumeration enum = values.keys(); while (enum.hasMoreElements()) { String name = (String)enum.nextElement(); removeValue(name); }

valid = false; }

public boolean isNew() { if (! valid) { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); }

if (thisAccessTime == creationTime) { return true; } else { return false; } } /** * @deprecated */

public void putValue(String name, Object value) { setAttribute(name, value); }

public void setAttribute(String name, Object value) { if (! valid) { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); }

if (name == null) { String msg = sm.getString("applicationSession.value.iae");

throw new IllegalArgumentException(msg); }

removeValue(name); // remove any existing binding

if (value != null && value instanceof HttpSessionBindingListener) { HttpSessionBindingEvent e = new HttpSessionBindingEvent(this, name);

((HttpSessionBindingListener)value).valueBound(e); }

values.put(name, value); }

/** * @deprecated */ public Object getValue(String name) { return getAttribute(name); }

public Object getAttribute(String name) { if (! valid) { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); }

if (name == null) { String msg = sm.getString("applicationSession.value.iae");

throw new IllegalArgumentException(msg); }

return values.get(name); }

/** * @deprecated */ public String[] getValueNames() { Enumeration e = getAttributeNames(); Vector names = new Vector();

while (e.hasMoreElements()) { names.addElement(e.nextElement()); }

String[] valueNames = new String[names.size()];

names.copyInto(valueNames);

return valueNames; }

public Enumeration getAttributeNames() { if (! valid) { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); }

Hashtable valuesClone = (Hashtable)values.clone();

return (Enumeration)valuesClone.keys(); }

/** * @deprecated */

public void removeValue(String name) { removeAttribute(name); }

public void removeAttribute(String name) { if (! valid) { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); }

if (name == null) { String msg = sm.getString("applicationSession.value.iae");

throw new IllegalArgumentException(msg); }

Object o = values.get(name);

if (o instanceof HttpSessionBindingListener) { HttpSessionBindingEvent e = new HttpSessionBindingEvent(this,name);

((HttpSessionBindingListener)o).valueUnbound(e); }

values.remove(name); }

public void setMaxInactiveInterval(int interval) { if (! valid) { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); }

inactiveInterval = interval; }

public int getMaxInactiveInterval() { if (! valid) { String msg = sm.getString("applicationSession.session.ise");

throw new IllegalStateException(msg); }

return inactiveInterval; }}

//-----------------------------------------------------------------------

package org.apache.tomcat.session;

import org.apache.tomcat.core.*;import org.apache.tomcat.util.StringManager;import java.io.*;import java.net.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;

/** * Core implementation of a server session * * @author James Duncan Davidson [[email protected]] * @author James Todd [[email protected]] */

public class ServerSession {

private StringManager sm = StringManager.getManager("org.apache.tomcat.session"); private Hashtable values = new Hashtable(); private Hashtable appSessions = new Hashtable(); private String id; private long creationTime = System.currentTimeMillis();; private long thisAccessTime = creationTime; private long lastAccessed = creationTime; private int inactiveInterval = -1; ServerSession(String id) { this.id = id; }

public String getId() { return id; }

public long getCreationTime() { return creationTime; }

public long getLastAccessedTime() { return lastAccessed; } public ApplicationSession getApplicationSession(Context context, boolean create) { ApplicationSession appSession = (ApplicationSession)appSessions.get(context);

if (appSession == null && create) {

// XXX // sync to ensure valid? appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); }

// XXX // make sure that we haven't gone over the end of our // inactive interval -- if so, invalidate and create // a new appSession return appSession; } void removeApplicationSession(Context context) { appSessions.remove(context); }

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

void validate()

ynchronized void invalidate() { Enumeration enum = appSessions.keys();

while (enum.hasMoreElements()) { Object key = enum.nextElement(); ApplicationSession appSession = (ApplicationSession)appSessions.get(key);

appSession.invalidate(); } } public void putValue(String name, Object value) { if (name == null) { String msg = sm.getString("serverSession.value.iae");

throw new IllegalArgumentException(msg); }

removeValue(name); // remove any existing binding values.put(name, value); }

public Object getValue(String name) { if (name == null) { String msg = sm.getString("serverSession.value.iae");

throw new IllegalArgumentException(msg); }

return values.get(name); }

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

public void removeValue(String name) { values.remove(name); }

public void setMaxInactiveInterval(int interval) { inactiveInterval = interval; }

public int getMaxInactiveInterval() { return inactiveInterval; }

// 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 = appSessions.keys();

while (enum.hasMoreElements()) { Object key = enum.nextElement(); ApplicationSession appSession = (ApplicationSession)appSessions.get(key);

appSession.validate(); } }}

;

/** * 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 (HttpSession) 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 * HttpSession view of this instance back to a Session view. * * @author Craig R. McClanahan * @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ */

final class StandardSession implements HttpSession, Session {

// ----------------------------------------------------------- Constructors

/** * Construct a new Session associated with the specified Manager. * * @param manager The manager with which this Session is associated */ public StandardSession(Manager manager) {

super(); this.manager = manager;

}

/** * The last accessed time for this Session. */ private long lastAccessedTime = creationTime;

/** * The Manager with which this Session is associated. */ private Manager manager = null;

/** * 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 maxInactiveInterval = -1;

/** * Flag indicating whether this session is new or not. */ private boolean isNew = true;

/** * Flag indicating whether this session is valid or not. */ private boolean isValid = false;

/** * The string manager for this package. */ private StringManager sm = StringManager.getManager("org.apache.tomcat.session");

/** * The HTTP session context associated with this session. */ private static HttpSessionContext sessionContext = null;

/** * The current accessed time for this session. */ private long thisAccessedTime = creationTime;

// ----------------------------------------------------- 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 setCreationTime(long time) {

this.creationTime = time; this.lastAccessedTime = time; this.thisAccessedTime = time;

}

/** * Return the session identifier for this session. */ public String getId() {

return (this.id);

}

/** * Set the session identifier for this session. * * @param id The new session identifier */ public void setId(String id) {

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

this.id = id;

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

}

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

return (this.info);

}

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

return (this.manager);

}

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

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 IllegalStateException if this method is called on * an invalidated session */ public int getMaxInactiveInterval() {

return (this.maxInactiveInterval);

/** * 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 ManagerBase)) ((ManagerBase) manager).remove(this);

// Unbind any objects associated with this session Vector results = new Vector(); Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { String attr = (String) attrs.nextElement(); results.addElement(attr); } Enumeration names = results.elements(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); removeAttribute(name); }

// Mark this session as invalid setValid(false);

}

/**

}

/** * Set the <code>isNew</code> flag for this session. * * @param isNew The new value for the <code>isNew</code> flag */ void setNew(boolean isNew) {

this.isNew = isNew;

}

/** * Set the <code>isValid</code> flag for this session. * * @param isValid The new value for the <code>isValid</code> flag */ void setValid(boolean isValid) {

this.isValid = isValid; }

// ------------------------------------------------- HttpSession Properties

/** * Return the time when this session was created, in milliseconds since * midnight, January 1, 1970 GMT. * * @exception IllegalStateException if this method is called on an * invalidated session */ public long getCreationTime() {

return (this.creationTime);

}

/** * 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 HttpSessionContext getSessionContext() {

if (sessionContext == null) sessionContext = new StandardSessionContext(); return (sessionContext);

}

// ----------------------------------------------HttpSession 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 IllegalStateException if this method is called on an * invalidated session */ public Object getAttribute(String name) {

return (attributes.get(name));

}

/** * Return an <code>Enumeration</code> of <code>String</code> objects * containing the names of the objects bound to this session. * * @exception IllegalStateException if this method is called on an * invalidated session */ public Enumeration getAttributeNames() {

return (attributes.keys());

}

/** * 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 IllegalStateException if this method is called on an * invalidated session * * @deprecated As of Version 2.2, this method is replaced by * <code>getAttribute()</code> */ public Object getValue(String name) {

return (getAttribute(name));

}

/** * Return the set of names of objects bound to this session. If there * are no such objects, a zero-length array is returned. * * @exception IllegalStateException if this method is called on an * invalidated session * * @deprecated As of Version 2.2, this method is replaced by * <code>getAttributeNames()</code> */ public String[] getValueNames() {

Vector results = new Vector(); Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { String attr = (String) attrs.nextElement(); results.addElement(attr); } String names[] = new String[results.size()]; for (int i = 0; i < names.length; i++) names[i] = (String) results.elementAt(i); return (names);

}

/** * Invalidates this session and unbinds any objects bound to it. * * @exception IllegalStateException 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 IllegalStateException if this method is called on an * invalidated session */ public boolean isNew() {

return (this.isNew);

}

* 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>HttpSessionBindingListener</code>, the container calls * <code>valueUnbound()</code> on the object. * * @param name Name of the object to remove from this session. * * @exception IllegalStateException if this method is called on an * invalidated session */ public void removeAttribute(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 HttpSessionBindingListener) { ((HttpSessionBindingListener) object).valueUnbound (new HttpSessionBindingEvent((HttpSession) this, 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>HttpSessionBindingListener</code>, the container calls * <code>valueBound()</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 IllegalArgumentException if an attempt is made to add a * non-serializable object in an environment marked distributable. * @exception IllegalStateException if this method is called on an * invalidated session */ public void setAttribute(String name, Object value) {

if ((manager != null) && manager.getDistributable() && !(value instanceof Serializable)) throw new IllegalArgumentException (sm.getString("standardSession.setAttribute.iae"));

synchronized (attributes) { removeAttribute(name); attributes.put(name, value); if (value instanceof HttpSessionBindingListener) ((HttpSessionBindingListener) value).valueBound (new HttpSessionBindingEvent((HttpSession) this, name)); }

}

// -------------------------------------------- HttpSession Private Methods

/** * 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 ClassNotFoundException if an unknown class is specified * @exception IOException if an input/output error occurs */ private void readObject(ObjectInputStream stream) throws ClassNotFoundException, IOException {

// Deserialize the scalar instance variables (except Manager) creationTime = ((Long) stream.readObject()). isValid = ((Boolean) stream.readObject()).booleanValue();

// Deserialize the attribute count and attribute values int n = ((Integer) stream.readObject()).intValue(); for (int i = 0; i < n; i++) { String name = (String) stream.readObject(); Object value = (Object) stream.readObject(); attributes.put(name, value); }

}

/** * 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>readObject()</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 writeObject(ObjectOutputStream stream) throws IOException {

// Write the scalar instance variables (except Manager) stream.writeObject(new Long(creationTime)); stream.writeObject(id); stream.writeObject(new Long(lastAccessedTime)); stream.writeObject(new Integer(maxInactiveInterval)); stream.writeObject(new Boolean(isNew)); stream.writeObject(new Boolean(isValid));

// Accumulate the names of serializable attributes Vector results = new Vector(); Enumeration attrs = getAttributeNames(); while (attrs.hasMoreElements()) { String attr = (String) attrs.nextElement(); Object value = attributes.get(attr); if (value instanceof Serializable) results.addElement(attr); }

// Serialize the attribute count and the attribute values stream.writeObject(new Integer(results.size())); Enumeration names = results.elements(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); stream.writeObject(name); stream.writeObject(attributes.get(name)); }

} crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | long getCreationTime() | Object getAttribute(String) | Enumeration getAttributeNames() | String[] getValueNames() | void invalidate() | boolean isNew() | void removeAttribute(String) | void setAttribute(String, Object)); static advice(StandardSession s): invalidate(s) { before { if (!s.isValid()) throw new IllegalStateException (s.sm.getString("standardSession." + thisJoinPoint.methodName + ".ise")); } } }

// -------------------------------------------------------------- Private Class

/** * This class is a dummy implementation of the <code>HttpSessionContext</code> * interface, to conform to the requirement that such an object be returned * when <code>HttpSession.getSessionContext()</code> is called. * * @author Craig R. McClanahan * * @deprecated As of Java Servlet API 2.1 with no replacement. The * interface will be removed in a future version of this API. */

final class StandardSessionContext implements HttpSessionContext {

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 getIds() {

return (dummy.elements());

}

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

return (null);

} }

separated – implementation of a concern can be treated as relatively separate entity

localized – implementation of a concern appears in one part of program

modular – above + has a clear, well defined interface to rest of system

Page 6: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

do we help with this problem?

:

System.out.println("foo called");

Helper.foo(n/3);

:

:

System.out.println("foo called");

Helper.foo(i+j+k);

:

:

System.out.println("foo called");

Helper.foo(x);

:

class Helper { :

public static void foo(int n) {

} :

}

every call to foois preceded by a log call

Page 7: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

not necessarily

:

System.out.println("foo called");

Helper.foo(…);

:

:

System.out.println("foo called");

Helper.foo(…);

:

:

System.out.println("foo called");

Helper.foo(…);

:

class Helper { :

public static void foo(int n) {

} :

}

class Helper { :

public static void foo(int n) {

System.out.println("foo called.");

} :

}

:

Helper.foo(n/3);

:

:

Helper.foo(i+j+k);

:

:

Helper.foo(x);

:

procedures canmodularize this case

unless logs use calling context, we don’t control

source of Helper…

Page 8: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

do we help with this problem?

2Point

getX()getY()setX(int)setY(int)moveBy(int, int)draw()refresh()

Line

getP1()getP2()setP1(Point)setP2(Point)moveBy(int, int)draw()refresh()

FigureElement

moveBy(int, int)

all subclasses have an identical method

Page 9: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

not necessarily

2Point

getX()getY()setX(int)setY(int)moveBy(int, int)draw()refresh()

Line

getP1()getP2()setP1(Point)setP2(Point)moveBy(int, int)draw()refresh()

FigureElement

moveBy(int, int)

2Point

getX()getY()setX(int)setY(int)moveBy(int, int)draw()

Line

getP1()getP2()setP1(Point)setP2(Point)moveBy(int, int)draw()

FigureElement

moveBy(int, int)refresh()

inheritance canmodularize this

Page 10: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

do we help with this problem?

2Point

getX()getY()setX(int)setY(int)moveBy(int, int)draw()

Line

getP1()getP2()setP1(Point)setP2(Point)moveBy(int, int)draw()

FigureElement

moveBy(int, int)refresh()

these methods all end withcall to:

Display.update();

Page 11: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

yes! – this is AspectJ’s fact(n)

DisplayUpdating

2Point

getX()getY()setX(int)setY(int)moveBy(int, int)draw()

Line

getP1()getP2()setP1(Point)setP2(Point)moveBy(int, int)draw()

FigureElement

moveBy(int, int)refresh()

after(): call(void FigureElement+.set*(..)) || call(void FigureElement.moveBy(int, int)){ Display.update();}

after(): call(void FigureElement+.set*(..)) || call(void FigureElement.moveBy(int, int)){ Display.update();}

Page 12: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

observations and questions

• modularity (aka SOC) techniques– S&T principle, mechanism modular structure– may apply across range of software artifacts

• many kinds of S&T, principles, structure S&T is not specific to AO AO is just one modularity technique

• questions to answer include:– what particular modularity problems do we address?

• our particular kind of S&T?– what’s our particular principle?

• procedure, object…– what’s our particular kind of structure?

• block, classification hierarchy…

Page 13: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

[Yvonne Coady AOSD 2003]

vm_fault

vm_pager_getpages

vnode_pager_getpages

ffs_getpages

ufs_bmap

path specific customization

ffs_validffs_calc_size

[Coady AOSD’03]

Page 14: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

CLASSIFYING BYCLASSIFICATION SIBLINGS

nontreetree

hardwood softwood

object

plant nestable predator

insectplant

nectarplant

dandelion

dandelion

bird

bird

woodsman

woodsmanlocust

maple

maple

cherry

cherry

pine

pine

object

Copyright © 1993 IBM Corporation

[Harrison, Ossher OOPSLA’93]

Page 15: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

[Jan Hanneman OOPSLA 2002] UBC software modularity group

observer pattern in AspectJ

FigureElement

getColor(): ColorsetColor(Color)

Point

getX(): intgetY(): intgetColor():ColorsetX(int)setY(int)setColor(Color)

Line

getP1():PointgetP2():PointgetColor():ColorsetP1(Point)setP2(Point)setColor(Color)

Screen

display()

A Figure Element SystemObserver Design Pattern

Subject

addObserver(Observer)removeObserver(Observer)notify()

Observer

update()

ConcreteSubject

getState()setState()notify()

subjectState

ConcreteObserver

update(Subject)

observerState

For all o in observers { o.update();}

observers

subject

observerState = subject.getState();

[Hanneman OOPSLA’02]

setX(int)setY(int)setColor(Color)

setP1(Point)setP2(Point)setColor(Color)

Page 16: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

Example of AOP with Composition Filters

• Add synchronization constraint (mutual exclusion) to a given list of classes

• Synchronization (assertions, dispatch, ..) is expressed by a filter of type Wait (Error, Dispatch, ..): – if the condition NoActiveThreads does not hold for an object, – a received message can not pass the filter,– and will be queued until it can pass.

• filtermodule (declarations + filter definition) is unit of superimposition

concern ConcurrentDocumentProcessing // ‘concern’ unifies ‘aspect’ & ‘class’ filtermodule MutExSync // unit of superimposition conditions NoActiveThreads; // is true when no thread is executing ‘within’ this object inputfilters buffer:Wait={ NoActiveThreads=>*}; // implements synchronization end; ... cont’d

[Aksit, Bergmans CACM AOP issue]

Copyright © 2003 Mehmet Aksit, Lodewijk Bergmans

Page 17: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

traversals and class graphs

P1

P2P3

P1

P6P2

P5 P3

P4P1

P2

Copyright © 2003 MiraMezini, David Lorenz, Karl Lieberherr

[Mezini, Lorenz, Lieberherr c.'98]

Page 18: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

analysis of some of our accounts

• tyranny of the dominant decomposition• crosscutting structure• aspect• weaving

an attempt to classify and evaluate some of the accounts – what do they

address, strengths, weaknesses

by "account" I mean a story we tell to explain part or all of AOSD

Page 19: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

tyrannny…

• describes– the problem– sometimes a single decomposition can’t localize all concerns– want multiple decompositions

• but…– exactly when does a single decomposition fail?– two decompositions? two decomposition paradigms?...

where do you file Sacred Hoops?

fitting Line in to

FigureElement and Point

fitting DisplayUpdating

in to FigureElement, Point and Line

vs.DisplayUpdating

# changeafter change()

2Point

getX()getY()setX(int)setY(int)moveBy(int, int)draw()

Line

getP1()getP2()setP1(Point)setP2(Point)moveBy(int, int)draw()

FigureElement

moveBy(int, int)refresh()

2Point

getX()getY()setX(int)setY(int)moveBy(int, int)draw()

Line

getP1()getP2()setP1(Point)setP2(Point)moveBy(int, int)draw()

FigureElement

moveBy(int, int)refresh()

Page 20: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

aspect

• describes– entities that become local in the alternate decomposition– aspect-of is different than part-of

• wheel is a part of a car• wind resistance is an aspect of a car• DisplayUpdating is an aspect of Point & Line

– when setX is called, updating happens• the prefetching optimization is an aspect of virtual memory

– runs as integral part of vnode access• but…

– what is the nature of the relationship exactly?– how does the alternate decomposition localize the aspect?– litmus test for a definition: discriminate between aspect and

object?– how does this fit with symmetric AOP

each player vs. “great ball movement”

Page 21: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

crosscutting

• describes– nature of relation between decompositions– cases where a single decomposition fails

• but…– what crosscuts?

• concern? structure? natural structure?

– crosscutting concern concern for which natural structures crosscut

– precise definition of crosscutting? • 1 to many and many to 1 correspondence (in general)

DisplayUpdating

# changeafter change()

2Point

getX()getY()setX(int)setY(int)moveBy(int, int)draw()

Line

getP1()getP2()setP1(Point)setP2(Point)moveBy(int, int)draw()

FigureElement

moveBy(int, int)refresh()

nontreetree

hardwood softwood

object

plant nestable predator

insectplant

nectarplant

dandelion

dandelion

bird

bird

woodsman

woodsmanlocust

maple

maple

cherry

cherry

pine

pine

object like a Fourier transform

Page 22: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

join point mechanisms

• describes– mechanism– coordinates (weaves) different semantic effects together at join

points– quantification and ob*** (transparency) – these accounts are the most solid

• but…– “weaving” connotes source code pre-processing?

• interleaving?– quantification connotes meta-programing– applicability of a technique doesn’t work to define an approach– I tried to downplay weaving, but…

systematically propagate and coordinate effects

Page 23: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

summary so far

current accounts of aspect-orientation– problem: tyranny of single decomposition

• cannot, in a single decomposition, modularize all concerns• bad modularity brittle (non-adaptive), fragile, buggy mess

– principle: aspects …• concerns that are local in the alternate decomposition• aspect of is different than part of

– structure: crosscutting• relationship between decompositions such that

– some concerns are localized (aspects)– and others are potentially spread out

– mechanism: join point mechanisms• coordinates effect of programs from different decompositions

Page 24: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

© Copyright 2003, Gregor Kiczales. All rights reserved.

thejoin

pointmechanism

the claimthat this is the community’s main contributionto date

Page 25: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

join point mechanisms

• one ontology for JP mechanisms– the join points– a means of identifying join points– a means of semantic effect at join points

after(): call(void FigureElement+.set*(..)) || call(void FigureElement.moveBy(int, int)) { Display.update();}

Page 26: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

join points means ofidentifying JPs

means ofsemantic effect at JPS

AJdynpoints in runtime control flow graph

by declaration signature including wildcards, lexical and dynamic properties

execute before, after or around

AJstaticmember signatures

by signature including wildcards and lexical properties

warn, error

add member

HJ member signatures

by signature including wildcards and lexical properties

extract to slice

compose in numerous ways

DJ

CF

diversity of JP mechanisms

Page 27: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

join points means ofidentifying JPs

means ofsemantic effect at JPS

AJdynpoints in runtime control flow graph

by declaration signature including wildcards, lexical and dynamic properties

execute before, after or around

AJstaticmember signatures

by signature including wildcards and lexical properties

warn, error

add member

HJ member signatures

by signature including wildcards and lexical properties

extract to slice

compose in numerous ways

DJ

diversity of JP mechanisms

AJdyn

HJ

DJ

fine

dynamic

staticcoarse

???

AJstatic

Page 28: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

community’s key contributions to date

• have discovered the space of join point mechanisms– different kinds of join points– different kinds of means of identifying join points– different kinds of means of specifying semantics

• have used this to program from multiple decompositions– bearing a variety of simultaneous structural relationships

• block, hierarchical, crosscutting

Page 29: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

pointcut entry(): !within(com.acme.product..*) && call(public * com.acme.product..*(..));

pointcut initialEntry(): entry() && !cflowbelow(entry());

around(): initialEntry() { <setup expensive dynamic context> proceed(); <tear down expensive dynamic context>}

compositional crosscuttingpackage structure

wrt control flow

Page 30: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

join point mechanisms

• but– if you add a new field color– you have to extend this pointcut

• so…

after(): call(void Point.setX(int)) || call(void Point.setY(int)) || call(void Line.setP1(Point)) || call(void Line.setP2(Point)) || call(void FigureElement.moveBy(int, int)) { Display.update();}

it is still it is better than without AOPthe dependence is explicit, localized, modular clear declarative interface(the structure of the crosscutting concern is explicit)

Page 31: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

a more precise means of identifying JPs

• robust against some edits • the abstraction of the pointcut is now more clear• but

– if you add a field that doesn’t have a set method– you still have to update the pointcut

• so…– you could solve this problem by prohibiting wildcards?– you could solve this problem by requiring tags on methods?– NO! solve it by making the means of identifying JPs more precise

after(): call(void FigureElement+.set*(..)) || call(void FigureElement.moveBy(int, int)) { Display.update();}

Page 32: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

idea for a more precise mechanism

predict the control flow of FigureElement.draw()

consider HOW the dependencies are stated,not just WHAT is depended on

sets to such fields require display update

find fields referenced in that control flow

pointcut* displayState():

pcflow(execution(void FigureElement+.draw())

&& get(* FigElt+.*);

after set(<displayState()>) (): {

Display.update();

}

Page 33: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

other ideas…

• dflow(<pointcut>, <variable>)– did the value of the variable come in a dataflow

through <pointcut>

• min(<predicted-cflow>, <predicted-cflow>)– the least common caller of the two cflows

• JP mechanism opens a new design space– a language design for packaging such analyses– how to think about programming with them– how to limit to tractable cases

Page 34: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

summary so far

• a number of accounts help describe the space– get at different aspects of our work– none is completely satisfactory

• JP mechanisms are key contribution to date– discovery of the space of join point mechanisms– using them to program from multiple decompositions

• we should increase the power of JP mechanisms– to make means of identifying JPs more precise– to make AOP more useful– and to make AOP more principled, more robust…

Page 35: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

© Copyright 2003, Gregor Kiczales. All rights reserved.

another perspective

onjoin

pointmechanisms

the conceptsof registration, effectiveness and themiddle distance between connection and disconnection

Page 36: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

[Smith, On the Origin of Objects1]

• how is it that we can see the world in different ways?

• registration is– process of ‘parsing’ objects out of fog of undifferentiated stuff– constantly registering and re-registering the world – mediates different perspectives on a changing world– enables moving in and out of connection with the world

• critical properties of registration– multiple routes to reference (aliasing is inherent)

• morning star, evening star– ability to exceed causal reach

• person closest to average height in Gorbachev's office now– indexical reference

• the one in front of him

1. On this slide, object means in the real-world.

Page 37: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

how JP mechanisms enable crosscutting

some program

stream of instructions

Page 38: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

how JP mechanisms enable crosscutting

pick out some of the points and

register them into this structure

Page 39: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

how JP mechanisms enable crosscutting

and add to the instruction

stream there

Page 40: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

how JP mechanisms enable crosscutting

and add to the instruction

stream there

Page 41: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

how JP mechanisms enable crosscutting

Page 42: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

how JP mechanisms enable crosscutting

Page 43: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

how JP mechanisms enable crosscutting

Page 44: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

how JP mechanisms enable crosscutting

Page 45: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

JP mechanisms reconsidered

• how to decompose software in different ways

• register aspects out of fog of undifferentiated points– means of identifying JPs (aka pointcut) registers– aspects/slices/concerns… group over that

• connect and have effect through that registration– means of semantic effect (aka advice)

• critical properties of registration– multiple routes to reference

• void setX(int nx) { … }, call(void setX(int)), cflow(…)– exceed causal reach

• within(com.sun..*), !within(com.mycompany.mysystem)– indexical reference

• cflow(…)

Page 46: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

a simple bridge

Page 47: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

models programs and systems

systemmodeleffective

abstract

Page 48: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

models programs and systems

i = 1while (i < 4) { print(i) i = i + 1}

systemmodel

abstract

effective

programs live in this magic space

Page 49: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

models programs and systems

i = 1while (i < 4) { print(i) i = i + 1}

systemmodel

Brian’s account talks(in part) about this space

abstract

effective

programs live in this magic space

Page 50: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

models programs and systems

i = 1while (i < 4) { print(i) i = i + 1}

systemmodel

abstract

effective

programs live in this magic space

cc

Brian’s account talks(in part) about this space

Page 51: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

models programs and systems

i = 1while (i < 4) { print(i) i = i + 1}

systemmodel

abstract

effective

programs live in this magic space

cc

Brian’s account talks(in part) about this space

Page 52: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

summary

• account of JP mechanism in terms of registration– possible basis for better foundational account of AO

• more interesting than objects? harder than objects?

– relation among• problems, decompositions, structures, mechanisms

– read On the Origin of Objects• (except it is not written in computer science vocabulary)

• JP mechanism seen as– means of connecting via different decompositions– means of switching between connected and disconnected

Page 53: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

© Copyright 2003, Gregor Kiczales. All rights reserved.

join point mechanisms

andsoftware

models

what can we do for models, model based development, fluid AO

Page 54: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

impact of JP mechanism on sw models

• models that abstract– simple UML class diagrams

• models that crosscut– patterns– UML sequence, state…

• models that connect and disconnect– fluid aspect-orientation

Page 55: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

use cases

• what is the system supposed to do for each user• the use cases crosscut the components• JP mechanism provides principled support to

organize modeling, implementation, testing…• multiple effects at a JP

– identifies an interaction in the design– means for resolving the issue– traceability in the code

• reasoning about composition of use cases = reasoning about composition of aspects

Page 56: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

Use cases – use case realizations -- componentsUse cases – use case realizations -- components Each use case is realized by a collaboration - a set of classes A class plays different roles in different use case realizations The total responsibility of a class is the composition of these roles

Each use case is realized by a collaboration - a set of classes A class plays different roles in different use case realizations The total responsibility of a class is the composition of these roles

Withdraw Cash

Deposit Funds

Transfer Funds

Cash Withdrawal

Cash Interface

Cash Interface Deposit Funds

Transfer Funds

Interface Interface

Funds Deposit

Cash Transfer Funds

CashWithdrawal

Use case Specification

Use case design

Component design &implementation

Page 57: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

Observer

Subject

Observer: Display

change

update: {...}

class Point {

int x; Getter/Setter

int y;

void draw() {

Graphics.drawOval(…);

}

...

}

patterns and classes

• pattern must be effective (connect to code)• ‘wizards’ might weave the pattern in

– brittle, hard to understand, hard to maintain

• would rather preserve a structure like this

Page 58: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

Observer

Subject

Observer: Display

change

update: {...}

class Point {

int x; Getter/Setter

int y;

void draw() {

Graphics.drawOval(…);

}

...

}

patterns and classes

• Observer refers to expansion of Getter/Setter– clearly, reliably, stably– alternate reference, beyond causal reach, indexical

• multiple routes to reference• beyond causal reach• indexical

Page 59: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

fluid AO

• static aspects– crosscut, but structures themselves are fixed

• fluid aspects– fluid connection and disconnection of models– models are used to edit code– non-effective models and domain transform idea

• connect model• edit code via model• disconnect model

Page 60: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

Extracting Latent ConcernsExtracting Latent Concerns

RegularTrackedname()

check()

print()

Employee Research

CorePersonnelname()

check()

print()

name()

check()

print()

name()

check()

print()

RegularTracked

tax()

pay()

Employee Research

Payrolltax()

pay()

tax()

pay()

tax()

pay()

package Personnel

Concern MappingConcern MappingFeature.CorePersonnel

operation tax Feature.Payrolloperation pay Feature.Payroll

class Employee { String name() {...} boolean check() {…} void print() {…} float tax() {...} void pay() {…}… }

FeatureFeature

ClassClass

Employee Research RegularTracked …

merge by name

Copyright © 2000 IBM Corporation

Page 61: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

1. use pointcut to identify scattered aspect

2. shows up below

3. delete them all

4. rewrite with advice

Page 62: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

connected non-effective models

• models that are not sufficiently complete to yield code • but can be used to analyze code• connect such models using JP mechanism• edit code through the model

• feature analysis? [robillard, murphy]– remove features that are mixed at finer granularity– compose features

• verification? testing?...

Page 63: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

© Copyright 2003, Gregor Kiczales. All rights reserved.

summary

Page 64: © Copyright 2003, Gregor Kiczales. All rights reserved. AOSD 2003 the fun has just begun Gregor Kiczales University of British Columbia © Copyright 2003,

AOSD 2003 © Copyright 2003, Gregor Kiczales. All rights reserved.

the fun has just begun

• JP mechanism is incredibly powerful and deep– connects programs/models/… with different decompositions

• current accounts of AO are intuitively useful– more work is needed for them to be foundational– that’s not surprising, see [Smith] for some ideas on this

• more fun with programming languages/tools– increase power of JP mechanisms to make languages/tools

• more practical, more useful, more principled• more fun with models

– patterns, use cases, more abstract models

• it’s a technology of connection across different perspectives– can bridge across software development process???