1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.expression.spel.ast;
18
19 import java.lang.reflect.Array;
20
21 import org.springframework.asm.MethodVisitor;
22 import org.springframework.asm.Type;
23 import org.springframework.expression.EvaluationException;
24 import org.springframework.expression.TypedValue;
25 import org.springframework.expression.spel.CodeFlow;
26 import org.springframework.expression.spel.ExpressionState;
27
28
29
30
31
32
33 public class TypeReference extends SpelNodeImpl {
34
35 private final int dimensions;
36
37 private transient Class<?> type;
38
39
40 public TypeReference(int pos, SpelNodeImpl qualifiedId) {
41 this(pos,qualifiedId,0);
42 }
43
44 public TypeReference(int pos, SpelNodeImpl qualifiedId, int dims) {
45 super(pos,qualifiedId);
46 this.dimensions = dims;
47 }
48
49
50 @Override
51 public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
52
53 String typeName = (String) this.children[0].getValueInternal(state).getValue();
54 if (!typeName.contains(".") && Character.isLowerCase(typeName.charAt(0))) {
55 TypeCode tc = TypeCode.valueOf(typeName.toUpperCase());
56 if (tc != TypeCode.OBJECT) {
57
58 Class<?> clazz = makeArrayIfNecessary(tc.getType());
59 this.exitTypeDescriptor = "Ljava/lang/Class";
60 this.type = clazz;
61 return new TypedValue(clazz);
62 }
63 }
64 Class<?> clazz = state.findType(typeName);
65 clazz = makeArrayIfNecessary(clazz);
66 this.exitTypeDescriptor = "Ljava/lang/Class";
67 this.type = clazz;
68 return new TypedValue(clazz);
69 }
70
71 private Class<?> makeArrayIfNecessary(Class<?> clazz) {
72 if (this.dimensions != 0) {
73 for (int i = 0; i < this.dimensions; i++) {
74 Object array = Array.newInstance(clazz, 0);
75 clazz = array.getClass();
76 }
77 }
78 return clazz;
79 }
80
81 @Override
82 public String toStringAST() {
83 StringBuilder sb = new StringBuilder("T(");
84 sb.append(getChild(0).toStringAST());
85 for (int d = 0; d < this.dimensions; d++) {
86 sb.append("[]");
87 }
88 sb.append(")");
89 return sb.toString();
90 }
91
92 @Override
93 public boolean isCompilable() {
94 return (this.exitTypeDescriptor != null);
95 }
96
97 @Override
98 public void generateCode(MethodVisitor mv, CodeFlow cf) {
99
100 if (this.type.isPrimitive()) {
101 if (this.type == Integer.TYPE) {
102 mv.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
103 }
104 else if (this.type == Boolean.TYPE) {
105 mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
106 }
107 else if (this.type == Byte.TYPE) {
108 mv.visitFieldInsn(GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;");
109 }
110 else if (this.type == Short.TYPE) {
111 mv.visitFieldInsn(GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;");
112 }
113 else if (this.type == Double.TYPE) {
114 mv.visitFieldInsn(GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;");
115 }
116 else if (this.type == Character.TYPE) {
117 mv.visitFieldInsn(GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;");
118 }
119 else if (this.type == Float.TYPE) {
120 mv.visitFieldInsn(GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;");
121 }
122 else if (this.type == Long.TYPE) {
123 mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;");
124 }
125 else if (this.type == Boolean.TYPE) {
126 mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
127 }
128 }
129 else {
130 mv.visitLdcInsn(Type.getType(this.type));
131 }
132 cf.pushDescriptor(this.exitTypeDescriptor);
133 }
134
135 }