123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- /* *******************************************************************
- * Copyright (c) 2005 Contributors.
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Public License v 2.0
- * which accompanies this distribution and is available at
- * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
- *
- * Contributors:
- * Adrian Colyer Initial implementation
- * ******************************************************************/
- package org.aspectj.weaver.reflect;
-
- import java.lang.reflect.Member;
-
- import org.aspectj.util.FuzzyBoolean;
- import org.aspectj.weaver.ResolvedType;
- import org.aspectj.weaver.World;
- import org.aspectj.weaver.ast.And;
- import org.aspectj.weaver.ast.Call;
- import org.aspectj.weaver.ast.FieldGetCall;
- import org.aspectj.weaver.ast.HasAnnotation;
- import org.aspectj.weaver.ast.ITestVisitor;
- import org.aspectj.weaver.ast.Instanceof;
- import org.aspectj.weaver.ast.Literal;
- import org.aspectj.weaver.ast.Not;
- import org.aspectj.weaver.ast.Or;
- import org.aspectj.weaver.ast.Test;
- import org.aspectj.weaver.ast.Var;
- import org.aspectj.weaver.internal.tools.MatchingContextBasedTest;
- import org.aspectj.weaver.patterns.ExposedState;
- import org.aspectj.weaver.tools.DefaultMatchingContext;
- import org.aspectj.weaver.tools.JoinPointMatch;
- import org.aspectj.weaver.tools.MatchingContext;
- import org.aspectj.weaver.tools.PointcutParameter;
- import org.aspectj.weaver.tools.ShadowMatch;
-
- /**
- * @author colyer Implementation of ShadowMatch for reflection based worlds.
- */
- public class ShadowMatchImpl implements ShadowMatch {
-
- private FuzzyBoolean match;
- private ExposedState state;
- private Test residualTest;
- private PointcutParameter[] params;
- private Member withinCode;
- private Member subject;
- private Class<?> withinType;
- private MatchingContext matchContext = new DefaultMatchingContext();
-
- public ShadowMatchImpl(FuzzyBoolean match, Test test, ExposedState state, PointcutParameter[] params) {
- this.match = match;
- this.residualTest = test;
- this.state = state;
- this.params = params;
- }
-
- public void setWithinCode(Member aMember) {
- this.withinCode = aMember;
- }
-
- public void setSubject(Member aMember) {
- this.subject = aMember;
- }
-
- public void setWithinType(Class<?> aClass) {
- this.withinType = aClass;
- }
-
- public boolean alwaysMatches() {
- return match.alwaysTrue();
- }
-
- public boolean maybeMatches() {
- return match.maybeTrue();
- }
-
- public boolean neverMatches() {
- return match.alwaysFalse();
- }
-
- public JoinPointMatch matchesJoinPoint(Object thisObject, Object targetObject, Object[] args) {
- if (neverMatches()) {
- return JoinPointMatchImpl.NO_MATCH;
- }
- if (new RuntimeTestEvaluator(residualTest, thisObject, targetObject, args, this.matchContext).matches()) {
- return new JoinPointMatchImpl(getPointcutParameters(thisObject, targetObject, args));
- } else {
- return JoinPointMatchImpl.NO_MATCH;
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.aspectj.weaver.tools.ShadowMatch#setMatchingContext(org.aspectj.weaver.tools.MatchingContext)
- */
- public void setMatchingContext(MatchingContext aMatchContext) {
- this.matchContext = aMatchContext;
- }
-
- private PointcutParameter[] getPointcutParameters(Object thisObject, Object targetObject, Object[] args) {
- Var[] vars = state.vars;
- PointcutParameterImpl[] bindings = new PointcutParameterImpl[params.length];
- for (int i = 0; i < bindings.length; i++) {
- bindings[i] = new PointcutParameterImpl(params[i].getName(), params[i].getType());
- bindings[i].setBinding(((ReflectionVar) vars[i]).getBindingAtJoinPoint(thisObject, targetObject, args, subject,
- withinCode, withinType));
- }
- return bindings;
- }
-
- private static class RuntimeTestEvaluator implements ITestVisitor {
-
- private boolean matches = true;
- private final Test test;
- private final Object thisObject;
- private final Object targetObject;
- private final Object[] args;
- private final MatchingContext matchContext;
-
- public RuntimeTestEvaluator(Test aTest, Object thisObject, Object targetObject, Object[] args, MatchingContext context) {
- this.test = aTest;
- this.thisObject = thisObject;
- this.targetObject = targetObject;
- this.args = args;
- this.matchContext = context;
- }
-
- public boolean matches() {
- test.accept(this);
- return matches;
- }
-
- public void visit(And e) {
- boolean leftMatches = new RuntimeTestEvaluator(e.getLeft(), thisObject, targetObject, args, matchContext).matches();
- if (!leftMatches) {
- matches = false;
- } else {
- matches = new RuntimeTestEvaluator(e.getRight(), thisObject, targetObject, args, matchContext).matches();
- }
- }
-
- public void visit(Instanceof instanceofTest) {
- ReflectionVar v = (ReflectionVar) instanceofTest.getVar();
- Object value = v.getBindingAtJoinPoint(thisObject, targetObject, args);
- World world = v.getType().getWorld();
- ResolvedType desiredType = instanceofTest.getType().resolve(world);
- if (value == null) {
- matches = false;
- } else {
- ResolvedType actualType = world.resolve(value.getClass().getName());
- matches = desiredType.isAssignableFrom(actualType);
- }
- }
-
- public void visit(MatchingContextBasedTest matchingContextTest) {
- matches = matchingContextTest.matches(this.matchContext);
- }
-
- public void visit(Not not) {
- matches = !new RuntimeTestEvaluator(not.getBody(), thisObject, targetObject, args, matchContext).matches();
- }
-
- public void visit(Or or) {
- boolean leftMatches = new RuntimeTestEvaluator(or.getLeft(), thisObject, targetObject, args, matchContext).matches();
- if (leftMatches) {
- matches = true;
- } else {
- matches = new RuntimeTestEvaluator(or.getRight(), thisObject, targetObject, args, matchContext).matches();
- }
- }
-
- public void visit(Literal literal) {
- if (literal == Literal.FALSE) {
- matches = false;
- } else {
- matches = true;
- }
- }
-
- public void visit(Call call) {
- throw new UnsupportedOperationException("Can't evaluate call test at runtime");
- }
-
- public void visit(FieldGetCall fieldGetCall) {
- throw new UnsupportedOperationException("Can't evaluate fieldGetCall test at runtime");
- }
-
- public void visit(HasAnnotation hasAnnotation) {
- ReflectionVar v = (ReflectionVar) hasAnnotation.getVar();
- Object value = v.getBindingAtJoinPoint(thisObject, targetObject, args);
- World world = v.getType().getWorld();
- ResolvedType actualVarType = world.resolve(value.getClass().getName());
- ResolvedType requiredAnnotationType = hasAnnotation.getAnnotationType().resolve(world);
- matches = actualVarType.hasAnnotation(requiredAnnotationType);
- }
-
- }
-
- }
|