Download presentation
Presentation is loading. Please wait.
1
Aspect-Oriented Programming
Seyyed Jamaleddin Pishvayi Graduate Student Department of Electronics and Computer Engineering University of Tehran Mehr 1383, Sharif Univ. 11/15/2018
2
What is AOP Aspect Oriented Programming Not an OO replacement
Technique for handling ‘Crosscutting concerns’ Tries to eliminate code-scattering and tangling Examples: log all exceptions, capture all SQL statements, authenticate users before access Mehr 1383, Sharif Univ. 11/15/2018
3
Programming Evolution
Overview Mehr 1383, Sharif Univ. 11/15/2018
4
Monolithic programs Mehr 1383, Sharif Univ. 11/15/2018
5
What is software? Software expresses solutions to problems
Humans decompose complex problems into simpler problems Humans express solutions to problems using a programming language Programming language imposes constraints on how the problem is decomposed Mehr 1383, Sharif Univ. 11/15/2018
6
Tackling the software problem
Programming in the small Decompose problem into programming language statements Programming in the medium Decompose problem into modules / classes / objects Programming in the large Decompose problem into components Mehr 1383, Sharif Univ. 11/15/2018
7
Unstructured code Code paths are tangled Goto's cross each other
10 let i = 1 20 if i > 4 then goto 60 30 print i 40 i = i + 1 50 goto 20 60 print "done" Mehr 1383, Sharif Univ. 11/15/2018
8
Elegant unstructured code
Code paths not tangled Code is compact Code is idiomatic Put test at end 10 let i = 1 20 print i 30 i = i + 1 40 if i < 4 then goto 20 50 print "done" Mehr 1383, Sharif Univ. 11/15/2018
9
Why does elegance matter?
Computer does not care! Programs always change ~10X maintenance vs. original development Programs become resistant to change over time Must be readable by others Must have obvious extensibility points Must have well-designed unit tests to encourage extensibility Mehr 1383, Sharif Univ. 11/15/2018
10
Language support for elegance
Language support encourages (enforces?) best practices Discourages goto int i = 1; while( i < 4 ) { print( i ); } Mehr 1383, Sharif Univ. 11/15/2018
11
Is elegance enough? Suitable for programming in the small
Suitable for enhancing localized understanding of code Unsuitable for sharing secrets Unsuitable for building larger abstractions Unsuitable for understanding larger abstractions Mehr 1383, Sharif Univ. 11/15/2018
12
Modular programming Mehr 1383, Sharif Univ. 11/15/2018
13
Modularization Decompose problem into independent modules
Each module exposes a public interface Each module hides implementation from caller Mehr 1383, Sharif Univ. 11/15/2018
14
Modularization: Windows
Windows operating system code is highly modularized kernel32.dll user32.dll gdi32.dll dbghelp.dll ole32.dll comctl32.dll ws2_32.dll mscoree.dll Mehr 1383, Sharif Univ. 11/15/2018
15
Modularization and Abstraction
Modularization == separation of concerns Based on common functionality Based on shared secrets Modularization encourages abstraction Interact with module only using its interface Lets us look at overall system structure Lets us zoom in on one part of system at a time Mehr 1383, Sharif Univ. 11/15/2018
16
Is modularization enough?
Modules are too coarse-grained Public interface is too wide (kernel32.dll exports 928 methods!) Hierarchical organization impossible Secrets go hand-in-hand with certain methods We need to raise the abstraction bar Think in terms of smaller "bundles" of code and data Helps us deal with increasing complexity Mehr 1383, Sharif Univ. 11/15/2018
17
Object-oriented programming
Mehr 1383, Sharif Univ. 11/15/2018
18
Object-oriented programming
Decompose problem into independent classes Each class exposes a public interface Each class exposes a protected interface Each class hides implementation from caller … Mehr 1383, Sharif Univ. 11/15/2018
19
Is OOP enough? Some code must cut across class hierarchies
Interface-based programming helps on definition Consider Cloneable, Serializable in Java API Offers no assistance on the implementation What happens if you need to retrofit cross-cutting code against existing client applications? Can't do it without modifying those apps! Mehr 1383, Sharif Univ. 11/15/2018
20
Good Modularity with OOP: URL Pattern Matching
URL pattern matching in org.apache.tomcat red shows relevant lines of code nicely fits in two boxes (using inheritance) Mehr 1383, Sharif Univ. 11/15/2018
21
But … Logging Is not Modularized
logging in org.apache.tomcat red shows lines of code that handle logging not in just one place not even in a small number of places Mehr 1383, Sharif Univ. 11/15/2018
22
Another Example: Session Expiration Is not Modularized
* The Apache Software License, Version 1.1 /* * * ==================================================================== * modification, are permitted provided that the following conditions * are met: * Redistribution and use in source and binary forms, with or without * reserved. * Copyright (c) 1999 The Apache Software Foundation. All rights * notice, this list of conditions and the following disclaimer. * 1. Redistributions of source code must retain the above copyright * distribution. * 3. The end-user documentation included with the redistribution, if * the documentation and/or other materials provided with the * notice, this list of conditions and the following disclaimer in * 2. Redistributions in binary form must reproduce the above copyright * Alternately, this acknowlegement may appear in the software * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * if and wherever such third-party acknowlegements normally appear. itself, * Apache Software Foundation ( * any, must include the following acknowlegement: * "This product includes software developed by the derived * Foundation" must not be used to endorse or promote products * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * 5. Products derived from this software may not be called "Apache" * from this software without prior written permission. For written * permission, please contact * 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 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * 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 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * This software consists of voluntary contributions made by many * SUCH DAMAGE. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * [Additional notices, if required by prior licensing conditions] * < * information on the Apache Software Foundation, please see * individuals on behalf of the Apache Software Foundation. For more */ import org.apache.tomcat.util.StringManager; package org.apache.tomcat.session; import org.apache.tomcat.core.*; import java.util.*; import java.net.*; import java.io.*; * Core implementation of an application level session James Duncan Davidson /** import javax.servlet.*; import javax.servlet.http.*; James Todd Jason Hunter private String id; private ServerSession serverSession; private Hashtable values = new Hashtable(); StringManager.getManager("org.apache.tomcat.session"); private StringManager sm = public class ApplicationSession implements HttpSession { private boolean valid = true; ApplicationSession(String id, ServerSession serverSession, private int inactiveInterval = -1; private long lastAccessed = creationTime; private Context context; private long creationTime = System.currentTimeMillis();; private long thisAccessTime = creationTime; this.inactiveInterval = context.getSessionTimeOut(); this.context = context; this.id = id; Context context) { this.serverSession = serverSession; } this.inactiveInterval *= 60; if (this.inactiveInterval != -1) { return serverSession; ServerSession getServerSession() { * inactivities can be dealt with accordingly. * Called by context when request comes in so that accesses and void accessed() { 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) { void validate() { validate(); // if we have an inactive interval, check to see if we've exceeded it invalidate(); if (thisInterval > inactiveInterval) { if (valid) { // HTTP SESSION IMPLEMENTATION METHODS public String getId() { String msg = sm.getString("applicationSession.session.ise"); } else { return id; return creationTime; public long getCreationTime() { throw new IllegalStateException(msg); return new SessionContextImpl(); public HttpSessionContext getSessionContext() { return lastAccessed; public long getLastAccessedTime() { public void invalidate() { // remove everything in the session serverSession.removeApplicationSession(context); removeValue(name); String name = (String)enum.nextElement(); Enumeration enum = values.keys(); while (enum.hasMoreElements()) { if (! valid) { valid = false; public boolean isNew() { 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); public String[] getValueNames() { names.addElement(e.nextElement()); while (e.hasMoreElements()) { Vector names = new Vector(); Enumeration e = getAttributeNames(); return valueNames; String[] valueNames = new String[names.size()]; names.copyInto(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) { Object o = values.get(name); ((HttpSessionBindingListener)o).valueUnbound(e); new HttpSessionBindingEvent(this,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 javax.servlet.http.HttpSession; import java.util.Hashtable; import java.util.Enumeration; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; 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. * However, because the class itself is not declared public, Java logic outside * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * <p> * to a different JVM for distributable session support. Craig R. McClanahan * HttpSession view of this instance back to a Session view. * of the <code>org.apache.tomcat.session</code> package cannot cast an $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ // Constructors implements HttpSession, Session { final class StandardSession manager The manager with which this Session is associated * Construct a new Session associated with the specified Manager. super(); this.manager = manager; public StandardSession(Manager manager) { // Instance Variables private Hashtable attributes = new Hashtable(); * The collection of user data attributes associated with this Session. * January 1, 1970 GMT. * The time this session was created, in milliseconds since midnight, private String id = null; * The session identifier of this Session. private long creationTime = 0L; private static final String info = "StandardSession/1.0"; * Descriptive information describing this Session implementation. * The last accessed time for this Session. private Manager manager = null; * The Manager with which this Session is associated. private long lastAccessedTime = creationTime; * 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() { * preparation for reuse of this object. * Release all object references, and initialize instance variables, in // Reset the instance variables associated with this Session maxInactiveInterval = -1; isValid = false; manager = null; isNew = true; lastAccessedTime = 0L; attributes.clear(); creationTime = 0L; id = null; ((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 * replaced. * 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. * 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. if (object == null) Object object = attributes.get(name); synchronized (attributes) { (new HttpSessionBindingEvent((HttpSession) this, name)); ((HttpSessionBindingListener) object).valueUnbound if (object instanceof HttpSessionBindingListener) { attributes.remove(name); // System.out.println( "Removing attribute " + name ); return; * <code>removeAttribute()</code> IllegalArgumentException if an attempt is made to add a * non-serializable object in an environment marked distributable. throw new IllegalArgumentException attributes.put(name, value); (sm.getString("standardSession.setAttribute.iae")); if ((manager != null) && manager.getDistributable() && !(value instanceof Serializable)) ((HttpSessionBindingListener) value).valueBound if (value instanceof HttpSessionBindingListener) // HttpSession Private Methods stream The input stream to read from * 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 IOException if an input/output error occurs ClassNotFoundException if an unknown class is specified id = (String) stream.readObject(); lastAccessedTime = ((Long) stream.readObject()).longValue(); creationTime = ((Long) stream.readObject()).longValue(); // Deserialize the scalar instance variables (except Manager) private void readObject(ObjectInputStream stream) throws ClassNotFoundException, IOException { isNew = ((Boolean) stream.readObject()).booleanValue(); maxInactiveInterval = ((Integer) stream.readObject()).intValue(); String name = (String) stream.readObject(); Object value = (Object) stream.readObject(); for (int i = 0; i < n; i++) { int n = ((Integer) stream.readObject()).intValue(); // Deserialize the attribute count and attribute values isValid = ((Boolean) stream.readObject()).booleanValue(); * object output stream. * Write a serialized version of this session object to the specified * explicitly. * <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 * Manager is set to <code>true</code>. stream The output stream to write to * be sure the <code>distributable</code> property of our associated * will be silently ignored. If you do not want any such attributes, stream.writeObject(new Long(creationTime)); stream.writeObject(id); // Write the scalar instance variables (except Manager) private void writeObject(ObjectOutputStream stream) throws IOException { stream.writeObject(new Boolean(isNew)); // Accumulate the names of serializable attributes stream.writeObject(new Boolean(isValid)); stream.writeObject(new Integer(maxInactiveInterval)); stream.writeObject(new Long(lastAccessedTime)); 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()) // Private Class * when <code>HttpSession.getSessionContext()</code> is called. * This class is a dummy implementation of the <code>HttpSessionContext</code> * interface, to conform to the requirement that such an object be returned As of Java Servlet API 2.1 with no replacement. The private Vector dummy = new Vector(); final class StandardSessionContext implements HttpSessionContext { * interface will be removed in a future version of this API. * This method must return an empty <code>Enumeration</code> As of Java Servlet API 2.1 with no replacement. * within this context. * Return the session identifiers of all sessions defined * and will be removed in a future version of the API. return (dummy.elements()); public Enumeration getIds() { * 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 org.w3c.dom.NamedNodeMap; import javax.servlet.http.Cookie; * Standard implementation of the <b>Manager</b> interface that provides import org.w3c.dom.Node; * <code> * checkInterval="60" maxActiveSessions="-1" * <Manager className="org.apache.tomcat.session.StandardManager" * in the following format: * Lifecycle configuration of this component assumes an XML node * no session persistence or distributable capabilities, but does support * an optional, configurable, maximum number of active sessions allowed. * </code> * maxInactiveInterval="-1" /> * <li><b>maxActiveSessions</b> - The maximum number of sessions allowed to * be active at once, or -1 for no limit. [-1] * <li><b>maxInactiveInterval</b> - The default maximum number of seconds of * thread checks for expired sessions. [60] * <li><b>checkInterval</b> - The interval (in seconds) between background * where you can adjust the following parameters, with default values * 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 extends ManagerBase $Revision: $ $Date: 2000/05/02 21:28:30 $ * </ul> implements Lifecycle, Runnable { private int checkInterval = 60; * The interval (in seconds) between checks for expired sessions. * The descriptive information about this implementation. private boolean configured = false; * Has this component been configured yet? private static final String info = "StandardManager/1.0"; protected int maxActiveSessions = -1; * The maximum number of active Sessions allowed, or -1 for no limit. * Has this component been started yet? private Thread thread = null; * The background thread. private boolean started = false; private boolean threadDone = false; * The background thread completion semaphore. * 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. public void setCheckInterval(int checkInterval) { checkInterval The new check interval * Set the check interval (in seconds) for this Manager. this.checkInterval = checkInterval; * Return descriptive information about this Manager implementation and public int getMaxActiveSessions() { return (this.maxActiveSessions); * no limit. * Return the maximum number of active Sessions allowed, or -1 for * 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 * method of the returned session. If a new session cannot be created * for any reason, return <code>null</code>. * 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 IllegalStateException if a new session cannot be return (super.createSession()); (sm.getString("standardManager.createSession.ise")); // Lifecycle Methods * Configure this component, based on the specified configuration IllegalStateException if this component has already been * (<B>FIXME: What object type should this really be?) parameters Configuration parameters for this component * parameters. This method should be called immediately after the * component instance is created, and before <code>start()</code> * is called. LifecycleException if this component detects a fatal error * configured and/or started if (configured) // 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")); throw new LifecycleException NamedNodeMap attributes = parameters.getAttributes(); if (!("Manager".equals(parameters.getNodeName()))) // Parse and process our configuration parameters if (parameters == null) Node node = null; } 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 (sm.getString("standardManager.notConfigured")); if (!configured) // Start the background reaper thread threadStart(); started = true; (sm.getString("standardManager.alreadyStarted")); 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 * Invalidate all sessions that have expired. long timeNow = System.currentTimeMillis(); private void processExpires() { (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 * The background thread that checks for session timeouts and shutdown. processExpires(); threadSleep(); // Loop until the termination semaphore is set public void run() { while (!threadDone) { 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. // GS, separates the session id from the jvm route static final char SESSIONID_ROUTE_SEP = '.'; public class SessionInterceptor extends BaseInterceptor implements RequestInterceptor { * add new interceptors for other methods. public SessionInterceptor() { ContextManager cm; int debug=0; 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; if (cookie.getName().equals("JSESSIONID")) { sessionId = cookie.getValue(); Cookie cookie = cookies[i]; for( int i=0; i<cookies.length; i++ ) { Cookie cookies[]=request.getCookies(); // assert !=null request.setRequestedSessionIdFromCookie(true); if (sessionId!=null){ sessionId=validateSessionId(request, sessionId); 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); * It will also clean up the session from load-balancing strings. sessionId, or null if not valid /** Validate and fix the session id. If the session is not valid return null. // We may still set it and just return session invalid. // XXX what is the correct behavior if the session is invalid ? // Separate them ... // GS, We piggyback the JVM id on top of the session cookie private String validateSessionId(Request request, String sessionId){ if(idex > 0) { sessionId = sessionId.substring(0, idex); int idex = sessionId.lastIndexOf(SESSIONID_ROUTE_SEP); if( debug>0 ) cm.log(" Orig sessionId " + sessionId ); if (null != sessionId) { // GS, We are in a problem here, we may actually get if (sessionId != null && sessionId.length()!=0) { SessionManager sM = ctx.getSessionManager(); sM.accessed(ctx, request, sessionId ); if(null != sM.findSession(ctx, sessionId)) { Context ctx=request.getContext(); // cookie. We must check for validity in the current context. // multiple Session cookies (one for the root // context and one for the real context... or old session return sessionId; request.setRequestedSessionId(sessionId); if( debug>0 ) cm.log(" Final session id " + 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 // context. sessionPath = "/"; if(null != jvmRoute) { String jvmRoute = rrequest.getJvmRoute(); reqSessionId = reqSessionId + SESSIONID_ROUTE_SEP + jvmRoute; if(!sessionPath.equals("/")) { // GS, piggyback the jvm route on the session id. reqSessionId); Cookie cookie = new Cookie("JSESSIONID", CookieTools.getCookieHeaderValue(cookie)); cookie.setVersion(0); response.addHeader( CookieTools.getCookieHeaderName(cookie), cookie.setVersion(1); cookie.setMaxAge(-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(); Mehr 1383, Sharif Univ. 11/15/2018
23
AOP: Identifying cross-cuts
Mehr 1383, Sharif Univ. 11/15/2018
24
AOP: Defining aspects Mehr 1383, Sharif Univ. 11/15/2018
25
AOP: Weaving aspects Mehr 1383, Sharif Univ. 11/15/2018
26
Cross Cutting BankAcct Product Serializable to XML Persistable
getBalance() getOwner() setOwner() setBalance() toXML() store() getSKU() getQty() setSKU() setQty() toXML() store() Serializable to XML Persistable Mehr 1383, Sharif Univ. 11/15/2018
27
Aspect-Oriented Programming
Identify concerns that cut across class / object boundaries Write code (an aspect) that encapsulates that concern Define a weave that specifies how the aspect will be weaved into existing code Mehr 1383, Sharif Univ. 11/15/2018
28
AOP Constructs Cross-Cutting Concern Point-Cut
Even though most classes in an OO model will perform a single, specific function, they often share common, secondary requirements with other classes. For example, we may want to add logging to all classes whenever a thread enters or exits a method. Even though the primary functionality of each class is very different, the code needed to perform the secondary functionality is often identical. Point-Cut This is the term given to the point of execution in the application at which cross-cutting concern needs to be applied. In our example, a point-cut is reached when the thread enters a method, and another point-cut is reached when the thread exits the method Mehr 1383, Sharif Univ. 11/15/2018
29
AOP Constructs (Cont.) Advice Aspect Joint Part
This is the additional code that you want to apply to your existing model. In our example, this is the logging code that we want to apply whenever the thread enters or exits a method Aspect The combination of the point-cut and the advice is termed an aspect. In the example below, we add a logging aspect to our application by defining a point-cut and giving the correct advice Joint Part Well defined locations in the execution of a program, typically, these include method invocations,field accesses, exception handlers, etc… Each join point is a possible place at which an aspect may specify behaviour Mehr 1383, Sharif Univ. 11/15/2018
30
An Example: Policies and software
Method implements three policies in addition to its code! Tracing policy: all public methods must be traceable Security policy: employee salary only readable by managers Exception policy: all FatalExceptions must be logged Should not mix policies and code Developers need to know to put policy code in there Policies obscure the method's implementation Mehr 1383, Sharif Univ. 11/15/2018
31
Aspects can implement policies
Public Function ReadEmployeeSalary( id as Integer ) as Single Trace.WriteLine( String.Format( "Reading employee # {0}'s salary", id ) ) If System.Threading.Thread.CurrentPrincipal.IsInRole( "manager" ) Then Try ' Code that reads employee's salary Catch e as FatalException Logging.LogFatalException( e, "ReadEmployeeSalary" ) End Try End If End Sub 1 2 3 Mehr 1383, Sharif Univ. 11/15/2018
32
Aspects can implement policies
public class TracingPolicy { public void Before( CallContext c ) Trace.WriteLine( String.Format( "Called: {0}", c.MethodName ) ); } 1 public class SecurityPolicy { public bool AccessCheck() return System.Threading.Thread.CurrentPrincipal.IsInRole( "manager" ); } 2 public class ExceptionPolicy { public void Thrown( FatalException e ) Logger.LogFatalException( e ); } 3 Mehr 1383, Sharif Univ. 11/15/2018
33
Weaving aspects before methods
public class TracingPolicy { public void Before( CallContext c ) Trace.WriteLine( String.Format( "Called: {0}", c.MethodName ) ); } <weave> <aspect target="public *.*::*( * )" type="Before" method="TracingPolicy.Before( CallContext )"/> </weave> Mehr 1383, Sharif Univ. 11/15/2018
34
Weaving aspects around methods
public class SecurityPolicy { public bool AccessCheck() return System.Threading.Thread.CurrentPrincipal.IsInRole( "manager" ); } <weave> <aspect target="[ interface:ManagerOnly == true ] public *.*::*( * )" type="Around" method="SecurityPolicy.AccessCheck()"/> </weave> [ ManagerOnly ] public interface ISensitiveEmployeeData { float ReadEmployeeSalary( int id ); ... } Mehr 1383, Sharif Univ. 11/15/2018
35
Weaving aspects around methods
public class ExceptionPolicy { public void Thrown( FatalException e ) Logger.LogFatalException( e ); } <weave> <aspect target="public *.*::*( * )" type="Thrown( FatalException )" method="ExceptionPolicy.Thrown( FatalException )"/> </weave> Mehr 1383, Sharif Univ. 11/15/2018
36
What is AspectJ? An open source language 100% Java compatible
An AOP implementation Extension to Java, new syntax Started at Xerox, now Eclipse project Mehr 1383, Sharif Univ. 11/15/2018
37
Getting and installing
Download from eclipse.org/aspectj Run executable JAR Use aspectjrt.jar on classpath Includes structure browser, debugger Mehr 1383, Sharif Univ. 11/15/2018
38
Writing an aspect Write the class Write the aspect (.java or .aj)
Weave with ‘ajc’ compiler Must have aspectjrt.jar for compile and runtime Simply use AJDT (AspectJ Development Tool ) as IDE Mehr 1383, Sharif Univ. 11/15/2018
39
Definitions Join point Pointcut Advice
Introduction (Inter-type declaration) Mehr 1383, Sharif Univ. 11/15/2018
40
Join points Points in a programs execution Method call
call( public void setOwner(String) ) Method call execution Constructor call initialization (BankAccount.new() ) Constructor call execution Field get Field set Exception handler execution Constructor Call Initializer Execution Static Initializer Execution Object Pre-Initialization Object Initialization No finer join points in AspectJ (loops, if checks) Mehr 1383, Sharif Univ. 11/15/2018
41
Join point patterns Names can be matched with *
call ( * * BankAccount.*(*)) Matches all calls on BankAccount, regardless of visibility or return type, with one argument call ( * *.(*)) Matches all method calls with 1 parameter call ( * * .(..)) Matches all method calls Mehr 1383, Sharif Univ. 11/15/2018
42
Join Point Patterns Cont
Subtypes can be matched with a + call (public void BankAccount+(..)) Can also match on throws patterns call (public void BankAccount+(..) throws Exception+) Watch out for infinite recursion! Aspects match aspects too Use ! within() Mehr 1383, Sharif Univ. 11/15/2018
43
Pointcuts Structure for selecting join points in a program and collecting context (args, target, source) Declaring a named pointcut pointcut changeBalance() : call (public void BankAccount.setBalance(java.math.BigDecimal)); Can be combined with logical operators, &&, ||, and ! Mehr 1383, Sharif Univ. 11/15/2018
44
Pointcuts (cont.) Valid on interfaces and classes Syntax
pointcut name ([parameters]) : designator (ajoinpoint); Name will be used to handle actions ajoinpoint is a signature match Designator decides when this join point will match like call , execution , … Mehr 1383, Sharif Univ. 11/15/2018
45
AspectJ Point-Cuts call(Signature) execution(Signature) get(Signature)
set(Signature) handler(TypePattern) initialization(Signature) staticinitialization(Signature) within(TypePattern) withincode(TypePattern) cflow(Pointcut) cflowbelow(Pointcut) this(TypePattern | Id) target(TypePattern | Id) args(TypePattern | Id, … ) PointcutId(TypePattern | Id ) if (BooleanExpression) Pointcut1 && Pointcut2 Pointcut1 || Pointcut2 ! Pointcut ( Pointcut ) Mehr 1383, Sharif Univ. 11/15/2018
46
AspectJ Advisers Advice defines crosscutting behavior.
It is defined in terms of pointcuts. The code of a piece of advice runs at every join point picked out by its pointcut. The code runs before, after, or around the join point Mehr 1383, Sharif Univ. 11/15/2018
47
Advice Type before after around excellent for preconditions
argument checking, setup code, lazy init after can be qualified with: after returning, or after throwing Cleanup of resources checking/manipulating the return value around the most powerful advice can replace invocation, or just surround use proceed() to call method Mehr 1383, Sharif Univ. 11/15/2018
48
Inter-type Declarations
AspectJ can be used to change the structure of existing code add members (id fields, dirty flag) add methods (toXML, storeToJDBC) add types that extend existing types or implement interfaces declare custom compilation errors or warnings convert checked exceptions to unchecked Can use from aspects, or regular code Write normal variable and methods in your aspect, but prefix them with your class name Mehr 1383, Sharif Univ. 11/15/2018
49
Inter-type declarations cont.
Very powerful Can do wacky things Add concrete fields & methods to interfaces (no constructors) Modify aspects Make an existing class dynamically implement an interface Make an existing class extend another Mehr 1383, Sharif Univ. 11/15/2018
50
AspectJ: Simple Example
public class Person { private String name; private String address; private int age; public static void main(String[] args) { Person person = new Person("Mahdi Minoochehr"); person.setAddress("Tehran,P15"); person.setAge(15); } public Person(String name){this.name=name;} public String getAddress() { return address; } public int getAge() { return age; } public String getName() { return name; } public void setAddress(String address) { this.address = address; } public void setAge(int age) { this.age = age; } Mehr 1383, Sharif Univ. 11/15/2018
51
AspectJ: Simple Example (cont.)
public aspect Logger { pointcut tracedCall() : call(void Person.*(..)); before() : tracedCall() { System.out.println("Entering: " thisJoinPointStaticPart.getSignature()); } after() : tracedCall() { System.out.println("Exiting: " + thisJoinPointStaticPart.getSignature()); Mehr 1383, Sharif Univ. 11/15/2018
52
The Risk: Aspect side-effects
Several aspects may be stacked at a join point Several unintended interactions are possible: Aspect 1 is unaware of the side effects of Aspect 2 Code at the join point is unaware of side effects of any aspect Mehr 1383, Sharif Univ. 11/15/2018
53
Who can use aspects? There will be different groups of users
Developers Testers Operations Library developers Systems administrators Systems engineers / consultants Mehr 1383, Sharif Univ. 11/15/2018
54
How can it be used? Development Optional runtime components
Check contracts, Logging Ensure good coding practices Tracing, Testing Optional runtime components Debugging Detecting incorrect usage (e.g. leaked DB connections) Detecting abusive usage (e.g. holding DB connections too long) Profiling Implement core system features Caching, Security Mehr 1383, Sharif Univ. 11/15/2018
55
Types of aspect weavers
Source-code aspect weavers AspectJ (V1.0+) Link-time aspect weavers Hyper/J (IBM Alphaworks) Run-time aspect weavers CLAW (prototype) Mehr 1383, Sharif Univ. 11/15/2018
56
Where to go for more information
An Introduction to Aspect-Oriented Programming & AspectJ Aspect Oriented Programming CLAW AOP without Buzzwords OnJava Mehr 1383, Sharif Univ. 11/15/2018
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.