~ubuntu-branches/ubuntu/wily/aspectj/wily-proposed

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* *******************************************************************
 * Copyright (c) 2008 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://www.eclipse.org/legal/epl-v10.html 
 *  
 * Contributors: 
 *     Andy Clement     initial implementation 
 * ******************************************************************/
package org.aspectj.weaver.bcel;

import java.util.Iterator;
import java.util.List;

import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
import org.aspectj.apache.bcel.classfile.annotation.EnumElementValue;
import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
import org.aspectj.apache.bcel.classfile.annotation.SimpleElementValue;
import org.aspectj.apache.bcel.generic.InstructionFactory;
import org.aspectj.apache.bcel.generic.InstructionList;
import org.aspectj.apache.bcel.generic.Type;
import org.aspectj.weaver.AnnotationAJ;
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;

/**
 * An AnnotationAccessVar represents access to a particular annotation, whilst an AnnotationAccessFieldVar represents access to a
 * specific field of that annotation.
 * 
 * @author Andy Clement
 */
class AnnotationAccessFieldVar extends BcelVar {

	private AnnotationAccessVar annoAccessor;
	private ResolvedType annoFieldOfInterest;

	public AnnotationAccessFieldVar(AnnotationAccessVar aav, ResolvedType annoFieldOfInterest) {
		super(annoFieldOfInterest, 0);
		this.annoAccessor = aav;
		this.annoFieldOfInterest = annoFieldOfInterest;
	}

	@Override
	public void appendLoadAndConvert(InstructionList il, InstructionFactory fact, ResolvedType toType) {
		// Only possible to do annotation field value extraction at
		// MethodExecution
		if (annoAccessor.getKind() != Shadow.MethodExecution) {
			return;
		}
		String annotationOfInterestSignature = annoAccessor.getType().getSignature();
		// So we have an entity that has an annotation on and within it is the
		// value we want
		Member holder = annoAccessor.getMember();
		AnnotationAJ[] annos = holder.getAnnotations();
		for (int i = 0; i < annos.length; i++) {
			AnnotationGen annotation = ((BcelAnnotation) annos[i]).getBcelAnnotation();
			if (annotation.getTypeSignature().equals(annotationOfInterestSignature)) {
				List<NameValuePair> vals = annotation.getValues();
				boolean doneAndDusted = false;
				for (Iterator<NameValuePair> iterator = vals.iterator(); iterator.hasNext();) {
					NameValuePair object = iterator.next();
					Object o = object.getValue();
					if (o instanceof EnumElementValue) {
						EnumElementValue v = (EnumElementValue) object.getValue();
						String s = v.getEnumTypeString();
						ResolvedType rt = toType.getWorld().resolve(UnresolvedType.forSignature(s));
						if (rt.equals(toType)) {
							il.append(fact.createGetStatic(rt.getName(), v.getEnumValueString(), Type.getType(rt.getSignature())));
							doneAndDusted = true;
						}
					} else if (o instanceof SimpleElementValue) {
						// FIXASC types other than String will go bang bang at runtime
						SimpleElementValue v = (SimpleElementValue) object.getValue();
						il.append(fact.createConstant(v.getValueString()));
						doneAndDusted = true;
						// String s = v.getEnumTypeString();
						// ResolvedType rt = toType.getWorld().resolve(UnresolvedType.forSignature(s));
						// if (rt.equals(toType)) {
						// il.append(fact.createGetStatic(rt.getName(), v.getEnumValueString(), Type.getType(rt.getSignature())));
						// doneAndDusted = true;
						// }
					}
				}
				if (!doneAndDusted) {
					ResolvedMember[] annotationFields = toType.getWorld()
							.resolve(UnresolvedType.forSignature(annotation.getTypeSignature())).getDeclaredMethods();

					// ResolvedMember[] fs = rt.getDeclaredFields();
					for (int ii = 0; ii < annotationFields.length; ii++) {
						if (annotationFields[ii].getType().equals(annoFieldOfInterest)) {
							String dvalue = annotationFields[ii].getAnnotationDefaultValue();
							// form will be LBLAHBLAHBLAH;X where X is the field
							// within X
							String typename = dvalue.substring(0, dvalue.lastIndexOf(';') + 1);
							String field = dvalue.substring(dvalue.lastIndexOf(';') + 1);
							ResolvedType rt = toType.getWorld().resolve(UnresolvedType.forSignature(typename));
							il.append(fact.createGetStatic(rt.getName(), field, Type.getType(rt.getSignature())));
						}
					}
				}
			}
		}
	}

	@Override
	public void insertLoad(InstructionList il, InstructionFactory fact) {
		// Only possible to do annotation field value extraction at
		// MethodExecution
		if (annoAccessor.getKind() != Shadow.MethodExecution) {
			return;
		}
		appendLoadAndConvert(il, fact, annoFieldOfInterest);
	}

	@Override
	public String toString() {
		return super.toString();
	}
}