Aspectj Tutorial

download Aspectj Tutorial

of 101

Transcript of Aspectj Tutorial

  • 8/11/2019 Aspectj Tutorial

    1/101

    1

    AspectJ Tutorial1

    Aspect-Oriented Programmingwith AspectJ

    the AspectJ.org team

    Xerox PARC

    Bill Griswold, Erik Hilsdale, Jim Hugunin,

    Mik Kersten, Gregor Kiczales, Jeffrey Palm

    partially funded by DARPA under contract F30602-97-C0246

    this tutorial is about...

    using AOP and AspectJ to: improve the modularity of crosscutting concerns

    design modularity

    source code modularity

    development process

    aspects are two things: concerns that crosscut [design level]

    a programming construct [implementation level]

    enables crosscutting concernsto be captured in modular units

    AspectJ is: is an aspect-oriented extension to Java that supports

    general-purpose aspect-oriented programming

  • 8/11/2019 Aspectj Tutorial

    2/101

    2

    problems like

    where is logging in org.apache.tomcat red shows lines of code that handle logging

    not in just one place

    not even in a small number of places

    logging is not modularized

    problems like

    /**= ================== =================== =================== ===========**TheApacheSoftwareLicense,Version1.1**Copyright(c)1999TheApacheSoftwareFoundation.Allrights*reserved.**Redistributionanduseinsourceandbinaryforms,withorwithout*modification,arepermittedprovidedthatthefollowingconditions*aremet:**1.Redistributionsofsourcecodemustretaintheabovecopyright* notice,thislistofconditionsandthefollowingdisclaimer.**2.Redistributionsinbinaryformmustreproducetheabovecopyright* notice,thislistofconditionsandthefollowingdisclaimer in* thedocumentationand/orothermaterialsprovidedwiththe* distribution.**3.Theend-userdocumentationincludedwiththeredistribution,if* any,mustincludethefollowingacknowlegement:* "Thisproductincludessoftwaredevelopedbythe* ApacheSoftwareFoundation(http://www.apache.org/)."* Alternately,thisacknowlegementmayappearinthesoftware

    itself,* ifandwhereversuchthird-partyacknowlegementsnormallyappear.**4.The names"TheJakartaProject","Tomcat",and"ApacheSoftware* Foundation"mustnotbeusedtoendorseorpromoteproducts

    derived* fromthissoftwarewithoutpriorwrittenpermission.Forwritten* permission,[email protected].**5.Productsderivedfromthissoftwaremaynotbecalled"Apache"* normay"Apache"appearintheirnameswithoutpriorwritten* permissionoftheApacheGroup.**THISSOFTWAREISPROVIDED ASIS''ANDANYEXPRESSEDORIMPLIED*WARRANTIES,INCLUDING,BUTNOTLIMITEDTO,THEIMPLIEDWARRANTIES*OFMERCHANTABILITYANDFITNESSFORAPARTICULARPURPOSEARE*DISCLAIMED.INNOEVENTSHALLTHEAPACHESOFTWAREFOUNDATIONOR*ITSCONTRIBUTORSBELIABLEFORANYDIRECT,INDIRECT,INCIDENTAL,*SPECIAL,EXEMPLARY,ORCONSEQUENTIALDAMAGES(INCLUDING,BUTNOT*LIMITEDTO,PROCUREMENTOFSUBSTITUTEGOODSORSERVICES;LOSSOF*USE,DATA,ORPROFITS;ORBUSINESSINTERRUPTION)HOWEVERCAUSEDAND*ONANYTHEORYOFLIABILITY,WHETHERINCONTRACT,STRICTLIABILITY,*ORTORT(INCLUDINGNEGLIGENCEOROTHERWISE)ARISINGINANYWAYOUT*OFTHEUSEOF THISSOFTWARE,EVENIFADVISEDOFTHEPOSSIBILITYOF*SUCH DAMAGE.*= ================== =================== =================== ===========**Thissoftwareconsistsof voluntarycontributionsmadebymany*individualsonbehalfoftheApacheSoftwareFoundation.Formore*informationontheApacheSoftwareFoundation,pleasesee*.**[Additionalnotices,ifrequiredbypriorlicensingconditions]**/

    packageorg.apache.tomcat.session;importorg.apache. tomcat.core.*;importorg.apache.tomcat.util.StringManager;importjava.io.*;importjava.net.*;importjava.u til.*;importjavax.servlet.*;importjavax.servlet.http.*;

    /***Coreimplementationofanapplicationlevelsession**@authorJamesDuncanDavidson[[email protected]]*@authorJasonHunter[[email protected]]*@author JamesTodd [[email protected]]*/

    publicclassApplicationSessionimplementsHttpSession{privateStringManagersm=

    StringManager.getManager( "org.apache.tom cat.session");privateHashtablevalues=newHashtable();privateStringid;privateServerSessionserverSession;privateContextcontext;privatelongcreationTime=System.currentTimeMillis();;privatelongthisAccessTime=creationTime;privatelonglastAccessed=creationTime;privateintinactiveInterval= -1;privatebooleanvalid=true;ApplicationSession(Stringid,ServerSessionserverSession,

    Contextcontext){this.serverSession=serverSession;this.context=co ntext;this.id=id;this.inactiveInterval=context.getSessionTimeOut();

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

    }}ServerSessiongetServerSession() {

    returnserverSession;}

    /***Calledbycontextwhenrequestcomesinsothataccessesand*inactivitiescanbedealtwithaccordingly.*/

    voidaccessed(){//setlastaccessedtothisAccessTimeasitwillbeleftover//fromthepreviousaccesslastAccessed= thisAccessTime ;thisAccessTime= System.currentTimeMillis( );

    validate();}voidvalidate(){

    //ifwehavean inactiveinterval,checktoseeifwe'veexceededitif(inactiveInterval!=-1){intthisInterval=

    (int)(System. currentTimeMillis( )-lastAccessed)/1000;if (thisInterval>inactiveInterval){

    invalidate();}

    }}//HTTPSESSIONIMPLEMENTATIONMETHODS

    publicStringgetId(){if(valid){returnid;}else{Stringmsg=sm.getString("applicationSession.session.ise");

    throw newIllegalStat eException(m sg);}

    }publiclonggetCreationTime() {

    if(valid){returncreationTime;

    }else{Stringmsg=sm.getString("applicationSession.session.ise");throw newIllegalStat eException(m sg);

    }}

    /****@deprecated*/

    publicHttpSessionContextgetSessionContext(){returnnewSessionContextImpl();}

    publiclonggetLastAccessedTime(){if(valid){returnlastAccessed;

    }else{Stringmsg=sm.getString("applicationSession.session.ise");

    throw newIllegalStat eException(m sg);}

    }

    publicvoidinvalidate(){serverSession.removeApplicationSession (context);

    //removeeverythinginthesessionEnumeration enum= values.keys();

    while(enum.hasMoreElements( ) ) {Stringname=(String)enum.nextElement();removeValue(name);

    }valid=false;

    }

    publicbooleanisNew() {if(!valid){Stringmsg=sm.getString("applicationSession.session.ise");throw newIllegalStat eException(m sg);

    }

    if(thisAccessTime==creationTime){returntrue;}else{returnfalse;

    }}

    /***@deprecated*/

    publicvoidputValue(Stringname,Objectvalue){setAttribute(name, value);}

    publicvoidsetAttribute(Stringname,Objectvalue){if(!valid){Stringmsg=sm.getString("applicationSession.session.ise");throw newIllegalStat eException(m sg);

    }

    if(name==null){Stringmsg=sm.getString("applicationSession.value.iae");throw newIllegalArgumentE xception (msg);

    }

    removeValue(name);//removeanyexistingbinding

    if(value!=null&&valueinstanceofHttpSessionBindingListener){HttpSessionBindingEvente=newHttpS essionBindingEvent(this,name );

    ((HttpSessionBindingListener)value).valueBound(e);}values.put(name,value);

    }

    /***@deprecated*/publicObjectgetValue(Stringname){returngetAttribute (name);

    }

    publicObjectgetAttribute(Stringname){if(!valid){Stringmsg=sm.getString("applicationSession.session.ise");

    throw newIllegalStat eException(m sg);}

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

    throw newIllegalArgumentE xception (msg);}

    returnvalues.get(name);}

    /***@deprecated*/

    publicString[]getValueNames(){Enumeratione =getAttributeNames();Vectornames=newVector();

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

    }String[ ]valueNames=n ewString[names. size()];

    names.copyInto(valueNames);

    returnvalueNames ;}

    publicEnumerationgetAttributeNames(){if(!valid){Stringmsg=sm.getString("applicationSession.session.ise");throw newIllegalStat eException(m sg);

    }

    HashtablevaluesClone= (Hashtable)values.clone();return(Enumeration)valuesClone.keys();

    }

    /***@deprecated*/

    publicvoidremoveValue(Stringname){removeAttribute(name);

    }publicvoidremoveAttribute(Stringname){

    if(!valid){Stringmsg=sm.getString("applicationSession.session.ise");

    throw newIllegalStat eException(m sg);}if(name==null){Stringmsg=sm.getString("applicationSession.value.iae");

    throw newIllegalArgumentE xception (msg);}Objecto =values.get(name);

    if(oinstanceofHttpSessionBindingListener) {HttpSessionBindingEvente=

    newHttpS essionBindingEvent(this,name );((HttpSessionBindingListener)o).valueUnbound (e);

    }

    values.remo ve(name);}

    publicvoidsetMaxInactiveInterval(intinterval){if(!valid){Stringmsg=sm.getString("applicationSession.session.ise");

    throw newIllegalStat eException(m sg);}

    inactiveInterval =interval;}

    publicintgetMaxInactiveInterval(){if(!valid){Stringmsg=sm.getString("applicationSession.session.ise");

    throw newIllegalStat eException(m sg);}returninactiveInt erval;

    }}

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

    ApplicationSessionpackageorg.apache.tomcat.session;

    importjava.io.IOException;importjava.io.ObjectInputStream ;importjava.io.ObjectOutputStream;importjava.io.Serializable;importjava.util. Enumeration;importjava.util.Hashtable;importjava.util .Vector;importjavax.servlet.ServletException ;importjavax.servlet.http.HttpSession;importjavax.servlet.http.HttpSessionBindingEvent ;importjavax.servlet.http.HttpSessionBindingListener;importjavax.servlet.http.HttpSessionContext ;importorg.apache.tomcat.catalina.*;importorg.apache.tomcat.util.StringManager;

    /***Standard implementationof theSession

    interface.Thisobjectis*serializable,sothatitcan bestoredinpersistentstorageortransferred*toadifferentJVMfordistributablesession

    support.* < p > *IMPLEMENTATIONNOTE:An instanceofthis

    classrepresentsboththe*internal(Session)andapplicationlevel(HttpSession)viewofthesession.*However,becausetheclassitselfisnotdeclared

    public,Javalogicoutside*of theorg.apache .tomcat.session

    packagecannotcastan*HttpSessionviewofthisinstancebacktoaSessionview.**@authorCraigR.McClanahan*@version$Revision:1.2$$Date:2000/05/15

    17:54:10$*/

    finalclassStandardSessionimplementsHttpSession,Session{

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

    /***ConstructanewSessionassociatedwiththespecifiedManager.**@parammanagerThemanagerwithwhichthis

    Sessionisassociated*/

    publicStandardSession(Managermanager){super();this.manager=man ager;

    }

    //--------------- --------------------- -----------------InstanceVariables

    /***ThecollectionofuserdataattributesassociatedwiththisSession.

    */privateHashtableattributes=newHashtable();

    /***Thetimethissessionwascreated,in

    millisecondssincemidnight,*January1, 1970GMT.*/

    privatelongcreationTime= 0L;

    /***ThesessionidentifierofthisSession.*/

    privateStringid=null;

    /***Descriptiveinformationdescribingthis

    Sessionimplementation.*/privatestaticfinalStringinfo=

    "StandardSession/1.0";

    /***ThelastaccessedtimeforthisSession.*/

    privatelonglastAccessedTime=creationTime;

    /***TheManagerwithwhichthisSessionisassociated.*/

    privateManagermanager=null;

    /***Themaximumtimeinterval,inseconds,betweenclientreques tsbefore

    *theservletcontainermay invalidatethissession.Anegativetime

    *indicatesthatthesessionshouldnevertimeout.*/privateintmaxInactiveInterval= -1;

    /***Flagindicatingwhetherthissessionisnewornot.*/

    privatebooleanisNew=true;

    /***Flagindicatingwhetherthissessionisvalidornot.

    */privatebooleanisValid=false;

    /***Thestringmanagerforthispackage.*/

    privateStringManagersm=

    StringManager.getManager("org.apache .tomcat.session");

    /***TheHTTPsessioncontextassociatedwiththis

    session.*/privatestaticHttpSessionContextsessionContext

    =null;

    /***Thecurrentaccessedtimeforthissession.*/

    privatelongthisAccessedTime=creationTime;

    //--------------- --------------------- -----------------SessionProperties

    /***Setthecreationtimeforthissession.Thismethodiscalledbythe

    *ManagerwhenanexistingSessioninstanceisreused.

    **@paramtimeThenewcreationtime*/

    publicvoidsetCreationTime(longtime){

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

    }

    /***Returnthesessionidentifierforthissession.*/

    publicStringgetId(){

    return(this.id);}

    /***Setthesessionidentifierforthissession.**@paramidThenewsessionidentifier*/

    publicvoidsetId(Stringid){

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

    this.id=id;

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

    }

    /***Returndescrip tiveinformation aboutthisSessionimplementationand

    *thecorrespondingversionnumber,intheformat

    */.*/

    publicStringgetInfo(){

    return(this.info);

    }

    /***Returnthelasttimetheclientsentarequest

    associatedwit hthis*session,asthenumberofmillisecondssincemidnight,January1,1970*GMT.Actionsthatyourapplicationtakes,

    suchasgettingorsetting*avalueassociatedwiththesession,donot

    affecttheaccesstime.*/publiclonggetLastAccessedTime(){

    return(this.lastAccessedTime );

    }

    /***ReturntheManagerwithinwhichthisSession

    isvalid.*/

    publicManagergetManager() {return(this.manager);

    }

    /***SettheManagerwithinwhichthisSessionis

    valid.**@parammanagerThenewManager*/publicvoidsetManager(Managermanager){

    this.manager=man ager;

    }

    /***Returnthemaximumtimeinterval,inseconds,

    betweenclientrequests*beforetheservletcontainerwillinvalidate

    thesession.Anegative*timeindicatesthatthesessionshouldnevertimeout.

    **@exception IllegalStateException ifthis

    methodiscalledon*aninvalidatedsession*/

    publicintgetMaxInactiveInterval(){

    return(this.maxInactiveInterval);

    }

    /***Setthemaximumtimeinterval,inseconds,

    betweenclientrequests*beforetheservletcontainerwillinvalidatethesession.Anegative*timeindicatesthatthesessionshouldnever

    timeout.**@paramintervalThenewmaximuminterval*/publicvoidsetMaxInactiveInterval(intinterval)

    {

    this.maxInactiveInterval =interval;

    }

    /***ReturntheHttpSessionforwhichthis

    object*isthefacade.*/

    publicHttpSessiongetSession(){

    return((HttpSession)this);

    }

    //-------------- ------------------------ -----------SessionPublicMethods

    /***Updatetheaccessedtimeinformationforthissession.

    Thismethod*shouldbecalledbythecontextwhenarequestcomesin

    foraparticular*session,eveniftheapplicationdoesnotreferenceit.*/

    publicvoidaccess(){

    this.lastAccessedTime =this.thisAccessedTime;this.thisAccessedTime =System. currentTimeMillis( );this.isNew=false;}

    /***Performtheinternalprocessingrequiredtoinvalidate

    thissession,*withouttriggeringanexceptionifthesessionhasalreadyexpired.

    */publicvoidexpire(){

    //Removethissessionfromourmanager'sactivesessionsif((manager!=null)&&(managerinstanceof

    ManagerBase))((ManagerBase)manager).remove(this);

    //UnbindanyobjectsassociatedwiththissessionVectorresults=newVector();Enumerationattrs=getAttributeNames();

    while(attrs.hasMoreElements()) {Stringattr=(String)attrs.nextElement();results.addElement(attr);

    }Enumerationnames=results.elements();while(names.hasMoreElements()) {

    Stringname=(String)names.nextElement();removeAttribute (name);

    }//MarkthissessionasinvalidsetValid(false);

    }

    /***Releaseallobjectreferences,andinitializeinstance

    variables,in*preparationforreuseofthisobject.*/

    publicvoidrecycle(){//Resettheinstancevariablesassociatedwiththis

    Sessionattributes.clear();creationTime= 0L;id=null;lastAccessedTime= 0L;

    manager=null;maxInactiveInterval= -1;isNew=true;isValid=false;//TellourManagerthatthisSessionhasbeenrecycledif((manager!=null)&&(managerinstanceof

    ManagerBase))((ManagerBase)manager).recycle(this);

    }

    //------------ -------------------- ---------------- SessionPackage Methods

    /***ReturntheisValidflagforthissession.*/

    booleanisValid() {

    return(this.isValid);}

    /***SettheisNewflagforthissession.**@paramisNewThenewvaluefortheisNew

    flag*/

    voidsetNew(booleanisNew){this.isNew=isNew;

    }

    /***SettheisValidflagforthissession.**@paramisValidThenewvalueforthe

    isValidflag*/

    voidsetValid(booleanisValid){this.isValid= isValid;

    }

    //-------------- ------------------------ -----------HttpSessionProperties

    /***Returnthetimewhenthissessionwascreated,in

    millisecondssince*midnight,January 1,1970GMT.**@exceptionIllegalStateExceptionifthismethodis

    calledonan* invalidatedsession*/publiclonggetCreationTime() {

    return(this.creationTime);

    }

    /***Returnthesessioncontextwithwhichthissessionis

    associated.**@deprecatedAsofVersion2.1,thismethodisdeprecatedandhasno* replacement. Itwillberemovedinafutureversionof

    the*Java ServletAPI.*/

    publicHttpSessionContextgetSessionContext(){if(sessionContext==null)sessionContext=newStandardSessionContext();

    return(sessionContext);

    }

    //------------- --------------------- ------------HttpSessionPublicMethods

    /***Returntheobjectboundwiththespecifiednameinthis

    session,or*nullifnoobjectisboundwiththatname.**@paramnameNameoftheattributetobereturned**@exceptionIllegalStateExceptionifthismethodis

    calledonan* invalidatedsession*/

    publicObjectgetAttribute(Stringname){return (attributes.get(name ));

    }

    /***ReturnanEnumerationof

    Stringobjects*containingthenamesoftheobjectsboundtothis

    session.**@exceptionIllegalStateExceptionifthismethodis

    calledonan* invalidatedsession

    */publicEnumerationgetAttributeNames(){return(attributes.keys());

    }

    /***Returntheobjectboundwiththespecifiednameinthissession,or

    *nullifnoobjectisboundwiththatname.**@paramnameNameofthevaluetobereturned**@exceptionIllegalStateExceptionifthismethodis

    calledonan* invalidatedsession**@deprecatedAsofVersion2.2,thismethodisreplaced

    by *getAttribute()*/

    publicObjectgetValue(Stringname){

    return(getAttribute(name));}

    /***Returnthesetofnamesofobjectsboundtothis

    session. Ifthere*arenosuchobjects,azero-lengtharrayisreturned.**@exceptionIllegalStateExceptionifthismethodis

    calledonan* invalidatedsession**@deprecatedAsofVersion2.2,thismethodisreplaced

    by*getAttributeNames()*/

    publicString[]getValueNames(){Vectorresults=newVector();Enumerationattrs=getAttributeNames();

    while(attrs.hasMoreElements()) {Stringattr=(String)attrs.nextElement();results.addElement(attr);

    }Stringnames[]= newString[results.size()];for(inti=0;i,thecont ainercalls*valueBound()ontheobject.**@paramnameNametowhichtheobjectisbound,cannotbenull*@paramvalueObjecttobebound,cannotbenull**@exceptionIllegalStateExceptionifthismethodiscalledonan* invalidatedsession**@deprecatedAsofVersion2.2,thismethodisreplacedby*setAttribute()*/

    publicvoidputValue(Stringname,Objectvalue){

    setAttribute(name, value);

    }

    /***Removetheobjectboundwiththespecifiednamefromthissession.If*thesessiondoesnothaveanobjectboundwiththisname,thismethod*doesnothing.*

    *Afterthismethodexecutes,andiftheobjectimplements*HttpSessionBindingListene r< /code>,thecont ainercalls*valueUnbound ()ontheo bject.**@paramnameNameoftheobjecttoremovefromthissession.**@exceptionIllegalStateExceptionifthismethodiscalledonan* invalidatedsession*/

    publicvoidremoveAttribute(Stringname){synchronized(attributes){Objectobject= attributes.get (name);if(object==null)

    return;attributes.remove(n ame);// System.out.println("Removingattribute"+name);if(object instanceof HttpSessionBindingListener){

    ((HttpSessionBindingListener) object).valueUnbound(newHttpSessionBindi ngEvent((HttpSession)this,name));

    }}

    }

    /***Removetheobjectboundwiththespecifiednamefromthissession.If*thesessiondoesnothaveanobjectboundwiththisname,thismethod*doesnothing.*

    *Afterthismethodexecutes,andiftheobjectimplements*HttpSessionBindingListene r< /code>,thecont ainercalls*valueUnbound ()ontheo bject.**@paramnameNameoftheobjecttoremovefromthissession.**@exceptionIllegalStateExceptionifthismethodiscalledonan* invalidatedsession**@deprecatedAsofVersion2.2,thismethodisreplacedby*removeAttribute()*/

    publicvoidremoveValue(Stringname){

    removeAttribute(name);}

    /***Bindanobjecttothissession,usingthespecifiedname.Ifanobject*ofthesamenameisalreadyboundtothissession,theobjectis*replaced.*

    *Afterthismethodexecutes,andiftheobjectimplements*HttpSessionBindingListene r< /code>,thecont ainercalls*valueBound()ontheobject.**@paramnameNametowhichtheobjectisbound,cannotbenull*@paramvalueObjecttobebound,cannotbenull**@exceptionIllegalArgumentExceptionifanattemptismadetoadda* n o n-serializableobjectinanenvironmentmarkeddistributable.*@exceptionIllegalStateExceptionifthismethodiscalledonan* invalidatedsession*/

    publicvoidsetAttribute(Stringname,Objectvalue){

    if((manager!=null)&&manager.getDistributable()&&!(valueinstanceof Serializable ))throw newIllegalArgument Exception

    (sm.getString("standardSession.setAttribute.iae"));

    synchronized(attributes){removeAttribute (name);attributes.put(name,value);if(valueinstanceofHttpSessionBindingListener)

    ((HttpSessionBindingListener )value). valueBound(newHttpSessionBindi ngEvent((HttpSession)this,name));

    }

    }

    //--------------- ----------------------- ------ HttpSessionP rivateMethods

    /***Readaserializedversionofthissessionobjectfromthespecified*objectinput stream.*

    *IMPLEMENTATIONNOTE:ThereferencetotheowningManager*isnotrestoredbythismethod,andmustbesetexplicitly.**@paramstreamTheinputstreamtoreadfrom**@exceptionC lassNotFoun dExceptionif anunknownclass isspecified*@exceptionIOExceptio nif aninput/output erroroccurs*/

    privatevoidreadObject(ObjectInpu tStreamstream)throwsClassNotFoundException,IOException{

    //Deserializethescalarinstancevariables(exceptManager)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();

    //Deserializetheattributecountandattributevaluesintn=((Integer)stream.readObject()).intValue();for(inti=0;i *LifecycleconfigurationofthiscomponentassumesanXMLnode*inthefollowingformat:** **whereyoucanadjustthefollowingparameters,withdefaultvalues*insquarebrackets:**checkInterval-Theinterval(inseconds)betweenbackground* threadchecksforexpiredsessions.[60]*maxActiveSessions- Themaximumnumberofsessionsallowedto* beactiveatonce,or-1fornolimit.[-1]*maxInactiveInterval -Thedefaultmaximumnumberofsecondsof* inactivitybeforewhichtheserv letcontainerisallowedtotimeout* asession,or-1fornolimit.Thisvalueshouldbeoverriddenfrom* thedefaultsessiontimeoutspecifiedinthewebapplicationdeployment* descriptor,ifany.[- 1]***@authorCraigR.McClanahan*@version$Revision:1.1.1.1$$Date:2000/05/0221:28:30$*/

    publicfinalclassStandardManagerextendsManagerBaseimplementsLifecycle,Runnable{

    //-------------- -------------------- ------------------- InstanceVariables

    /***Theinterval(inseconds)betweenchecksforexpiredsessions.*/

    privateintcheckInterval= 60;

    /***Hasthiscomp onentbeenco nfiguredyet?*/

    privatebooleanconfigured=false;

    /***Thedescrip tiveinformation aboutthis implementation.*/

    privatestaticfinalStringinfo="StandardManager/1.0";

    /***ThemaximumnumberofactiveSessionsallowed,or-1fornolimit.*/

    protectedintmaxActiveSessions= -1;

    /***Thestringmanagerforthispackage.*/

    privateStringManagersm=StringManager.getManager( "org.apache.tom cat.session");

    /***Hasthiscomponentbeenstartedyet?*/

    privatebooleanstarted=false;

    /***Thebackground thread.*/

    privateThreadthread=null;

    /***Thebackgroundthreadcompletionsemaphore.*/

    privatebooleanthreadDone=false;

    /***Nametoregisterforthebackgroundthread.*/

    privateStringthreadName= "StandardManager" ;

    //--------------- ----------------------- ----------------------- Properties

    /***Returnthecheckinterval(inseconds)forthisManager.*/publicintgetCheckInterval() {

    return(this.checkInterval);

    }

    /***Setthecheckinterval(inseconds)forthisManager.**@paramcheckIntervalThenew checkinterval*/publicvoidsetCheckInterval(intcheckInterval){

    this.checkInterval=checkInterval;

    }

    /***ReturndescriptiveinformationaboutthisManagerimplementationand*thecorrespondingversionnumber,intheformat*/.*/publicStringgetInfo(){

    return(this.info);

    }

    /***ReturnthemaximumnumberofactiveSessionsallowed,or-1for*nolimit.*/

    publicintgetMaxActiveSessions(){return(this.maxActiveSessions);

    }

    /***SetthemaximumnumberofactivesSessionsallowed,or-1for*nolimit.**@parammax Thenewmaximumnumberofsessions*/publicvoidsetMaxActiveSessions(intmax){

    this.maxActiveSessions=max;

    }

    //---------- -------------- -------------- -------------- -----PublicMethods

    /***Constructandreturnanewsessionobject,basedonthedefault*settingsspecifiedbythisManager'sproperties.Thesession*idwillbeassignedbythismethod,andavailableviathegetId()*methodofthereturnedsession.Ifa newsessioncannotbecreated*foranyre ason,return null.**@exceptionIllegalStateExceptionif anewsessioncannotbe*instantiatedforanyreason*/

    publicSessioncreateSession (){

    if((maxActiveSessions>=0)&&(sessions.size()>= maxActiveSessions))throw newIllegalState Exception

    (sm.getString("standardManager.createSession.ise"));

    return(super.createSession());

    }

    //---------------- ------------------------ -------------- LifecycleMethod s

    /***Configurethiscomponent,basedonthespecifiedconfiguration*parameters. Thismethodshouldbecalledimmediatelyafterthe*componentinstanceiscreated,andbeforestart()*iscalled.**@paramparametersConfigurationparametersforthiscomponent*(FIXME:Whatobjecttypeshouldthisreallybe?)**@exceptionIllegalStateExceptionif thiscomponenthasalreadybeen*configuredand/orstarted*@exceptionLifecycleExceptionifthiscomponentdetectsafatalerror*intheconfigurationparametersitwasgiven*/

    publicvoidconfigure(Nodeparameters)throwsLifecycleException{

    //Validateandupdateourcurrentcomponentstateif(configured)throw newLifecycleException

    (sm.getString("standardManager.alreadyConfigured"));configured=true;if(parameter s==null)return;

    //Parseandprocessourconfigurationparametersif(!("Manager".equals(parameters.getNodeName ())))return;

    NamedNodeMapattributes=parameters.getAttributes();Nodenode=null;node= attributes.getNamedItem("checkInterval");if(node!=null){try{

    setCheckInterval (Integer.parseInt(node.getNo deValue()));}catch(Throwablet) {

    ; //XXX-Throwexception?}}

    node= attributes.getNamedItem("maxActiveSessions");if(node!=null){try{setMaxActiveSe ssions(Inte ger.parseInt(node.getNodeValue()));}catch(Throwablet) {

    ; //XXX-Throwexception?}

    }node= attributes.getNamedItem("maxInactiveInterval");if(node!=null){try{

    setMaxInacti veInterval(Integer.parseInt(node.getNodeValue()));}catch(Throwablet) {

    ; //XXX-Throwexception?}}

    }

    /***Prepareforthebeginningofactiveuseofthepublicmethodsofthis*component.Thismethodshouldbecalledafterconfigure(),*andbeforeanyofthepublicmethodsofthecomponentareutilized.**@exceptionIllegalStateExceptionif thiscomponenthasnotyetbeen*configured(ifrequiredforthiscomponent)*@exceptionIllegalStateExceptionif thiscomponenthasalreadybeen*started*@exceptionLifecycleExceptionifthiscomponentdetectsafatalerror* thatpreventsthiscomponentfrombeingused*/

    publicvoidstart()throwsLifecycleException {

    //Validateandupdateourcurrentcomponentstateif(!configured)throw newLifecycleException

    (sm.getString("standardManager.notConfigured"));if(started)throw newLifecycleException

    (sm.getString("standardManager.alreadyStarted "));started=true;//StartthebackgroundreaperthreadthreadStart();

    }

    /***Gracefullyterminatetheactiveuseofthepublicmethodsofthis*component.Thismethodshouldbethelastonecalledonagiven*instanceofthi scomponent.**@exceptionIllegalStateExceptionifthiscomponenthasnotbeenstarted*@exceptionIllegalStateExceptionif thiscomponenthasalready* beenstopped*@exceptionLifecycleExceptionifthiscomponentdetectsafatalerror* thatneedstobe reported*/publicvoidstop()throwsLifecycleException{

    //Validateandupdateourcurrentcomponentstateif(!started)throw newLifecycleException

    (sm.getString("standardManager.notStarted"));started=false;

    //StopthebackgroundreaperthreadthreadStop();

    //Expireall activesessionsSessionsessions[]=findSessions();for(inti=0;i *XXX-Atpresent,useofStandardManagerishardcoded,

    *andlifecycleconfigurationisnotsupported.* < p > *IMPLEMENTATIONNOTE:Oncewecommittothenew

    Manager/Session*paradigm,Iwouldsuggestmovingthelogicimplementedherebackinto

    *thecorelevel.TheTomcat.Next"Manager"interfaceactsmorelikea*collectionclass,andhasminimalknowledgeofthedetailedrequest*processingsemanticsofhandlingsessions.* < p >

    *XXX-Atpresent,thereisnoway(viatheSessionManagerinterface)for

    *aContexttotelltheManagerthatwecreatewhatthedefaultsession*timeoutforthiswebapplication(specifiedinthedeployment

    descriptor)*shouldbe.**@authorCraigR.McClanahan

    */

    publicfinalclassStandardSessionManagerimplementsSessionManager{

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

    /***CreateanewSessionManagerthatadaptstothecorresponding

    Manager*implementation.*/

    publicStandardSessionManager(){

    manager=newStandardManager();if(managerinstanceofLifecycle){

    try{((Lifecycle)manager).configure(null);((Lifecycle) manager).start();

    }catch(LifecycleException e){

    thrownewIllegalStateException(""+e);}

    }

    }

    //---------------- -------------------- ----------------- InstanceVariables

    /***TheManagerimplementationweareactuallyusing.*/

    privateManagermanager=null;

    // ----------------------- -------------------------- -------- PublicMethods

    /***Markthespecifiedsession'slastaccessedtime.Thisshouldbe*calledforeachrequestbyaRequestInterceptor.

    **@paramsessionThesessiontobemarked*/

    publicvoidaccessed(Contextctx,Requestreq,Stringid){

    HttpSessionsession=findSession( ctx,id);if(session==null)return;if(sessioninstanceofSession)((Session)sessio n).access();

    //cachetheHttpSession- avoidanotherfindreq.setSession( session);

    }

    //XXXshouldwethrowexceptionorjustreturnnull??publicHttpSessionfindSession(Contextctx,Stringid){

    try{

    Sessionsession=manager.findSession(id);if(session!=null)

    returnsession.getSession();}catch(IOExceptione){

    }return(null);

    }

    publicHttpSessioncreateSession(Contextctx){returnmanager.createSession().getSession();

    }

    /***RemoveallsessionsbecauseourassociatedContextisbeingshut

    down.**@paramctxThecontextthatisbeingshutdown*/

    publicvoidremoveSessions(Contextctx){

    //XXXXXXamanagermaybesharedbymultiple//contexts,wejustwanttoremovethesessionsofctx!

    //Themanagerwillstillrunafterthat(i.e.keepdatabase//connectionopenif(managerinstanceofLifecycle){try{

    ((Lifecycle)manager).stop();}catch(LifecycleException e){

    thrownewIllegalStateException(""+e);}

    }

    }

    /***Usedbycontexttoconfigurethesessionmanager'sinactivity

    timeout.**TheSessionManagermayhavesomedefaultsessiontimeout,the*Contextontheotherhandhasit'stimeoutsetbythedeployment

    *descriptor(web.xml).Thismethodletsthe Contextconforgurethe*sessionmanageraccordingtothisvalue.**@paramminutesThesessioninactivitytimeoutinminutes.

    */publicvoidsetSessionTimeOut(intminutes){

    if(-1!=minutes){//Themanagerworkswithseconds...

    manager.setMaxInactiveInterval(minutes* 60);}

    }}

    ServerSessionManagerpackageorg.apache.tomcat.session;

    importorg.apache.to mcat.util.*;importorg.apache.to mcat.core.*;importjava.io.*;importjava.net.*;importjava.ut il.*;importjavax.servlet.http.*;

    /****@authorJamesDuncanDavidson[ [email protected]]*@authorJasonHunter[[email protected]]*@author JamesTodd [[email protected]]*/

    publicclassServerSessionManagerimplementsSessionManager{

    privateStringManagersm=StringManager.getManager ("org.apache.t omcat.session") ;

    privatestaticServerSessionManagermanager;//=newServerSessionManager();protectedintinactiveInterval=-1;

    static{manager=newServerSessionManager();

    }publicstaticServerSessionManagergetManager(){

    returnmanager;}

    privateHashtablesessions=newHashtable();privateReaperreaper;privateServerSessionManager (){

    reaper= Reaper.getReaper();reaper.setServe rSessionManager(this);reaper.start();

    }publicvoidaccessed(Contextctx, Requestreq,Stringid){

    ApplicationSessionapS=(ApplicationSession)findSession(ctx,id);if(apS==null)return;

    ServerSessionservS =apS.getServerSession();servS.accessed();apS.accessed();

    //cacheit -noneedtocomputeitagainreq.setSession( apS);

    }publicHttpSessioncreateSession(Contextctx){

    StringsessionId=SessionIdGenerator.generateId();ServerSessionsession=newServerSession(sessionId);sessions.put(sessionId,session);if(-1 !=inactiveInterval){session.setMaxInactiveInterval(inactiveInterval) ;

    }returnsession.getApplicationSession( ctx,true);

    }publicHttpSessionfindSession(Contextctx,Stringid){

    ServerSessionsSession=(ServerSession)sessions.get(id);if(sSession==null)return null;

    returnsSession.getApplicationSession(ctx, false);}

    / / X X X//sync'dfor safty-- nootherthreadshouldbegettingsomething//fromthiswhilewearereaping.Thisisn'tthemostoptimal//solutionforthis,butwe'lldeterminesomethingelselater.synchronizedvoidreap(){

    Enumeration enum= sessions.keys();

    while(enum.hasMoreElements( ) ) {Objectkey=enum.nextElement();ServerSessionsession=( ServerSession)sessions.get(key);session.reap();session.validate() ;

    }}synchronizedvoidremoveSession(ServerSessionsession){

    Stringid=session.getId();

    session.invalidate();sessions.remove(id);

    }publicvoidremoveSessions(Contextcontext){

    Enumeration enum= sessions.keys();

    while(enum.hasMoreElements( ) ) {Objectkey=enum.nextElement();ServerSessionsession=( ServerSession)sessions.get(key);

    ApplicationSessionappSession=session.getAppli cationSess ion(context,false);

    if (appSessi on!=null){appSession.invalidate();}

    }}

    /***Usedbycontexttoconfigurethesessionmanager'sinactivitytimeout.**TheSessionManagermayhavesomedefaultsessiontimeout,the*Contextontheotherhandhasit'stimeoutsetbythedeployment*descriptor(web.xml).Thismethodletsthe Contextconforgurethe*sessionmanageraccordingtothisvalue.**@paramminutesThesessioninactivitytimeoutinminutes.*/

    publicvoidsetSessionTimeOut(intminutes){if(-1!=minutes){//Themanagerworkswithseconds...inactiveInterval=(minutes*60);}

    }}

    SessionInterceptorpackageorg.apache.tomcat.request;

    importorg.apache.to mcat.core.*;importorg.apache.to mcat.util.*;importjava.io.*;importjava.net.*;importjava.ut il.*;importjavax.servlet.http.*;

    /***WillprocesstherequestanddeterminethesessionId,andsetit*in theRequest.*Italsomarksthesessionasaccessed.**ThisimplementationonlyhandlesCookiessessions,pleaseextendor*addnewinterceptorsforothermethods.**/

    publicclassSessionInterceptorextends BaseInterceptorimplementsRequestInterceptor{

    //GS,separatesthesessionidfromthejvmroutestaticfinalcharSESSIONID_ROUTE_SEP='.';intdebug=0;ContextManagercm;

    publicSessionInterceptor(){}

    publicvoidsetDebug(inti){System.out.print ln("Setdebugto"+i);debug=i;

    }

    publicvoidsetContextManager(ContextManagercm){this.cm=cm;}

    publicintrequestMap(Requestrequest){StringsessionId =null;Cookiecookies[]=request.getCookies();//a ssert!=nul l

    for(inti=0;i0)cm.log("XXXRURI="+request.getRequestURI());if((foundAt=request.getRequestURI().indexOf(sig))!=-1){sessionId=request.getRequestURI(). substring(foundAt+ sig.length( ));//rewriteURL,doIneedtodoanythingmore?request.setRequestURI(request.getRequestURI().substring(0,foundAt));sessionId=validateSessionId (request,sessionId );if (sessionId!=null){

    request.setReque stedSession IdFromURL(true);}}return0;

    }

    //XXXwhatisthecorrectbehaviorifthesessionisinvalid?//Wemaystillsetitandjustreturnsessioninvalid.

    /**Validateandfix thesessionid.If thesessionisnot validreturnnull.*Itwillalsocleanupthesessionfromload-balancingstrings.*@returnsessionId,ornullifnot valid*/privateStringvalidateSessionId(Requestrequest,StringsessionId){//GS,WepiggybacktheJVMidontopofthe sessioncookie//Separatethem...

    if(debug>0)cm.log("OrigsessionId" +sessionId);if(null!=sessionId){intidex=sessionId.lastIndexOf(SESSIONID_ROUTE_SEP);if(idex>0){

    sessionId=sessionId.substring(0,idex);}

    }if(sessionId!=null&&sessionId.length()!=0){//GS,Wearein aproblemhere,wemayactuallyget//multipleSessioncookies(oneforthe root//contextandonefortherealcontext...oroldsession//cookie.Wemustcheckforvalidityinthecurrentcontext.Contextctx=request.getContext();SessionManagersM =ctx.getSessionManager();if(null!= sM.findSession( ctx,sessionId)){

    sM.accessed(ctx,request,sessionId) ;request.setRequestedSessionId(sessionId);if(debug>0)cm.log("Finalsessionid" +sessionId);returnsessionId;}

    }returnnull;

    }

    publicintbeforeBody(Requestrrequest,Responseresponse){StringreqSessionId=response.getSessionId();if(debug>0)cm.log("BeforeBody"+reqSessionId);if(reqSessionId==nul l)return0;

    //GS,setthepathattributetothecookie.Thisway//multiplesessioncookiescanbeused,oneforeach//context.StringsessionPath=rrequest.getContext().getPath();if(sessionPath .length()==0){sessionPath=" / " ;

    }//GS,piggybackthejvmrouteonthesessionid.if(!sessionPath.equals("/")){StringjvmRoute= rrequest.getJvmRoute();if(null!= jvmRoute){

    reqSessionId=reqSessionId+SESSIONID_ROUTE_SEP+jvmRoute;}}

    Cookiecookie =new Cookie("JSESSIONID",reqSessionId);

    cookie.setMaxAge(- 1);cookie.setPath( sessionPath);cookie.setVersion(1);

    response.addH eader(CookieTools.getCookieHeaderName(cookie),CookieTools.getCookieHeaderValue(cookie) );

    cookie.setVersion(0);response.addH eader(CookieTools.getCookieHeaderName(cookie),CookieTools.getCookieHeaderValue(cookie) );

    return0;}

    /**Notificationofcontextshutdown*/

    publicvoidcontextShutdown(Contextctx)throwsTomcatException

    {if(ctx.getDebug()>0) ctx.log("Removingsessionsfrom"+ ctx);ctx.getSessionManager().removeSessions(ctx);

    }

    }

    ServerSessionpackageorg.apache.tomcat.session;

    importorg.apache. tomcat.core.*;importorg.apache.tomcat.util.StringManager;importjava.io.*;importjava.net.*;importjava.u til.*;importjavax.servlet.*;importjavax.servlet.http.*;

    /***Coreimplementationofaserversession**@authorJamesDuncanDavidson[[email protected]]*@author JamesTodd [[email protected]]*/

    publicclassServerSession{

    privateStringManagersm=StringManager.getManager( "org.apache.tom cat.session");

    privateHashtablevalues=newHashtable();privateHashtableappSessions=newHashtable();privateStringid;privatelongcreationTime=System.currentTimeMillis();;privatelongthisAccessTime=creationTime;privatelonglastAccessed=creationTime;privateintinactiveInterval= -1;ServerSession(Stringid) {

    this.id=id;}

    publicStringgetId(){returnid;}

    publiclonggetCreationTime() {returncreationTime ;

    }publiclonggetLastAccessedTime(){

    returnlastAccessed ;}

    publicApplicationSessiongetApplicationSession(Contextcontext,booleancreate){ApplicationSessionappSession=

    (ApplicationSess ion)appSessions.ge t(contex t);

    if(appSession==null&&create){

    / / X X X//synctoensurevalid?

    appSession= newApplicationSession(id,this, context);appSessions.put(context,appSession);

    }//XXX//makesurethatwehaven'tgoneovertheendofour//inactiveinterval--ifso,invalidateandcreate//a newappSession

    returnappSession ;}

    voidremoveApplicationSession(Contextcontext){appSessions.remove(context);

    }/***Calledbycontextwhenrequestcomesinsothataccessesand*inactivitiescanbedealtwithaccordingly.*/

    voidaccessed(){//setlastaccessedtothisAccessTimeasitwillbeleftover//fromthepreviousaccess

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

    }

    voidvalidate()

    voidvalidate(){//ifwehavean inactiveinterval,checktoseeif//we'veexceededit

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

    if (thisInterval>inactiveInterval){invalidate();ServerSessionManagerssm=

    ServerSessio nManager.getManager();

    ssm.removeSession(this);}

    }}

    synchronizedvoidinvalidate(){Enumerationenum=appSessions.keys();

    while(enum.hasMoreElements( ) ) {Objectkey=enum.nextElement( );ApplicationSessionappSession=

    (ApplicationSession)appSessions.get(key);

    appSession .invalidate();}}

    publicvoidputValue(Stringname,Objectvalue){if(name==null){Stringmsg=sm.getString("serverSession.value.iae");throw newIllegalArgumentExc eption (msg);

    }

    removeValue(name);//removeanyexistingbindingvalues.put(name,value);

    }publicObjectgetValue(Stringname){

    if(name==null){Stringmsg=sm.getString("serverSession.value.iae");

    throw newIllegalArgumentExc eption (msg);}

    returnvalues.get(name);}

    publicEnumerationgetValueNames() {returnvalues.keys();}

    publicvoidremoveValue(Stringname){values.remov e(name);

    }publicvoidsetMaxInactiveInterval(intinterval){

    inactiveInterval =interval;}

    publicintgetMaxInactiveInterval(){returninactiveInte rval;}

    //XXX//sync'dfor safty--no otherthreadshouldbegettingsomething//fromthiswhilewearereaping.Thisisn'tthemostoptimal//solutionforthis,butwe'lldeterminesomethingelselater.

    synchronizedvoidreap(){Enumerationenum=appSessions.keys();

    while(enum.hasMoreElements( ) ) {Objectkey=enum.nextElement( );ApplicationSessionappSession=

    (ApplicationSession)appSessions.get(key);

    appSession .validate();}}

    }

    session expiration is not modularized

  • 8/11/2019 Aspectj Tutorial

    3/101

    3

    problems like

    HTTPRequest

    HTTPResponse

    Servlet

    getCookies ()getRequestURI()(doc)

    getSession()getRequestedSessionId()...

    getRequest()

    setContentType(contentType)getOutptutStream()setSessionId(id)

    ...

    SessionInterceptor

    requestMap(request)beforeBody(req, resp)

    ...

    Session

    getAttribute(name)setAttribute(name, val)

    invalidate()...

    session tracking is not modularized

    the cost of tangled code

    redundant code same fragment of code in many places

    difficult to reason about non-explicit structure

    the big picture of the tangling isnt clear

    difficult to change have to find all the code involved

    and be sure to change it consistently

    and be sure not to break it by accident

  • 8/11/2019 Aspectj Tutorial

    4/101

    4

    crosscutting concerns

    HTTPRequest

    Session

    HTTPResponse

    Servlet

    getCookies ()getRequestURI()(doc)

    getSession()getRequestedSessionId()...

    getAttribute(name)setAttribute(name, val)

    invalidate()...

    getRequest()

    setContentType(contentType)getOutptutStream()setSessionId(id)

    ...

    SessionInterceptor

    requestMap(request)beforeBody(req, resp)

    ...

    the AOP idea

    crosscutting is inherent in complex systems

    crosscutting concerns have a clear purpose

    have a natural structure

    defined set of methods, module boundary crossings,points of resource utilization, lines of dataflow

    so, lets capture the structure of crosscuttingconcerns explicitly... in a modular way

    with linguistic and tool support

    aspects are well-modularized crosscutting concerns

    aspect-oriented programming

  • 8/11/2019 Aspectj Tutorial

    5/101

  • 8/11/2019 Aspectj Tutorial

    6/101

    6

    AspectJ is

    a small and well-integrated extension to Java

    a general-purpose AO language just as Java is a general-purpose OO language

    freely available implementation compiler is Open Source

    includes IDE support emacs, JBuilder 3.5, JBuilder 4, Forte 4J

    user feedback is driving language design

    [email protected] [email protected]

    currently at 0.8 release 1.0 planned for June 2001

    expected benefits of using AOP

    good modularity,even for crosscutting concerns

    less tangled code

    more natural code

    shorter code

    easier maintenance and evolution easier to reason about, debug, change

    more reusable library aspects

    plug and play aspects when appropriate

  • 8/11/2019 Aspectj Tutorial

    7/101

    7

    outline

    I AOP overview brief motivation, essence of AOP idea

    II AspectJ language mechanisms basic concepts, language semantics

    III development environment IDE support, running the compiler, debugging etc.

    IV using aspects

    aspect examples, how to use AspectJ to program

    aspects, exercises to solidify the ideas

    V related work survey of other activities in the AOP community

    looking ahead

    AspectJ mechanisms

    Part II:

    crosscutting in the code

    mechanisms AspectJ provides

    problem structure

    Part IV:

    crosscutting in the design, and

    how to use AspectJ to capture that

  • 8/11/2019 Aspectj Tutorial

    8/101

    8

    Part II

    Basic Mechanisms of AspectJ

    goals of this chapter

    present basic language mechanisms

    using one simple example

    emphasis on what the mechanisms do

    small scale motivation

    later chapters elaborate on

    environment, tools

    larger examples, design and SE issues

  • 8/11/2019 Aspectj Tutorial

    9/101

    9

    basic mechanisms

    1 overlay onto Java join points

    points in the execution of Java programs

    4 small additions to Java

    pointcuts primitive pointcuts

    pick out sets of join points and values at those points

    user-defined pointcuts

    named collections of join points and values

    advice

    additional action to take at join points in a pointcut

    introduction

    additional fields/methods/constructors for classes aspect

    a crosscutting type

    comprised of advice, introduction,

    field,constructor and method declarations

    a simple figure editor

    class Line implements FigureElement{private Point _p1, _p2;

    Point getP1() { return_p1; }Point getP2() { return_p2; }

    voidsetP1(Point p1) { _p1 = p1; }voidsetP2(Point p2) { _p2 = p2; }

    }

    class Point implements FigureElement {private int_x = 0, _y = 0;

    int getX() { return_x; }int getY() { return_y; }

    voidsetX(int x) { _x = x; }voidsetY(int y) { _y = y; }

    }

    display must be

    updated when

    objects move

  • 8/11/2019 Aspectj Tutorial

    10/101

    10

    move tracking

    collection of figure elements that change periodically

    must monitor changes to refreshthe display as needed

    collection can be complex

    hierarchical

    asynchronous events

    other examples session liveness

    value caching

    a Figure

    a Line

    join points

    and returns or

    throws

    object

    receives a

    method call

    dispatch

    dispatch

    key points in dynamic call graph

    object receives a

    method call

    and a return or

    exception is received

    by this method

    a method call toanother object

    and returns

    or throws

  • 8/11/2019 Aspectj Tutorial

    11/101

    11

    join point terminology

    11 kinds of join points

    method & constructorcall reception join points

    method & constructorcall join points method & constructor execution join points

    field get & set join points

    exception handler execution join points

    static & dynamic initialization join points

    a Line

    dispatch

    method call

    join points

    method call

    reception

    join points

    key points in dynamic call graph

    join point terminology

    a Line

    aFigure

    a Point

    a Point

    the method call join point

    corresponding to this

    method reception join point

    all join points on this slide are

    within the control flow of

    this join point

    repeated calls to

    the same method

    on the same objectresult in multiple

    join points

    key points in dynamic call graph

  • 8/11/2019 Aspectj Tutorial

    12/101

    12

    the pointcut construct

    each time a Line receives a

    void setP1(Point) or void setP2(Point) method call

    names certain join points

    or

    reception of a void Line.setP2(Point) call

    name and parametersreception of a void Line.setP1(Point) call

    pointcutmoves():receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point));

    pointcut designators

    primitive pointcut designator, can also be:- calls, executions - instanceof,- gets, sets - within, withincode

    - handlers - cflow, cflowtop

    pointcutmoves():receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point));

    user-defined pointcut designator

  • 8/11/2019 Aspectj Tutorial

    13/101

    13

    pointcutmoves():receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point));

    after(): moves() {

    < r u n s a f t e r mov es > }

    after advice action to take aftercomputation under join points

    a Line

    after advice runson the way back out

    aspectMoveTracking {private boolean_flag = false;public boolean testAndClear() {boolean result = _flag;_flag = false;return result;

    }

    pointcutmoves():receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point));

    after(): moves() {_flag = true;}

    }

    a simple aspect

    aspect defines a

    special class that can

    crosscut other classes

    MoveTracking v1

    box means complete running code

  • 8/11/2019 Aspectj Tutorial

    14/101

    14

    without AspectJ

    what you would expect calls to set flag are tangled through the code

    what is going on is less explicit

    class MoveTracking {private static boolean _flag = false;

    public static void setFlag() {_flag = true;

    }

    public static boolean testAndClear() {boolean result = _flag;_flag = false;return result;

    }}

    class Line {private Point _p1, _p2;

    Point getP1() { return _p1; }Point getP2() { return _p2; }

    voidsetP1(Point p1) {_p1 = p1;MoveTracking.setFlag();

    }voidsetP2(Point p2) {_p2 = p2;MoveTracking.setFlag();

    }}

    MoveTracking v1

    the pointcut constructcan cut across multiple classes

    pointcutmoves():receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(voidPoint.setX(int)) ||receptions(voidPoint.setY(int));

  • 8/11/2019 Aspectj Tutorial

    15/101

    15

    aspectMoveTracking {private boolean_flag = false;public boolean testAndClear() {boolean result = _flag;_flag = false;return result;

    }

    pointcutmoves():receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(voidPoint.setX(int)) ||receptions(voidPoint.setY(int));

    after(): moves() {_flag = true;}

    }

    a multi-class aspectMoveTracking v2

    pointcutmoves(FigureElement figElt):instanceof(figElt) &&(receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(voidPoint.setX(int)) ||receptions(voidPoint.setY(int)));

    after(FigureElement fe): moves(fe) {

    }

    using context in advice

    pointcut can explicitly expose certain values

    advice can use value

    demonstrate first, explain in detail afterwards

    parameter

    mechanism is

    being used

  • 8/11/2019 Aspectj Tutorial

    16/101

    16

    context & multiple classesMoveTracking v3

    aspectMoveTracking {private Set _movees = new HashSet();public Set getMovees() {

    Set result = _movees;_movees = new HashSet();return result;

    }

    pointcutmoves(FigureElement figElt):instanceof(figElt) &&(receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(voidPoint.setX(int)) ||

    receptions(voidPoint.setY(int)));

    after(FigureElement fe): moves(fe) {_movees.add(fe);}

    }

    parameters

    variable bound in user-defined pointcut designator

    variable in place of type name in pointcut designator

    pulls corresponding value out of joinpoints

    makes value accessible on pointcutpointcut parameterspointcutmoves(Line l):

    receptions(void l.setP1(Point)) ||receptions(void l.setP2(Point));

    after(Line line): moves(line) {

    }

    variable in place of type name

    of user-defined pointcut designator

  • 8/11/2019 Aspectj Tutorial

    17/101

    17

    parameters

    variable bound in advice

    variable in place of type name in pointcut designator

    pulls corresponding value out of join points

    makes value accessible within advice

    pointcut moves(Line l):receptions(void l.setP1(Point)) ||receptions(void l.setP2(Point));

    after(Line line): moves(line) {

    }

    typed variable in place

    of type nameadvice parameters

    of advice

    parameters

    value is pulled

    right to left across : left side : right side

    from pointcut designators to user-defined pointcut designators

    from pointcut to advice

    pointcutmoves(Line l):receptions(void l.setP1(Point)) ||receptions(void l.setP2(Point));

    after(Line line): moves(line) {

    }

  • 8/11/2019 Aspectj Tutorial

    18/101

    18

    instanceof

    instanceof()

    any join point at which

    currently executing object is instanceof type (or class) name

    instanceof(Point)instanceof(Line)instanceof(FigureElement)

    any join point means it matches join points of all 11 kinds method & constructor call join points

    method & constructor call reception join points method & constructor execution join points

    field get & set join points exception handler execution join points

    static & dynamic initialization join points

    primitive pointcut designator

    pointcutmoves(FigureElement figElt):instanceof(figElt) &&(receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(voidPoint.setX(int)) ||receptions(voidPoint.setY(int)));

    after(FigureElement fe): moves(fe) {

    }

    an idiom for

    instanceof() &&

    does not further restrict the join points

    does pick up the currently executing object (this)

    getting object in a polymorphic pointcut

  • 8/11/2019 Aspectj Tutorial

    19/101

    19

    context & multiple classesMoveTracking v3

    aspectMoveTracking {private Set _movees = new HashSet();public Set getMovees() {

    Set result = _movees;_movees = new HashSet();return result;

    }

    pointcutmoves(FigureElement figElt):instanceof(figElt) &&(receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(voidPoint.setX(int)) ||

    receptions(voidPoint.setY(int)));

    after(FigureElement fe): moves(fe) {_movees.add(fe);}

    }

    without AspectJ

    class Line {private Point _p1, _p2;

    Point getP1() { return _p1; }Point getP2() { return _p2; }

    voidsetP1(Point p1) {_p1 = p1;

    }voidsetP2(Point p2) {_p2 = p2;

    }}

    class Point {private int_x = 0, _y = 0;

    int getX() { return_x; }

    int getY() { return_y; }

    voidsetX(int x) {_x = x;

    }voidsetY(int y) {_y = y;

    }}

  • 8/11/2019 Aspectj Tutorial

    20/101

    20

    class Line {private Point _p1, _p2;

    Point getP1() { return _p1; }Point getP2() { return _p2; }

    voidsetP1(Point p1) {_p1 = p1;MoveTracking.setFlag();}voidsetP2(Point p2) {_p2 = p2;MoveTracking.setFlag();}

    }

    class Point {private int_x = 0, _y = 0;

    int getX() { return_x; }int getY() { return_y; }

    voidsetX(int x) {_x = x;

    }voidsetY(int y) {_y = y;

    }}

    class MoveTracking {private static boolean _flag = false;

    public static void setFlag() {_flag = true;}

    public static boolean testAndClear() {boolean result = _flag;_flag = false;return result;

    }}

    without AspectJMoveTracking v1

    class Line {private Point _p1, _p2;

    Point getP1() { return _p1; }Point getP2() { return _p2; }

    voidsetP1(Point p1) {_p1 = p1;MoveTracking.setFlag();}voidsetP2(Point p2) {_p2 = p2;MoveTracking.setFlag();}

    }

    class Point {private int_x = 0, _y = 0;

    int getX() { return_x; }

    int getY() { return_y; }

    voidsetX(int x) {_x = x;MoveTracking.setFlag();}voidsetY(int y) {_y = y;MoveTracking.setFlag();}

    }

    without AspectJMoveTracking v2

    classMoveTracking {private static boolean_flag = false;

    public static voidsetFlag() {_flag = true;}

    public static boolean testAndClear() {boolean result = _flag;_flag = false;return result;

    }}

  • 8/11/2019 Aspectj Tutorial

    21/101

    21

    class Line {private Point _p1, _p2;

    Point getP1() { return _p1; }Point getP2() { return _p2; }

    voidsetP1(Point p1) {_p1 = p1;MoveTracking.collectOne(this);}voidsetP2(Point p2) {_p2 = p2;MoveTracking.collectOne(this);}

    }

    class Point {private int_x = 0, _y = 0;

    int getX() { return_x; }int getY() { return_y; }

    voidsetX(int x) {_x = x;MoveTracking.collectOne(this);}voidsetY(int y) {_y = y;MoveTracking.collectOne(this);}

    }

    class MoveTracking {private static Set _movees = new HashSet();

    public static void collectOne(Object o) {_movees.add(o);}

    public static Set getmovees() {Set result = _movees;_movees = new HashSet();return result;

    }}

    without AspectJ

    evolution is cumbersome changes in all three classes

    have to track all callers

    change method name

    add argument

    MoveTracking v3

    with AspectJ

    class Line {private Point _p1, _p2;

    Point getP1() { return _p1; }Point getP2() { return _p2; }

    voidsetP1(Point p1) {_p1 = p1;}voidsetP2(Point p2) {_p2 = p2;}

    }

    class Point {private int_x = 0, _y = 0;

    int getX() { return_x; }int getY() { return_y; }

    voidsetX(int x) {_x = x;}voidsetY(int y) {_y = y;}

    }

  • 8/11/2019 Aspectj Tutorial

    22/101

    22

    with AspectJ

    class Line {private Point _p1, _p2;

    Point getP1() { return _p1; }Point getP2() { return _p2; }

    voidsetP1(Point p1) {_p1 = p1;}voidsetP2(Point p2) {_p2 = p2;}

    }

    class Point {private int_x = 0, _y = 0;

    int getX() { return_x; }int getY() { return_y; }

    voidsetX(int x) {

    _x = x;}voidsetY(int y) {_y = y;}

    }

    aspect MoveTracking {private boolean _flag = false;public boolean testAndClear() {boolean result = _flag;_flag = false;return result;

    }

    pointcut moves():receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point));

    after(): moves() {_flag = true;}

    }

    MoveTracking v1

    class Line {private Point _p1, _p2;

    Point getP1() { return _p1; }Point getP2() { return _p2; }

    voidsetP1(Point p1) {_p1 = p1;}voidsetP2(Point p2) {_p2 = p2;}

    }

    class Point {private int_x = 0, _y = 0;

    int getX() { return_x; }int getY() { return_y; }

    voidsetX(int x) {_x = x;}voidsetY(int y) {_y = y;}

    }

    with AspectJMoveTracking v2

    aspectMoveTracking {private boolean_flag = false;publicboolean testAndClear() {boolean result = _flag;_flag = false;return result;

    }

    pointcut moves():receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(void Point.setX(int)) ||receptions(void Point.setY(int));

    after(): moves() {_flag = true;}

    }

  • 8/11/2019 Aspectj Tutorial

    23/101

    23

    class Line {private Point _p1, _p2;

    Point getP1() { return _p1; }Point getP2() { return _p2; }

    voidsetP1(Point p1) {_p1 = p1;}voidsetP2(Point p2) {_p2 = p2;}

    }

    class Point {private int_x = 0, _y = 0;

    int getX() { return_x; }int getY() { return_y; }

    voidsetX(int x) {

    _x = x;}voidsetY(int y) {_y = y;}

    }

    aspectMoveTracking {private Set _movees = new HashSet();public Set getmovees() {

    Set result = _movees;_movees = new HashSet();return result;

    }

    pointcut moves(FigureElement figElt):instanceof(figElt) &&(receptions(voidLine.setP1(Point)) ||receptions(voidLine.setP2(Point)) ||receptions(voidPoint.setX(int)) ||receptions(voidPoint.setY(int)));

    after(FigureElement fe): moves(fe) {_movees.add(fe);}

    }

    with AspectJ

    evolution is more modular all changes in single aspect

    MoveTracking v3

    advice is

    before before proceeding at join point

    after returning a value to join point

    after throwing a throwable to join point

    after returning to join point either way

    around on arrival at join point gets explicitcontrol over when&if program proceeds

    additional action to take at join points

  • 8/11/2019 Aspectj Tutorial

    24/101

    24

    contract checking

    pre-conditions check whether parameter is valid

    post-conditions

    check whether values were set

    condition enforcement force parameters to be valid

    simple example of before/after/around

    pre-condition

    aspect PointBoundsPreCondition {

    before(Point p, int newX):receptions(voidp.setX(newX)) {

    assert(newX >= MIN_X);assert(newX = MIN_Y);assert(newY

  • 8/11/2019 Aspectj Tutorial

    25/101

    25

    post-condition

    aspect PointBoundsPostCondition {

    after(Point p, int newX):receptions(voidp.setX(newX)) {

    assert(p.getX() == newX);}

    after(Point p, int newY):receptions(voidp.setY(newY)) {

    assert(p.getY() == newY);}

    voidassert(boolean v) {if ( !v )throw new RuntimeException();

    }}

    using after advice

    condition enforcement

    aspect PointBoundsEnforcement {

    around(Point p, int newX) returns void:receptions(voidp.setX(newX)) {

    thisJoinPoint.runNext(p, clip(newX, MIN_X, MAX_X));}

    around(Point p, int newY) returns void:receptions(voidp.setY(newY)) {

    thisJoinPoint.runNext(p, clip(newY, MIN_Y, MAX_Y));}

    int clip(int val, intmin, intmax) {returnMath.max(min, Math.min(max, val));

    }}

    using around advice

  • 8/11/2019 Aspectj Tutorial

    26/101

    26

    special static method

    proceed(arg1, arg2)

    available only in around advice

    means run what would have run if this around advice had not been

    defined

    other primitive pointcuts

    instanceof()within()withincode()

    any join point at which

    currently executing object is instanceof type or class name

    currently executing code is contained within class namecurrently executing code is specified method or constructor

    gets(int Point.x)

    sets(int Point.x)gets(int Point.x)[val]sets(int Point.x)[oldVal][newVal]

    field reference or assignment join points

  • 8/11/2019 Aspectj Tutorial

    27/101

    27

    using field set pointcuts

    aspect PointCoordinateTracing {

    pointcut coordChanges(Point p, int oldVal, int newVal):sets(intp._x)[oldVal][newVal] ||sets(intp._y)[oldVal][newVal];

    after(Point p, int oldVal, int newVal):coordChanges(p, oldVal, newVal) {

    System.out.println(At +tjp.getSignature() + field was changed from +oldVal +

    to +newVal +.);

    }}

    special value

    thisJoinPoint.

    Signature getSignature()

    Object[] getParameters()

    ...

    available in any advice

    thisJoinPoint is abbreviated to tjp occasionally in these

    slides

    * introspective subset of reflection consistent with Java

    reflective* access to the join point

  • 8/11/2019 Aspectj Tutorial

    28/101

    28

    other primitive pointcuts

    calls(voidPoint.setX(int))method/constructor call join points (at call site)

    receptions(voidPoint.setX(int))method/constructor call reception join points (at called object)

    executions(void Point.setX(int))method/constructor execution join points (at actual called method)

    initializations(Point)

    object initialization join points

    staticinitializations(Point)class initialization join points (as the class is loaded)

    context sensitive aspects

    aspectMoveTracking {List _movers = new LinkedList();List _movees = new LinkedList();//

    pointcutmoveCalls(Object mover, FigureElement movee):instanceof(mover) &&(lineMoveCalls(movee) || pointMoveCalls(movee));

    pointcut lineMoveCalls(Line ln):calls(voidln.setP1(Point)) || calls(voidln.setP2(Point));

    pointcutpointMoveCalls(Point pt):calls(voidpt.setX(int)) || calls(voidpt.setY(int));

    after(Object mover, FigureElement movee):moveCalls(mover, movee) {

    _movers.add(mover);_movees.add(movee);}

    }

    MoveTracking v4a

  • 8/11/2019 Aspectj Tutorial

    29/101

    29

    context sensitive aspects

    aspectMoveTracking {List _movers = new LinkedList();List _movees = new LinkedList();//

    pointcutmoveCalls(Object mover, FigureElement movee):instanceof(mover) &&(calls(void((Line)movee).setP1(Point)) ||calls(void((Line)movee).setP2(Point)) ||calls(void((Point)movee).setX(int)) ||calls(void((Point)movee).setY(int)));

    after(Object mover, FigureElement movee):moveCalls(mover, movee) {

    _movers.add(mover);_movees.add(movee);}

    }

    MoveTracking v4b

    does

    this

    make

    sense?

    fine-grained protection

    class Point implement FigureElement {private int_x = 0, _y = 0;

    int getX() { return_x; }int getY() { return_y; }

    voidsetX(int nv) { primitiveSetX(nv); }voidsetY(int nv) { primitiveSetY(nv); }

    voidprimitiveSetX(int x) { _x = x; }voidprimitiveSetY(int y) { _y = y; }

    }

    aspect PrimitiveSetterEnforcement {pointcut illegalSets(Point pt):

    !(withincode(voidPoint.primitiveSetX(int)) ||withincode(voidPoint.primitiveSetY(int))) &&

    (sets(intpt._x) || sets(intpt._y));

    before(Point p): illegalSets(p) {throw new Error("Illegal primitive setter call.");

    }}

  • 8/11/2019 Aspectj Tutorial

    30/101

    30

    other primitive pointcuts

    cflow(po i n t c ut d es i gna t or )cflowtop(po i n t c ut d es i g na t o r )

    all join points within the dynamic control flow of any join

    point in pointcut designator

    cflowtop doesnt start a new one on re-entry

    context sensitive aspects

    aspect MoveTracking {private Set _movees = new HashSet();public Set getMovees() {

    Set result = _movees;_movees = new HashSet();

    return result;}

    pointcutmoves(FigureElement figElt):instanceof(figElt) &&(receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(voidPoint.setX(int)) ||receptions(voidPoint.setY(int)));

    pointcut topLevelMoves(FigureElement figElt):moves(figElt) && !cflow(moves(FigureElement));

    after(FigureElement fe): topLevelMoves(fe) {_movees.add(fe);}

    }

    MoveTracking v5

  • 8/11/2019 Aspectj Tutorial

    31/101

    31

    wildcarding in pointcuts

    instanceof(Point)instanceof(graphics.geom.Point)instanceof(graphics.geom.*) any type in graphics.geominstanceof(graphics..*) any type in any sub-package

    of graphics

    receptions(void Point.setX(int))receptions(public * Point.*(..)) any public method on Pointreceptions(public * *..*.*(..)) any public method on any type

    receptions(void Point.getX())receptions(void Point.getY())

    receptions(void Point.get*())receptions(void get*()) any getter

    receptions(Point.new(int, int))receptions(new(..)) any constructor

    * is wild card

    .. is multi-part wild card

    property-based crosscutting

    crosscuts of methods with a common property

    public/private, return a certain value, in a particular package

    logging, debugging, profiling

    log on entry to every public method

    package com.xerox.print;public class C1 {

    public voidfoo() {A.doSomething();

    }

    }

    package com.xerox.scan;public class C2 {

    public int frotz() {A.doSomething();

    }public intbar() {A.doSomething();

    }

    }

    package com.xerox.copy;public class C3 {

    public String s1() {A.doSomething();

    }

    }

  • 8/11/2019 Aspectj Tutorial

    32/101

    32

    property-based crosscutting

    consider code maintenance another programmer adds a public method i.e. extends public interface this code will still work

    another programmer reads this code whats really going on is explicit

    aspect PublicErrorLogging {

    Log log = new Log();

    pointcutpublicInterface ():receptions(public * com.xerox..*.*(..));

    after() throwing (Error e): publicInterface() {log.write(e);

    }}

    neatly captures public

    interface of mypackage

    aspect statewhat if you want a per-object log?

    aspect PublicErrorLoggingof eachobject(PublicErrorLogging.publicInterface()) {

    Log log = new Log();

    pointcutpublicInterface ():receptions(public * com.xerox..*.*(..));

    after() throwing (Error e): publicInterface() {log.write(e);

    }

    one instance of the aspect for each object

    that ever executes at these points

  • 8/11/2019 Aspectj Tutorial

    33/101

    33

    looking up aspect instances

    static method of aspects of eachobject()

    of eachclass()

    of eachcflowroot() returns aspect instance or null

    :

    static Log getLog(Object obj) {return (PublicErrorLogging.aspectOf(obj)).log;

    }}

    of each relations

    eachobject()

    one aspect instance for each

    object that is ever this at

    the join points

    eachclass()

    one aspect instance for each class of

    object that is ever this at the join points

    eachcflowroot()

    one aspect instance for each join point

    in pointcut, is available at all joinpoints in && cflow()

    p1l1

    l2p3

    p2

    FigureElement

    Point Line

  • 8/11/2019 Aspectj Tutorial

    34/101

    34

    inheritance & specialization

    pointcuts can have additional advice aspect with

    concrete pointcut

    perhaps no advice on the pointcut

    in figure editormoves() can have advice from multiple aspects

    module can expose certain well-defined pointcuts

    abstract pointcuts can be specialized

    aspect with abstract pointcut

    concrete advice on the abstract pointcut

    a shared pointcut

    public class FigureEditor {public pointcutmoves(FigureElement figElt):

    instanceof(figElt) &&(receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(voidPoint.setX(int)) ||receptions(voidPoint.setY(int)));

    ...

    }

    aspectMoveTracking {

    after(FigureElement fe):FigureEditor.moves(fe) { ... }

    ...}

  • 8/11/2019 Aspectj Tutorial

    35/101

    35

    a reusable aspect

    abstract public aspect RemoteExceptionLogging {

    abstract pointcut logPoints();

    after() throwing (RemoteException e): logPoints() {log.println(Remote call failed in: +

    thisJoinPoint.toString() +( + e + ).);

    }}

    public aspectMyRMILogging extends RemoteExceptionLogging {

    pointcut logPoints():receptions(* RegistryServer.*.*(..)) ||receptions(private * RMIMessageBrokerImpl.*.*(..));

    }

    abstract

    introduction

    aspectMoveTracking {private Set _movees = new HashSet();

    public Set getMovees() {Set result = _movees;

    _movees = new HashSet();return result;

    }

    introduction FigureElement {private Object lastMovedBy;

    public Object getLastMovedBy() { return lastMovedBy; }}

    pointcutMoveCalls(Object mover, FigureEl ement movee):instanceof(mover) &&(lineMoveCalls(movee) || pointMoveCalls(movee));

    pointcut lineMoveCalls(Line ln):calls(voidln.setP1(Point)) || calls(voidln.setP2(Point));

    pointcutpointMoveCalls (Point pt):calls(voidpt.setX(in t)) || calls(voidpt.setY(int));

    after(Object mover, FigureElement movee):MoveCalls(mover, movee) {

    _movees.add(movee);movee.lastMovedBy = mover;}

    }

    (like open classes) MoveTracking v6

    introduction adds members to target type

    public and private are

    with respect to enclosing

    aspect declaration

  • 8/11/2019 Aspectj Tutorial

    36/101

    36

    calls/receptions/executions

    :classMyPoint extends Point {

    :int getX() { return super.getX(); }:

    }

    aspect ShowAccesses {before(): calls(voidPoint.getX()) { }before(): receptions(voidPoint.getX()) { }before(): executions(voidPoint.getX()) { }}

    code runs once

    (newMyPoint()).getX() code runs oncecode runs twice

    differences among

    calls/receptions/executions

    :classMyPoint extends Point {

    :MyPoint() { ... }:

    }

    aspect ShowAccesses {before(): calls(Point.new()) { }before(): receptions(Point.new()) { }before(): executions(Point.new()) { }}

    code runs once

    newMyPoint() code runs oncecode runs twice

    remember the implicit

    super call here!

    differences among

  • 8/11/2019 Aspectj Tutorial

    37/101

    37

    summary

    dispatch

    advicebefore

    after

    around

    of each

    inheritance

    introduction

    pointcuts

    -primitive-calls receptions

    executions

    handlers

    gets sets

    initializations

    instanceof

    hasaspect

    within withincode

    cflow cflowtop

    -user-defined-pointcut

    declaration

    abstract

    overriding

    join points

    method & constructor

    calls

    call receptions

    executions

    field

    gets

    sets

    exception handler

    executions

    initializations

    aspectscrosscutting type

    of eachobject

    class

    cflowroot

    where we have been

    AspectJ mechanisms

    Part II:

    crosscutting in the code

    mechanisms AspectJ provides

    problem structure

    Part IV:

    crosscutting in the design, and

    how to use AspectJ to capture that

    and where we are going

  • 8/11/2019 Aspectj Tutorial

    38/101

    38

    Part III

    AspectJ IDE support

    programming environment

    AJDE support for emacs, JBuilder 3.5, JBuilder 4, Forte 4J

    also jdb style debugger (ajdb)

    and window-based debugger

    navigating AspectJ code

    compiling

    tracking errors debugging

    ajdoc

  • 8/11/2019 Aspectj Tutorial

    39/101

    39

    Part IV

    Using Aspects

    where we have been

    AspectJ mechanisms

    Part II:

    crosscutting in the code

    mechanisms AspectJ provides

    problem structure

    Part IV:

    crosscutting in the design, and

    how to use AspectJ to capture that

    and where we are going

  • 8/11/2019 Aspectj Tutorial

    40/101

    40

    goals of this chapter

    present examples of aspects in design intuitions for identifying aspects

    present implementations in AspectJ how the language support can help

    work on implementations in AspectJ putting AspectJ into practice

    raise some style issues

    objects vs. aspects when are aspects appropriate?

    example 1

    plug tracing into the system

    exposes join points and uses very simpleadvice

    an unpluggable aspect

    the programs functionality is unaffected by theaspect

    uses both aspect and object

    plug & play tracing

  • 8/11/2019 Aspectj Tutorial

    41/101

    41

    tracing without AspectJ

    TraceSupport

    class Point {voidset(int x, int y) {TraceSupport.traceEntry(Point.set);

    _x = x; _y = y;TraceSupport.traceExit(Point.set);

    }}

    class TraceSupport {static int TRACELEVEL = 0;static protectedPrintStream stream = null;static protected int callDepth = -1;

    static voidinit(PrintStream _s) {stream=_s;}

    static voidtraceEntry(String str) {if (TRACELEVEL == 0) return;callDepth++;printEntering(str);

    }

    static voidtraceExit(String str) {if (TRACELEVEL == 0) return;callDepth--;printExiting (str);

    }

    }

    a clear crosscutting structure

    all modules of the system use thetrace facility in a consistent way:

    entering the methods andexiting the methods

    this line is aboutinteracting withthe trace facility

    TraceSupport

  • 8/11/2019 Aspectj Tutorial

    42/101

    42

    tracing as an aspect

    aspectMyClassTracing {

    pointcutpoints():within(com.bigboxco.boxes.*) &&executions(* *(..));

    before(): points() {TraceSupport.traceEntry(

    tjp.className + . + tjp.methodName);}after(): points() {TraceSupport.traceExit(

    tjp.className + . + tjp.methodName);}

    }

    TraceSupport

    plug in:

    unplug:

    or

    plug and debug

    ajc Point.java Line.java

    ajc Point.java Line.javaTraceSupport.java MyClassTracing.java

  • 8/11/2019 Aspectj Tutorial

    43/101

    43

    plug and debug

    //From ContextManager

    publicvo idservice( Request rrequest, Responserresponse ) {// log( "New request " + rrequest) ;try {

    // System.out.print("A");rrequest.setContextManager( this );rrequest.setResponse(rr espons e);rresponse.setRequest(rrequest );

    // wront request - parsing errorint statu s=rresponse.getSta tus();

    if( status < 400 )status=processRequest( rrequest );

    if(status==0)status=authenticate( rrequest, rresponse );

    if(status == 0)status=authorize( rrequest, rresponse );

    if( status == 0 ) {rrequest .getWrappe r().handleRequest(rrequest ,

    rresponse);} else {

    // something went wronghandleError( rrequest, rresponse, null, status );

    }} catch (Throwable t) {

    handleError( rrequest, rresponse, t, 0 );}// System.out.print("B");try {

    rresponse.finish();rrequest.recycle();rresponse.recycle();

    } catch ( Throwable ex ) {if(debug>0) log( "Error closing request " + ex);

    }// log( "Done with request " + rrequest );// System.out.print("C");return;}

    // log( "New request " + rrequest );

    // System.out.print(A);

    // System.out.print("B");

    // log("Done with request " + rrequest);

    if(debug>0)

    log("Error closing request " + ex);

    // System.out.print("C");

    plug and debug

    turn debugging on/off without editingclasses

    debugging disabled with no runtimecost

    can save debugging code betweenuses

    can be used for profiling, logging easy to be sure it is off

  • 8/11/2019 Aspectj Tutorial

    44/101

    44

    aspects in the design

    objects are no longer responsible for usingthe trace facility trace aspect encapsulates that responsibility, for

    appropriate objects

    if the Trace interface changes, that change isshielded from the objects only the trace aspect is affected

    removing tracing from the design is trivial just remove the trace aspect

    have these benefits

    aspects in the code

    object code contains no calls to tracefunctions trace aspect code encapsulates those calls, for

    appropriate objects

    if the trace interface changes, there is noneed to modify the object classes only the trace aspect class needs to be modified

    removing tracing from the application istrivial compile without the trace aspect class

    have these benefits

  • 8/11/2019 Aspectj Tutorial

    45/101

    45

    tracing: object vs. aspect

    using an objectcaptures tracingsupport, but doesnot capture itsconsistent usage byother objects

    using an aspectcaptures theconsistent usage ofthe tracing supportby the objects

    TraceSupport TraceSupport

    tracing

    Make the tracing aspect a library aspectby using an abstract pointcut.

    The after advice used runs whether thepoints returned normally or threwexceptions, but the exception thrown isnot traced. Add advice to do so.

    exercises

  • 8/11/2019 Aspectj Tutorial

    46/101

    46

    exercise

    aspect TracingXXX {// what goes here?

    }

    aspect TraceMyClasses extends TracingXXX {// what goes here?

    }

    refactor TraceMyClasses into a reusable

    (library) aspect and an extension

    equivalent to TraceMyClasses

    exercise

    abstract aspect TracingProtocol {

    abstractpointcut tracePoints();

    before(): points() {Trace.traceEntry(tjp.className + . + tjp.methodName);

    }after(): points() {Trace.traceExit(tjp.className + . + tjp.methodName);

    }}

    aspect TraceMyClasses extends TracingProtocol {

    pointcut points():within(com.bigboxco.boxes.*) &&executions(* *(..));

    }

    we now have the Trace class, and two

    aspects, from a design perspective,

    what does each implement?

  • 8/11/2019 Aspectj Tutorial

    47/101

    47

    example 2

    Point

    x: double

    y: doubletheta: double

    rho: double

    rotate(angle:double)

    offset(dx:double,dy:double)...

    CloneablePoint

    clone()

    ComparablePoint

    compareTo(o:Object)

    HashablePoint

    equals(o:Object)

    hashCode()

    roles/views

    CloneablePoint

    aspect CloneablePoint {

    Point +implements Cloneable;

    public Object Point.clone() throws CloneNotSupportedException {// we choose to bring all fields up to date before cloning

    makeRectangular(); // defined in class PointmakePolar(); // defined in class Pointreturn super.clone();

    }}

  • 8/11/2019 Aspectj Tutorial

    48/101

    48

    roles/views

    Write the HashablePoint andComparablePoint aspects.

    Consider a more complex system.Would you want the HashablePointaspect associated with the Point class,or with other HashableX objects, orboth?

    Compare using aspects for role/view

    abstraction with other techniques orpatterns.

    exercises

    example 3

    interface OutputStream {public voidwrite(byte b);public voidwrite(byte[] b);

    }

    /*** This SIMPLE aspect keeps a global count of all* all the bytes ever written to an OutputStream.*/aspect ByteCounting {

    int count = 0;

    int getCount() { return count; }

    // //// what goes here? //// //

    }

    counting bytes

  • 8/11/2019 Aspectj Tutorial

    49/101

    49

    exercise complete the codefor ByteCounting

    /*** This SIMPLE aspect keeps a global count of all* all the bytes ever written to an OutputStream.*/aspect ByteCounting {

    int count = 0;int getCount() { return count; }

    }

    counting bytes v1

    aspect ByteCounting {

    int count = 0;int getCount() { return count; }

    after():receptions(voidOutputStream.write(byte)) {

    count = count + 1;}

    after(byte[] bytes):receptions(voidOutputStream.write(bytes)) {

    count = count + bytes.length;}

    }

    a first attempt

  • 8/11/2019 Aspectj Tutorial

    50/101

    50

    counting bytes

    class SimpleOutputStreamimplements OutputStream {public voidwrite(byteb) { }

    public voidwrite(byte[] b) {for (int i = 0; i < b.length; i++) write(b[i]);

    }}

    class OneOutputStreamimplements OutputStream {public voidwrite(byteb) {..}

    public voidwrite(byte[] b) {..}}

    some stream implementations

    counting bytes

    class OtherOutputStreamimplements OutputStream {public voidwrite(byteb) {

    byte[] bs = new byte[1];bs[0] = b;write(bs);

    }

    public voidwrite(byte[] b) { }}

    another implementation

  • 8/11/2019 Aspectj Tutorial

    51/101

    51

    counting bytes v2

    aspect ByteCounting {

    int count = 0;

    int getCount() { return count; }

    pointcut allWrites(): receptions(voidOutputStream.write(byte)) ||receptions(voidOutputStream.write(byte[]));

    pointcutwithinWrite(): cflow(allWrites());

    after():!withinWrite() && receptions(voidOutputStream .write(byte)) {

    count++;}

    after(byte[] bytes):

    !withinWrite() && receptions(voidOutputStream .write(bytes)) {count = count + bytes.length;}

    }

    using cflow for more robust counting

    counting bytes v3

    aspect ByteCounting of eachobject(allWrites()) {int count;

    int getCountOf(OutputStream str) {return ByteCounting.aspectOf(str).count;

    }

    ... count++;

    ... count += bytes.length;

    }

    per-stream counting

  • 8/11/2019 Aspectj Tutorial

    52/101

    52

    counting bytes

    How would you count bytes writtenover this interface without aspects?

    How do the aspects change if themethod voidwrite(Collection c) isadded to the OutputStream interface?

    Consider a system in which you wrotenot only bytes, but byte generators(Objects with a run() method that may

    output its own bytes). How would youneed to change v2?

    exercises

    example 4

    workers need to know the caller:

    capabilities

    charge backs to customize result

    caller1

    caller2

    Service

    worker 1 worker 3worker 2

    context-passing aspects

  • 8/11/2019 Aspectj Tutorial

    53/101

  • 8/11/2019 Aspectj Tutorial

    54/101

  • 8/11/2019 Aspectj Tutorial

    55/101

    55

    abstract aspect CapabilityChecking {

    pointcut invocations(Caller c):instanceof(c) && calls(void Service.doService(String));

    pointcut workPoints(Worker w):receptions(void w.doTask(Task));

    pointcut perCallerWork(Caller c, Worker w):cflow(invocations(c)) && workPoints(w);

    before (Caller c, Worker w): perCallerWork(c, w) {

    w.checkCapabilities(c);}

    }

    context-passing aspects

    context-passing aspects

    The before advice on theperCallerWork pointcut calls the

    workers checkCapabilities methodto check the capabilities of the caller.What would be an appropriate way towrite that method?

    exercises

  • 8/11/2019 Aspectj Tutorial

    56/101

    56

    example 5properties of interfaces

    interface Forest {

    int howManyTrees();

    int howManyBirds();

    ...

    }

    pointcut forestReceptions():receptions(* Forest.*(..));

    before(): forestReceptions(): {

    }

    aspects on interfaces

    aspect Forestry {

    pointcut ForestMethodReceptions():

    receptions(* Forest.*(..));

    before(): ForestMethodReceptions() {

    System.out.println(thisJoinPoint.methodName +

    " is a Forest-method.");

    }

    }

    a first attempt

  • 8/11/2019 Aspectj Tutorial

    57/101

  • 8/11/2019 Aspectj Tutorial

    58/101

    58

    aspects on interfaces

    In this example you needed toconstrain a pointcut because ofundesired inheritance. Think of anexample where you would want tocapture methods in a super-interface.

    Constraining a pointcut in this way canbe seen as an aspect id iom. What otheridioms have you seen in this tutorial?

    exercises

    example 6

    client reactions to failures:

    - abort- try another server

    RMI exception aspects

  • 8/11/2019 Aspectj Tutorial

    59/101

    59

    a TimeServer design

    the TimeService

    public interface TimeService extends Remote {

    /*** What's the time?*/

    public Date getTime() throws RemoteException;

    /*** Get the name of the server*/

    public String getName() throws RemoteException;

    /*** Exported base name for the service

    */public static final String nameBase = "TimeService";}

  • 8/11/2019 Aspectj Tutorial

    60/101

    60

    the TimeServer

    public class TimeServer extends UnicastRemoteObjectimplements TimeService {

    /*** The remotely accessible methods

    */public Date getTime() throws RemoteException {return new Date();}public String getName() throws RemoteException {return toString();}/**

    * Make a new server object and register it*/

    public static voidmain(String[] args) {Time