Download presentation
Presentation is loading. Please wait.
1
Aspect-Oriented Software Design
Motivating the Problem What does OO Offer? When and How does OO Fail? Looking at the Problem Large Scale Aspect-Oriented Software Design (AOSD) Concepts, Ideas, and Benefits Aspect-Oriented Programming (AOP) and AspectJ From Design to Programming The AspectJ AOP Model Examples to Illustrate Key Ideas Concluding Remarks on AOSD/AOP
2
Recall: What does OO Offer?
Classes are a Very Good Technique to Modularize the Components of the System Abstraction Classes and Objects Usually Represent Concepts from the Real World, Abstracting Unnecessary Details. Encapsulation Classes Encapsulate their Behavior into Manageable Units, by Hiding their Implementation to the Clients Classification Hierarchies Provide a Good way to Organize and Classify Classes
3
Classic OO program Survey Management example
Concerns are Separated into Different Classes class Survey_List { public void Add_Survey_Header(Survey_Header sh) { } public List Survey_Title_Search(String title) { } public void Update_Survey_List() { } public void Delete_Survey_Header(Survey_Header sh) { } } class Survey_Header { public void Create_Survey_Header() { } public void Add_Question(String q) { } public void Add_Special_Question(String sq) { } } class Public_Survey_Results { public List Get_General_Statistics() { } public List Get_Questions() { } }
4
When and How does OO fail?
The Object-Oriented Paradigm Provides the Class as the Main unit to Decompose a Software System A Good Designer can Decompose the Main Concerns of an Application into Classes and Hierarchies However, no Matter how Good is the Design there are still Concerns that Cannot be Well Modularized Sound Modeling for One Concern (GUI) may Lead to Poor Modeling for Another Concern (Database) This Leads to: Scattering – Code for Concern is Distributed Tangling – Code for Multiple Concerns is Present in Each Abstraction (Class, Method, etc.)
5
Survey Management Application
A Visual Example Access-control Code is Scattered Through Both Classes Each Class has Tangled both Access-control Code and Domain-specific Code public void Survey_Title_Search(String title) { if (user.canSearch()){ slist.search(title); ... } public void public void Add_Special_Question(String sq) { if (user.canAddSpecialQuestion()){ Question_List.add(sq); ... }
6
What Occurs at Larger Scale?
Consider Apache Tomcat as a Set of Abstractions that Represents its Broad Functionality for: XML Parsing UML Pattern Matching Logging of User Activity Many Other Capabilities Represented Pictorially as:
7
An Example of Good Modularity
XML Parsing in org.apache.tomcat Red shows Relevant lines of code Nicely Located in one box – Well Defined OOP is an idea about how to structure systems the idea of an “object” has proven to be a powerful fundamentally about classification and specialization (classes and inheritance) © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
8
Another Example of Good Modularity
URL Pattern Matching in org.apache.tomcat Red shows Relevant lines of code Nicely Located in two boxes – (using inheritance) OOP is an idea about how to structure systems the idea of an “object” has proven to be a powerful fundamentally about classification and specialization (classes and inheritance) © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
9
An Example of Poor Modularity
Logging in org.apache.tomcat Red Shows lines of code Handle Logging Not in just one place Not even in a small number of places Just a Mess… OOP is an idea about how to structure systems the idea of an “object” has proven to be a powerful fundamentally about classification and specialization (classes and inheritance) © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
10
Another Example of Poor Modularity …
/* * * ==================================================================== * modification, are permitted provided that the following conditions * Redistribution and use in source and binary forms, with or without * reserved. * The Apache Software License, Version 1.1 * Copyright (c) 1999 The Apache Software Foundation. All rights * 1. Redistributions of source code must retain the above copyright * are met: * 3. The end-user documentation included with the redistribution, if * distribution. * the documentation and/or other materials provided with the * 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 * any, must include the following acknowlegement: * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * if and wherever such third-party acknowlegements normally appear. itself, * "This product includes software developed by the * Apache Software Foundation ( * Alternately, this acknowlegement may appear in the software * from this software without prior written permission. For written * Foundation" must not be used to endorse or promote products derived * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * permission of the Apache Group. * nor may "Apache" appear in their names without prior written * 5. Products derived from this software may not be called "Apache" * permission, please contact * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * 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 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * 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, * information on the Apache Software Foundation, please see * < * individuals on behalf of the Apache Software Foundation. For more * This software consists of voluntary contributions made by many * SUCH DAMAGE. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF */ * [Additional notices, if required by prior licensing conditions] import java.net.*; import java.util.*; import java.io.*; import org.apache.tomcat.util.StringManager; package org.apache.tomcat.session; import org.apache.tomcat.core.*; James Duncan Davidson Jason Hunter * Core implementation of an application level session /** import javax.servlet.*; import javax.servlet.http.*; James Todd private String id; private ServerSession serverSession; private Hashtable values = new Hashtable(); StringManager.getManager("org.apache.tomcat.session"); public class ApplicationSession implements HttpSession { private StringManager sm = private long lastAccessed = creationTime; ApplicationSession(String id, ServerSession serverSession, private boolean valid = true; private int inactiveInterval = -1; private long thisAccessTime = creationTime; private Context context; private long creationTime = System.currentTimeMillis();; this.inactiveInterval = context.getSessionTimeOut(); this.context = context; this.id = id; this.serverSession = serverSession; Context context) { } this.inactiveInterval *= 60; if (this.inactiveInterval != -1) { return serverSession; ServerSession getServerSession() { void accessed() { * inactivities can be dealt with accordingly. * Called by context when request comes in so that accesses and thisAccessTime = System.currentTimeMillis(); lastAccessed = thisAccessTime; // from the previous access // set last accessed to thisAccessTime as it will be left over int thisInterval = (int)(System.currentTimeMillis() - lastAccessed) / 1000; if (inactiveInterval != -1) { // if we have an inactive interval, check to see if we've exceeded it validate(); void validate() { invalidate(); if (thisInterval > inactiveInterval) { return id; if (valid) { // HTTP SESSION IMPLEMENTATION METHODS throw new IllegalStateException(msg); String msg = sm.getString("applicationSession.session.ise"); } else { public String getId() { return creationTime; public long getCreationTime() { return new SessionContextImpl(); public HttpSessionContext getSessionContext() { return lastAccessed; public long getLastAccessedTime() { public void invalidate() { serverSession.removeApplicationSession(context); removeValue(name); while (enum.hasMoreElements()) { String name = (String)enum.nextElement(); // remove everything in the session Enumeration enum = values.keys(); public boolean isNew() { valid = false; if (! valid) { return true; return false; if (thisAccessTime == creationTime) { public void setAttribute(String name, Object value) { setAttribute(name, value); public void putValue(String name, Object value) { removeValue(name); // remove any existing binding throw new IllegalArgumentException(msg); String msg = sm.getString("applicationSession.value.iae"); if (name == null) { new HttpSessionBindingEvent(this, name); ((HttpSessionBindingListener)value).valueBound(e); HttpSessionBindingEvent e = if (value != null && value instanceof HttpSessionBindingListener) { values.put(name, value); public Object getAttribute(String name) { return getAttribute(name); public Object getValue(String name) { return values.get(name); Vector names = new Vector(); names.addElement(e.nextElement()); while (e.hasMoreElements()) { Enumeration e = getAttributeNames(); public String[] getValueNames() { names.copyInto(valueNames); String[] valueNames = new String[names.size()]; return valueNames; public Enumeration getAttributeNames() { return (Enumeration)valuesClone.keys(); Hashtable valuesClone = (Hashtable)values.clone(); public void removeAttribute(String name) { removeAttribute(name); public void removeValue(String name) { ((HttpSessionBindingListener)o).valueUnbound(e); new HttpSessionBindingEvent(this,name); Object o = values.get(name); if (o instanceof HttpSessionBindingListener) { public void setMaxInactiveInterval(int interval) { values.remove(name); public int getMaxInactiveInterval() { inactiveInterval = interval; return inactiveInterval; // ApplicationSession import java.io.IOException; import java.util.Vector; import javax.servlet.ServletException; import java.util.Hashtable; import java.util.Enumeration; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionContext; import org.apache.tomcat.catalina.*; import javax.servlet.http.HttpSessionBindingListener; import javax.servlet.http.HttpSessionBindingEvent; * serializable, so that it can be stored in persistent storage or transferred * Standard implementation of the <b>Session</b> interface. This object is * internal (Session) and application level (HttpSession) view of the session. * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * <p> * to a different JVM for distributable session support. * HttpSession view of this instance back to a Session view. * of the <code>org.apache.tomcat.session</code> package cannot cast an * However, because the class itself is not declared public, Java logic outside $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ Craig R. McClanahan // Constructors implements HttpSession, Session { final class StandardSession public StandardSession(Manager manager) { manager The manager with which this Session is associated * Construct a new Session associated with the specified Manager. this.manager = manager; super(); // Instance Variables * The collection of user data attributes associated with this Session. private Hashtable attributes = new Hashtable(); private long creationTime = 0L; * The time this session was created, in milliseconds since midnight, * January 1, 1970 GMT. private String id = null; * The session identifier of this Session. * Descriptive information describing this Session implementation. private static final String info = "StandardSession/1.0"; private long lastAccessedTime = creationTime; * The last accessed time for this Session. private Manager manager = null; * The Manager with which this Session is associated. * indicates that the session should never time out. * the servlet container may invalidate this session. A negative time * The maximum time interval, in seconds, between client requests before private int maxInactiveInterval = -1; private boolean isNew = true; * Flag indicating whether this session is new or not. private boolean isValid = false; * Flag indicating whether this session is valid or not. * The string manager for this package. * The HTTP session context associated with this session. private static HttpSessionContext sessionContext = null; private long thisAccessedTime = creationTime; * The current accessed time for this session. // Session Properties * Manager when an existing Session instance is reused. * Set the creation time for this session. This method is called by the this.creationTime = time; this.lastAccessedTime = time; public void setCreationTime(long time) { time The new creation time this.thisAccessedTime = time; * Return the session identifier for this session. return (this.id); id The new session identifier * Set the session identifier for this session. ((ManagerBase) manager).remove(this); (manager instanceof ManagerBase)) if ((this.id != null) && (manager != null) && public void setId(String id) { ((ManagerBase) manager).add(this); if ((manager != null) && (manager instanceof ManagerBase)) * the corresponding version number, in the format * Return descriptive information about this Session implementation and * <code><description>/<version></code>. return (this.info); public String getInfo() { * Return the last time the client sent a request associated with this * a value associated with the session, do not affect the access time. * GMT. Actions that your application takes, such as getting or setting * session, as the number of milliseconds since midnight, January 1, 1970 return (this.lastAccessedTime); return (this.manager); public Manager getManager() { * Return the Manager within which this Session is valid. public void setManager(Manager manager) { manager The new Manager * Set the Manager within which this Session is valid. * Return the maximum time interval, in seconds, between client requests IllegalStateException if this method is called on * time indicates that the session should never time out. * before the servlet container will invalidate the session. A negative * an invalidated session return (this.maxInactiveInterval); * Set the maximum time interval, in seconds, between client requests interval The new maximum interval this.maxInactiveInterval = interval; public HttpSession getSession() { * is the facade. * Return the <code>HttpSession</code> for which this object return ((HttpSession) this); // Session Public Methods * session, even if the application does not reference it. * should be called by the context when a request comes in for a particular * Update the accessed time information for this session. This method this.isNew=false; this.thisAccessedTime = System.currentTimeMillis(); this.lastAccessedTime = this.thisAccessedTime; public void access() { * without triggering an exception if the session has already expired. * Perform the internal processing required to invalidate this session, // Remove this session from our manager's active sessions public void expire() { while (attrs.hasMoreElements()) { Enumeration attrs = getAttributeNames(); Vector results = new Vector(); // Unbind any objects associated with this session while (names.hasMoreElements()) { String name = (String) names.nextElement(); Enumeration names = results.elements(); results.addElement(attr); String attr = (String) attrs.nextElement(); setValid(false); // Mark this session as invalid public void recycle() { // Reset the instance variables associated with this Session * preparation for reuse of this object. * Release all object references, and initialize instance variables, in manager = null; isNew = true; maxInactiveInterval = -1; lastAccessedTime = 0L; attributes.clear(); creationTime = 0L; id = null; isValid = false; ((ManagerBase) manager).recycle(this); // Tell our Manager that this Session has been recycled // Session Package Methods boolean isValid() { * Return the <code>isValid</code> flag for this session. return (this.isValid); void setNew(boolean isNew) { isNew The new value for the <code>isNew</code> flag * Set the <code>isNew</code> flag for this session. this.isNew = isNew; isValid The new value for the <code>isValid</code> flag * Set the <code>isValid</code> flag for this session. this.isValid = isValid; void setValid(boolean isValid) { // HttpSession Properties * midnight, January 1, 1970 GMT. * Return the time when this session was created, in milliseconds since * invalidated session IllegalStateException if this method is called on an return (this.creationTime); * Return the session context with which this session is associated. * Java Servlet API. * replacement. It will be removed in a future version of the As of Version 2.1, this method is deprecated and has no return (sessionContext); sessionContext = new StandardSessionContext(); if (sessionContext == null) // HttpSession Public Methods * <code>null</code> if no object is bound with that name. * Return the object bound with the specified name in this session, or name Name of the attribute to be returned return (attributes.get(name)); * Return an <code>Enumeration</code> of <code>String</code> objects * containing the names of the objects bound to this session. return (attributes.keys()); name Name of the value to be returned * <code>getAttribute()</code> As of Version 2.2, this method is replaced by return (getAttribute(name)); * are no such objects, a zero-length array is returned. * Return the set of names of objects bound to this session. If there * <code>getAttributeNames()</code> names[i] = (String) results.elementAt(i); return (names); for (int i = 0; i < names.length; i++) String names[] = new String[results.size()]; * Invalidates this session and unbinds any objects bound to it. expire(); // Cause this session to expire * session, or if the client chooses not to join the session. For * Return <code>true</code> if the client does not yet know about the * request. * has disabled the use of cookies, then a session would be new on each * example, if the server used only cookie-based sessions, and the client return (this.isNew); * 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 name Name to which the object is bound, cannot be null value Object to be bound, cannot be null * <code>valueBound()</code> on the object. * replaced. * After this method executes, and if the object implements * <code>HttpSessionBindingListener</code>, the container calls * <code>setAttribute()</code> * does nothing. * the session does not have an object bound with this name, this method * Remove the object bound with the specified name from this session. If name Name of the object to remove from this session. * <code>valueUnbound()</code> on the object. Object object = attributes.get(name); synchronized (attributes) { ((HttpSessionBindingListener) object).valueUnbound (new HttpSessionBindingEvent((HttpSession) this, name)); if (object instanceof HttpSessionBindingListener) { // System.out.println( "Removing attribute " + name ); return; attributes.remove(name); if (object == null) * <code>removeAttribute()</code> IllegalArgumentException if an attempt is made to add a * non-serializable object in an environment marked distributable. throw new IllegalArgumentException (sm.getString("standardSession.setAttribute.iae")); !(value instanceof Serializable)) if ((manager != null) && manager.getDistributable() && ((HttpSessionBindingListener) value).valueBound if (value instanceof HttpSessionBindingListener) attributes.put(name, value); // HttpSession Private Methods * is not restored by this method, and must be set explicitly. * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager * object input stream. * Read a serialized version of this session object from the specified ClassNotFoundException if an unknown class is specified IOException if an input/output error occurs stream The input stream to read from lastAccessedTime = ((Long) stream.readObject()).longValue(); maxInactiveInterval = ((Integer) stream.readObject()).intValue(); id = (String) stream.readObject(); // Deserialize the scalar instance variables (except Manager) private void readObject(ObjectInputStream stream) creationTime = ((Long) stream.readObject()).longValue(); throws ClassNotFoundException, IOException { isValid = ((Boolean) stream.readObject()).booleanValue(); isNew = ((Boolean) stream.readObject()).booleanValue(); String name = (String) stream.readObject(); Object value = (Object) stream.readObject(); for (int i = 0; i < n; i++) { // Deserialize the attribute count and attribute values int n = ((Integer) stream.readObject()).intValue(); * object output stream. * Write a serialized version of this session object to the specified * explicitly. * will be silently ignored. If you do not want any such attributes, * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable * <code>readObject()</code>, you must set the associated Manager * in the serialized representation of this Session. After calling * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored stream The output stream to write to * be sure the <code>distributable</code> property of our associated * Manager is set to <code>true</code>. stream.writeObject(new Long(creationTime)); private void writeObject(ObjectOutputStream stream) throws IOException { stream.writeObject(new Boolean(isValid)); stream.writeObject(new Integer(maxInactiveInterval)); stream.writeObject(new Long(lastAccessedTime)); stream.writeObject(id); // Write the scalar instance variables (except Manager) // Accumulate the names of serializable attributes stream.writeObject(new Boolean(isNew)); if (value instanceof Serializable) Object value = attributes.get(attr); stream.writeObject(new Integer(results.size())); // Serialize the attribute count and the attribute values stream.writeObject(attributes.get(name)); stream.writeObject(name); Enumeration getAttributeNames() | String[] getValueNames() | Object getAttribute(String) | long getCreationTime() | crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | static advice(StandardSession s): invalidate(s) { before { void setAttribute(String, Object)); void removeAttribute(String) | void invalidate() | boolean isNew() | + ".ise")); (s.sm.getString("standardSession." + thisJoinPoint.methodName throw new IllegalStateException if (!s.isValid()) * interface, to conform to the requirement that such an object be returned * when <code>HttpSession.getSessionContext()</code> is called. * This class is a dummy implementation of the <code>HttpSessionContext</code> // Private Class private Vector dummy = new Vector(); final class StandardSessionContext implements HttpSessionContext { * interface will be removed in a future version of this API. As of Java Servlet API 2.1 with no replacement. The As of Java Servlet API 2.1 with no replacement. * Return the session identifiers of all sessions defined * within this context. return (dummy.elements()); public Enumeration getIds() { * and will be removed in a future version of the API. * This method must return an empty <code>Enumeration</code> * This method must return null and will be removed in a id Session identifier for which to look up a session * specified session identifier. * Return the <code>HttpSession</code> associated with the public HttpSession getSession(String id) { * future version of the API. return (null); StandardSession import javax.servlet.http.Cookie; import org.w3c.dom.Node; import org.w3c.dom.NamedNodeMap; * an optional, configurable, maximum number of active sessions allowed. * no session persistence or distributable capabilities, but does support * Standard implementation of the <b>Manager</b> interface that provides * checkInterval="60" maxActiveSessions="-1" * maxInactiveInterval="-1" /> * <Manager className="org.apache.tomcat.session.StandardManager" * <code> * Lifecycle configuration of this component assumes an XML node * in the following format: * where you can adjust the following parameters, with default values * </code> * <li><b>maxActiveSessions</b> - The maximum number of sessions allowed to * <li><b>maxInactiveInterval</b> - The default maximum number of seconds of * be active at once, or -1 for no limit. [-1] * thread checks for expired sessions. [60] * <li><b>checkInterval</b> - The interval (in seconds) between background * in square brackets: * <ul> * descriptor, if any. [-1] * the default session timeout specified in the web application deployment * inactivity before which the servlet container is allowed to time out * a session, or -1 for no limit. This value should be overridden from public final class StandardManager $Revision: $ $Date: 2000/05/02 21:28:30 $ * </ul> implements Lifecycle, Runnable { extends ManagerBase private int checkInterval = 60; * The interval (in seconds) between checks for expired sessions. private boolean configured = false; * Has this component been configured yet? private static final String info = "StandardManager/1.0"; * The descriptive information about this implementation. protected int maxActiveSessions = -1; * The maximum number of active Sessions allowed, or -1 for no limit. private boolean started = false; * Has this component been started yet? private Thread thread = null; * The background thread. * The background thread completion semaphore. private boolean threadDone = false; * Name to register for the background thread. // Properties private String threadName = "StandardManager"; return (this.checkInterval); public int getCheckInterval() { * Return the check interval (in seconds) for this Manager. checkInterval The new check interval * Set the check interval (in seconds) for this Manager. public void setCheckInterval(int checkInterval) { this.checkInterval = checkInterval; * Return descriptive information about this Manager implementation and public int getMaxActiveSessions() { * no limit. * Return the maximum number of active Sessions allowed, or -1 for return (this.maxActiveSessions); * Set the maximum number of actives Sessions allowed, or -1 for this.maxActiveSessions = max; public void setMaxActiveSessions(int max) { max The new maximum number of sessions // Public Methods * for any reason, return <code>null</code>. IllegalStateException if a new session cannot be * method of the returned session. If a new session cannot be created * id will be assigned by this method, and available via the getId() * settings specified by this Manager's properties. The session * Construct and return a new session object, based on the default if ((maxActiveSessions >= 0) && (sessions.size() >= maxActiveSessions)) public Session createSession() { * instantiated for any reason return (super.createSession()); (sm.getString("standardManager.createSession.ise")); // Lifecycle Methods * component instance is created, and before <code>start()</code> * parameters. This method should be called immediately after the * Configure this component, based on the specified configuration * configured and/or started IllegalStateException if this component has already been * (<B>FIXME: What object type should this really be?) parameters Configuration parameters for this component * is called. LifecycleException if this component detects a fatal error if (configured) throw new LifecycleException // Validate and update our current component state throws LifecycleException { * in the configuration parameters it was given public void configure(Node parameters) configured = true; (sm.getString("standardManager.alreadyConfigured")); Node node = null; NamedNodeMap attributes = parameters.getAttributes(); // Parse and process our configuration parameters if (parameters == null) if (!("Manager".equals(parameters.getNodeName()))) } catch (Throwable t) { ; // XXX - Throw exception? setCheckInterval(Integer.parseInt(node.getNodeValue())); try { if (node != null) { node = attributes.getNamedItem("checkInterval"); setMaxActiveSessions(Integer.parseInt(node.getNodeValue())); node = attributes.getNamedItem("maxActiveSessions"); setMaxInactiveInterval(Integer.parseInt(node.getNodeValue())); node = attributes.getNamedItem("maxInactiveInterval"); IllegalStateException if this component has not yet been * configured (if required for this component) * and before any of the public methods of the component are utilized. * component. This method should be called after <code>configure()</code>, * Prepare for the beginning of active use of the public methods of this public void start() throws LifecycleException { * that prevents this component from being used * started if (!configured) // Start the background reaper thread threadStart(); started = true; (sm.getString("standardManager.alreadyStarted")); (sm.getString("standardManager.notConfigured")); if (started) * component. This method should be the last one called on a given * Gracefully terminate the active use of the public methods of this * been stopped * that needs to be reported IllegalStateException if this component has already * instance of this component. IllegalStateException if this component has not been started public void stop() throws LifecycleException { // Stop the background reaper thread threadStop(); started = false; if (!started) (sm.getString("standardManager.notStarted")); // Expire all active sessions continue; session.expire(); if (!session.isValid()) StandardSession session = (StandardSession) sessions[i]; Session sessions[] = findSessions(); for (int i = 0; i < sessions.length; i++) { // Private Methods private void processExpires() { long timeNow = System.currentTimeMillis(); * Invalidate all sessions that have expired. (int) ((timeNow - session.getLastAccessedTime()) / 1000L); if (timeIdle >= maxInactiveInterval) int timeIdle = // Truncate, do not round up if (maxInactiveInterval < 0) int maxInactiveInterval = session.getMaxInactiveInterval(); private void threadSleep() { * property. * Sleep for the duration specified by the <code>checkInterval</code> ; } catch (InterruptedException e) { Thread.sleep(checkInterval * 1000L); if (thread != null) private void threadStart() { * Start the background thread that will periodically check for * session timeouts. thread.start(); thread.setDaemon(true); thread = new Thread(this, threadName); threadDone = false; private void threadStop() { * Stop the background thread that is periodically checking for if (thread == null) thread.join(); thread.interrupt(); threadDone = true; thread = null; // Background Thread threadSleep(); processExpires(); while (!threadDone) { // Loop until the termination semaphore is set public void run() { * The background thread that checks for session timeouts and shutdown. StandardManager StandardSessionManager import org.apache.tomcat.util.SessionUtil; import org.apache.tomcat.core.SessionManager; import org.apache.tomcat.core.Response; import org.apache.tomcat.core.Context; import org.apache.tomcat.core.Request; * XXX - At present, use of <code>StandardManager</code> is hard coded, * that adapts to the new component-based Manager implementation. * Specialized implementation of org.apache.tomcat.core.SessionManager * and lifecycle configuration is not supported. * the core level. The Tomcat.Next "Manager" interface acts more like a * collection class, and has minimal knowledge of the detailed request * paradigm, I would suggest moving the logic implemented here back into * <b>IMPLEMENTATION NOTE</b>: Once we commit to the new Manager/Session * a Context to tell the Manager that we create what the default session * XXX - At present, there is no way (via the SessionManager interface) for * processing semantics of handling sessions. * should be. * timeout for this web application (specified in the deployment descriptor) implements SessionManager { public final class StandardSessionManager * Create a new SessionManager that adapts to the corresponding Manager manager = new StandardManager(); public StandardSessionManager() { * implementation. if (manager instanceof Lifecycle) { } catch (LifecycleException e) { throw new IllegalStateException("" + e); ((Lifecycle) manager).start(); ((Lifecycle) manager).configure(null); * The Manager implementation we are actually using. * Mark the specified session's last accessed time. This should be public void accessed(Context ctx, Request req, String id) { session The session to be marked * called for each request by a RequestInterceptor. HttpSession session=findSession(ctx, id); // cache the HttpSession - avoid another find ((Session) session).access(); if (session instanceof Session) if( session == null) return; req.setSession( session ); Session session = manager.findSession(id); public HttpSession findSession( Context ctx, String id ) { // XXX should we throw exception or just return null ?? } catch (IOException e) { if(session!=null) return session.getSession(); return manager.createSession().getSession(); public HttpSession createSession(Context ctx) { * Remove all sessions because our associated Context is being shut down. ctx The context that is being shut down // contexts, we just want to remove the sessions of ctx! // The manager will still run after that ( i.e. keep database // XXX XXX a manager may be shared by multiple public void removeSessions(Context ctx) { // connection open ((Lifecycle) manager).stop(); * Used by context to configure the session manager's inactivity timeout. * descriptor (web.xml). This method lets the Context conforgure the * Context on the other hand has it's timeout set by the deployment * The SessionManager may have some default session time out, the public void setSessionTimeOut(int minutes) { minutes The session inactivity timeout in minutes. * session manager according to this value. manager.setMaxInactiveInterval(minutes * 60); if(-1 != minutes) { // The manager works with seconds... ServerSessionManager import org.apache.tomcat.util.*; public class ServerSessionManager implements SessionManager { static { manager = new ServerSessionManager(); protected int inactiveInterval = -1; private static ServerSessionManager manager; // = new ServerSessionManager(); private Hashtable sessions = new Hashtable(); return manager; public static ServerSessionManager getManager() { reaper.setServerSessionManager(this); reaper = Reaper.getReaper(); private ServerSessionManager() { private Reaper reaper; if( apS==null) return; ServerSession servS=apS.getServerSession(); ApplicationSession apS=(ApplicationSession)findSession( ctx, id); public void accessed( Context ctx, Request req, String id ) { reaper.start(); req.setSession( apS ); // cache it - no need to compute it again apS.accessed(); servS.accessed(); if(-1 != inactiveInterval) { sessions.put(sessionId, session); ServerSession session = new ServerSession(sessionId); String sessionId = SessionIdGenerator.generateId(); session.setMaxInactiveInterval(inactiveInterval); ServerSession sSession=(ServerSession)sessions.get(id); if(sSession==null) return null; public HttpSession findSession(Context ctx, String id) { return session.getApplicationSession( ctx, true ); return sSession.getApplicationSession(ctx, false); // XXX Enumeration enum = sessions.keys(); synchronized void reap() { // solution for this, but we'll determine something else later. // sync'd for safty -- no other thread should be getting something // from this while we are reaping. This isn't the most optimal session.reap(); session.validate(); ServerSession session = (ServerSession)sessions.get(key); Object key = enum.nextElement(); synchronized void removeSession(ServerSession session) { public void removeSessions(Context context) { sessions.remove(id); session.invalidate(); String id = session.getId(); if (appSession != null) { appSession.invalidate(); session.getApplicationSession(context, false); ApplicationSession appSession = inactiveInterval = (minutes * 60); SessionInterceptor package org.apache.tomcat.request; * This implementation only handles Cookies sessions, please extend or * It also marks the session as accessed. * Will process the request and determine the session Id, and set it * in the Request. static final char SESSIONID_ROUTE_SEP = '.'; int debug=0; public class SessionInterceptor extends BaseInterceptor implements RequestInterceptor { * add new interceptors for other methods. public SessionInterceptor() { ContextManager cm; // GS, separates the session id from the jvm route public void setContextManager( ContextManager cm ) { debug=i; System.out.println("Set debug to " + i); public void setDebug( int i ) { String sessionId = null; public int requestMap(Request request ) { this.cm=cm; sessionId = cookie.getValue(); sessionId=validateSessionId(request, sessionId); if (cookie.getName().equals("JSESSIONID")) { Cookie cookie = cookies[i]; Cookie cookies[]=request.getCookies(); // assert !=null for( int i=0; i<cookies.length; i++ ) { request.setRequestedSessionIdFromCookie(true); if (sessionId!=null){ sessionId=request.getRequestURI().substring(foundAt+sig.length()); request.setRequestURI(request.getRequestURI().substring(0, foundAt)); // rewrite URL, do I need to do anything more? if ((foundAt=request.getRequestURI().indexOf(sig))!=-1){ if( debug>0 ) cm.log(" XXX RURI=" + request.getRequestURI()); String sig=";jsessionid="; int foundAt=-1; return 0; request.setRequestedSessionIdFromURL(true); /** Validate and fix the session id. If the session is not valid return null. * It will also clean up the session from load-balancing strings. // We may still set it and just return session invalid. // XXX what is the correct behavior if the session is invalid ? // GS, We piggyback the JVM id on top of the session cookie private String validateSessionId(Request request, String sessionId){ sessionId, or null if not valid if(idex > 0) { sessionId = sessionId.substring(0, idex); int idex = sessionId.lastIndexOf(SESSIONID_ROUTE_SEP); if (null != sessionId) { // Separate them ... if( debug>0 ) cm.log(" Orig sessionId " + sessionId ); Context ctx=request.getContext(); if(null != sM.findSession(ctx, sessionId)) { SessionManager sM = ctx.getSessionManager(); // cookie. We must check for validity in the current context. // context and one for the real context... or old session if (sessionId != null && sessionId.length()!=0) { // GS, We are in a problem here, we may actually get // multiple Session cookies (one for the root return sessionId; if( debug>0 ) cm.log(" Final session id " + sessionId ); sM.accessed(ctx, request, sessionId ); request.setRequestedSessionId(sessionId); return null; public int beforeBody( Request rrequest, Response response ) { if( reqSessionId==null) if( debug>0 ) cm.log("Before Body " + reqSessionId ); String reqSessionId = response.getSessionId(); if(sessionPath.length() == 0) { String sessionPath = rrequest.getContext().getPath(); // multiple session cookies can be used, one for each // GS, set the path attribute to the cookie. This way // GS, piggyback the jvm route on the session id. sessionPath = "/"; // context. if(null != jvmRoute) { reqSessionId = reqSessionId + SESSIONID_ROUTE_SEP + jvmRoute; String jvmRoute = rrequest.getJvmRoute(); if(!sessionPath.equals("/")) { cookie.setMaxAge(-1); reqSessionId); Cookie cookie = new Cookie("JSESSIONID", CookieTools.getCookieHeaderValue(cookie)); cookie.setVersion(0); response.addHeader( CookieTools.getCookieHeaderName(cookie), cookie.setVersion(1); cookie.setPath(sessionPath); { if( ctx.getDebug() > 0 ) ctx.log("Removing sessions from " + ctx ); public void contextShutdown( Context ctx ) throws TomcatException /** Notification of context shutdown ctx.getSessionManager().removeSessions(ctx); ServerSession * Core implementation of a server session public class ServerSession { private Hashtable appSessions = new Hashtable(); ServerSession(String id) { (ApplicationSession)appSessions.get(context); public ApplicationSession getApplicationSession(Context context, boolean create) { appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); // sync to ensure valid? if (appSession == null && create) { return appSession; // a new appSession // inactive interval -- if so, invalidate and create // make sure that we haven't gone over the end of our appSessions.remove(context); void removeApplicationSession(Context context) { void validate() // if we have an inactive interval, check to see if // we've exceeded it ssm.removeSession(this); ServerSessionManager ssm = ServerSessionManager.getManager(); Enumeration enum = appSessions.keys(); synchronized void invalidate() { (ApplicationSession)appSessions.get(key); String msg = sm.getString("serverSession.value.iae"); return values.keys(); public Enumeration getValueNames() { appSession.validate(); Session Expiration is Distributed Throughout the Software © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
11
AOSD Promotes Separation of Concerns
For Improved SWD&D, AOSD Promotes Separation of All Important Concerns of an Application. Design and Implementation Languages Should Provide Decomposition Mechanisms Understand the Requirements By Partitioning Problem into Pieces Composition Mechanisms Provide Infrastructure to Assemble Pieces of System into a Whole More Powerful Decomposition Mechanisms Needed on Top of OOP!
12
Separation of Concerns
Separation of Concerns Approaches have Driven Towards Formalism since Early Days R&D Efforts include: William Harrison , Harold Ossher, Subject-oriented programming: a critique of pure objects, Proc. of OOPSLA, 1993, Washington, D.C. Siobhán Clarke, Composition of object-oriented software design models, Dublin City Univ., 2001. Gregor Kiczales et al. Aspect-Oriented Programming. Proc. Of ECOOP, 1997. E. Gamma, R. Helm, R. Johnson, J. Vlissides. Design Patterns. Addison Wesley,1995.
13
Model Composition New approach for Designing Software Systems
Based in previous work in “Subject-Oriented Programming” System decomposed into Subjects Each Subject represents a Particular “Subjective” View of the System Subjects Akin to Roles Decompose Software into Different views that may Represent Specific Concerns Integrate all Views into one Final Model by using Specific Model Composition Rules UML Extensions are Subjects and Composition Relationships
14
Model Composition Pictorially
15
Applying AOP to Large Application
Java Code with 10,000 Files and 500 Developers Existing Policy Implementations for Logging, Error Handling, and Profiling Affect Every File 5-30 Page Policy Documents Applied By Developers Affect Every Developer Must Understand Policy Document Repeated for New Code Assets Awkward to Support Variants Complicates Product Line Don’t Even Think About Changing the Policy Policy Evolution Not Supported © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
16
Policies Re-implemented with AOP
AOP Captures Logging, Error Handling, And Profiling Policies Compatible with Existing Code Base and Platform Support Policy Evolution Result: One Reusable Crosscutting Module Policy Captured Explicitly Applies Policy Uniformly For All Time Written By Central Team No Burden On Other 492 Developers Automatically Applied to New Code Easy Plug/Unplug - Simplifies Product Line Issues Changes to Policy Happen in One Place © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
17
Existing Implementation
Problem: session tracking is not modularized HTTPRequest SessionInterceptor requestMap(request) beforeBody(req, resp) ... getCookies() getRequestURI()(doc) getSession() getRequestedSessionId() Session getAttribute(name) setAttribute(name, val) invalidate() ... HTTPResponse getRequest() setContentType(contentType) getOutptutStream() setSessionId(id) ... Servlet © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
18
Result – High Cost of Tangled Code
Redundant Code Same Fragment of Code in Many Places Difficult To Reason About Non-explicit Structure Big Picture of the Tangling isn’t Clear Difficult To Change Have to Find All The Code Involved And Be Sure to Change it Consistently And Be Sure Not to Break it By Accident © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
19
Establish a Crosscutting Concern
HTTPRequest SessionInterceptor getCookies() getRequestURI()(doc) getSession() getRequestedSessionId() ... requestMap(request) beforeBody(req, resp) ... Session HTTPResponse getAttribute(name) setAttribute(name, val) invalidate() ... getRequest() setContentType(contentType) getOutptutStream() setSessionId(id) ... Servlet © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
20
What are Cross-Cutting Concerns?
Critical Aspects of Large Systems Don’t Fit Traditional Modules Logging and Error Handling Synchronization & Security Memory Management Performance Optimizations Tangled Code Has A Cost Difficult To Understand and Change Increases With Size of System Maintenance Costs Are Huge Programmers Work Hard to Eliminate Tangled Code Last 10% of Tangled Code Causes 90% of Development and Maintenance Headaches What’s hard to do now and what’s the business impact how much gas is left in the old car… make it clear that people are already doing it… what are they betting on… bring it down… ground the source of pain with an example make it clear what the market is already doing, Don’t say word example, just say many hard problems get scattered & tangled throughout object implementations then many special case solutions but not systematic or valuable, consider EJB it lets you define security, transactions, and persistence. But enterprise beans don’t extend for defining security like regional managers can only execute some operations for their region’s data. © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
21
What is AOSD? AOSD seeks to Provide a Means to Compartmentalize Cross-Cutting Concerns which are Tangled/Distributed Across the Application Critical to Application w.r.t. Indispensable Features Security, Logging, Synchronization Performance Tracking and Optimization AOSD Must Provide Means to Identify, Separate, Represent, and Compose Cross-Cutting Concerns Ability to Model Cross Cutting Concerns Describe the Integration and Interplay of Concerns Abstractions Consistent with OO Design
22
Symptoms of Cross-Cutting Concerns
Scattering: Occurs when a Concern is Implemented in Several Separated Places (Different Classes) in the Code Code Related to a Single Concern is Spread Across Several Modules Tangling: Occurs when a Modular Unit of an Application Implements Several Requirements Code Unrelated to Primary Concern of a Module is Mixed In with Other Code Interface Pollution: Interface Requirements of Several Clients are Combined into A Single Interface Public Interfaces are Combinations of All Requirements for All Users – A Muddle of Concerns Slides from Jason Furlong,
23
Consider Another Example
Slides from Jason Furlong,
24
Consider Another Example
Slides from Jason Furlong,
25
Consider Another Example
Slides from Jason Furlong,
26
Consider Another Example
//C++ Solution Would Require Specific and //Difficult to Modify Code SecurityManager security = System.getSecurityManager(); try{ security.checkXXX(argument, ); } catch (SecurityException secexp){ //code for denial of access //… Slides from Jason Furlong,
27
Solution Separates the Concerns
Slides from Jason Furlong,
28
Objective of AOSD Capture Orthogonal Design Requirements
Replicated Class Hierarchy Each Color is a Different Cross-Cutting Concern Slides from Jason Furlong,
29
Combining Cross Cutting Concerns
Multiple Abstraction Models must be Superimposed with one Another to Yield the Combined Model This Combined Model Represents Conjoined Functionality of All Cross Cutting Concerns Reciprocally, Decomposition Also Available Slides from Jason Furlong,
30
Benefits of AOSD Increased Comprehensibility: Source Code Reduction
Better Separation of Concerns: Decomposition of Modules Previously Considered Monolithic More Adaptable and Easier to Reuse (Hard to Prove) Simpler System Evolution: Increased Modularity of AOSD Solutions mean fewer modules are affected when modules Change SWE Specialization via Application Transparency Some Concerns, Such as Security, Can Be Better Implemented Act of Implementing Additional Orthogonal Concerns to an Oblivious Base Functionality via Successive Application of Overlapping Modules Source: Elrad and Coady Slides from Jason Furlong,
31
Benefits of AOSD/AOP support variability
architectural quality & flexibility reuse extensibility untangle core concerns simple, natural code improve agility leverage experts improve analysis untangle auxiliary concerns improve quality reduce code size simplify problem solving retire legacy tools Value Add Aspects to Code Restructure Code for Aspects Aspect-Oriented Architecture © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
32
Other Thoughts on Aspects
Tyranny of Decomposition: “…the tyranny of the dominant decomposition is the single most significant cause of the failure, to date, to achieve many of the expected benefits of separation of concerns” Ossher and Tarr, HyperJ User Manual, 2001 Principle of Obliviousness “ … allows programmers to make quantified programmatic assertions over programs written by programmer oblivious to such assertions” Filman & Friedman, “AOP is Quantification and Obliviousness” Security “As things exist today, you must touch so many disparate pieces to create a tight security policy. In reality, most individual developers cannot build concurrent, secure, distributed system. Therefore, by rallying security around an aspect you compartmentalize the problem…” Booch, UML Architect, April 2003 Source: Elrad and Coady Slides from Jason Furlong,
33
Aspect-Oriented Programming (AOP)
Crosscutting is Inherent in Complex Systems Crosscutting Concerns have a Clear Purpose and a Natural Structure Defined Set of Methods, Module Boundary Crossings, Points of Resource Utilization, Lines of Dataflow… So, Let’s Capture the Structure of Crosscutting Concerns Explicitly... In a Modular Way With Linguistic and Tool Support Aspects Are Well-modularized Crosscutting Concerns here’s where we pick up the crystallization of style and analogy to OOP points people know this, they deal with it a variety of ways, we can make that explicit (1) It rests on an assumption that crosscutting is inherent. That in any sufficiently complex system… I haven’t proven this assumption today, I’ve just reminded you about the problem. But I believe it, and we can talk an EXAMPLES HERE (2) But that crosscutting concerns are not random… © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
34
Aspects in AOP Requirements that Crosscut Several Viewpoints (or Concerns) are Realized as Aspects Aspects are one Category of Concern[Kiczales97]: “… an aspect is a (program) property that cannot be cleanly encapsulated in a generalized procedure (such as an object, method, procedure, or API)” Aspects are a Distributed Abstraction that can Capture the Same Concern Across Multiple Classes As Such, Aspects are Modular Entities These Module Entities are “Woven” into the Application at Specific “Join Points” Weaving Distributes the Aspect Across the Application into Targeted Areas Aspects to be Woven are Decided by SWE here’s where we pick up the crystallization of style and analogy to OOP points people know this, they deal with it a variety of ways, we can make that explicit (1) It rests on an assumption that crosscutting is inherent. That in any sufficiently complex system… I haven’t proven this assumption today, I’ve just reminded you about the problem. But I believe it, and we can talk an EXAMPLES HERE (2) But that crosscutting concerns are not random… Slides from Jason Furlong,
35
Objective in Discussing AOP
Using AOP And AspectJ to: Improve the Modularity of Crosscutting Concerns Design Modularity Source Code Modularity Development Process Aspects are Two Things: Concerns That Crosscut [design Level] A Programming Construct [Implementation Level] Crosscutting Concerns Captured in Modular Units AspectJ An AO Extension to Java™ that Supports General-purpose Aspect-Oriented Programming © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
36
AOP in AspectJ™ A Small and Well-integrated Extension to Java™
Outputs .Class Files Compatible with Any JVM All Java Programs are AspectJ Programs A General-purpose AO Language Just as Java is a General-purpose OO Language Includes IDE Support Emacs, Jbuilder, Forte 4J, Eclipse Freely Available Implementation Compiler is Open Source Active User Community © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
37
AspectJ Technology (www.aspectj.org)
AspectJ is a small extension to Java™ Valid Java Programs are Valid AspectJ Programs AspectJ has its own Compiler, ajc Runs on Java 2 platform (Java 1.3 and later) Produces Java platform-compatible .class files (JDK 1.1 and later) AspectJ tools support IDE extensions: Emacs, JBuilder, Forte4J, Eclipse ajdoc to parallel javadoc JPDA Debugger Integration (JSR 45 support) License Compiler, Runtime and Tools are free for any use Compiler and tools are Open Source JSR45 © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
38
Modularizing Crosscutting Concerns
Each Class Should Contain Only the Code that is Specifically Related to its Main Function Survey_List Class Should Only Contain Code to Manage Surveys, and Nothing Else E.g., Don’t Track Logging of Actions, Security, Database Interactions, etc. Crosscutting Code Removed from each Class Should be Factorized into a Specific Place Isolate in a Module the Access Control Code Scattered in the Survey Management Application These are the Concerns that are Identified that Impact all Application Classes Allow Select/Customized Concerns to be Added as Desired by Application Designers/Builders
39
Aspect as a Modular Unit
AOSD/AOP Utilizes a New Modular Unit to Isolate Crosscutting Concerns – Referred to as an Aspect Three Components of an Aspect Join Points – Location of Code Where Application Behavior Will be Modified Pointcuts – Named Collection of Join Points with a Common Basis Advices – The Code that is Attached to a Pointcut (or set of Pointcuts) to Realize Aspect’s Function Integration of an Aspect into the Application is Achieved via a Mechanism called Weaving.
40
Create_Survey_Header
Join Points Specific Place in the Application where we Want to Alter the Behavior of the Application Examples Method Call, Attribute Assignment Exception Raising, Creation of an Object In Example Below, Joint Point Intercepts Call from Add_Survey_Header to Create_Survey_Header Intercept could Log, Check Security, etc. Create_Survey_Header Add_Survey_Header Survey_List Survey Header Join Point
41
Intercepting Calls Among Classes
Join Points key points in dynamic call graph Intercepting Calls Among Classes Instance x dispatch a method execution a method call Instance Y dispatch returning or throwing returning or throwing a method execution returning or throwing © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
42
Join Point Terminology
Several Kinds of Join Points Method & Constructor Call Method & Constructor Execution Field Get & Set Exception Handler Execution Static & Dynamic Initialization dispatch method call join points method execution join points Instance x © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
43
Pointcuts A Pointcut is a Named Collection of Join Points Sharing Specific Static Properties A Pointcut is a Kind of Predicate on Join Points that: Can Match or Not Match Any Given Join Point And Optionally, Can Pull Out Some of The Values at that Join Point For example - in AspectJ … Pointcuts are Defined with Quantified Boolean Formulas Defined over Method Names, Class Names, Control Flow or Lexical Scopes
44
Pointcuts Survey Management Example
call(* Survey_Header.Create_Survey_Header( )) Pointcuts can be Composed using AND (&&), OR (||), and NOT (!) For Example: call(* Survey_Header.Create_Survey_Header( )) || call(* Survey_Header.Add_Question()) Call Occurs Whenever a Survey_Header Instance Receives Either of the Two Method Calls\ Pointcuts can Also be Named: pointcut login( ): call(User SecurityAdmin.logIn(..)); User is a Return Type, SecurityAdmin a Class
45
Advice in an Aspect Advice is a Code Fragment that Implements Part of an Aspect and is Intended to be Woven with the Main Program at Specific Join Points Implements Part of the Specific Concern that is Modularized in the Aspect Three Types of Advice Before – Action (Code) Invoked Prior to a Join Point After – Action (Code) Invoked After Returning from a Join Point Around – On Arrival at Join Point, Provides Explicit Control Over When and If Program Proceeds
46
Advice in an Aspect Advices are Examples of Constraint Checking
Indicate the Constraints that Must be Verified Before and After Indicate the Conditions that Must be True and Guide the Execution – Around Conceptually: Before Pre-condition – is Parameter Valid After Post-Condition – Check Whether values were Set Around Force Parameters to be Valid Before Continuing This Controls the When and If of Execution
47
Before Advice – Pre-condition
aspect PointBoundsPreCondition { before(int newX): call(void Point.setX(int)) && args(newX) { assert(newX >= MIN_X); assert(newX <= MAX_X); } before(int newY): call(void Point.setY(int)) && args(newY) { assert(newY >= MIN_Y); assert(newY <= MAX_Y); private void assert(boolean v) { if ( !v ) throw new RuntimeException(); what follows the ‘:’ is always a pointcut – primitive or user-defined © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
48
After Advice – Post-condition
aspect PointBoundsPostCondition { after(Point p, int newX) returning: call(void Point.setX(int)) && target(p) && args(newX) { assert(p.getX() == newX); } after(Point p, int newY) returning: call(void Point.setY(int)) && target(p) && args(newY) { assert(p.getY() == newY); private void assert(boolean v) { if ( !v ) throw new RuntimeException(); © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
49
Around Advice – Condition Enforcement
aspect PointBoundsEnforcement { void around(int newX): call(void Point.setX(int)) && args(newX) { proceed(clip(newX, MIN_X, MAX_X)); } void around(int newY): call(void Point.setY(int)) && args(newY) { proceed(clip(newY, MIN_Y, MAX_Y)); private int clip(int val, int min, int max) { return Math.max(min, Math.min(max, val)); ADD CAche example here. © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
50
A Second AOP Example A Library Items Locator that Maintains a Relation Between Library Items and Their Physical Locations
51
Synchronization in Example
Exclusion Constraints Concurrent Execution of Methods within a Single Object Which Operations are Allowed to Execute Concurrently and Which are Not State Constraints Conditions Under Which Operations Can Be Applied to an Object May Involve Object’s Internal State or Environment State Coordination Constraints Coordinating Operations Involving a Number of Independent Objects
52
Incorporating Synchronization without AOP
public class LibraryItemLocator { protected Item items[]; protected Location locations[]; protected int nitems; protected int activeReaders = 0; protected int activeWriters = 0; public Location locate(String str) throws ItemNotFound{ Item an_item = items[0]; int i = 0; boolean found = false; Location l; synchronized(this) { while (activeWriters > 0) { try{ wait(); } catch (InterruptedException e) {} } ++activeReaders; while (i < nitems && found == false) { if (an_item.get_title().compareTo(str) == 0) found = true; else an_item = items[++i]; if (found == false) { synchronized(this) { --activeReaders; notifyAll(); } throw new ItemNotFound (str); l = locations[i]; return l;
53
Incorporating Synchronization without AOP
public class BookLocator extends LibraryItemLocator{ public register() { beforewrite(); if (nitems > items.length()) { afterwrite(); throw new LocatorFull(); } else { //book specific registration code protected synchronized void beforewrite() { while ((activeReaders > 0) || (activeWrites > 0)) { try { wait(); } catch (InterruptedException e) {} ++activeWriters; protected synchronized void afterwrite() { --activeWriters; notifyAll(); public class JournalLocator extends LibraryItemLocator { public register() { beforewrite(); if (nitems > items.length()) { afterwrite(); throw new LocatorFull(); } else { //journal specific registration code protected synchronized void beforewrite() { while ((activeReaders > 0) || (activeWrites > 0)) { try { wait(); } catch (InterruptedException e) {} ++activeWriters; protected synchronized void afterwrite() { --activeWriters; notifyAll();
54
AOP Modeling of Sychronization
55
Example in AOP and Aspect J
public class LibraryItemLocator { protected Item items[]; protected Location locations[]; protected int nitems; public Location locate(String str) throws ItemNotFound{ Item an_item = items[0]; int i = 0; boolean found = false; Location l; while (i < nitems && found == false) { if (an_item.get_title().compareTo(str) == 0) found = true; else an_item = items[++i]; } if (found == false) { throw new ItemNotFound (str); l = locations[i]; return l; public class BookLocator extends LibraryItemLocator{ public register() { //book specific registration code } public class JournalLocator extends LibraryItemLocator { //journal specific registration code
56
Example in AOP and Aspect J
public aspect Locator_Coordinator { private int activeReaders = 0; private int activeWriters = 0; pointcut write(): execution(public * *.register(..)) pointcut read(): execution(public * *.locate(..)) before(): write() { synchronized(thisJointPoint.get This()) { while ((activeReaders > 0) || (activeWrites > 0)) { try { wait(); } catch (InterruptedException e) {} } ++activeWriters; if (nitems > items.length()) throw new LocatorFull(); after(): write() { --activeWriters; notifyAll(); before(): read() { synchronized(thisJointPoint.getTh is()) { while (activeWrites > 0) { try{ wait (); } catch (InterruptedException e) {} } ++activeReaders; after() : read(){ --activeReaders; notifyAll();
57
Weaving Weaving Process is a Compilation Technique that Composes Multiple Concern-Specific Code into the Final Application Weaving Identifies Join Points in Pointcuts and Modifies the Code at each Site According to the Specified Advices Provides Facility to Integrate Each Aspect into the Application Code Integration is Customizable – Not all Aspects Must be Woven for Every Compilation Pick and Choose Aspects – Security, Logging, etc.
58
Weaving Process Varies
Multiple AOP Models w.r.t. Weaving Jointpoint Interception (AspectJ) – Our Focus G. Kiczales AspectJ, AspectC, AspectC++ Hypermodules (HyperJ) Multidimensional Separation of Concerns Creates Hypermodules H. Ossher and P. Tarr Composition Filters (ComposeJ) AOP Technique where Different Aspects Expressed as Filters Filters are Declarative and Orthogonal Message Transformation Specifications U. Twente, Holland Slides from Jason Furlong,
59
Concluding Remarks on AOP/AOSD
AOSD Future – see aosd.net Language Design - Dynamic Crosscuts, Typing … Tools - More IDE Support, Aspect Discovery, Re-factoring, Re-cutting, Crosscutting Views… Software Engineering - UML Extension, Finding Aspects, … Theory - Type System For Crosscutting, Faster Compilation, Advanced Crosscut Constructs, … AOP Future: Tools - Incremental Compilation, Refactoring Language Changes - Aspect Configuration, Extensible Pointcuts, Generic Types (Java 1.5), Dynamic Crosscut Constructs/Weaving © Copyright Palo Alto Research Center Incorporated. All rights reserved. ApsectJ.org.
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.