aop - Pointcut for super() call to Java API -


i'm trying use aspectj hook calls java api. example, let's have aspect java.io.file:

import java.io.file;  aspect filetest {   file around(string arg0): args(arg0) && call(public file.new(string)) {     throw new runtimeexception("example");   } } 

this hooks calls file(string) constructor fine. not following code:

public class fileloophole extends file {     public fileloophole(string filename) {         super(filename);     } } 

according https://eclipse.org/aspectj/doc/next/progguide/language-joinpoints.html, should use execution() pointcut handle super() calls instead. however, doesn't work because execution point in java api, can't weave code into. there pointcut capture these super() callsites? there way without knowing fileloophole class beforehand?

you have 2 options:

  • use pattern file+ in order match pointcuts including subclasses. there no need know names.
  • use aspectj binary (post-compile) weaving , inject aspect code directly jdk classes rt.jar, creating modified version of or packaging modified jdk classes new jar , prepending boot classpath.

while former approach non-intrusive , independent of ability modify jdk in runtime environment, indirect , not asked for. latter approach asked not thing want except special cases.

driver application:

package de.scrum_master.app;  import java.io.file;  public class fileloophole extends file {     public fileloophole(string filename) {         super(filename);     }      public static void main(string[] args) {         new file("file.txt");         new fileloophole("loophole.txt");     } } 

aspect:

package de.scrum_master.aspect;  import java.io.file;  public aspect fileinterceptor {     object around(string filename): call(file+.new(string)) && args(filename) {         system.out.println(thisjoinpoint + " -> " + filename);         return proceed(filename);     }      void around(string filename): execution(file+.new(string))  && args(filename) {         system.out.println(thisjoinpoint + " -> " + filename);         proceed(filename);     } } 

console output:

call(java.io.file(string)) -> file.txt call(de.scrum_master.app.fileloophole(string)) -> loophole.txt execution(de.scrum_master.app.fileloophole(string)) -> loophole.txt 

p.s.: please note while call(*.new(..)) returns object, execution(*.new(..)) not, why around() advice's return type void. these semantics described in aspectj documentation.


update: asked inner classes in comment. well, pointcut works static inner classes without change. non-static inner class needs instance of surrounding class in constructor. check out, created class + debug aspect you:

package de.scrum_master.app;  import java.io.file;  public class application {     private class fileloophole extends file {         public fileloophole(string filename) {             super(filename);         }     }      public static void main(string[] args) {         new file("file.txt");         new application().new fileloophole("loophole.txt");     } } 
package de.scrum_master.aspect;  public aspect fileinterceptor {     before() : within(de.scrum_master.app.application) {         system.out.println(thisjoinpoint);     } } 

now @ console log:

staticinitialization(de.scrum_master.app.application.<clinit>) execution(void de.scrum_master.app.application.main(string[])) call(java.io.file(string)) call(de.scrum_master.app.application()) preinitialization(de.scrum_master.app.application()) initialization(de.scrum_master.app.application()) execution(de.scrum_master.app.application()) call(class java.lang.object.getclass()) call(de.scrum_master.app.application.fileloophole(application, string)) staticinitialization(de.scrum_master.app.application.fileloophole.<clinit>) preinitialization(de.scrum_master.app.application.fileloophole(application, string)) initialization(de.scrum_master.app.application.fileloophole(application, string)) execution(de.scrum_master.app.application.fileloophole(application, string)) 

as can see @ end of log, inner class's constructor converted takes surrounding class instance first parameter, mismatch. now, knowing that, can change our original pointcut in order capture constructors:

void around(): execution(file+.new(..)) {     system.out.println(thisjoinpoint);     proceed(); } 

if still want capture file name, gets little more complicated:

void around(string filename): execution(file+.new(*, string)) && args(*, filename) {     system.out.println(thisjoinpoint + " -> " + filename);     proceed(filename); } 

Comments