Hi James,
nice to hear my code was somewhat useful.

Have you seen the comments on your feature request?

Simone

James Elliott wrote:
> I played with Simone's code a bit, and it does seem to work as described.
>
> Here's the solution I came up with for when the constructor call is
> made within a constructor call.
>
> This solution works assuming that the only places where A or it's
> subclasses are instantiated within the constructor of A or it's
> subclasses are in code that can be woven, which, for my project, is a
> safe assumption.
>
> I made the class abstract so that it can be easily reused whenever
> this pattern is appropriate.
>
> I don't like having the getMyClass() method, but I don't know of a
> good way to get the generic type without it.
>
> I am also caching the return value from isAssignableFrom, since this
> call appears to be relatively expensive in some versions of java.
>
> It's still a bit of a hack, but it seems to fulfill my needs.
>
> public abstract aspect InitializationAspect<T> {
>       /* Cache to avoid reflective calls */
>       private Map<String, Boolean> isAssignableMap = new HashMap<String, 
> Boolean>();
>       
>       /**
>        * Returns the class highest in the hierarchy.  Should be T.
>        */
>       protected abstract Class<T> getMyClass();
>       
>       /**
>        * The Advice to perform after an object has been instantiated.
>        * @param t The object that was created.
>        */
>       protected abstract void myAdvice(T t);
>       
>       /**
>        * Checks to make sure that the constructor that is executing
>        * is the type of the object to be created (i.e. lowest on the stack)
>        * and calls myAdvice() if it is. Does nothing if not.
>        * @param t The object that was created
>        */
>       after(T t) : execution(T+.new(..)) && this(t)  {
>               if (isLastConstructorInChain(getMyClass())) {
>                       myAdvice(t);
>               }
>       }
>       
>       /**
>        * Captures any calls to create a new object of type T or it's subtypes
>        * that happen within type T or it's subtypes, and calls myAdvice().
>        */
>       after() returning(T t): call(T+.new()) && withincode(T+.new(..)) {
>               myAdvice(t);
>       }
>       
>       /**
>        * Returns true if a class' constructor the lowest method call in a
>        * chain of constructor calls.  If it isn't, return true if the next 
> lowest
>        * call is not type T or a subclass of type T, false otherwise.
>        * @param clazz The class to look for.
>        */
>       public boolean isLastConstructorInChain(Class<?> clazz) {
>               StackTraceElement[] stackTrace =
>                       Thread.currentThread().getStackTrace();
>               
>               // find the first constructor, cause there are a few AspectJ
> internal calls before it
>               int acpos = 0;
>               while (acpos < stackTrace.length &&
>                               
> !stackTrace[acpos].getMethodName().equals("<init>")) {
>                       acpos++;
>               }
>               // Check if we run out, should never happen
>               if (acpos >= stackTrace.length) {
>                       return false;
>               }
>               // Now we have the last call to <init>
>               // if the following one is not a constructor (or is not 
> present),
>               // we can skip all the checks and return true
>               if (acpos + 1 == stackTrace.length ||
>                               !stackTrace[acpos + 
> 1].getMethodName().equals("<init>")) {
>                       return true;    
>               }
>               // Otherwise we have to check it the next constructor in the
>               // chain is a proper subclass of the current class
>               String callingClass = stackTrace[acpos + 1].getClassName();
>               
>               Boolean isAssignable = isAssignableMap.get(callingClass);
>               
>               if(isAssignable == null) {
>                       Class<?> forname = null;
>                       try {
>                               forname = Class.forName(callingClass);
>                       }
>                       catch (ClassNotFoundException e) {
>                               e.printStackTrace();
>                               isAssignable = false;
>                       }
>                       isAssignable = !clazz.isAssignableFrom(forname);
>                       
>                       isAssignableMap.put(callingClass, isAssignable);
>               }
>               return isAssignable;
>       }
> }
>
> public aspect AAspect extends InitializationAspect<A> {
>       protected Class<A> getMyClass() {
>               return A.class;
>       }
>       
>       protected void myAdvice(A a) {
>               System.out.println("Done:" + a.getClass());
>       }
> }
> _______________________________________________
> aspectj-users mailing list
> [email protected]
> https://dev.eclipse.org/mailman/listinfo/aspectj-users
>   


-- 
Simone Gianni
http://www.simonegianni.it/
CEO Semeru s.r.l.
Apache Committer

_______________________________________________
aspectj-users mailing list
[email protected]
https://dev.eclipse.org/mailman/listinfo/aspectj-users

Reply via email to