Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[aspectj-users] Restricting visibility of a method via AspectJ

Hi,

I had the idea that it should be possible to use an annotation to declare custom visibility of a method that is really public. You could use this to annotate methods that have been made public for unit testing, or because you just need 1 particular class in another package to use it.

I just want to put down what I have got so far, maybe others can build on it or improve if they like the idea.

Idea #1: Restrict the calling of the public method to test code (assuming TestNG here)

1) Create an annotation called @TestingOnly and put that on any method that only should be called by testing code

2) The following aspect should do it:
public aspect IllegalTestOnlyMethodCallChecker {
 
    declare error: testCallOutsideTestCode(): "Don't call test methods outside test code!";
 
    pointcut clientCall() : call(@TestingOnly * *(..)) 
    && !within(@org.testng.annotations.Test *) 
    && !withincode(@org.testng.annotations.Test * *(..)) ;
    }

Idea #2: Restrict the calling of a public method to only being called from an approved class

1) Create an annotation @RestrictedVisibility

@Retention(RetentionPolicy.RUNTIME)
public @interface RestrictedVisibility {
    Class allowedClass();
}

2) Use the annotation like this:

public class DomainObject {

    @RestrictedVisibility(allowedClass = TestService.class)
    public void domainMethod()  {
       
    }
}

This would mean that only TestService is allowed to call the method 'domainMethod'

3) Use this aspect

public aspect RestrictedVisibilityAspect {

    pointcut callToRestricted(Object targetObject, Object callingObject):call( @RestrictedVisibility * *(..) )
                                                            && target(targetObject)
                                                            && this(callingObject);
   
          
    before(Object targetObject, Object callingObject) : callToRestricted(targetObject, callingObject)
    {
        System.out.println( thisJoinPointStaticPart.getSignature() );
        System.out.println(targetObject);
        System.out.println(callingObject);
       
        Method m = ((MethodSignature)thisJoinPointStaticPart.getSignature()).getMethod();
        RestrictedVisibility rv = m.getAnnotation(RestrictedVisibility.class);
        if( rv.allowedClass().equals( callingObject.getClass() ))
        {
            System.out.println( "It is ok!");
        }
        else
        {
            System.out.println( "This call is not allowed!");
        }
    };
}

Note that I was not able to use declare error anymore due to the use of this() and target(). You should ofcourse throw a RunTimeException instead of just printing something like I did here.

Is it possible to avoid the reflection and casting?
Is anybody else using an Aspect simular to this?

regards,

Wim



Back to the top