Package org.codehaus.aspectwerkz.intercept

Source Code of org.codehaus.aspectwerkz.intercept.AdvisableImpl

/**************************************************************************************
* Copyright (c) Jonas Bon�r, Alexandre Vasseur. All rights reserved.                 *
* http://aspectwerkz.codehaus.org                                                    *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the LGPL license      *
* a copy of which has been included with this distribution in the license.txt file.  *
**************************************************************************************/
package org.codehaus.aspectwerkz.intercept;

import java.util.ArrayList;
import java.util.List;

import gnu.trove.TIntObjectHashMap;
import org.codehaus.aspectwerkz.reflect.ClassInfo;
import org.codehaus.aspectwerkz.reflect.MethodInfo;
import org.codehaus.aspectwerkz.reflect.FieldInfo;
import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo;
import org.codehaus.aspectwerkz.reflect.impl.java.JavaClassInfo;
import org.codehaus.aspectwerkz.expression.ExpressionVisitor;
import org.codehaus.aspectwerkz.expression.PointcutType;
import org.codehaus.aspectwerkz.expression.ExpressionContext;
import org.codehaus.aspectwerkz.expression.ExpressionInfo;
import org.codehaus.aspectwerkz.transform.inlining.AsmHelper;
import org.codehaus.aspectwerkz.transform.TransformationConstants;

/**
* Implementation of the <code>Advisable</code> mixin.
*
* @author <a href="mailto:jboner@codehaus.org">Jonas Bon�r </a>
*/
public class AdvisableImpl implements Advisable {

    private static final String EXPRESSION_NAMESPACE = "___AW_ADVISABLE_AW___";

    public static final ClassInfo CLASS_INFO;
    public static final AroundAdvice[] EMPTY_AROUND_ADVICE_ARRAY = new AroundAdvice[0];
    public static final BeforeAdvice[] EMPTY_BEFORE_ADVICE_ARRAY = new BeforeAdvice[0];
    public static final AfterAdvice[] EMPTY_AFTER_ADVICE_ARRAY = new AfterAdvice[0];
    public static final AfterReturningAdvice[] EMPTY_AFTER_RETURNING_ADVICE_ARRAY = new AfterReturningAdvice[0];
    public static final AfterThrowingAdvice[] EMPTY_AFTER_THROWING_ADVICE_ARRAY = new AfterThrowingAdvice[0];

    static {
        final Class clazz = AdvisableImpl.class;
        try {
            CLASS_INFO = AsmClassInfo.getClassInfo(clazz.getName(), clazz.getClassLoader());
        } catch (Exception e) {
            throw new Error("could not create class info for [" + clazz.getName() + ']');
        }
    }

    private final Advisable m_targetInstance;

    private final TIntObjectHashMap m_aroundAdvice = new TIntObjectHashMap();
    private final TIntObjectHashMap m_beforeAdvice = new TIntObjectHashMap();
    private final TIntObjectHashMap m_afterAdvice = new TIntObjectHashMap();
    private final TIntObjectHashMap m_afterReturningAdvice = new TIntObjectHashMap();
    private final TIntObjectHashMap m_afterThrowingAdvice = new TIntObjectHashMap();

    /**
     * Creates a new mixin impl.
     *
     * @param targetInstance the target for this mixin instance (perInstance deployed)
     */
    public AdvisableImpl(final Object targetInstance) {
        if (!(targetInstance instanceof Advisable)) {
            throw new RuntimeException(
                    "advisable mixin applied to target class that does not implement the Advisable interface"
            );
        }
        m_targetInstance = (Advisable) targetInstance;
    }

    /**
     * @param pattern
     * @param advice
     */
    public void aw$addAdvice(final String pattern, final Advice advice) {
        ClassInfo classInfo = JavaClassInfo.getClassInfo(m_targetInstance.getClass());
        boolean hasParenthesis = pattern.indexOf('(') > -1;
        boolean hasSpace = pattern.indexOf(' ') > -1;
        if (hasParenthesis) {
            addAdviceToMethods(pattern, advice, classInfo.getMethods());
        } else if (hasSpace) {
            addAdviceToFields(pattern, advice, classInfo.getFields());
        } else {
            addAdviceToCatchHandlers(pattern, advice);
        }
    }

    /**
     * @param pattern
     * @param adviceClass
     */
    public void aw$removeAdvice(final String pattern, final Class adviceClass) {
        ClassInfo classInfo = JavaClassInfo.getClassInfo(m_targetInstance.getClass());
        boolean hasParenthesis = pattern.indexOf('(') > -1;
        boolean hasSpace = pattern.indexOf(' ') > -1;
        if (hasParenthesis) {
            removeAdviceFromMethods(pattern, adviceClass, classInfo.getMethods());
        } else if (hasSpace) {
            removeAdviceFromFields(pattern, adviceClass, classInfo.getFields());
        } else {
            removeAdviceFromCatchHandlers(pattern, adviceClass);
        }
    }

    /**
     * @param joinPointIndex
     * @return
     */
    public AroundAdvice[] aw$getAroundAdvice(final int joinPointIndex) {
        Object advice = m_aroundAdvice.get(joinPointIndex);
        if (advice == null) {
            return EMPTY_AROUND_ADVICE_ARRAY;
        } else {
            return (AroundAdvice[]) advice;
        }
    }

    /**
     * @param joinPointIndex
     * @return
     */
    public BeforeAdvice[] aw$getBeforeAdvice(final int joinPointIndex) {
        Object advice = m_beforeAdvice.get(joinPointIndex);
        if (advice == null) {
            return EMPTY_BEFORE_ADVICE_ARRAY;
        } else {
            return (BeforeAdvice[]) advice;
        }
    }

    /**
     * @param joinPointIndex
     * @return
     */
    public AfterAdvice[] aw$getAfterAdvice(final int joinPointIndex) {
        Object advice = m_afterAdvice.get(joinPointIndex);
        if (advice == null) {
            return EMPTY_AFTER_ADVICE_ARRAY;
        } else {
            return (AfterAdvice[]) advice;
        }
    }

    /**
     * @param joinPointIndex
     * @return
     */
    public AfterReturningAdvice[] aw$getAfterReturningAdvice(final int joinPointIndex) {
        Object advice = m_afterReturningAdvice.get(joinPointIndex);
        if (advice == null) {
            return EMPTY_AFTER_RETURNING_ADVICE_ARRAY;
        } else {
            return (AfterReturningAdvice[]) advice;
        }
    }

    /**
     * @param joinPointIndex
     * @return
     */
    public AfterThrowingAdvice[] aw$getAfterThrowingAdvice(final int joinPointIndex) {
        Object advice = m_afterThrowingAdvice.get(joinPointIndex);
        if (advice == null) {
            return EMPTY_AFTER_THROWING_ADVICE_ARRAY;
        } else {
            return (AfterThrowingAdvice[]) advice;
        }
    }

    /**
     * @param methodPattern
     * @param advice
     * @param methods
     */
    private void addAdviceToMethods(final String methodPattern,
                                    final Advice advice,
                                    final MethodInfo[] methods) {
        ExpressionInfo expressionInfo = new ExpressionInfo("execution(" + methodPattern + ')', EXPRESSION_NAMESPACE);
        ExpressionVisitor expression = expressionInfo.getExpression();
        for (int i = 0; i < methods.length; i++) {
            MethodInfo method = methods[i];
            if (method.getName().startsWith(TransformationConstants.SYNTHETIC_MEMBER_PREFIX)) {
                continue;
            }
            if (expression.match(new ExpressionContext(PointcutType.EXECUTION, method, null))) {
                int joinPointHash = AsmHelper.calculateMethodHash(method.getName(), method.getSignature());
                addAroundAdvice(advice, joinPointHash);
                addBeforeAdvice(advice, joinPointHash);
                addAfterAdvice(advice, joinPointHash);
                addAfterReturningAdvice(advice, joinPointHash);
                addAfterThrowingAdvice(advice, joinPointHash);
            }
        }
    }

    /**
     * @param fieldPattern
     * @param advice
     * @param fields
     */
    private void addAdviceToFields(final String fieldPattern,
                                   final Advice advice,
                                   final FieldInfo[] fields) {
        ExpressionInfo expressionInfo = new ExpressionInfo("set(" + fieldPattern + ')', EXPRESSION_NAMESPACE);
        ExpressionVisitor expression = expressionInfo.getExpression();
        for (int i = 0; i < fields.length; i++) {
            FieldInfo field = fields[i];
            if (field.getName().startsWith(TransformationConstants.SYNTHETIC_MEMBER_PREFIX)) {
                continue;
            }
            if (expression.match(new ExpressionContext(PointcutType.SET, field, null))) {
                int joinPointHash = AsmHelper.calculateFieldHash(field.getName(), field.getSignature());
                addAroundAdvice(advice, joinPointHash);
                addBeforeAdvice(advice, joinPointHash);
                addAfterAdvice(advice, joinPointHash);
                addAfterReturningAdvice(advice, joinPointHash);
                addAfterThrowingAdvice(advice, joinPointHash);
            }
        }
    }

    /**
     * @param typeName
     * @param advice
     */
    private void addAdviceToCatchHandlers(final String typeName, final Advice advice) {
        int joinPointHash = AsmHelper.calculateClassHash('L' + typeName.replace('.', '/') + ';');
        addBeforeAdvice(advice, joinPointHash);
    }

    /**
     * @param methodPattern
     * @param adviceClass
     * @param methods
     */
    private void removeAdviceFromMethods(final String methodPattern,
                                         final Class adviceClass,
                                         final MethodInfo[] methods) {
        ExpressionInfo expressionInfo = new ExpressionInfo("execution(" + methodPattern + ')', EXPRESSION_NAMESPACE);
        ExpressionVisitor expression = expressionInfo.getExpression();
        for (int i = 0; i < methods.length; i++) {
            MethodInfo method = methods[i];
            if (method.getName().startsWith(TransformationConstants.SYNTHETIC_MEMBER_PREFIX)) {
                continue;
            }
            if (expression.match(new ExpressionContext(PointcutType.EXECUTION, method, null))) {
                int joinPointHash = AsmHelper.calculateMethodHash(method.getName(), method.getSignature());
                removeAroundAdvice(adviceClass, joinPointHash);
                removeBeforeAdvice(adviceClass, joinPointHash);
                removeAfterAdvice(adviceClass, joinPointHash);
                removeAfterReturningAdvice(adviceClass, joinPointHash);
                removeAfterThrowingAdvice(adviceClass, joinPointHash);
            }
        }
    }

    /**
     * @param fieldPattern
     * @param adviceClass
     * @param fields
     */
    private void removeAdviceFromFields(final String fieldPattern,
                                        final Class adviceClass,
                                        final FieldInfo[] fields) {
        ExpressionInfo expressionInfo = new ExpressionInfo("set(" + fieldPattern + ')', EXPRESSION_NAMESPACE);
        ExpressionVisitor expression = expressionInfo.getExpression();
        for (int i = 0; i < fields.length; i++) {
            FieldInfo field = fields[i];
            if (field.getName().startsWith(TransformationConstants.SYNTHETIC_MEMBER_PREFIX)) {
                continue;
            }
            if (expression.match(new ExpressionContext(PointcutType.SET, field, null))) {
                int joinPointHash = AsmHelper.calculateFieldHash(field.getName(), field.getSignature());
                removeAroundAdvice(adviceClass, joinPointHash);
                removeBeforeAdvice(adviceClass, joinPointHash);
                removeAfterAdvice(adviceClass, joinPointHash);
                removeAfterReturningAdvice(adviceClass, joinPointHash);
                removeAfterThrowingAdvice(adviceClass, joinPointHash);
            }
        }
    }

    /**
     * @param typeName
     * @param adviceClass
     */
    private void removeAdviceFromCatchHandlers(final String typeName, final Class adviceClass) {
        int joinPointHash = AsmHelper.calculateClassHash('L' + typeName.replace('.', '/') + ';');
        removeBeforeAdvice(adviceClass, joinPointHash);
    }

    /**
     * @param advice
     * @param joinPointHash
     */
    private void addAroundAdvice(final Advice advice, int joinPointHash) {
        if (advice instanceof AroundAdvice) {
            AroundAdvice aroundAdvice = (AroundAdvice) advice;
            AroundAdvice[] advices;
            AroundAdvice[] olds = aw$getAroundAdvice(joinPointHash);
            if (olds != null) {
                advices = new AroundAdvice[olds.length + 1];
                System.arraycopy(olds, 0, advices, 0, olds.length);
                advices[advices.length - 1] = aroundAdvice;
            } else {
                advices = new AroundAdvice[]{aroundAdvice};
            }
            m_aroundAdvice.put(joinPointHash, advices);
        }
    }

    /**
     * @param advice
     * @param joinPointHash
     */
    private void addBeforeAdvice(final Advice advice, int joinPointHash) {
        if (advice instanceof BeforeAdvice) {
            BeforeAdvice beforeAdvice = (BeforeAdvice) advice;
            BeforeAdvice[] advices;
            BeforeAdvice[] olds = aw$getBeforeAdvice(joinPointHash);
            if (olds != null) {
                advices = new BeforeAdvice[olds.length + 1];
                System.arraycopy(olds, 0, advices, 0, olds.length);
                advices[advices.length - 1] = beforeAdvice;
            } else {
                advices = new BeforeAdvice[]{beforeAdvice};
            }
            m_beforeAdvice.put(joinPointHash, advices);
        }
    }

    /**
     * @param advice
     * @param joinPointHash
     */
    private void addAfterAdvice(final Advice advice, int joinPointHash) {
        if (advice instanceof AfterAdvice) {
            AfterAdvice afterFinallyAdvice = (AfterAdvice) advice;
            AfterAdvice[] advices;
            AfterAdvice[] olds = aw$getAfterAdvice(joinPointHash);
            if (olds != null) {
                advices = new AfterAdvice[olds.length + 1];
                System.arraycopy(olds, 0, advices, 0, olds.length);
                advices[advices.length - 1] = afterFinallyAdvice;
            } else {
                advices = new AfterAdvice[]{afterFinallyAdvice};
            }
            m_afterAdvice.put(joinPointHash, advices);
        }
    }

    /**
     * @param advice
     * @param joinPointHash
     */
    private void addAfterReturningAdvice(final Advice advice, int joinPointHash) {
        if (advice instanceof AfterReturningAdvice) {
            AfterReturningAdvice afterReturningAdvice = (AfterReturningAdvice) advice;
            AfterReturningAdvice[] advices;
            AfterReturningAdvice[] olds = aw$getAfterReturningAdvice(joinPointHash);
            if (olds != null) {
                advices = new AfterReturningAdvice[olds.length + 1];
                System.arraycopy(olds, 0, advices, 0, olds.length);
                advices[advices.length - 1] = afterReturningAdvice;
            } else {
                advices = new AfterReturningAdvice[]{afterReturningAdvice};
            }
            m_afterReturningAdvice.put(joinPointHash, advices);
        }
    }

    /**
     * @param advice
     * @param joinPointHash
     */
    private void addAfterThrowingAdvice(final Advice advice, int joinPointHash) {
        if (advice instanceof AfterThrowingAdvice) {
            AfterThrowingAdvice afterThrowingAdvice = (AfterThrowingAdvice) advice;
            AfterThrowingAdvice[] advices;
            AfterThrowingAdvice[] olds = aw$getAfterThrowingAdvice(joinPointHash);
            if (olds != null) {
                advices = new AfterThrowingAdvice[olds.length + 1];
                System.arraycopy(olds, 0, advices, 0, olds.length);
                advices[advices.length - 1] = afterThrowingAdvice;
            } else {
                advices = new AfterThrowingAdvice[]{afterThrowingAdvice};
            }
            m_afterThrowingAdvice.put(joinPointHash, advices);
        }
    }

    /**
     * @param adviceClass
     * @param joinPointHash
     */
    private void removeAroundAdvice(final Class adviceClass, int joinPointHash) {
        if (isAroundAdvice(adviceClass)) {
            AroundAdvice[] oldArray = aw$getAroundAdvice(joinPointHash);
            if (oldArray.length == 0) {
            } else if (oldArray.length == 1) {
                m_aroundAdvice.put(joinPointHash, EMPTY_AROUND_ADVICE_ARRAY);
            } else {
                List newArrayList = new ArrayList();
                for (int i = 0; i < oldArray.length; i++) {
                    AroundAdvice aroundAdvice = oldArray[i];
                    if (!aroundAdvice.getClass().equals(adviceClass)) {
                        newArrayList.add(aroundAdvice);
                    }
                }
                m_aroundAdvice.put(
                        joinPointHash,
                        (AroundAdvice[]) newArrayList.toArray(new AroundAdvice[newArrayList.size()])
                );
            }
        }
    }

    /**
     * @param adviceClass
     * @param joinPointHash
     */
    private void removeBeforeAdvice(final Class adviceClass, int joinPointHash) {
        if (isBeforeAdvice(adviceClass)) {
            BeforeAdvice[] oldArray = aw$getBeforeAdvice(joinPointHash);
            if (oldArray.length == 0) {
            } else if (oldArray.length == 1) {
                m_beforeAdvice.put(joinPointHash, EMPTY_BEFORE_ADVICE_ARRAY);
            } else {
                List newArrayList = new ArrayList();
                for (int i = 0; i < oldArray.length; i++) {
                    BeforeAdvice beforeAdvice = oldArray[i];
                    if (!beforeAdvice.getClass().equals(adviceClass)) {
                        newArrayList.add(beforeAdvice);
                    }
                }
                m_beforeAdvice.put(
                        joinPointHash,
                        (BeforeAdvice[]) newArrayList.toArray(new BeforeAdvice[newArrayList.size()])
                );
            }
        }
    }

    /**
     * @param adviceClass
     * @param joinPointHash
     */
    private void removeAfterAdvice(final Class adviceClass, int joinPointHash) {
        if (isAfterAdvice(adviceClass)) {
            AfterAdvice[] oldArray = aw$getAfterAdvice(joinPointHash);
            if (oldArray.length == 0) {
            } else if (oldArray.length == 1) {
                m_afterAdvice.put(joinPointHash, EMPTY_AFTER_ADVICE_ARRAY);
            } else {
                List newArrayList = new ArrayList();
                for (int i = 0; i < oldArray.length; i++) {
                    AfterAdvice afterAdvice = oldArray[i];
                    if (!afterAdvice.getClass().equals(adviceClass)) {
                        newArrayList.add(afterAdvice);
                    }
                }
                m_afterAdvice.put(
                        joinPointHash,
                        (AfterAdvice[]) newArrayList.toArray(new AfterAdvice[newArrayList.size()])
                );
            }
        }
    }

    /**
     * @param adviceClass
     * @param joinPointHash
     */
    private void removeAfterReturningAdvice(final Class adviceClass, int joinPointHash) {
        if (isAfterReturningAdvice(adviceClass)) {
            AfterReturningAdvice[] oldArray = aw$getAfterReturningAdvice(joinPointHash);
            if (oldArray.length == 0) {
            } else if (oldArray.length == 1) {
                m_afterReturningAdvice.put(joinPointHash, EMPTY_AFTER_RETURNING_ADVICE_ARRAY);
            } else {
                List newArrayList = new ArrayList();
                for (int i = 0; i < oldArray.length; i++) {
                    AfterReturningAdvice afterReturningAdvice = oldArray[i];
                    if (!afterReturningAdvice.getClass().equals(adviceClass)) {
                        newArrayList.add(afterReturningAdvice);
                    }
                }
                m_afterReturningAdvice.put(
                        joinPointHash,
                        (AfterReturningAdvice[]) newArrayList.toArray(new AfterReturningAdvice[newArrayList.size()])
                );
            }
        }
    }

    /**
     * @param adviceClass
     * @param joinPointHash
     */
    private void removeAfterThrowingAdvice(final Class adviceClass, int joinPointHash) {
        if (isAfterThrowingAdvice(adviceClass)) {
            AfterThrowingAdvice[] oldArray = aw$getAfterThrowingAdvice(joinPointHash);
            if (oldArray.length == 0) {
            } else if (oldArray.length == 1) {
                m_afterThrowingAdvice.put(joinPointHash, EMPTY_AFTER_THROWING_ADVICE_ARRAY);
            } else {
                List newArrayList = new ArrayList();
                for (int i = 0; i < oldArray.length; i++) {
                    AfterThrowingAdvice advice = oldArray[i];
                    if (!advice.getClass().equals(adviceClass)) {
                        newArrayList.add(advice);
                    }
                }
                m_afterThrowingAdvice.put(
                        joinPointHash,
                        (AfterThrowingAdvice[]) newArrayList.toArray(new AfterThrowingAdvice[newArrayList.size()])
                );
            }
        }
    }

    private boolean isAroundAdvice(final Class adviceClass) {
        if (adviceClass == AroundAdvice.class) {
            return true;
        }
        Class[] interfaces = adviceClass.getInterfaces();
        for (int i = 0; i < interfaces.length; i++) {
            Class anInterface = interfaces[i];
            if (anInterface == AroundAdvice.class) {
                return true;
            }
        }
        return false;
    }

    private boolean isBeforeAdvice(final Class adviceClass) {
        if (adviceClass == BeforeAdvice.class) {
            return true;
        }
        Class[] interfaces = adviceClass.getInterfaces();
        for (int i = 0; i < interfaces.length; i++) {
            Class anInterface = interfaces[i];
            if (anInterface == BeforeAdvice.class) {
                return true;
            }
        }
        return false;
    }

    private boolean isAfterAdvice(final Class adviceClass) {
        if (adviceClass == AfterAdvice.class) {
            return true;
        }
        Class[] interfaces = adviceClass.getInterfaces();
        for (int i = 0; i < interfaces.length; i++) {
            Class anInterface = interfaces[i];
            if (anInterface == AfterAdvice.class) {
                return true;
            }
        }
        return false;
    }

    private boolean isAfterReturningAdvice(final Class adviceClass) {
        if (adviceClass == AfterReturningAdvice.class) {
            return true;
        }
        Class[] interfaces = adviceClass.getInterfaces();
        for (int i = 0; i < interfaces.length; i++) {
            Class anInterface = interfaces[i];
            if (anInterface == AfterReturningAdvice.class) {
                return true;
            }
        }
        return false;
    }

    private boolean isAfterThrowingAdvice(final Class adviceClass) {
        if (adviceClass == AfterThrowingAdvice.class) {
            return true;
        }
        Class[] interfaces = adviceClass.getInterfaces();
        for (int i = 0; i < interfaces.length; i++) {
            Class anInterface = interfaces[i];
            if (anInterface == AfterThrowingAdvice.class) {
                return true;
            }
        }
        return false;
    }
}
TOP

Related Classes of org.codehaus.aspectwerkz.intercept.AdvisableImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.