    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
    015package org.apache.tapestry5.internal.plastic;
    016
    017import java.lang.annotation.Annotation;
    018import java.lang.reflect.Method;
    019
    020import org.apache.tapestry5.plastic.InstanceContext;
    021import org.apache.tapestry5.plastic.MethodInvocation;
    022
    023public 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    @Override
    051    public void rethrow()
    052    {
    053        if (checkedException != null)
    054            throw new RuntimeException(checkedException);
    055    }
    056
    057    @Override
    058    public boolean didThrowCheckedException()
    059    {
    060        return checkedException != null;
    061    }
    062
    063    @Override
    064    public <T extends Throwable> T getCheckedException(Class<T> exceptionType)
    065    {
    066        assert exceptionType != null;
    067
    068        if (exceptionType.isInstance(checkedException))
    069            return exceptionType.cast(checkedException);
    070
    071        return null;
    072    }
    073
    074    @Override
    075    public Object getInstance()
    076    {
    077        return instance;
    078    }
    079
    080    @Override
    081    public InstanceContext getInstanceContext()
    082    {
    083        return instanceContext;
    084    }
    085
    086    @Override
    087    public MethodInvocation proceed()
    088    {
    089        if (adviceIndex == bundle.advice.length)
    090            proceedToAdvisedMethod();
    091        else
    092            bundle.advice[adviceIndex++].advise(this);
    093
    094        return this;
    095    }
    096
    097    @Override
    098    public MethodInvocation setCheckedException(Exception exception)
    099    {
    100        checkedException = exception;
    101
    102        return this;
    103    }
    104
    105    @Override
    106    public <T extends Annotation> boolean hasAnnotation(Class<T> annotationType)
    107    {
    108        return getAnnotation(annotationType) != null;
    109    }
    110
    111    @Override
    112    public <T extends Annotation> T getAnnotation(Class<T> annotationType)
    113    {
    114        return getMethod().getAnnotation(annotationType);
    115    }
    116
    117    @Override
    118    public Method getMethod()
    119    {
    120        return bundle.getMethod(getInstance());
    121    }
    122
    123    /** This is implemented in a runtime-generated subclass. */
    124    protected abstract void proceedToAdvisedMethod();
    125}