    001    // Copyright 2011 The Apache Software Foundation
    002    //
    003    // Licensed under the Apache License, Version 2.0 (the "License");
    004    // you may not use this file except in compliance with the License.
    005    // You may obtain a copy of the License at
    006    //
    007    // http://www.apache.org/licenses/LICENSE-2.0
    008    //
    009    // Unless required by applicable law or agreed to in writing, software
    010    // distributed under the License is distributed on an "AS IS" BASIS,
    011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012    // See the License for the specific language governing permissions and
    013    // limitations under the License.
    014
    015    package org.apache.tapestry5.internal.plastic;
    016
    017    import java.lang.annotation.Annotation;
    018    import java.lang.reflect.Method;
    019
    020    import org.apache.tapestry5.plastic.InstanceContext;
    021    import org.apache.tapestry5.plastic.MethodInvocation;
    022
    023    public abstract class AbstractMethodInvocation implements MethodInvocation
    024    {
    025        private final Object instance;
    026
    027        private final InstanceContext instanceContext;
    028
    029        private final MethodInvocationBundle bundle;
    030
    031        private int adviceIndex;
    032
    033        protected AbstractMethodInvocation(Object instance, InstanceContext instanceContext, MethodInvocationBundle bundle)
    034        {
    035            this.instance = instance;
    036            this.instanceContext = instanceContext;
    037            this.bundle = bundle;
    038        }
    039
    040        private Exception checkedException;
    041
    042        /**
    043         * Invoked from the implementation of {@link MethodInvocation#setReturnValue(Object)}.
    044         */
    045        protected void clearCheckedException()
    046        {
    047            checkedException = null;
    048        }
    049
    050        public void rethrow()
    051        {
    052            if (checkedException != null)
    053                throw new RuntimeException(checkedException);
    054        }
    055
    056        public boolean didThrowCheckedException()
    057        {
    058            return checkedException != null;
    059        }
    060
    061        public <T extends Throwable> T getCheckedException(Class<T> exceptionType)
    062        {
    063            assert exceptionType != null;
    064
    065            if (exceptionType.isInstance(checkedException))
    066                return exceptionType.cast(checkedException);
    067
    068            return null;
    069        }
    070
    071        public Object getInstance()
    072        {
    073            return instance;
    074        }
    075
    076        public InstanceContext getInstanceContext()
    077        {
    078            return instanceContext;
    079        }
    080
    081        public MethodInvocation proceed()
    082        {
    083            if (adviceIndex == bundle.advice.length)
    084                proceedToAdvisedMethod();
    085            else
    086                bundle.advice[adviceIndex++].advise(this);
    087
    088            return this;
    089        }
    090
    091        public MethodInvocation setCheckedException(Exception exception)
    092        {
    093            checkedException = exception;
    094
    095            return this;
    096        }
    097
    098        public <T extends Annotation> boolean hasAnnotation(Class<T> annotationType)
    099        {
    100            return getAnnotation(annotationType) != null;
    101        }
    102
    103        public <T extends Annotation> T getAnnotation(Class<T> annotationType)
    104        {
    105            return getMethod().getAnnotation(annotationType);
    106        }
    107
    108        public Method getMethod()
    109        {
    110            return bundle.getMethod(getInstance());
    111        }
    112
    113        /** This is implemented in a runtime-generated subclass. */
    114        protected abstract void proceedToAdvisedMethod();
    115    }