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
_______________________________________________
aspectj-users mailing list
aspectj-users@eclipse.org
https://dev.eclipse.org/mailman/listinfo/aspectj-users

Reply via email to