001    /*******************************************************************************
002     * Portions created by Sebastian Thomschke are copyright (c) 2005-2011 Sebastian
003     * Thomschke.
004     * 
005     * All Rights Reserved. This program and the accompanying materials
006     * are made available under the terms of the Eclipse Public License v1.0
007     * which accompanies this distribution, and is available at
008     * http://www.eclipse.org/legal/epl-v10.html
009     * 
010     * Contributors:
011     *     Sebastian Thomschke - initial implementation.
012     *******************************************************************************/
013    package net.sf.oval.guard;
014    
015    import java.lang.reflect.Constructor;
016    import java.lang.reflect.Method;
017    
018    import net.sf.oval.internal.Log;
019    import net.sf.oval.internal.util.Invocable;
020    
021    import org.aspectj.lang.ProceedingJoinPoint;
022    import org.aspectj.lang.annotation.Around;
023    import org.aspectj.lang.annotation.Aspect;
024    import org.aspectj.lang.annotation.DeclareParents;
025    import org.aspectj.lang.annotation.SuppressAjWarnings;
026    import org.aspectj.lang.reflect.ConstructorSignature;
027    import org.aspectj.lang.reflect.MethodSignature;
028    
029    /**
030     * This is an annotations based version of the GuardAspect aspect.
031     * 
032     * In contrast to GuardAspect no custom scopes are supported yet, 
033     * so only guarding based on the @Guarded annotation is possible right now.
034     *
035     * To workaround an AspectJ bug use the -XnoInline weave option, in case you are getting errors like:
036     * java.lang.VerifyError: (class: net/sf/oval/guard/GuardAspect2, method: ajc$inlineAccessMethod$net_sf_oval_guard_GuardAspect2$net_sf_oval_guard_Guard$guardMethodPost signature: (Lnet/sf/oval/guard/Guard;Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;Ljava/lang/Object;)V) Illegal use of nonvirtual function call
037     *
038     * @author Sebastian Thomschke
039     */
040    @Aspect
041    public abstract class GuardAspect2 extends ApiUsageAuditor2
042    {
043            private static final class ProceedInvocable implements Invocable
044            {
045                    final ProceedingJoinPoint thisJoinPoint;
046    
047                    protected ProceedInvocable(final ProceedingJoinPoint thisJoinPoint)
048                    {
049                            this.thisJoinPoint = thisJoinPoint;
050                    }
051    
052                    /**
053                     * {@inheritDoc}
054                     */
055                    public Object invoke() throws Throwable
056                    {
057                            return thisJoinPoint.proceed();
058                    }
059            }
060    
061            private static final Log LOG = Log.getLog(GuardAspect2.class);
062    
063            @SuppressWarnings("unused")
064            // add the IsGuarded marker interface to all classes annotated with @Guarded
065            @DeclareParents("(@net.sf.oval.guard.Guarded *)")
066            private IsGuarded implementedInterface;
067    
068            private Guard guard;
069    
070            /**
071             * Constructor instantiating a new Guard object.
072             */
073            public GuardAspect2()
074            {
075                    this(new Guard());
076                    getGuard().setParameterNameResolver(new ParameterNameResolverAspectJImpl());
077            }
078    
079            /**
080             * Constructor using the given Guard object
081             * @param guard the guard to use
082             */
083            public GuardAspect2(final Guard guard)
084            {
085                    LOG.info("Instantiated");
086    
087                    setGuard(guard);
088            }
089    
090            @Around("execution((@net.sf.oval.guard.Guarded *).new(..))")
091            public Object allConstructors(final ProceedingJoinPoint thisJoinPoint) throws Throwable
092            {
093                    final ConstructorSignature signature = (ConstructorSignature) thisJoinPoint.getSignature();
094    
095                    LOG.debug("aroundConstructor() {1}", signature);
096    
097                    final Constructor< ? > ctor = signature.getConstructor();
098                    final Object[] args = thisJoinPoint.getArgs();
099                    final Object target = thisJoinPoint.getTarget();
100    
101                    // pre conditions
102                    {
103                            guard.guardConstructorPre(target, ctor, args);
104                    }
105    
106                    final Object result = thisJoinPoint.proceed();
107    
108                    // post conditions
109                    {
110                            guard.guardConstructorPost(target, ctor, args);
111                    }
112    
113                    return result;
114            }
115    
116            @SuppressAjWarnings("adviceDidNotMatch")
117            @Around("execution(* (@net.sf.oval.guard.Guarded *).*(..))")
118            public Object allMethods(final ProceedingJoinPoint thisJoinPoint) throws Throwable
119            {
120                    final MethodSignature signature = (MethodSignature) thisJoinPoint.getSignature();
121    
122                    LOG.debug("aroundMethod() {1}", signature);
123    
124                    final Method method = signature.getMethod();
125                    final Object[] args = thisJoinPoint.getArgs();
126                    final Object target = thisJoinPoint.getTarget();
127    
128                    return guard.guardMethod(target, method, args, new ProceedInvocable(thisJoinPoint));
129            }
130    
131            /**
132             * @return the guard
133             */
134            public Guard getGuard()
135            {
136                    return guard;
137            }
138    
139            public final void setGuard(final Guard guard)
140            {
141                    this.guard = guard;
142            }
143    }