Download SEAS : Part III

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Everything is About Good
Code Architecture
!
SEAS : Part III
Programing models, tools and techniques
with one shared goal :
!
!
Aspect-Oriented Programming
AspectJ
!
!
Vania Marangozova,
[email protected]
(kindly replacing Sara Bouchenak,
[email protected])
© S. Bouchenak
!
!
Produce a well-organized code
Easy to debug
Easy to maintain
Easy to evolve
Separation of concerns
Good modularity
AOP - AspectJ
© S. Bouchenak, V.Marangozova
XML Parsing
About Good Modularity
!
red shows the code we are interested in
!
all the code is in one module (class) "
© S. Bouchenak, V.Marangozova
AOP - AspectJ
2
URL Pattern Recognition
About Good Modularity
Parsing XML in org.apache.tomcat
!
AOP - AspectJ
!
URL pattern recognition in org.apache.tomcat
!
3
the code we are interested in is in two classes "
© S. Bouchenak, V.Marangozova
AOP - AspectJ
4
Non Modular Tracing
Problems
Sess on Term nat on
Problems
ApplicationSession
/*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*
notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*
notice, this list of conditions and the following disclaimer in
*
the documentation and/or other materials provided with the
*
distribution.
*
* 3. The end-user documentation included with the redistribution, if
*
any, must include the following acknowlegement:
*
"This product includes software developed by the
*
Apache Software Foundation (http://www.apache.org/)."
*
Alternately, this acknowlegement may appear in the software
itself,
*
if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
*
Foundation" must not be used to endorse or promote products
dérive
*
from this software without prior written permission. For written
*
permission, please contact [email protected].
*
* 5. Products derived from this software may not be called "Apache"
*
nor may "Apache" appear in their names without prior written
*
permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* [Additional notices, if required by prior licensing conditions]
*
*/
public void invalidate() {
serverSession.removeApplicationSession(context);
// remove everything in the session
Enumeration enum = values.keys();
while (enum.hasMoreElements()) {
String name = (String)enum.nextElement();
removeValue(name);
}
valid = false;
}
public boolean isNew() {
if (! valid) {
String msg = sm.getString("applicationSession.session.ise");
}
if (thisAccessTime == creationTime) {
return true;
} else {
return false;
}
}
/**
* @deprecated
*/
public void putValue(String name, Object value) {
setAttribute(name, value);
}
public void setAttribute(String name, Object value) {
if (! valid) {
String msg = sm.getString("applicationSession.session.ise");
}
}
}
}
String[] valueNames = new String[names.size()];
names.copyInto(valueNames);
public Enumeration getAttributeNames() {
if (! valid) {
String msg = sm.getString("applicationSession.session.ise");
}
return (Enumeration)valuesClone.keys();
}
/**
* The session identifier of this Session.
*/
private String id = null;
throw new IllegalArgumentException(msg);
if (o instanceof HttpSessionBindingListener) {
HttpSessionBindingEvent e =
new HttpSessionBindingEvent(this,name);
}
}
public long getCreationTime() {
if (valid) {
return creationTime;
} else {
String msg = sm.getString("applicationSession.session.ise");
((HttpSessionBindingListener)o).valueUnbound(e);
values.remove(name);
public void setMaxInactiveInterval(int interval) {
if (! valid) {
String msg = sm.getString("applicationSession.session.ise");
}
throw new IllegalStateException(msg);
}
/**
*
* @deprecated
*/
throw new IllegalStateException(msg);
inactiveInterval = interval;
public int getMaxInactiveInterval() {
if (! valid) {
String msg = sm.getString("applicationSession.session.ise");
public HttpSessionContext getSessionContext() {
return new SessionContextImpl();
}
}
}
}
/**
* Flag indicating whether this session is new or
*/
private boolean isNew = true;
throw new IllegalStateException(msg);
if (name == null) {
String msg = sm.getString("applicationSession.value.iae");
Object o = values.get(name);
throw new IllegalStateException(msg);
return inactiveInterval;
//-----------------------------------------------------------------------
throw new IllegalStateException(msg);
/**
* Flag indicating whether this session is valid or
not.
*/
private boolean isValid = false;
return (this.isValid);
}
//
----------------------------------------------------Session Properties
/**
* Set the creation time for this session. This
method is called by the
* Manager when an existing Session instance is
reused.
*
* @param time The new creation time
*/
public void setCreationTime(long time) {
this.creationTime = time;
this.lastAccessedTime = time;
this.thisAccessedTime = time;
}
}
/**
* Set the <code>isValid</code> flag for this session.
*
* @param isValid The new value for the <code>isValid</code>
this.isValid = isValid;
/**
* Return the time when this session was created, in
milliseconds since
* midnight, January 1, 1970 GMT.
*
* @exception IllegalStateException if this method is called
* invalidated session
*/
public long getCreationTime() {
/**
* Return the session context with which this session is
associated.
*
* @deprecated As of Version 2.1, this method is deprecated
and has no
* replacement. It will be removed in a future version of
the
* Java Servlet API.
*/
public HttpSessionContext getSessionContext() {
// ----------------------------------------------HttpSession
Public Methods
/**
* Return the object bound with the specified name in this
session, or
* <code>null</code> if no object is bound with that name.
*
* @param name Name of the attribute to be returned
*
* @exception IllegalStateException if this method is called
on an
* invalidated session
*/
public Object getAttribute(String name) {
// Accumulate the names of serializable attributes
Vector results = new Vector();
Enumeration attrs = getAttributeNames();
while (attrs.hasMoreElements()) {
String attr = (String) attrs.nextElement();
Object value = attributes.get(attr);
if (value instanceof Serializable)
results.addElement(attr);
}
return (attributes.get(name));
/**
* Return the session identifier for this session.
*/
public String getId() {
return (this.id);
}
/**
* Set the session identifier for this session.
*
* @param id The new session identifier
*/
public void setId(String id) {
if ((this.id != null) && (manager != null) &&
(manager instanceof ManagerBase))
((ManagerBase) manager).remove(this);
this.id = id;
if ((manager != null) && (manager instanceof
ManagerBase))
((ManagerBase) manager).add(this);
}
/**
* Return descriptive information about this
Session implementation and
* the corresponding version number, in the format
* <code>&lt;description&gt;/&lt;version&gt;</
code>.
*/
public String getInfo() {
return (this.info);
}
/**
* Return the last time the client sent a request
associated with this
* session, as the number of milliseconds since
midnight, January 1, 1970
* GMT. Actions that your application takes, such
as getting or setting
* a value associated with the session, do not
affect the access time.
*/
public long getLastAccessedTime() {
}
/**
* Return an <code>Enumeration</code> of <code>String</code>
objects
* containing the names of the objects bound to this session.
*
* @exception IllegalStateException if this method is called
on an
* invalidated session
*/
public Enumeration getAttributeNames() {
// Serialize the attribute count and the attribute values
stream.writeObject(new Integer(results.size()));
Enumeration names = results.elements();
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
stream.writeObject(name);
stream.writeObject(attributes.get(name));
}
return (attributes.keys());
}
/**
* Return the object bound with the specified name in this
session, or
* <code>null</code> if no object is bound with that name.
*
* @param name Name of the value to be returned
*
* @exception IllegalStateException if this method is called
on an
* invalidated session
*
* @deprecated As of Version 2.2, this method is replaced by
* <code>getAttribute()</code>
*/
public Object getValue(String name) {
}
return (this.lastAccessedTime);
/**
* This class is a dummy implementation of the <code>HttpSessionContext</code>
* interface, to conform to the requirement that such an object be returned
* when <code>HttpSession.getSessionContext()</code> is called.
*
* @author Craig R. McClanahan
*
* @deprecated As of Java Servlet API 2.1 with no replacement. The
* interface will be removed in a future version of this API.
*/
on
final class StandardSessionContext implements HttpSessionContext {
!
Tracing in org.apache.tomcat
!
!
!
red lines
are not in one module
are almost everywhere
© S. Bouchenak, V.Marangozova
return (this.manager);
}
this.manager = manager;
}
while (enum.hasMoreElements()) {
Object key = enum.nextElement();
ServerSession session = (ServerSession)sessions.get(key);
}
synchronized void removeSess
}
session.reap();
session.validate();
private StringManager sm =
StringManager.getManager("org.apache.tomcat.session");
private static ServerSessionManager manager; // = new ServerSessionManager();
return (dummy.elements());
* an invalidated session
*/
public void invalidate() {
}
/**
* Return <code>true</code> if the client does not yet know
about the
* session, or if the client chooses not to join the session.
For
* example, if the server used only cookie-based sessions,
and the client
* has disabled the use of cookies, then a session would be
new on each
* request.
*
* @exception IllegalStateException if this method is called
on an
* invalidated session
*/
public boolean isNew() {
/**
* Start the background thread that will periodically check for
* session timeouts.
*/
private void threadStart() {
*
* @param ctx The context that is being shut down
*/
public void removeSessions(Context ctx) {
// XXX XXX a manager may be shared by multiple
// contexts, we just want to remove the sessions of ctx!
// The manager will still run after that ( i.e. keep database
// connection open
if (manager instanceof Lifecycle) {
try {
((Lifecycle) manager).stop();
} catch (LifecycleException e) {
throw new IllegalStateException("" + e);
}
}
}
/**
* Used by context to configure the session manager's inactivity
timeout.
*
* The SessionManager may have some default session time out, the
* Context on the other hand has it's timeout set by the deployment
* descriptor (web.xml). This method lets the Context conforgure the
* session manager according to this value.
*
* @param minutes The session inactivity timeout in minutes.
*/
public void setSessionTimeOut(int minutes) {
if(-1 != minutes) {
// The manager works with seconds...
}
}
manager.setMaxInactiveInterval(minutes * 60);
}
if (thread != null)
return;
/**
* Stop the background thread that is periodically checking for
* session timeouts.
*/
private void threadStop() {
if (thread == null)
return;
threadDone = true;
thread.interrupt();
try {
thread.join();
} catch (InterruptedException e) {
;
}
thread = null;
}
// ------------------------------------------------------ Background Thread
public void accessed( Context ctx, Request req, String id ) {
ApplicationSession apS=(ApplicationSession)findSession( ctx, id);
if( apS==null) return;
/**
* The background thread that checks for session timeouts and shutdown.
*/
public void run() {
ServerSession servS=apS.getServerSession();
servS.accessed();
apS.accessed();
// Loop until the termination semaphore is set
while (!threadDone) {
threadSleep();
processExpires();
// cache it - no need to compute it again
req.setSession( apS );
if(-1 != inactiveInterval) {
session.setMaxInactiveInterval(inactiveInterval);
public HttpSession createSession(Context ctx) {
return manager.createSession().getSession();
}
* The Manager implementation we are actually using.
*/
private Manager manager = null;
}
}
public HttpSession createSession(Context ctx) {
String sessionId = SessionIdGenerator.generateId();
ServerSession session = new ServerSession(sessionId);
sessions.put(sessionId, session);
}
}
}
/**
threadDone = false;
thread = new Thread(this, threadName);
thread.setDaemon(true);
thread.start();
if ((maxActiveSessions >= 0) &&
(sessions.size() >= maxActiveSessions))
throw new IllegalStateException
(sm.getString("standardManager.createSession.ise"));
return (super.createSession());
}
private Hashtable sessions = new Hashtable();
private Reaper reaper;
private ServerSessionManager() {
reaper = Reaper.getReaper();
reaper.setServerSessionManager(this);
reaper.start();
}
}
/**
* Return the <code>HttpSession</code> associated with the
* specified session identifier.
*
* @param id Session identifier for which to look up a session
*
* @deprecated As of Java Servlet API 2.1 with no replacement.
* This method must return null and will be removed in a
* future version of the API.
*/
public HttpSession getSession(String id) {
}
}
public static ServerSessionManager getManager() {
return manager;
}
} catch (LifecycleException e) {
throw new IllegalStateException("" + e);
}
}
/**
// ----------------------------------------------------- Instance
* Remove all sessions because our associated Context is being shut
Variables
down.
try {
Thread.sleep(checkInterval * 1000L);
} catch (InterruptedException e) {
;
}
// --------------------------------------------------------- Public Methods
}
private Vector dummy = new Vector();
/**
* Return the session identifiers of all sessions defined
* within this context.
*
* @deprecated As of Java Servlet API 2.1 with no replacement.
* This method must return an empty <code>Enumeration</code>
* and will be removed in a future version of the API.
*/
public Enumeration getIds() {
*
* @exception IllegalStateException if this method is called
// Cause this session to expire
expire();
/**
* Set the Manager within which this Session is
valid.
*
* @param manager The new Manager
*/
public void setManager(Manager manager) {
synchronized void reap() {
Enumeration enum = sessions.keys();
public class ServerSessionManager implements SessionManager {
Session session = manager.findSession(id);
if(session!=null)
return session.getSession();
} catch (IOException e) {
}
return (null);
/**
* Sleep for the duration specified by the <code>checkInterval</code>
* property.
*/
private void threadSleep() {
this.maxActiveSessions = max;
/**
*
* @author James Duncan Davidson [[email protected]]
* @author Jason Hunter [[email protected]]
* @author James Todd [[email protected]]
*/
// cache the HttpSession - avoid another find
req.setSession( session );
((Lifecycle) manager).configure(null);
((Lifecycle) manager).start();
for (int i = 0; i < sessions.length; i++) {
StandardSession session = (StandardSession) sessions[i];
if (!session.isValid())
continue;
int maxInactiveInterval = session.getMaxInactiveInterval();
if (maxInactiveInterval < 0)
continue;
int timeIdle = // Truncate, do not round up
(int) ((timeNow - session.getLastAccessedTime()) / 1000L);
if (timeIdle >= maxInactiveInterval)
session.expire();
}
/**
* Construct and return a new session object, based on the default
* settings specified by this Manager's properties. The session
* id will be assigned by this method, and available via the getId()
* method of the returned session. If a new session cannot be created
* for any reason, return <code>null</code>.
*
* @exception IllegalStateException if a new session cannot be
* instantiated for any reason
*/
public Session createSession() {
}
// -------------------------------------------------------------- Private Class
/**
* Invalidates this session and unbinds any objects bound to
}
/**
* Set the maximum number of actives Sessions allowed, or -1 for
* no limit.
*
* @param max The new maximum number of sessions
*/
public void setMaxActiveSessions(int max) {
static {
manager = new ServerSessionManager();
}
}
return (this.maxActiveSessions);
}
This should be
HttpSession session=findSession(ctx, id);
if( session == null) return;
if (session instanceof Session)
((Session) session).access();
// XXX should we throw exception or just return null ??
public HttpSession findSession( Context ctx, String id ) {
try {
manager = new StandardManager();
if (manager instanceof Lifecycle) {
try {
long timeNow = System.currentTimeMillis();
Session sessions[] = findSessions();
}
protected int inactiveInterval = -1;
Vector results = new Vector();
Enumeration attrs = getAttributeNames();
while (attrs.hasMoreElements()) {
String attr = (String) attrs.nextElement();
results.addElement(attr);
}
String names[] = new String[results.size()];
for (int i = 0; i < names.length; i++)
names[i] = (String) results.elementAt(i);
return (names);
* Mark the specified session's last accessed time.
* called for each request by a RequestInterceptor.
*
* @param session The session to be marked
*/
public void accessed(Context ctx, Request req, String id) {
*/
public StandardSessionManager() {
/**
* Invalidate all sessions that have expired.
*/
private void processExpires() {
return (this.info);
// XXX
// sync'd for safty -- no other thread should be getting something
// from this while we are reaping. This isn't the most optimal
// solution for this, but we'll determine something else later.
/**
*
* @author Craig R. McClanahan
*/
public final class StandardSessionManager
implements SessionManager {
// ----------------------------------------------------------Constructors
// -------------------------------------------------------- Private Methods
/**
* Return the maximum number of active Sessions allowed, or -1 for
* no limit.
*/
public int getMaxActiveSessions() {
ServerSessionManager
* processing semantics of handling sessions.
* <p>
* XXX - At present, there is no way (via the SessionManager interface) for
* a Context to tell the Manager that we create what the default session
* timeout for this web application (specified in the deployment
descriptor)
* should be.
}
}
package org.apache.tomcat.session;
static advice(StandardSession s): invalidate(s) {
before {
if (!s.isValid())
throw new IllegalStateException
(s.sm.getString("standardSession."
+ thisJoinPoint.methodName
+ ".ise"));
}
return (getAttribute(name));
}
/**
* Return the Manager within which this Session is
valid.
*/
public Manager getManager() {
this.checkInterval = checkInterval;
import org.apache.tomcat.util.*;
import org.apache.tomcat.core.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.servlet.http.*;
* and lifecycle configuration is not supported.
* <p>
* <b>IMPLEMENTATION NOTE</b>: Once we commit to the new Manager/Session
* paradigm, I would suggest moving the logic implemented here back into
* the core level. The Tomcat.Next "Manager" interface acts more like a
* collection class, and has minimal knowledge of the detailed request
// Expire all active sessions
Session sessions[] = findSessions();
for (int i = 0; i < sessions.length; i++) {
StandardSession session = (StandardSession) sessions[i];
if (!session.isValid())
continue;
session.expire();
/**
* Return descriptive information about this Manager implementation and
* the corresponding version number, in the format
* <code>&lt;description&gt;/&lt;version&gt;</code>.
*/
public String getInfo() {
crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() |
long getCreationTime() |
Object getAttribute(String) |
Enumeration getAttributeNames() |
String[] getValueNames() |
void invalidate() |
boolean isNew() |
void removeAttribute(String) |
void setAttribute(String, Object));
* Specialized implementation of org.apache.tomcat.core.SessionManager
* that adapts to the new component-based Manager implementation.
* <p>
* XXX - At present, use of <code>StandardManager</code> is hard coded,
}
}
}
}
/**
* Return the set of names of objects bound to this session.
If there
* are no such objects, a zero-length array is returned.
*
* @exception IllegalStateException if this method is called
on an
* invalidated session
*
* @deprecated As of Version 2.2, this method is replaced by
* <code>getAttributeNames()</code>
*/
public String[] getValueNames() {
it.
}
// Write the scalar instance variables (except Manager)
stream.writeObject(new Long(creationTime));
stream.writeObject(id);
stream.writeObject(new Long(lastAccessedTime));
stream.writeObject(new Integer(maxInactiveInterval));
stream.writeObject(new Boolean(isNew));
stream.writeObject(new Boolean(isValid));
/**
// Stop the background reaper thread
threadStop();
/**
* Set the check interval (in seconds) for this Manager.
*
* @param checkInterval The new check interval
*/
public void setCheckInterval(int checkInterval) {
/**
* Write a serialized version of this session object to the specified
* object output stream.
* <p>
* <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored
* in the serialized representation of this Session. After calling
* <code>readObject()</code>, you must set the associated Manager
* explicitly.
* <p>
* <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable
* will be silently ignored. If you do not want any such attributes,
* be sure the <code>distributable</code> property of our associated
* Manager is set to <code>true</code>.
*
* @param stream The output stream to write to
*
* @exception IOException if an input/output error occurs
*/
private void writeObject(ObjectOutputStream stream) throws IOException {
// --------------------------------------------------------- Public Methods
import javax.servlet.http.HttpSession;
import org.apache.tomcat.catalina.*;
import org.apache.tomcat.core.Context;
import org.apache.tomcat.core.Request;
import org.apache.tomcat.core.Response;
import org.apache.tomcat.core.SessionManager;
import org.apache.tomcat.util.SessionUtil;
// Validate and update our current component state
if (!started)
throw new LifecycleException
(sm.getString("standardManager.notStarted"));
started = false;
return (this.checkInterval);
}
if (sessionContext == null)
sessionContext = new StandardSessionContext();
return (sessionContext);
/**
* Gracefully terminate the active use of the public methods of this
* component. This method should be the last one called on a given
* instance of this component.
*
* @exception IllegalStateException if this component has not been started
* @exception IllegalStateException if this component has already
* been stopped
* @exception LifecycleException if this component detects a fatal error
* that needs to be reported
*/
public void stop() throws LifecycleException {
/**
* Return the check interval (in seconds) for this Manager.
*/
public int getCheckInterval() {
}
}
// Start the background reaper thread
threadStart();
}
/**
* Name to register for the background thread.
*/
private String threadName = "StandardManager";
// ------------------------------------------------------------- Properties
// Deserialize the attribute count and attribute values
int n = ((Integer) stream.readObject()).intValue();
for (int i = 0; i < n; i++) {
String name = (String) stream.readObject();
Object value = (Object) stream.readObject();
attributes.put(name, value);
return (this.creationTime);
}
package org.apache.tomcat.session;
import java.io.IOException;
import javax.servlet.http.Cookie;
* Create a new SessionManager that adapts to the corresponding Manager
}
* implementation.
// Validate and update our current component state
if (!configured)
throw new LifecycleException
(sm.getString("standardManager.notConfigured"));
if (started)
throw new LifecycleException
(sm.getString("standardManager.alreadyStarted"));
started = true;
/**
* The background thread.
*/
private Thread thread = null;
/**
* The background thread completion semaphore.
*/
private boolean threadDone = false;
// Deserialize the scalar instance variables (except Manager)
creationTime = ((Long) stream.readObject()).longValue();
id = (String) stream.readObject();
lastAccessedTime = ((Long) stream.readObject()).longValue();
maxInactiveInterval = ((Integer) stream.readObject()).intValue();
isNew = ((Boolean) stream.readObject()).booleanValue();
isValid = ((Boolean) stream.readObject()).booleanValue();
on an
StandardSessionManager
/**
* Prepare for the beginning of active use of the public methods of this
* component. This method should be called after <code>configure()</code>,
* and before any of the public methods of the component are utilized.
*
* @exception IllegalStateException if this component has not yet been
* configured (if required for this component)
* @exception IllegalStateException if this component has already been
* started
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
public void start() throws LifecycleException {
/**
* Has this component been started yet?
*/
private boolean started = false;
// -------------------------------------------- HttpSession Private Methods
/**
* Read a serialized version of this session object from the specified
* object input stream.
* <p>
* <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager
* is not restored by this method, and must be set explicitly.
*
* @param stream The input stream to read from
*
* @exception ClassNotFoundException if an unknown class is specified
* @exception IOException if an input/output error occurs
*/
private void readObject(ObjectInputStream stream)
throws ClassNotFoundException, IOException {
*/
void setValid(boolean isValid) {
}
// ------------------------------------------------HttpSession Properties
node = attributes.getNamedItem("maxInactiveInterval");
if (node != null) {
try {
setMaxInactiveInterval(Integer.parseInt(node.getNodeValue()));
} catch (Throwable t) {
;
// XXX - Throw exception?
}
}
/**
/**
* The string manager for this package.
*/
private StringManager sm =
StringManager.getManager("org.apache.tomcat.session");
}
flag
node = attributes.getNamedItem("maxActiveSessions");
if (node != null) {
try {
setMaxActiveSessions(Integer.parseInt(node.getNodeValue()));
} catch (Throwable t) {
;
// XXX - Throw exception?
}
}
}
/**
* The descriptive information about this implementation.
*/
private static final String info = "StandardManager/1.0";
/**
* The maximum number of active Sessions allowed, or -1 for no limit.
*/
protected int maxActiveSessions = -1;
synchronized (attributes) {
removeAttribute(name);
attributes.put(name, value);
if (value instanceof HttpSessionBindingListener)
((HttpSessionBindingListener) value).valueBound
(new HttpSessionBindingEvent((HttpSession) this, name));
this.isNew = isNew;
node = attributes.getNamedItem("checkInterval");
if (node != null) {
try {
setCheckInterval(Integer.parseInt(node.getNodeValue()));
} catch (Throwable t) {
;
// XXX - Throw exception?
}
}
/**
* The interval (in seconds) between checks for expired sessions.
*/
private int checkInterval = 60;
/**
* Has this component been configured yet?
*/
private boolean configured = false;
if ((manager != null) && manager.getDistributable() &&
!(value instanceof Serializable))
throw new IllegalArgumentException
(sm.getString("standardSession.setAttribute.iae"));
/**
* Set the <code>isNew</code> flag for this session.
*
* @param isNew The new value for the <code>isNew</code> flag
*/
void setNew(boolean isNew) {
// Parse and process our configuration parameters
if (!("Manager".equals(parameters.getNodeName())))
return;
NamedNodeMap attributes = parameters.getAttributes();
Node node = null;
// ----------------------------------------------------- Instance Variables
/**
* Bind an object to this session, using the specified name. If an object
* of the same name is already bound to this session, the object is
* replaced.
* <p>
* After this method executes, and if the object implements
* <code>HttpSessionBindingListener</code>, the container calls
* <code>valueBound()</code> on the object.
*
* @param name Name to which the object is bound, cannot be null
* @param value Object to be bound, cannot be null
*
* @exception IllegalArgumentException if an attempt is made to add a
* non-serializable object in an environment marked distributable.
* @exception IllegalStateException if this method is called on an
* invalidated session
*/
public void setAttribute(String name, Object value) {
/**
* Return the <code>isValid</code> flag for this session.
*/
boolean isValid() {
}
// Validate and update our current component state
if (configured)
throw new LifecycleException
(sm.getString("standardManager.alreadyConfigured"));
configured = true;
if (parameters == null)
return;
public final class StandardManager
extends ManagerBase
implements Lifecycle, Runnable {
removeAttribute(name);
}
}
/**
* The string manager for this package.
*/
private StringManager sm =
/**
* The current accessed time for this session.
*/
private long thisAccessedTime = creationTime;
// Reset the instance variables associated with this
attributes.clear();
creationTime = 0L;
id = null;
lastAccessedTime = 0L;
manager = null;
maxInactiveInterval = -1;
isNew = true;
isValid = false;
// Tell our Manager that this Session has been recycled
if ((manager != null) && (manager instanceof
ManagerBase))
((ManagerBase) manager).recycle(this);
// ------------------------------------------------ Session
Package Methods
StringManager.getManager("org.apache.tomcat.session");
/**
* The HTTP session context associated with this
session.
*/
private static HttpSessionContext sessionContext =
null;
/**
* Remove the object bound with the specified name from this session. If
* the session does not have an object bound with this name, this method
* does nothing.
* <p>
* After this method executes, and if the object implements
* <code>HttpSessionBindingListener</code>, the container calls
* <code>valueUnbound()</code> on the object.
*
* @param name Name of the object to remove from this session.
*
* @exception IllegalStateException if this method is called on an
* invalidated session
*
* @deprecated As of Version 2.2, this method is replaced by
* <code>removeAttribute()</code>
*/
public void removeValue(String name) {
// Mark this session as invalid
setValid(false);
/**
* Release all object references, and initialize instance
variables, in
* preparation for reuse of this object.
*/
public void recycle() {
// ------------------------------------------------------ Lifecycle Methods
/**
* Configure this component, based on the specified configuration
* parameters. This method should be called immediately after the
* component instance is created, and before <code>start()</code>
* is called.
*
* @param parameters Configuration parameters for this component
* (<B>FIXME: What object type should this really be?)
*
* @exception IllegalStateException if this component has already been
* configured and/or started
* @exception LifecycleException if this component detects a fatal error
* in the configuration parameters it was given
*/
public void configure(Node parameters)
throws LifecycleException {
/**
* Standard implementation of the <b>Manager</b> interface that provides
* no session persistence or distributable capabilities, but does support
* an optional, configurable, maximum number of active sessions allowed.
* <p>
* Lifecycle configuration of this component assumes an XML node
* in the following format:
* <code>
*
&lt;Manager className="org.apache.tomcat.session.StandardManager"
*
checkInterval="60" maxActiveSessions="-1"
*
maxInactiveInterval="-1" />
* </code>
* where you can adjust the following parameters, with default values
* in square brackets:
* <ul>
* <li><b>checkInterval</b> - The interval (in seconds) between background
*
thread checks for expired sessions. [60]
* <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
*
inactivity before which the servlet container is allowed to time out
*
a session, or -1 for no limit. This value should be overridden from
*
the default session timeout specified in the web application deployment
*
descriptor, if any. [-1]
* </ul>
*
* @author Craig R. McClanahan
* @version $Revision: 1.1.1.1 $ $Date: 2000/05/02 21:28:30 $
*/
}
}
Session
package org.apache.tomcat.session;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import org.apache.tomcat.catalina.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpSession;
import org.apache.tomcat.util.StringManager;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
synchronized (attributes) {
Object object = attributes.get(name);
if (object == null)
return;
attributes.remove(name);
//
System.out.println( "Removing attribute " + name );
if (object instanceof HttpSessionBindingListener) {
((HttpSessionBindingListener) object).valueUnbound
(new HttpSessionBindingEvent((HttpSession) this, name));
}
}
// Unbind any objects associated with this session
Vector results = new Vector();
Enumeration attrs = getAttributeNames();
while (attrs.hasMoreElements()) {
String attr = (String) attrs.nextElement();
results.addElement(attr);
}
Enumeration names = results.elements();
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
removeAttribute(name);
}
/**
* The Manager with which this Session is
associated.
*/
private Manager manager = null;
not.
}
}
throw new IllegalStateException(msg);
/**
* Remove the object bound with the specified name from this session. If
* the session does not have an object bound with this name, this method
* does nothing.
* <p>
* After this method executes, and if the object implements
* <code>HttpSessionBindingListener</code>, the container calls
* <code>valueUnbound()</code> on the object.
*
* @param name Name of the object to remove from this session.
*
* @exception IllegalStateException if this method is called on an
* invalidated session
*/
public void removeAttribute(String name) {
// Remove this session from our manager's active sessions
if ((manager != null) && (manager instanceof
ManagerBase))
((ManagerBase) manager).remove(this);
/**
* The last accessed time for this Session.
*/
private long lastAccessedTime = creationTime;
/**
* The maximum time interval, in seconds, between
client requests before
* the servlet container may invalidate this
session. A negative time
* indicates that the session should never time
out.
*/
private int maxInactiveInterval = -1;
* @deprecated
*/
public String getId() {
if (valid) {
return id;
} else {
String msg = sm.getString("applicationSession.session.ise");
}
StandardManager
setAttribute(name, value);
}
this.lastAccessedTime = this.thisAccessedTime;
this.thisAccessedTime = System.currentTimeMillis();
this.isNew=false;
/**
* Perform the internal processing required to invalidate
this session,
* without triggering an exception if the session has already
expired.
*/
public void expire() {
/**
* Descriptive information describing this Session
implementation.
*/
private static final String info =
"StandardSession/1.0";
public void removeValue(String name) {
removeAttribute(name);
}
if (thisInterval > inactiveInterval) {
invalidate();
}
// HTTP SESSION IMPLEMENTATION METHODS
}
/**
* The collection of user data attributes
associated with this Session.
*/
private Hashtable attributes = new Hashtable();
/**
* The time this session was created, in
milliseconds since midnight,
* January 1, 1970 GMT.
*/
private long creationTime = 0L;
* Bind an object to this session, using the specified name. If an object
* of the same name is already bound to this session, the object is
* replaced.
* <p>
* After this method executes, and if the object implements
* <code>HttpSessionBindingListener</code>, the container calls
* <code>valueBound()</code> on the object.
*
* @param name Name to which the object is bound, cannot be null
* @param value Object to be bound, cannot be null
*
* @exception IllegalStateException if this method is called on an
* invalidated session
*
* @deprecated As of Version 2.2, this method is replaced by
* <code>setAttribute()</code>
*/
public void putValue(String name, Object value) {
return ((HttpSession) this);
//
---------------------------------------------------------- Constructors
//
----------------------------------------------------Instance Variables
/**
/**
* Return the <code>HttpSession</code> for which this object
* is the facade.
*/
public HttpSession getSession() {
}
// ------------------------------------------------- Session
Public Methods
/**
* Update the accessed time information for this session.
This method
* should be called by the context when a request comes in
for a particular
* session, even if the application does not reference it.
*/
public void access() {
/**
* Construct a new Session associated with the
specified Manager.
*
* @param manager The manager with which this
Session is associated
*/
public StandardSession(Manager manager) {
public void removeAttribute(String name) {
if (! valid) {
String msg = sm.getString("applicationSession.session.ise");
/**
validate();
void validate() {
// if we have an inactive interval, check to see if we've exceeded it
if (inactiveInterval != -1) {
int thisInterval =
(int)(System.currentTimeMillis() - lastAccessed) / 1000;
}
throw new IllegalStateException(msg);
Hashtable valuesClone = (Hashtable)values.clone();
/**
* Called by context when request comes in so that accesses and
* inactivities can be dealt with accordingly.
*/
void accessed() {
// set last accessed to thisAccessTime as it will be left over
// from the previous access
lastAccessed = thisAccessTime;
thisAccessTime = System.currentTimeMillis();
public long getLastAccessedTime() {
if (valid) {
return lastAccessed;
} else {
String msg = sm.getString("applicationSession.session.ise");
final class StandardSession
implements HttpSession, Session {
}
if (this.inactiveInterval != -1) {
this.inactiveInterval *= 60;
}
ServerSession getServerSession() {
return serverSession;
}
/**
* Standard implementation of the <b>Session</b>
interface. This object is
* serializable, so that it can be stored in persistent
storage or transferred
* to a different JVM for distributable session
support.
* <p>
* <b>IMPLEMENTATION NOTE</b>: An instance of this
class represents both the
* internal (Session) and application level
(HttpSession) view of the session.
* However, because the class itself is not declared
public, Java logic outside
* of the <code>org.apache.tomcat.session</code>
package cannot cast an
* HttpSession view of this instance back to a Session
view.
*
* @author Craig R. McClanahan
* @version $Revision: 1.2 $ $Date: 2000/05/15 17:54:10
$
*/
return valueNames;
}
}
throw new IllegalArgumentException(msg);
return values.get(name);
while (e.hasMoreElements()) {
names.addElement(e.nextElement());
}
this.inactiveInterval = context.getSessionTimeOut();
}
throw new IllegalStateException(msg);
if (name == null) {
String msg = sm.getString("applicationSession.value.iae");
}
}
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import javax.servlet.ServletException;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionContext;
import org.apache.tomcat.catalina.*;
import org.apache.tomcat.util.StringManager;
super();
this.manager = manager;
/**
* @deprecated
*/
public String[] getValueNames() {
Enumeration e = getAttributeNames();
Vector names = new Vector();
ApplicationSession(String id, ServerSession serverSession,
Context context) {
this.serverSession = serverSession;
this.context = context;
this.id = id;
StandardSession
package org.apache.tomcat.session;
}
public Object getAttribute(String name) {
if (! valid) {
String msg = sm.getString("applicationSession.session.ise");
private StringManager sm =
StringManager.getManager("org.apache.tomcat.session");
private Hashtable values = new Hashtable();
private String id;
private ServerSession serverSession;
private Context context;
private long creationTime = System.currentTimeMillis();;
private long thisAccessTime = creationTime;
private long lastAccessed = creationTime;
private int inactiveInterval = -1;
private boolean valid = true;
}
((HttpSessionBindingListener)value).valueBound(e);
/**
* @deprecated
*/
public Object getValue(String name) {
return getAttribute(name);
}
public class ApplicationSession implements HttpSession {
}
// remove any existing binding
values.put(name, value);
}
import org.apache.tomcat.core.*;
import org.apache.tomcat.util.StringManager;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
}
throw new IllegalArgumentException(msg);
removeValue(name);
if (value != null && value instanceof HttpSessionBindingListener) {
HttpSessionBindingEvent e =
new HttpSessionBindingEvent(this, name);
/**
* Core implementation of an application level session
*
* @author James Duncan Davidson [[email protected]]
* @author Jason Hunter [[email protected]]
* @author James Todd [[email protected]]
*/
}
throw new IllegalStateException(msg);
if (name == null) {
String msg = sm.getString("applicationSession.value.iae");
package org.apache.tomcat.session;
}
throw new IllegalStateException(msg);
}
}
return session.getApplicationSession( ctx, true );
public HttpSession findSession(Context ctx, String id) {
ServerSession sSession=(ServerSession)sessions.get(id);
if(sSession==null) return null;
}
return sSession.getApplicationSession(ctx, false);
return (null);
}
}
return (this.isNew);
}
/**
* Return the maximum time interval, in seconds,
between client requests
* before the servlet container will invalidate the
session. A negative
* time indicates that the session should never
time out.
*
* @exception IllegalStateException if this method
is called on
* an invalidated session
*/
public int getMaxInactiveInterval() {
return (this.maxInactiveInterval);
}
/**
* Set the maximum time interval, in seconds,
between client requests
* before the servlet container will invalidate the
session. A negative
* time indicates that the session should never
time out.
*
* @param interval The new maximum interval
*/
public void setMaxInactiveInterval(int interval) {
this.maxInactiveInterval = interval;
}
#
AOP - AspectJ
5
© S. Bouchenak, V.Marangozova
AOP - AspectJ
6
org apache tomcat
Conslusion about the Code
!
Loca zed treatments
!
Con gura on
About Scattered Code
!
es XML pars ng
In most cases, we can d fferent ate two types of
code
!
!
Treatments mp emented w th few c asses
!
!
HTTP reques s regu ar express ons
!
!
Treatments that are scattered everywhere
!
©
rac ng ana ys s o prob ems accoun o encoun ered
prob ems dur ng reques rea men
M
O
©
Bas c unc ona y app ca on code
Managemen code code ha makes he bas c unc ona y
code o rea y work
The organ za on o he code o ows he bas c unc ona y
code og c
! n consequence he managemen code s usua y
sca ered
! Th s s why managemen code s d cu
o wr e
M
O
What are the problems with
non modular code?
!
!
!
Separate tangled code
!
Minimize inter-code dependancies
!
All treatments should have
Same treatments repeated throughout the application code
Obscure code
!
!
AOP Principles
Redundancy
!
!
Aspect-Oriented Programming
Code structure is not explicit
Global code architecture difficult to understand
!
Difficult to change/maintain code
!
!
!
We need to found the fragments that concern the feature
we want to change
We need to make sure that changes are consistent i.e that
a change in one place does not “hurt” a change in another
place
No tools to help...
© S. Bouchenak, V.Marangozova
AOP - AspectJ
9
Outline
$
a clear objective
a well-defined modular structure
Aspects
!
Modular treatments that can be “mixed”/composed/
tangled/organized together
© S. Bouchenak, V.Marangozova
AOP - AspectJ
10
AOP Definition
1.
Introduction to AOP
2.
Introduction to AspectJ
3.
Syntax of AspectJ
4.
Software Development with AspectJ
5.
Conclusion and References
© S. Bouchenak, V.Marangozova
!
AOP - AspectJ
11
!
AOP = Aspect-Oriented Programming
!
"Aspect-oriented programming allows the
factorization of treatments whose
implementation is scattered through a
system”
© S. Bouchenak, V.Marangozova
AOP - AspectJ
12
Types of Aspects
AOP Methodology
A software system comprises:
!
!
!
Applicational aspects that correspond to
core concerns. These are the software modules
that implement the basic functionality of a
system..
Orthogonal aspects : cross-cutting concerns.
Software modules that implement system code
to be used by several other softwrae modules..
© S. Bouchenak, V.Marangozova
AOP - AspectJ
13
AOP Methodology :
1. Decompose in aspects
!
!
Application aspects.
Example of a banking system : clients, accounts,
transfers, etc.
Management aspects.
Examples : data persistancy, authentification,
tracing, ressource sharing, performance, etc.
© S. Bouchenak, V.Marangozova
AOP - AspectJ
1.
Decompose a system into aspects
2.
Implement the aspects
3.
Recompose the aspects
© S. Bouchenak, V.Marangozova
AOP - AspectJ
14
AOP Methodology :
2. Aspect Implementation
Separate the software treatments into :
!
How do we do AOP?
!
15
Implementatio of aspects in an independent
way i.e each aspect alone
!
Implementation techniques
!
!
!
procedural languages
OO Techniques
© S. Bouchenak, V.Marangozova
AOP - AspectJ
16
AOP Methodology :
3. Aspects Composition (Weaving)
!
!
!
!
Rules for composing aspects
These rules are used in order to produce the final
system
Composition process: integration or weaving
Example : before each operation on the banking
system, the client must be authentified.
composition rule
How to AOP?
AOP is a methodologie, how do we put it into
practice?
!
applicational
aspect
!
Aspect languages : C, C++, Java, etc.
!
Languages for speifying the rules for asepct weaving :
AspectC, AspectJ, etc.
!
Aspect integration tool : aspect weaver, AOP compiler
(AspectC, AspectJ, etc.)
management
aspect
© S. Bouchenak, V.Marangozova
AOP - AspectJ
17
© S. Bouchenak, V.Marangozova
AOP in Java
18
Outline
AOP Introduction
1.
aspects
aspects
fonctionnels
functional
fonctionnels
aspects
Java
Introduction to AspectJ
2.
!
Java
!
composition
rules
AOP compiler
AspectJ
compilo AspectJ
!
!
Java
AOP - AspectJ
19
AspectJ Composition
join point, pointcut, advice, introduction, declaration, aspect
Programming
Examples
3.
AspectJ syntax
4.
Development with AspectJ
5.
Conclusion and Refs
final system
aspects
aspects
fonctionnels
system
fonctionnels
aspects
© S. Bouchenak, V.Marangozova
AOP - AspectJ
© S. Bouchenak, V.Marangozova
AOP - AspectJ
20
Composition elements in
AspectJ
Composition in AspectJ
Static composition
!
!
!
!
!
!
Composition in AspectJ
!
Join point
Pointcut
Advice
Introduction
Declaration (at compile-time)
Aspect
!
We cans add new behaviour to the normal behaviour of the
program
We can extend or replace an operation
We can operate before or after the execution of some
operations s
!
is an extension of Java
for definig rules for dynamic and static composition
!
Dynamic composition
!
AspectJ
!
We can change the structure of the system :
classes and interfaces
We cans add methods and attributes
We can declare warnings or compile-time errors
!
!
!
!
!
!
© S. Bouchenak, V.Marangozova
AOP - AspectJ
21
Join point
!
!
Example
!
execution (void Account.credit(float))
public class Account {
float balance;
void credit(float amount) {
this.balance += amount;
}
!
!
The Account join points include
!
!
Pointcut
!
}
!
A pointcut is used to select a join point
and get the execution context of this join point
!
Example
!
22
Definition
!
An well-identified point in the execution af a program
Can be a method call or the access of an attribute
!
AOP - AspectJ
Pointcut
Definition
!
© S. Bouchenak, V.Marangozova
select the join point correspondint to the call of the credit method
of the Account class
get the execution context for this method : the object on which
the method is called, the method’s parameters
the execution of the credit method
the access to the balance attribute
© S. Bouchenak, V.Marangozova
AOP - AspectJ
23
© S. Bouchenak, V.Marangozova
AOP - AspectJ
24
Advice
Introduction
Definition
!
!
Definition
!
The code associated to a pointcut i.e
the code to be executed when the pointcut happens during the
execution of a program
Execution before, after or in replacement of a pointcut
!
!
Example
!
Example
!
declare parents : Account implements BankingEntity;
before() : execution (void Account.credit(float)) {
System.out.println("About to perform credit operation");
}
private float Account._minimalBalance;
!
!
!
AOP - AspectJ
25
Compile-time declaration
!
© S. Bouchenak, V.Marangozova
!
!
!
declare warning : call (void Persistence.save(Object)) :
"Deprecated method Persistence.save(),
Consider using Persistence.saveOptimized()";
!
Example de fichier ExampleAspect.java
public aspect ExampleAspect {
declare parents : Account implements BankingEntity;
Declaration
!
!
!
26
A code module containing the rules for static and dynamic
composition
Introductions + declarations + pointcuts + advices = aspect
An aspect in AspectJ is equivalent to a Java class
!
Example
!
AOP - AspectJ
Definition
!
Add instructions to be composed statically
Add warnings or errors for the compilation process
!
extension of the class hierarchy
from now on (actually, after weaving...) Account will implement
the BankingAccount interface
add a new attribute _minimalBalance to Account
Aspect
Definition
!
!
message printing
before the execution of the credit method of the Account class
© S. Bouchenak, V.Marangozova
Introduction
!
Advice
!
Static change of aclass or an interface
Add a method or an attribute, extend inheritance relations
!
before() : execution (void Account.credit(float)) {
System.out.println("About to perform credit operation");
}
declare a warning
print a message of the save method of the Persistence call is
called
declare warning : call (void Persistence.save(Object)) :
"Deprecated method Persistence.save(),
Consider using Persistence.saveOptimized()";
}
© S. Bouchenak, V.Marangozova
AOP - AspectJ
27
© S. Bouchenak, V.Marangozova
AOP - AspectJ
28
Programming Methodology
Example Hello (1 / 4)
Design
!
1.
2.
!
1.
2.
3.
4.
Program an aspect containing the implementation of the above
design
Program the desired join points
Program the advice to be associated to the above join pojnts i.e
define the new behaviour to execute at these join points
Add rules for static composition if necessary (introductions,
declarations)
© S. Bouchenak, V.Marangozova
AOP - AspectJ
29
Example Hello (2 / 4)
public class Test {
public static void main(String[] args) {
Communicator.print("Want to learn AspectJ?");
Communicator.print("Tom", "how are you?");
}
}
© S. Bouchenak, V.Marangozova
AOP - AspectJ
30
Example Hello (3 / 4)
Compilation Java
!
Aspect
public aspect HelloAspect {
% javac Communicator.java Test.java
!
public class Communicator {
public static void print(String message) {
System.out.println(message);
}
public static void print(String person, String message) {
System.out.println(person + ", " + message);
}
}
Implementation
!
!
Application
Identify the join points where the program behaviour should be
changed/extended
Design the new behaviour to be inserted at these join ponts
& Declaration of an aspect
pointcut printCall() : call (void Communicator.print(..)); ' Declaration of a pointcut
Execution
before() : printCall() {
System.out.print("Hello! ");
}
% java Test
Want to learn AspectJ?
( Declaration of an advice
Tom, how are you?
}
© S. Bouchenak, V.Marangozova
AOP - AspectJ
31
© S. Bouchenak, V.Marangozova
AOP - AspectJ
32
Example Hello (4 / 4)
!
Tracing Example (1/4)
Compilation AspectJ
!
Initial application
package banking;
% ajc Communicator.java Test.java HelloAspect.java
public class Account {
float balance;
!
Execution
void credit(float amount) {
this.balance += amount;
% java Test
Hello! Want to learn AspectJ?
}
Hello! Tom, how are you?
void debit(float amount) {
this.balance -= amount;
}
}
© S. Bouchenak, V.Marangozova
AOP - AspectJ
33
Tracing Example (2 / 4)
!
AOP - AspectJ
34
Tracing Example (3 / 4)
“By hand” Modifications
!
Another solution : Aspect for automatic tracing
public aspect AutoLogAspect {
package banking;
pointcut methodExecution() : execution (* banking.Account.*(..));
public class Account {
float balance;
before() : methodExecution() {
Signature sig = thisJoinPointStaticPart.getSignature();
String className = sig.getDeclaringType().getName();
String methodName = sig.getName();
Logger.entering(className, methodName);
}
void credit(float amount) {
Logger.entering("banking.Account", "credit(float)");
this.balance += amount;
Logger.exiting("banking.Account", "credit(float)");
}
after() : methodExecution() {
Signature sig = thisJoinPointStaticPart.getSignature();
String className = sig.getDeclaringType().getName();
String methodName = sig.getName();
Logger.exiting(className, methodName);
}}
void debit(float amount) {
Logger.entering("banking.Account", "debit(float)");
this.balance -= amount;
Logger.exiting("banking.Account", "debit(float)");
}
}
© S. Bouchenak, V.Marangozova
© S. Bouchenak, V.Marangozova
AOP - AspectJ
35
© S. Bouchenak, V.Marangozova
AOP - AspectJ
36
Tracing Example (4 / 4)
Outline
initial
application
Account
Java
Java
AutoLogAspect
1.
Introduction to AOP
2.
Introduction to AspectJ
Syntaxe AspectJ
3.
authomatic
tracing
aspect
!
AOP compiler
compilo AspectJ
AspectJ
!
!
application with tracing
!
!
Logger
Account + Logger
tracing
module
Java
© S. Bouchenak, V.Marangozova
AOP - AspectJ
37
Pointcut
!
Pointcut
Call vs. Execution
Pointcuts de flot de contrôle, de structure lexicale
Advice
Passage de paramètres entre pointcut et advice
4.
Software Development with AspectJ
5.
Conclusion and Refs
© S. Bouchenak, V.Marangozova
AOP - AspectJ
38
Signature of a pointcut
pointcut syntax
!
Example
[mode_accès] pointcut nom_pointcut([args]) : definition_pointcut
public pointcut printCall() : call ( void Communicator.print(..) )
!
Example
pointcut type
pointcut name
keyword
mode d’accès
public pointcut printCall() : call ( void Communicator.print(..) )
pointcut type
pointcut name
!
signature
Signature of a pointcut
%
keyword
mode d’accès
%
%
© S. Bouchenak, V.Marangozova
AOP - AspectJ
signature
39
Signature of a type
Signature of methods/constructors
Signature of an attribute
© S. Bouchenak, V.Marangozova
AOP - AspectJ
40
Pointcut :
Method Signature
Pointcut : Type Signature
Signature
Types associés
Signature
Account
Type (classe / interface) called Account
*Account
Type whose name ends with Account, e.g SavingsAccount,
CheckingAccount
java.*.Date
Type Date in a direct subpackage of the package java, e.g
java.util.Date, java.sql.Date
java..Date
All types Date in the package java or in a subpackage (direct or
indirect subpackage of the java package)
java.util.List+
Type inheriting the java.util.List interface (implementing)
© S. Bouchenak, V.Marangozova
AOP - AspectJ
41
Pointcut :
Constructor Signature
Signature
Methods associées
public void
Collection.clear()
public method clear() of the Collection class, method with no
parameters returning void
public void
Account.set*(*)
Each public method of the Account class, whose name starts with
set and returning void (no constraint on the parameters)
* Account.*()
Each method of the class Account, no parameters, whatever the
returning type, whatever its access mode
public void
Account.*(..)
All public methods of the class Account, returning void
* *.*(..) throws
RemoteException
All methods raising exception of type RemoteException
© S. Bouchenak, V.Marangozova
Whatever the name, whatever the parameters
AOP - AspectJ
42
Pointcut :
Attribute Signature
Constructors associés
Signature
Attributes associés
public
Account.new()
public constructor of the class Account, no parameters
private float
Account.balance
The private attribute balance of the class Account
public
Account.new(int)
public constructor of the class Account, one int parameter
* Account.*
All Account attributes, whatever its type, name or access mode
public
Account.new(..)
All constructors of the class Account, whatever the parameters
public static *
banking..*.*
All public static attributes of a class in the banking package or in
one of the subpackages
public Account
+.new(..)
All constructors of the Account class or of one if its subclasses
* *.*
All attributes of all classes
© S. Bouchenak, V.Marangozova
AOP - AspectJ
43
© S. Bouchenak, V.Marangozova
AOP - AspectJ
44
Pointcut Operators
!
Unary Operator : !
!
public !final *.*
All public and non final attributes
!Vector
All types different from Vector
!
pointcut Type
Example
public pointcut printCall() : call ( void Communicator.print(..) )
Binary Operators : && (et) || (ou)
Vector ||
Hashtable
pointcut type
pointcut name
keyword
access mode
Type Vector or Hashtable
!
java.util.RandomA All type implementing both interfaces
ccess+ &&
java.util.List
pointcut type
%
%
%
© S. Bouchenak, V.Marangozova
AOP - AspectJ
45
Types de pointcuts
method, constructor call
method, constructor execution
Access to an attribute (read/write)
© S. Bouchenak, V.Marangozova
AOP - AspectJ
46
Call vs. Execution (1 / 5)
!
Pointcut Type
signature
Example
Syntaxe
method call
call(signature_method)
method execution
execution(signature_method)
constructor call
call(signature_constructor)
constructor execution
execution(signature_constructor)
classe initialization
staticinitialization(signature_type)
Read access of an attribute
get(signature_attribute)
write access of an attribute
set(signature_attribute)
Traitant d’exception
handler(signature_type)
public class Account {
float balance;
void credit(float amount) {
execution
this.balance += amount;
}
}
public class Test {
public static void main(String[] args) {
Account account = new Account();
call
accout.credit(100);
}
}
© S. Bouchenak, V.Marangozova
AOP - AspectJ
47
© S. Bouchenak, V.Marangozova
AOP - AspectJ
48
Call vs. Execution (2 / 5)
!
Call vs. Execution (3 / 5)
Aspect using the call
!
public class Account {
float balance;
public aspect AutoLogAspect_Call {
pointcut creditMethodCall() : call (* Account.credit(..));
void credit(float amount) {
before() : creditMethodCall() {
…
Logger.entering(className, methodName);
}
}
this.balance += amount;
}
public class Test {
public static void main(String[] args) {
Account account = new Account();
Logger.entering("Account", "credit(float)");
accout.credit(100);
}
}
}
© S. Bouchenak, V.Marangozova
AOP - AspectJ
49
Call vs. Execution (4 / 5)
!
Application de l’AutoLogAspect_Call
© S. Bouchenak, V.Marangozova
AOP - AspectJ
50
Call vs. Execution (5 / 5)
Aspect using execution
!
Application de l’AutoLogAspect_Execution
public class Account {
float balance;
public aspect AutoLogAspect_Execution {
pointcut creditMethodExecution() : execution (* Account.credit(..));
void credit(float amount) {
Logger.entering("Account", "credit(float)");
this.balance += amount;
}
before() : creditMethodExecution() {
…
Logger.entering(className, methodName);
}
}
public class Test {
public static void main(String[] args) {
Account account = new Account();
}
accout.credit(100);
}
}
© S. Bouchenak, V.Marangozova
AOP - AspectJ
51
© S. Bouchenak, V.Marangozova
AOP - AspectJ
52
Control Flow Pointcuts
Pointcut
cflow / cflowbelow
!
Description
cflow(call
(* Account.credit(..)))
All join points in the control flow of the method credit of the
Account class, including the call of the method
cflowbelow(call
(* Account.credit(..)))
All join points in the control flow of the method credit of the
Account class, without the call of the method
cflow(
creditMethodCall())
All join points in the control flow of the pointcut creditMethodCall
cflowbelow(execution
(* Account.new(..)))
All join points in the control flow of a cnstructor of the class
Account, without the execution of the constructor itself
Example
public class Test {
public static void main(String[] args) {
Account account = new Account();
accout.credit(100);
© S. Bouchenak, V.Marangozova
AOP - AspectJ
53
}
}
© S. Bouchenak, V.Marangozova
AOP - AspectJ
54
cflow / cflowbelow :
cflow / cflowbelow
public class Account {
int
id;
// account id
Database database; // associated database
public class Database {
float getBalance() {
float query(String sqlQuery) {
return database.query("SELECT balance FROM accounts WHERE id=" + id);
… lecture de la base de données
}
}
void setBalance(float b) {
void update(String sqlQuery) {
database.update("UPDATE accounts SET balance="+b+" WHERE id=" + id);
… écriture dans la base de données
}
}
void credit(float amount) {
}
setBalance(getBalance() + amount);
}
}
© S. Bouchenak, V.Marangozova
AOP - AspectJ
55
© S. Bouchenak, V.Marangozova
AOP - AspectJ
56
cflow / cflowbelow
!
cflow
Flot de contrôle à l’appel de la method credit
!
Test.main
Aspect utilisant le cflow
public aspect AutoLogAspect_CallF {
pointcut creditMethodCallF() : cflow( call (* Account.credit(..)) );
new
Account
Account.credit
Account.getBalance
before() : creditMethodCallF() {
System.out.println("Hello!");
}
Account.setBalance
}
Database.query
© S. Bouchenak, V.Marangozova
Database.update
AOP - AspectJ
57
cflow : important…
!
!
Test.main
Account.setBalance
Database.query
© S. Bouchenak, V.Marangozova
58
Example
public class Test {
public static void main(String[] args) {
Account account = new Account();
System.out.println("Hello!");
accout.credit(100);
}
}
Account.credit
Account.getBalance
AOP - AspectJ
cflow : mais encore…
cflow( call(* Account.credit(..)) )
new
Account
© S. Bouchenak, V.Marangozova
Database.update
AOP - AspectJ
59
© S. Bouchenak, V.Marangozova
AOP - AspectJ
60
cflow : mais encore…
cflowbelow
!
public class Account {
int
id;
// account id
Database database; // associated database
float getBalance() {
System.out.println("Hello!");
return database.query("SELECT balance FROM accounts WHERE id=" + id);
Aspect utilisant le cflowbelow
public aspect AutoLogAspect_CallFB {
pointcut creditMethodCallFB() : cflowbelow( call (* Account.credit(..)) );
}
before() : creditMethodCallFB() {
System.out.println("Hello!");
}
void setBalance(float b) {
System.out.println("Hello!");
database.update("UPDATE accounts SET balance="+b+" WHERE id=" + id);
}
}
void credit(float amount) {
System.out.println("Hello!");
setBalance(getBalance() + amount);
}
}
© S. Bouchenak, V.Marangozova
AOP - AspectJ
61
cflowbelow : mais encore…
!
!
Test.main
Account.setBalance
Database.query
© S. Bouchenak, V.Marangozova
62
Example
public class Test {
public static void main(String[] args) {
Account account = new Account();
System.out.println("Hello!");
accout.credit(100);
}
}
Account.credit
Account.getBalance
AOP - AspectJ
cflowbelow
cflowbelow( call(* Account.credit(..)) )
new
Account
© S. Bouchenak, V.Marangozova
Database.update
AOP - AspectJ
63
© S. Bouchenak, V.Marangozova
AOP - AspectJ
64
Pointcuts related to the lexical
structure
cflowbelow : mais encore…
public class Account {
int
id;
// account id
Database database; // associated database
Pointcut
Description
float getBalance() {
System.out.println("Hello!");
return database.query("SELECT balance FROM accounts WHERE id=" + id);
within(Account)
All join point in the class Account
}
within(Account+)
All join point in the class Account and in its subclasses
withincode(*
Account.credit(..))
All join points in the method credit of the class Account
void setBalance(float b) {
System.out.println("Hello!");
database.update("UPDATE accounts SET balance="+b+" WHERE id=" + id);
}
void credit(float amount) {
System.out.println("Hello!");
setBalance(getBalance() + amount);
}
}
© S. Bouchenak, V.Marangozova
AOP - AspectJ
65
Aspect with execution
Pointcut
pointcut methodExecution() : execution (* Account.*(..))
&& within(banking..*);
target(Account)
Every join point where the object on which the method is called is
instance of Account or of one of its subclasses. Pointcut used in
combination with call
!
}
!
67
Description
Every join point where this is instance of the Account class or of
one of its subclasses ( during a method call or the access of appel
de method ou accès à l’attribute d’un objet Account). This pointcut
is used in combination with execution
before() : methodExecution() {
…
Logger.entering(className, methodName);
}
AOP - AspectJ
66
this(Account)
public aspect AutoLogAspect_Execution {
© S. Bouchenak, V.Marangozova
AOP - AspectJ
Pointcuts related to the
execution object
Example with within
!
© S. Bouchenak, V.Marangozova
this(Type) or this(ObjectIdentifier)
target(Type) or target(ObjectIdentifier)
© S. Bouchenak, V.Marangozova
AOP - AspectJ
68
Pointcuts arguments
Advice
!
Advice :
!
Pointcut
args(String,..,int)
Description
!
Syntax of an advice
All join points of all the methods where the first argument is of type
String and the last of type int.
specification_advice([args]) : nom_pointcut([args}) {
… advice body
}
!
!
Code to execute at a join point
args(Type or ObjectIdentifier,..)
Example
before () : printCall () {
… advice body
}
pointcut name
specification d’advice
© S. Bouchenak, V.Marangozova
AOP - AspectJ
69
Advice : Syntax
!
© S. Bouchenak, V.Marangozova
70
Types of advice
Syntaxe d’un advice
!
specification_advice([args]) : definition_pointcut {
… advice body
}
!
AOP - AspectJ
Advice before
!
!
Example
executes before the join point
Advice after
!
executes after join point
before () : call ( void Communicator.print(..) ) {
!
… corps de l’advice
}
Advice around
!
signature
surrounds the execution of the join point
pointcut type
specification d’advice
© S. Bouchenak, V.Marangozova
AOP - AspectJ
71
© S. Bouchenak, V.Marangozova
AOP - AspectJ
72
Advice before
!
Advice after
Example
!
Termination (normal or exception)
after () : call ( * Account.*(..)) {
before () : call ( * Account.*(..)) {
}
!
!
If the adfice raises an exception, the ethod is not executed
Normal termination
}
!
Examples
!
after() throwing () : call ( * Account.*(..)) {
}
AOP - AspectJ
73
Replace a treatment
© S. Bouchenak, V.Marangozova
!
around () : call ( void Account.credit(float)) {
… new implementation of the method
AOP - AspectJ
74
Parameter passing
before (Account account , float amount ) :
}
!
… trace the exception
Context Passing between a
join point and the advice (1 / 3)
Advice around
!
…
Termination with an exception
Tracing, authentification, etc.
© S. Bouchenak, V.Marangozova
… trace all terminations
after() returning () : call ( * Account.*(..)) {
Particlular case
!
!
}
… authentify the user
Surround a treatment
call ( * Account.credit(float)) && target( account ) && args( amount ) {
around (Account acount, float amount) :
call ( * Account.credit(float)) && target(account) && args(amount) {
System.out.println("Crediting from " + account + " value " + amount );
}
… trace the beginning of the method execution
proceed(account, amount); //go on with the method execution
… trace the end of the method execution
}
© S. Bouchenak, V.Marangozova
AOP - AspectJ
75
© S. Bouchenak, V.Marangozova
AOP - AspectJ
76
Context Passing between a
join point and the advice (2 / 3)
!
Get the result
Context Passing between a
join point and the advice (3 / 3)
!
after returning (Object object ) :
Get the exception
after throwing (RemoteException except ) :
call ( Object Account.*(..)) {
call ( * Account.*(..) throws RemoteException ) {
System.out.println("Result " + object );
System.out.println("Exception " + except );
}
}
© S. Bouchenak, V.Marangozova
AOP - AspectJ
77
Outline
AOP - AspectJ
78
AspectJ Compiler
1.
Introduction to l’AOP
2.
Introduction to AspectJ
3.
Syntax of AspectJ
4.
Software Development with AspectJ
5.
Conclusion and Refs
© S. Bouchenak, V.Marangozova
© S. Bouchenak, V.Marangozova
!
ajc commande
classes and
aspects Java
(.java)
AOP - AspectJ
compiler
AspectJ
(ajc)
final system
(.class ou .jar)
library (.jar)
79
© S. Bouchenak, V.Marangozova
AOP - AspectJ
80
Browser AspectJ (ajbrowser)
AOP in few words
!
© S. Bouchenak, V.Marangozova
AOP - AspectJ
81
Web
AOP : what for?
!
EXtend an existing system so as to integrate new
treatments
!
Modular design of a system composed of multiple
aspects (application and management)
© S. Bouchenak, V.Marangozova
AOP - AspectJ
82
Bibliography
!
Aspect-Oriented Programming, Kiczales et. al., ECOOP’1997
!
An Overview of AspectJ, Kiczales et. al., ECOOP’2001
!
Getting Started with AspectJ, Kiczales et. al., CACM 44(10), Oct.
2001
AOP in C, C++
http://www.aspectc.org/
!
Aspect-Oriented Programming with AspectJ, Ivan Kiselev, SAMS
2002
Google is your friend :)
!
Mastering AspectJ: Aspect-Oriented Programming in Java,
Joseph D. Gradecki, Nicholas Lesiecki, John Wiley & Sons 2003
!
AspectJ in Action, R. Laddad, Manning, 2003.
!
AOP
http://aosd.net
!
AspectJ
http://aspectj.org
!
!
© S. Bouchenak, V.Marangozova
AOP - AspectJ
83
© S. Bouchenak, V.Marangozova
AOP - AspectJ
84