Adaptive Aspect-Oriented Programming in AspectJ
-
Upload
lysandra-foley -
Category
Documents
-
view
48 -
download
1
description
Transcript of Adaptive Aspect-Oriented Programming in AspectJ
UCI Feb 03 1
Adaptive Aspect-Oriented Programming in AspectJ
Karl J. Lieberherr
Northeastern University
Joint work of Demeter Research Group
UCI Feb 03 2
Overview
• What is “adaptive programming”?• Examples in AspectJ. What is behind adaptiveness in
AspectJ?• Why we need more adaptiveness in AspectJ.• DAJ: a simple adaptive add-on to AspectJ.• Abstraction behind “more adaptiveness”• LoD in AspectJ (adapts to any Java program)• Conclusions
UCI Feb 03 3
Adaptive?
• A program is adaptive if it changes its behavior according to its context.
• Adaptive programs: Concurrency policy, Distribution policy, Logging Aspect, Adaptive Method, Law of Demeter Checker in AspectJ
• Possible contexts– Java program or its execution tree
– UML class diagram or object diagram
UCI Feb 03 4
What is the role of adaptive features in AOP
• They become increasingly more important as AOP is applied to larger problems.
• Encapsulating an aspect without abstracting over the relevant join points leads to brittle code.
• AspectJ has many adaptive features but more is needed.
UCI Feb 03 5
Adaptive Aspectsabstract public aspect RemoteExceptionLogging { abstract pointcut logPoint(); after() throwing (RemoteException e): logPoint() { log.println(“Remote call failed in: ” + thisJoinPoint.toString() + “(” + e + “).”); }}
public aspect MyRMILogging extends RemoteExceptionLogging { pointcut logPoint(): call(* RegistryServer.*.*(..)) || call(private * RMIMessageBrokerImpl.*.*(..));}
abstract
AspectJ team slide
UCI Feb 03 6
A Different Kind of Adaptive Aspect
abstract aspect CapabilityChecking {
pointcut invocations(Caller c): this(c) && call(void Service.doService(String));
pointcut workPoints(Worker w): target(w) && call(void Worker.doTask(Task));
pointcut perCallerWork(Caller c, Worker w): cflow(invocations(c)) && workPoints(w);
before (Caller c, Worker w): perCallerWork(c, w) { w.checkCapabilities(c); }}
AspectJ team slide
UCI Feb 03 7
A more complex adaptive aspect:Law of Demeter Checker
(Object Form)aspect Check { … after(): Any.MethodCall{ // call (* *(..)); // check whether // thisJoinPoint.getTarget() // is a preferred supplier // object}
UCI Feb 03 8
Observation 1• Many AspectJ programs are adaptive (designed for a
family of Java programs)– Context: Java program or its execution tree (lexical joinpoints
or dynamic join points)
• Features enabling adaptiveness: – *, .. (wildcards) – cflow, + (graph transitivity)– this(s), target(s), args(a), call (…), …
(inheritance as wild card)• pc(Object s, Object t):
this(s) && target(t) && call(… f …)
UCI Feb 03 9
Observation 2
• Want to improve the adaptive capabilities of AspectJ: AspectJ still leads to tangling and duplication.
UCI Feb 03 10
Overview
• What is “adaptive programming”?• Examples in AspectJ. What is behind adaptiveness in
AspectJ?• Why we need more adaptiveness in AspectJ.• DAJ: a simple adaptive add-on to AspectJ.• Abstraction behind “more adaptiveness”• LoD in AspectJ• Conclusions
UCI Feb 03 11
Listing files in a FileSystem
:FileSystem :CompoundFile
:CompoundFile
:File_PList :NonEmpty_File_PList
:FileNameroot
contents
next
first
it
contents
f
fparent
UCI Feb 03 12
public aspect FileSystemTraversals { public void CompoundFile.listAll() { FileLister v = new FileLister(); eachFile(v); void CompoundFile.eachFile(…) { … if (contents != null) eachFile_crossing_contents(newTokens); } void CompoundFile. eachFile_crossing_contents(…) { this.contents.eachFile(tokens); } // much more}
UCI Feb 03 13
Example of an Adaptive Method in AspectJ (DAJ)
aspect FileSystemTraversals {
declare traversal:
void listAll():
"from CompoundFile to File"
(FileLister);
}
UCI Feb 03 14
http://daj.sourceforge.net/
• DAJ gives you– the power of AspectJ and – the beauty of DJ and – the convenience of DemeterJ
• all at once without having to learn a new programming language other than AspectJ and a schema notation (Java Data Binding) .
UCI Feb 03 15
Another Adaptive Method
aspect FileSystemTraversals {
declare strategy: eachFile:
"intersect(from CompoundFile to File,
down)";
declare traversal: void listAll():
eachFile(FileLister);
declare strategy: down: "from *
bypassing -> *,parent,* to *";
}
UCI Feb 03 16
What To Do
class FileLister { Stack path = new Stack(); void before(File file) { path.push(file.name);} void after(File file) { System.out.print(" ."); Iterator it = path.iterator(); it.next(); while (it.hasNext()) System.out.print("/" + it.next()); System.out.println(); path.pop();}}
High-level AspectJ advice using dynamic join points!
UCI Feb 03 17
Ordinary Java Class
class Main {
public static void main(String[] args) {
FileSystem fs = FileSystem.parse(new File(args[0]));
Commands script = Commands.parse(new File(args[1]));
script.interpret(fs.root);
System.out.println(" Status of File System ");
fs.root.listAll();
}
}
UCI Feb 03 18
Domain-specific aspect languages
• What is a good infrastructure for this?
• Goes back to the theme of Crista: domain-specific aspect languages.
UCI Feb 03 19
DAJ
• What is new for the AspectJ programmer
• Two additional declarations– declare strategy: including intersection– declare traversal
• Object structure and language aspect– class dictionary files
UCI Feb 03 20
range of AOP languagesmeans of … join points
add memberssignaturesclass members static JPM
DemeterJ, DAJ
dynamic JPM
static JPM 1
static JPM 2
static JPM 3
AspectJ dynamic JPM
JPM
when traversal reaches object or edge
class members
class members
class members
points in execution call, get, set…
join points
visitor method signatures
traversal spec. sclass graph g
class names
class graph
signaturesw/ wildcards & other properties of JPs
identifying
visitor method bodies
s + g (result = traversal implementation)
add members
class graph with tokens=grammar (result = parsing and printing implementation)
advice
specifying semantics at
UCI Feb 03 21
Overview
• What is “adaptive programming”?• Examples in AspectJ. What is behind adaptiveness in
AspectJ?• Why we need more adaptiveness in AspectJ.• DAJ: a simple adaptive add-on to AspectJ.• Abstraction behind “more adaptiveness”• LoD in AspectJ• Conclusions
UCI Feb 03 22
A General Graph-based Adaptive Mechanism
• Three layers of graphs: Bottom, Middle, Top – Bottom layer: trees to select subtrees guided by
top layer. Each bottom layer tree has a graph from the
– Middle layer associated with it that contains meta-information about the bottom layer tree. Acts as an abstraction barrier between the top and bottom layers. Used to reduce search space.
– Top layer graph is basically a subgraph of the transitive closure of the middle layer graph, decorated with additional information attached to the edges.
UCI Feb 03 23
Middle graph: Abstraction barrier
Bottom tree: select subtrees
A B
A B
C
Top graph: subgraph of transitive closure of middle layer
C
AB c1:C
c2:Cc3:C
UCI Feb 03 24
Graph-based adaptiveness
• The call graph application (AspectJ): – Top: computational pattern, – Middle: static call graph, – Bottom: call tree.
• The standard application (Demeter): – Top: strategy graph, – Middle: class graph, – Bottom: object trees.
UCI Feb 03 25
Call graph example
jp_lock = call(R.lock())jp_write = call(R.write())jp_unlock = call(R.unlock())jp_read = call(R.read())
jps1 = from jp_start to {jp_lock, jp_write, jp_unlock, jp_read}jps2 = from jp_start bypassing {jp_lock, jp_write, jp_unlock, jp_read} to {jp_lock, jp_write, jp_unlock, jp_read}
jps1 = jps2.
UCI Feb 03 26
Overview
• What is “adaptive programming”?• Examples in AspectJ. What is behind adaptiveness in
AspectJ?• Why we need more adaptiveness in AspectJ.• DAJ: a simple adaptive add-on to AspectJ.• Abstraction behind “more adaptiveness”• LoD in AspectJ• Conclusions
UCI Feb 03 27
Aspects and lexical join points
• Going to the roots of the Northeastern branch of AOP: Law of Demeter.
• Closing the circle: Write an ultimately adaptive program in AspectJ: – Works with all Java programs– Checks the object-form of the Law of Demeter:
“talk only to your friends”
UCI Feb 03 28
Instrumentation of Java programs with Aspects
Supplier
TargetBinStack
ReturnValueBin
ArgumentBin
GlobalPreferredBin
LocallyConstructedBin
ImmediatePartBin
Checker
StatisticsRequirements:
Good Separation of Concerns in Law of Demeter Checker
Aspect Diagram
uses pointcuts
Aspect framework
UCI Feb 03 29
Explanation
• The *bin* aspects collect potential preferred supplier objects that represent good coupling in the context of a method body.
• The Checker aspect checks each method call whether the receiver is a preferred supplier object.
• The Statistics aspect counts events generated by the Checker aspect.
UCI Feb 03 30
Law of Demeter(Join Point Form)
JPT(ID) =
[<target> ID]
<args> List(ID)
<children> List(JPT)
[<ret> ID].
List(S) ~ {S}.
UCI Feb 03 31
JPT(ID) =
[<target> ID]
<args> List(ID)
<children> List(JPT)
[<ret> ID].
List(S) ~ {S}.Jr1.foo1()a1.bar()t2.foo2()r3.foo2()
Etarget t2args {a1,a2}
target t2ret r1
target nullret r3
UCI Feb 03 32
Generic Law of Demeter(Join Point Form)
Definition 1: The LoD_JPF requires that for each join point J, target(J) is a potential preferred supplier of J.
Definition 2: The set of potential preferred suppliers to a join point J, child to the enclosing join point E, is the union of the objects in the following sets:
UCI Feb 03 33
• Argument rule: the args of the enclosing join point E, including the target
• Associated rule: the associated values of E: the ret values of the children of E before J whose target is the target of E or whose target is null.
Generic Law of Demeter(Join Point Form)
UCI Feb 03 34
aspect LoD extends Violation { pointcut LoD_JPF(): //LoD definition ArgumentRule() || AssociatedRule(); pointcut ArgumentRule(): if(thisEnclosingJoinPoint.getArgs() .contains(thisJoinPoint.getTarget()); pointcut AssociatedRule(): if(thisEnclosingJoinPoint .hasSelfishChild(thisJoinPoint .getTarget()));}
UCI Feb 03 35
Pseudo Aspect
• LoD is a ``pseudo'' aspect because it cannot run in the current implementation of AspectJ, which doesn't allow declare warning to be defined on any pointcut with an if expression.
UCI Feb 03 36
Join Point Form
• The pointcuts ArgumentRule and AssociatedRule select the ``good'' join points.
• ArgumentRule selects those join points whose target is one of the arguments of the enclosing join point;
UCI Feb 03 37
Join Point Form
• AssociatedRule selects those join points whose target is in the set of locally returned ID's, and the ID's created in the siblings of the current node.
UCI Feb 03 38
Map Dynamic Object Form (DOF) to LoD_JPF
• We use LoD_JPF pointcut to check DOF: – Dynamic join point model is mapped to JPT.
• Object is mapped to ID.
• Method invocations are mapped to JPF join points. The enclosing join point is the parent in the control flow.
UCI Feb 03 39
Map Lexical Class Form (LCF) to LoD_JPF
• We use LoD_JPF to check LCF as follows. – Lexical join point model is mapped to JPT. Lexical join points
are nodes in the abstract syntax tree
– Class is mapped to ID.
– Join points are signatures of call sites. The enclosing join point is the signature of the method in which the call site resides. To run the aspect, a suitable ordering has to be given to the elements of children:
• all constructor calls, followed by local method calls, followed by the other join points.
UCI Feb 03 40
AspectJ code
• In AOSD 2003 paper with David Lorenz and Pengcheng Wu
• DOF: AspectJ works well. Program uses most adaptive ingredients of AspectJ: *, cflow, this, target, etc.
• LCF: AspectJ cannot do it. We sketch how to add statically executable advice to AspectJ.
UCI Feb 03 41
package lawOfDemeter;public abstract class Any { public pointcut scope(): !within(lawOfDemeter..*) && !cflow(withincode(* lawOfDemeter..*(..))); public pointcut StaticInitialization(): scope() && staticinitialization(*); public pointcut MethodCallSite(): scope() && call(* *(..)); public pointcut ConstructorCall(): scope() && call(*.new (..)); public pointcut MethodExecution(): scope() && execution(* *(..)); public pointcut ConstructorExecution(): scope() && execution(*.new (..)); public pointcut Execution(): ConstructorExecution() || MethodExecution(); public pointcut MethodCall(Object thiz, Object target): MethodCallSite() && this(thiz) && target(target);
UCI Feb 03 42
public pointcut SelfCall(Object thiz, Object target): MethodCall(thiz, target) && if(thiz == target); public pointcut StaticCall(): scope() && call(static * *(..)); public pointcut Set(Object value): scope() && set(* *.*) && args(value); public pointcut Initialization(): scope() && initialization(*.new(..));}
Class Any continued
UCI Feb 03 43
package lawOfDemeter.objectform;import java.util.*;abstract class ObjectSupplier { protected boolean containsValue(Object supplier){ return targets.containsValue(supplier); } protected void add(Object key,Object value){ targets.put(key,value); } protected void addValue(Object supplier) { add(supplier,supplier); } protected void addAll(Object[] suppliers) { for(int i=0; i< suppliers.length; i++) addValue(suppliers[i]); } private IdentityHashMap targets = new IdentityHashMap();}
UCI Feb 03 44
package lawOfDemeter.objectform;public aspect Pertarget extends ObjectSupplier pertarget(Any.Initialization()) { before(Object value): Any.Set(value) { add(fieldIdentity(thisJoinPointStaticPart), value); } public boolean contains(Object target) { return super.containsValue(target) || Percflow.aspectOf().containsValue(target); } private String fieldIdentity(JoinPoint.StaticPart sp) { … } private static HashMap fieldNames = new HashMap();}
UCI Feb 03 45
package lawOfDemeter.objectform;aspect Check { private pointcut IgnoreCalls(): call(* java..*.*(..)); private pointcut IgnoreTargets(): get(static * java..*.*); after() returning(Object o):IgnoreTargets() { ignoredTargets.put(o,o); } after(Object thiz,Object target): Any.MethodCall(thiz, target) && !IgnoreCalls() { if (!ignoredTargets.containsKey(target) && !Pertarget.aspectOf(thiz).contains(target)) System.out.println( " !! LoD Object Violation !! " + thisJoinPointStaticPart/*[*/ + at(thisJoinPointStaticPart)/*]*/); } private IdentityHashMap ignoredTargets = new IdentityHashMap();}
UCI Feb 03 46
package lawOfDemeter.objectform;aspect Percflow extends ObjectSupplier percflow(Any.Execution() || Any.Initialization()){ before(): Any.Execution() { addValue(thisJoinPoint.getThis()); addAll(thisJoinPoint.getArgs()); } after() returning (Object result): Any.SelfCall(Object,Object) || Any.StaticCall() || Any.ConstructorCall() { addValue(result); }}
UCI Feb 03 47
Conclusions
• Aspects and adaptiveness must work closely together to achieve best results. Crosscutting is closely linked to adaptiveness.
• AspectJ and DemeterJ have been very well integrated (DAJ on Source Forge).
• AP is a specialization of AOP and AOP is a specialization of AP. It goes both ways.
• AspectJ is a really useful language but we are a little concerned about how difficult it was to debug the Law of Demeter checkers.
UCI Feb 03 48
UCI Feb 03 49
A O S D
UCI Feb 03 50
City = <routes> List(BusRoute) <flights> List(Flight).BusRoute = <cities> List(City).Flight = <cities> List(City).
City routes BusRoute cities City (routes BusRoute cities City)
{ City -> BusRoute bypassing CityBusRoute -> City bypassing City }source: City target: City
UCI Feb 03 51
Ordinary Java Class
class Main {
public static void main(String[] args) {
FileSystem fs = FileSystem.parse(new File(args[0]));
Commands script = Commands.parse(new File(args[1]));
script.interpret(fs.root);
System.out.println(" Status of File System ");
fs.root.listAll();
}
}
UCI Feb 03 52
Domain-specific aspect languages
• What is a good infrastructure for this?
• Goes back to the old theme of Crista: domain-specific aspect languages.
UCI Feb 03 53
Aspect-Oriented Programmingwith Extensible Plugins
• How can we integrate numerous domain specific aspect languages?
• Idea: Use AspectJ as basic aspect language and translate domain specific aspect languages to AspectJ.
• Case study: Redo DAJ in this style.
UCI Feb 03 54
Interfaces of Aspects
• For functionality– Expects– Provides
• For join points– Import– Export
UCI Feb 03 55
Kinds of Aspects
• Class Dictionary Aspect
• Traversal Aspect
• Traversal Advice Aspect
• AspectJ Aspect
• Class
Everything reduced to classes and AspectJ aspects
UCI Feb 03 56
Kinds of Aspects
• Class Dictionary Aspect– Imports: nothing (is a sink)– Exports: class graph nodes and edges– Expects: nothing (is a sink)– Provides: parser, numerous traversal advice (print, copy,
display, check, equal)
• Traversal Aspect– Imports: class graph nodes and edges– Exports: dynamic join points during traversal– Expects: traversal advice– Provides: (adaptive) methods
Import and exportJoin pointsDynamic/lexical
Provide and expectSomething executable
UCI Feb 03 57
Kinds of Aspects
• Traversal Advice Aspect– Imports: object graph slice nodes and edges– Exports: dynamic join points during visitor methods– Expects: methods – Provides: visitor methods (advice)
• AspectJ Aspect– Imports: class graph nodes, dynamic join points– Exports: dynamic join points during advice– Expects: abstract methods and pointcuts– Provides: advice, introductions
Import and exportJoin pointsDynamic/lexical
Provide and expectSomething executable
UCI Feb 03 58
ClassDictionary Aspect
aspect FileSys [ClassDictionary] {
FileSystem = <root> CompoundFile EOF.
File : SimpleFile | CompoundFile common
<name> Ident.
SimpleFile = "simple".
CompoundFile = "compound" <contents>
FileList [<parent> CompoundFile].
FileList ~ "(" { File } ")".
}
Join point examples
EBNF
UCI Feb 03 59
Traversal Aspect
aspect FileSystemTraversals [Traversal] {
declare strategy: eachFile: "intersect(from
CompoundFile to File, down)";
declare traversal:
void listAll() : eachFile(FileLister);
declare strategy: down: "from * bypassing ->
*,parent,* to *";
declare strategy: up: "from * bypassing ->
*,contents,* to *";
}Happens to be AspectJ code
UCI Feb 03 60
Need for Glue
• The class dictionary aspect and traversal aspect. Use name mapping:– CompoundFile, File, parent, content
• Need to check whether there is a path from CompoundFile to File in the class graph that is exported from the class dictionary aspect.
UCI Feb 03 61
Glue Aspect
aspect FileSystemMethods [Cd_Traversal] {
default name map;
// FileSys.CompoundFile =
// FileSystemTraversals.CompoundFile
// etc.
}
UCI Feb 03 62
AspectJ Aspect
aspect FileSystemMethods [AspectJ] { File CompoundFile.getFile(Ident name) { for (Iterator it = contents.iterator(); it.hasNext();) { File file = (File) it.next(); if (file.name.equals(name)) return file; } return null; }}
UCI Feb 03 63
Traversal Advice Aspect
aspect FileLister [TraversalAdvice] { Stack path = new Stack(); void before(File file) { path.push(file.name);} void after(File file) { System.out.print(" ."); Iterator it = path.iterator(); it.next(); while (it.hasNext()) System.out.print("/" + it.next()); System.out.println(); path.pop();}}
Happens to be a Java class
UCI Feb 03 64
LoD for Fred (D. Orleans)
• The set of potential preferred suppliers to a message-send expression M in the body of a branch B is the union of the objects in the following sets:
• the argument list A of the decision point E that caused the invocation of B;
• the associated values of E, that is, – the results of message-send expressions M' in the body of B
before M whose argument lists A' intersect with A;– instances that were created in the control flow of the body of B
before M.
Fred (AOSD 02): simplest AOP language: decision points, branches
UCI Feb 03 65
UCI Feb 03 66
Meta programProgramJoin point trees
Join point treesSubtrees
cflowNodes: *, ..,+Edges:
Meta classesClassesPathsets
Object treesSubtrees
from ANodes: *Edges: *
Meta aspectsAspects
Aspect object treeSubtrees
lexical
dynamic
UCI Feb 03 67
Meta programProgramLexical call graphJoin point trees
Join point trees =Dynamic call graphSubtrees
cflowNodes: *, ..,+Edges:
Meta classesClassesClass graphPathsets
Object trees
Subtreesfrom A
Nodes: *Edges: *
Meta aspectsAspectsAspect graph
Aspect object tree
Subtrees
lexical
dynamic
Reflection connections: CR, ARAspect extent: duration of method call, object only: context object paper.