/* *******************************************************************
 * Copyright (c) 2005 Contributors.
 * All rights reserved. 
 * This program and the accompanying materials are made available 
 * under the terms of the Eclipse Public License v1.0 
 * which accompanies this distribution and is available at 
 * http://eclipse.org/legal/epl-v10.html 
 *  
 * Contributors: 
 *   Adrian Colyer			Initial implementation
 * ******************************************************************/
package org.aspectj.weaver.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.aspectj.bridge.ISourceLocation;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.World;
import org.aspectj.weaver.ast.Var;
import org.aspectj.weaver.tools.MatchingContext;

Author:colyer
/** * @author colyer * */
public class ReflectionShadow extends Shadow { private final World world; private final ResolvedType enclosingType; private final ResolvedMember enclosingMember; private final MatchingContext matchContext; private Var thisVar = null; private Var targetVar = null; private Var[] argsVars = null; private Var atThisVar = null; private Var atTargetVar = null; private Map atArgsVars = new HashMap(); private Map withinAnnotationVar = new HashMap(); private Map withinCodeAnnotationVar = new HashMap(); private Map annotationVar = new HashMap(); private AnnotationFinder annotationFinder; public static Shadow makeExecutionShadow(World inWorld, java.lang.reflect.Member forMethod, MatchingContext withContext) { Kind kind = (forMethod instanceof Method) ? Shadow.MethodExecution : Shadow.ConstructorExecution; Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(forMethod, inWorld); ResolvedType enclosingType = signature.getDeclaringType().resolve(inWorld); return new ReflectionShadow(inWorld, kind, signature, null, enclosingType, null, withContext); } public static Shadow makeAdviceExecutionShadow(World inWorld, java.lang.reflect.Method forMethod, MatchingContext withContext) { Kind kind = Shadow.AdviceExecution; Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedAdviceMember(forMethod, inWorld); ResolvedType enclosingType = signature.getDeclaringType().resolve(inWorld); return new ReflectionShadow(inWorld, kind, signature, null, enclosingType, null, withContext); } public static Shadow makeCallShadow(World inWorld, java.lang.reflect.Member aMember, java.lang.reflect.Member withinCode, MatchingContext withContext) { Shadow enclosingShadow = makeExecutionShadow(inWorld, withinCode, withContext); Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(aMember, inWorld); ResolvedMember enclosingMember = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(withinCode, inWorld); ResolvedType enclosingType = enclosingMember.getDeclaringType().resolve(inWorld); Kind kind = aMember instanceof Method ? Shadow.MethodCall : Shadow.ConstructorCall; return new ReflectionShadow(inWorld, kind, signature, enclosingShadow, enclosingType, enclosingMember, withContext); } public static Shadow makeCallShadow(World inWorld, java.lang.reflect.Member aMember, Class thisClass, MatchingContext withContext) { Shadow enclosingShadow = makeStaticInitializationShadow(inWorld, thisClass, withContext); Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(aMember, inWorld); ResolvedMember enclosingMember = ReflectionBasedReferenceTypeDelegateFactory.createStaticInitMember(thisClass, inWorld); ResolvedType enclosingType = enclosingMember.getDeclaringType().resolve(inWorld); Kind kind = aMember instanceof Method ? Shadow.MethodCall : Shadow.ConstructorCall; return new ReflectionShadow(inWorld, kind, signature, enclosingShadow, enclosingType, enclosingMember, withContext); } public static Shadow makeStaticInitializationShadow(World inWorld, Class forType, MatchingContext withContext) { Member signature = ReflectionBasedReferenceTypeDelegateFactory.createStaticInitMember(forType, inWorld); ResolvedType enclosingType = signature.getDeclaringType().resolve(inWorld); Kind kind = Shadow.StaticInitialization; return new ReflectionShadow(inWorld, kind, signature, null, enclosingType, null, withContext); } public static Shadow makePreInitializationShadow(World inWorld, Constructor forConstructor, MatchingContext withContext) { Kind kind = Shadow.PreInitialization; Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(forConstructor, inWorld); ResolvedType enclosingType = signature.getDeclaringType().resolve(inWorld); return new ReflectionShadow(inWorld, kind, signature, null, enclosingType, null, withContext); } public static Shadow makeInitializationShadow(World inWorld, Constructor forConstructor, MatchingContext withContext) { Kind kind = Shadow.Initialization; Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(forConstructor, inWorld); ResolvedType enclosingType = signature.getDeclaringType().resolve(inWorld); return new ReflectionShadow(inWorld, kind, signature, null, enclosingType, null, withContext); } public static Shadow makeHandlerShadow(World inWorld, Class exceptionType, Class withinType, MatchingContext withContext) { Kind kind = Shadow.ExceptionHandler; Shadow enclosingShadow = makeStaticInitializationShadow(inWorld, withinType, withContext); Member signature = ReflectionBasedReferenceTypeDelegateFactory.createHandlerMember(exceptionType, withinType, inWorld); ResolvedMember enclosingMember = ReflectionBasedReferenceTypeDelegateFactory.createStaticInitMember(withinType, inWorld); ResolvedType enclosingType = enclosingMember.getDeclaringType().resolve(inWorld); return new ReflectionShadow(inWorld, kind, signature, enclosingShadow, enclosingType, enclosingMember, withContext); } public static Shadow makeHandlerShadow(World inWorld, Class exceptionType, java.lang.reflect.Member withinCode, MatchingContext withContext) { Kind kind = Shadow.ExceptionHandler; Shadow enclosingShadow = makeExecutionShadow(inWorld, withinCode, withContext); Member signature = ReflectionBasedReferenceTypeDelegateFactory.createHandlerMember(exceptionType, withinCode.getDeclaringClass(), inWorld); ResolvedMember enclosingMember = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(withinCode, inWorld); ResolvedType enclosingType = enclosingMember.getDeclaringType().resolve(inWorld); return new ReflectionShadow(inWorld, kind, signature, enclosingShadow, enclosingType, enclosingMember, withContext); } public static Shadow makeFieldGetShadow(World inWorld, Field forField, Class callerType, MatchingContext withContext) { Shadow enclosingShadow = makeStaticInitializationShadow(inWorld, callerType, withContext); Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedField(forField, inWorld); ResolvedMember enclosingMember = ReflectionBasedReferenceTypeDelegateFactory.createStaticInitMember(callerType, inWorld); ResolvedType enclosingType = enclosingMember.getDeclaringType().resolve(inWorld); Kind kind = Shadow.FieldGet; return new ReflectionShadow(inWorld, kind, signature, enclosingShadow, enclosingType, enclosingMember, withContext); } public static Shadow makeFieldGetShadow(World inWorld, Field forField, java.lang.reflect.Member inMember, MatchingContext withContext) { Shadow enclosingShadow = makeExecutionShadow(inWorld, inMember, withContext); Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedField(forField, inWorld); ResolvedMember enclosingMember = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(inMember, inWorld); ResolvedType enclosingType = enclosingMember.getDeclaringType().resolve(inWorld); Kind kind = Shadow.FieldGet; return new ReflectionShadow(inWorld, kind, signature, enclosingShadow, enclosingType, enclosingMember, withContext); } public static Shadow makeFieldSetShadow(World inWorld, Field forField, Class callerType, MatchingContext withContext) { Shadow enclosingShadow = makeStaticInitializationShadow(inWorld, callerType, withContext); Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedField(forField, inWorld); ResolvedMember enclosingMember = ReflectionBasedReferenceTypeDelegateFactory.createStaticInitMember(callerType, inWorld); ResolvedType enclosingType = enclosingMember.getDeclaringType().resolve(inWorld); Kind kind = Shadow.FieldSet; return new ReflectionShadow(inWorld, kind, signature, enclosingShadow, enclosingType, enclosingMember, withContext); } public static Shadow makeFieldSetShadow(World inWorld, Field forField, java.lang.reflect.Member inMember, MatchingContext withContext) { Shadow enclosingShadow = makeExecutionShadow(inWorld, inMember, withContext); Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedField(forField, inWorld); ResolvedMember enclosingMember = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(inMember, inWorld); ResolvedType enclosingType = enclosingMember.getDeclaringType().resolve(inWorld); Kind kind = Shadow.FieldSet; return new ReflectionShadow(inWorld, kind, signature, enclosingShadow, enclosingType, enclosingMember, withContext); } public ReflectionShadow(World world, Kind kind, Member signature, Shadow enclosingShadow, ResolvedType enclosingType, ResolvedMember enclosingMember, MatchingContext withContext) { super(kind, signature, enclosingShadow); this.world = world; this.enclosingType = enclosingType; this.enclosingMember = enclosingMember; this.matchContext = withContext; if (world instanceof IReflectionWorld) { this.annotationFinder = ((IReflectionWorld) world).getAnnotationFinder(); } } /* * (non-Javadoc) * * @see org.aspectj.weaver.Shadow#getIWorld() */ public World getIWorld() { return world; } /* * (non-Javadoc) * * @see org.aspectj.weaver.Shadow#getThisVar() */ public Var getThisVar() { if (thisVar == null && hasThis()) { thisVar = ReflectionVar.createThisVar(getThisType().resolve(world), this.annotationFinder); } return thisVar; } /* * (non-Javadoc) * * @see org.aspectj.weaver.Shadow#getTargetVar() */ public Var getTargetVar() { if (targetVar == null && hasTarget()) { targetVar = ReflectionVar.createTargetVar(getThisType().resolve(world), this.annotationFinder); } return targetVar; } /* * (non-Javadoc) * * @see org.aspectj.weaver.Shadow#getEnclosingType() */ public UnresolvedType getEnclosingType() { return this.enclosingType; } /* * (non-Javadoc) * * @see org.aspectj.weaver.Shadow#getArgVar(int) */ public Var getArgVar(int i) { if (argsVars == null) { this.argsVars = new Var[this.getArgCount()]; for (int j = 0; j < this.argsVars.length; j++) { this.argsVars[j] = ReflectionVar.createArgsVar(getArgType(j).resolve(world), j, this.annotationFinder); } } if (i < argsVars.length) { return argsVars[i]; } else { return null; } } public Var getThisJoinPointVar() { return null; } public Var getThisJoinPointStaticPartVar() { return null; } public Var getThisEnclosingJoinPointStaticPartVar() { return null; } public Var getThisAspectInstanceVar(ResolvedType aspectType) { return null; } public Var getKindedAnnotationVar(UnresolvedType forAnnotationType) { ResolvedType annType = forAnnotationType.resolve(world); if (annotationVar.get(annType) == null) { Var v = ReflectionVar.createAtAnnotationVar(annType, this.annotationFinder); annotationVar.put(annType, v); } return (Var) annotationVar.get(annType); } /* * (non-Javadoc) * * @see org.aspectj.weaver.Shadow#getWithinAnnotationVar(org.aspectj.weaver.UnresolvedType) */ public Var getWithinAnnotationVar(UnresolvedType forAnnotationType) { ResolvedType annType = forAnnotationType.resolve(world); if (withinAnnotationVar.get(annType) == null) { Var v = ReflectionVar.createWithinAnnotationVar(annType, this.annotationFinder); withinAnnotationVar.put(annType, v); } return (Var) withinAnnotationVar.get(annType); } /* * (non-Javadoc) * * @see org.aspectj.weaver.Shadow#getWithinCodeAnnotationVar(org.aspectj.weaver.UnresolvedType) */ public Var getWithinCodeAnnotationVar(UnresolvedType forAnnotationType) { ResolvedType annType = forAnnotationType.resolve(world); if (withinCodeAnnotationVar.get(annType) == null) { Var v = ReflectionVar.createWithinCodeAnnotationVar(annType, this.annotationFinder); withinCodeAnnotationVar.put(annType, v); } return (Var) withinCodeAnnotationVar.get(annType); } /* * (non-Javadoc) * * @see org.aspectj.weaver.Shadow#getThisAnnotationVar(org.aspectj.weaver.UnresolvedType) */ public Var getThisAnnotationVar(UnresolvedType forAnnotationType) { if (atThisVar == null) { atThisVar = ReflectionVar.createThisAnnotationVar(forAnnotationType.resolve(world), this.annotationFinder); } return atThisVar; } /* * (non-Javadoc) * * @see org.aspectj.weaver.Shadow#getTargetAnnotationVar(org.aspectj.weaver.UnresolvedType) */ public Var getTargetAnnotationVar(UnresolvedType forAnnotationType) { if (atTargetVar == null) { atTargetVar = ReflectionVar.createTargetAnnotationVar(forAnnotationType.resolve(world), this.annotationFinder); } return atTargetVar; } /* * (non-Javadoc) * * @see org.aspectj.weaver.Shadow#getArgAnnotationVar(int, org.aspectj.weaver.UnresolvedType) */ public Var getArgAnnotationVar(int i, UnresolvedType forAnnotationType) { ResolvedType annType = forAnnotationType.resolve(world); if (atArgsVars.get(annType) == null) { Var[] vars = new Var[getArgCount()]; atArgsVars.put(annType, vars); } Var[] vars = (Var[]) atArgsVars.get(annType); if (i > (vars.length - 1)) return null; if (vars[i] == null) { vars[i] = ReflectionVar.createArgsAnnotationVar(annType, i, this.annotationFinder); } return vars[i]; } /* * (non-Javadoc) * * @see org.aspectj.weaver.Shadow#getEnclosingCodeSignature() */ public Member getEnclosingCodeSignature() { // XXX this code is copied from BcelShadow with one minor change... if (getKind().isEnclosingKind()) { return getSignature(); } else if (getKind() == Shadow.PreInitialization) { // PreInit doesn't enclose code but its signature // is correctly the signature of the ctor. return getSignature(); } else if (enclosingShadow == null) { return this.enclosingMember; } else { return enclosingShadow.getSignature(); } } /* * (non-Javadoc) * * @see org.aspectj.weaver.Shadow#getSourceLocation() */ public ISourceLocation getSourceLocation() { return null; } public MatchingContext getMatchingContext() { return this.matchContext; } }