/// each aspect should be in separate file, just gathered for convenience... import java.io.PrintStream; import javax.swing.*; // Cross cutting aspects of the program: (for base aop18.java) aspect trace // trace the construction of each object, plus run function { // after advice after(Object c) : (execution(student+.new(..)) || execution(pc.new(..)) || execution(vehicle.new(..))) && target(c) && !adviceexecution() { System.out.println("Object created: "+c ); } }//trace // aspect Auto-retry aspect FaultTolerance // only use on stateless functions { private static int max = 3; public static void setmax(int m) {max=m;} void around(Object c): call(void *.run()) && target(c) { int cx = max; // allow 3 attempts to run while (cx-- >0) { try { proceed(c); // proceed with run() on target c cx = 0; // stops while loop } catch (RuntimeException re) { System.out.println(re); if (cx==0) System.out.println("run failed after "+max+" tries"); } }//while }//around advice } // censorship advice aspect WholesomeOutput { void around(String s):call( void PrintStream+.print*(..)) && args(s,..) { s = s.replaceAll("hell","heck"); s = s.replaceAll("damn","darn"); s = s.replaceAll("Liang is bad.","Liang is badass."); proceed(s); } } // Real extension methods, supporting dynamic dispatch class studentathlete extends student { String sport = "basketball"; public studentathlete(String n) { super(n); } public void run() { System.out.println("whoooosh!"); } } // aspect to add new method to both student and studentathlete interface stuinterface { int tuition(); } privileged aspect extendstudent // privileged can access private fields { declare parents: student implements stuinterface; // now *obligated* to extend student classes public int student.tuition() { if (this.gpa>3.7) return 10000; // scholarship student else return 40000; } public int studentathlete.tuition() { return 0; } // all student athletes are on scholarship // changing main without changing main... after() : execution(public static void *.main(String[])) { student s1 = new studentathlete("Farma Nimal"); System.out.println(s1.tuition()); // dynamic dispatch? YES } }//extendstudent privileged aspect privileged aspect extendinterface // add method to existing interface { public abstract void stuinterface.whine(); public void student.whine() { System.out.println("2pm is too early for me! Too much math!"); } student s; // instance of student to be captured on creation after(student stu) : execution(public student+.new(..)) && target(stu) { s = stu; } // capture student instance to be used in next advice: after() : execution(public static void *.main(String[])) { System.out.print(s.name+" is whining: "); s.whine(); s.changeGPA(4.0); // used with next aspect } } // currently extendstudent advice has precedence over extendinterface aspect orderaspects { declare precedence: extendinterface, extendstudent; } privileged aspect secureGPA // securely change the GPA (private is not secure) { public void student.changeGPA(double gpa) { this.gpa = gpa; } private String student.password; // private within aspect, not student static String randomstring() // utility function { int n = (int)(Math.random()*5)+4; // random password length; String s = ""; for(;n>0;n--) s+=(char)( (int)(Math.random()*26)+97 ); //lower case return s; } after(student s): execution(public student.new(..)) && target(s) { s.password = randomstring(); // generate random password JOptionPane.showMessageDialog(null, s.name+", Your password is "+s.password); } before(student s): call(void student.changeGPA(double)) && target(s) { String pswd = JOptionPane.showInputDialog(null, s.name+", Enter password: "); if (!s.password.equals(pswd)) throw new RuntimeException("Wrong password. Beware of motherhackers!"); } }//secureGPA // not really secure until you encrypt it and only present the encrypted // version ...