1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
package org.apache.commons.classscan.bcel; |
15 | |
|
16 | |
import org.apache.bcel.classfile.AnnotationElementValue; |
17 | |
import org.apache.bcel.classfile.AnnotationEntry; |
18 | |
import org.apache.bcel.classfile.ArrayElementValue; |
19 | |
import org.apache.bcel.classfile.ClassElementValue; |
20 | |
import org.apache.bcel.classfile.ElementValue; |
21 | |
import org.apache.bcel.classfile.ElementValuePair; |
22 | |
import org.apache.bcel.classfile.EnumElementValue; |
23 | |
import org.apache.bcel.classfile.SimpleElementValue; |
24 | |
import org.apache.commons.classscan.builtin.ClassNameHelper; |
25 | |
import org.apache.commons.classscan.model.MetaClass; |
26 | |
import org.apache.commons.classscan.spi.model.SpiMetaAnnotation.SpiProperty; |
27 | |
import org.apache.commons.classscan.spi.model.SpiMetaClassLoader; |
28 | |
import org.slf4j.Logger; |
29 | |
import org.slf4j.LoggerFactory; |
30 | |
|
31 | |
public class BcelProperty implements SpiProperty { |
32 | |
|
33 | 11 | private static final Logger logger = LoggerFactory.getLogger(BcelProperty.class); |
34 | |
|
35 | |
private final String propertyName; |
36 | |
private Object value; |
37 | |
|
38 | 6127 | public BcelProperty(ElementValuePair evPair) { |
39 | 6127 | propertyName = evPair.getNameString(); |
40 | 6127 | value = evPair.getValue(); |
41 | 6127 | } |
42 | |
|
43 | |
@Override |
44 | |
public boolean resolve(SpiMetaClassLoader classLoader) { |
45 | 6083 | value = createObject(classLoader, value); |
46 | 6083 | return value!=null; |
47 | |
} |
48 | |
|
49 | |
@Override |
50 | |
public String getName() { |
51 | 2530 | return propertyName; |
52 | |
} |
53 | |
|
54 | |
@Override |
55 | |
public Object getValue() { |
56 | 308 | return value; |
57 | |
} |
58 | |
|
59 | |
private Object createObject(SpiMetaClassLoader classLoader, Object ev) { |
60 | 9207 | if (ev instanceof SimpleElementValue) { |
61 | 2827 | return createWrapper((SimpleElementValue) ev); |
62 | |
} |
63 | 6380 | if (ev instanceof EnumElementValue) { |
64 | 3201 | return createEnum(classLoader, (EnumElementValue) ev); |
65 | |
} |
66 | 3179 | if (ev instanceof ClassElementValue) { |
67 | 1364 | return createMetaClass(classLoader, (ClassElementValue) ev); |
68 | |
} |
69 | 1815 | if (ev instanceof ArrayElementValue) { |
70 | 1782 | return createArray(classLoader, (ArrayElementValue) ev); |
71 | |
} |
72 | 33 | if (ev instanceof AnnotationElementValue) { |
73 | 33 | return createAnnotation((AnnotationElementValue) ev); |
74 | |
} |
75 | 0 | logger.info("unknown annotation value type "+ev.getClass().getCanonicalName()+" for annotation property "+propertyName); |
76 | 0 | return null; |
77 | |
} |
78 | |
|
79 | |
private Object createWrapper(SimpleElementValue sev) { |
80 | 2827 | char primitiveTypeCode = (char) sev.getElementValueType(); |
81 | |
|
82 | 2827 | switch (primitiveTypeCode) { |
83 | |
case 'B': |
84 | 0 | return sev.getValueByte(); |
85 | |
case 'C': |
86 | 11 | return sev.getValueChar(); |
87 | |
case 'D': |
88 | 11 | return sev.getValueDouble(); |
89 | |
case 'F': |
90 | 11 | return sev.getValueFloat(); |
91 | |
case 'I': |
92 | 44 | return sev.getValueInt(); |
93 | |
case 'J': |
94 | 77 | return sev.getValueLong(); |
95 | |
case 'S': |
96 | 0 | return sev.getValueShort(); |
97 | |
case 'Z': |
98 | 22 | return sev.getValueBoolean(); |
99 | |
case 's': |
100 | 2651 | return sev.getValueString(); |
101 | |
default: |
102 | 0 | return null; |
103 | |
} |
104 | |
} |
105 | |
|
106 | |
private MetaClass createMetaClass(SpiMetaClassLoader classLoader, ClassElementValue ev) { |
107 | 1364 | String internalClassName = ev.getClassString(); |
108 | 1364 | String canonicalName = ClassNameHelper.internalToCanonicalName(internalClassName); |
109 | 1364 | return classLoader.resolveMetaClass(canonicalName); |
110 | |
} |
111 | |
|
112 | |
private Object createAnnotation(AnnotationElementValue aev) { |
113 | 33 | AnnotationEntry ae = ((AnnotationElementValue) aev).getAnnotationEntry(); |
114 | 33 | return new BcelAnnotation(ae); |
115 | |
} |
116 | |
|
117 | |
private Object createEnum(SpiMetaClassLoader classLoader, EnumElementValue eev) { |
118 | 3201 | String enumTypeString = ClassNameHelper.internalToCanonicalName(eev.getEnumTypeString()); |
119 | 3201 | MetaClass dmc = classLoader.resolveMetaClass(enumTypeString); |
120 | 3201 | if(dmc==null) { |
121 | 0 | logger.info("unknown enum type "+enumTypeString+" for annotation property "+propertyName); |
122 | 0 | return null; |
123 | |
} |
124 | 3201 | String enumInstanceName = eev.getEnumValueString(); |
125 | 3201 | return new BcelEnumProperty(dmc, enumInstanceName); |
126 | |
} |
127 | |
|
128 | |
private Object[] createArray(SpiMetaClassLoader classLoader, ArrayElementValue ev) { |
129 | 1782 | ArrayElementValue aev = (ArrayElementValue) ev; |
130 | 1782 | ElementValue[] elementValues = aev.getElementValuesArray(); |
131 | 1782 | Object[] returnValues = new Object[elementValues.length]; |
132 | 1782 | int i = 0; |
133 | 4906 | for (ElementValue elementValue : elementValues) { |
134 | 3124 | Object obj = createObject(classLoader, elementValue); |
135 | 3124 | if(obj==null) { |
136 | 0 | return null; |
137 | |
} |
138 | 3124 | returnValues[i++] = obj; |
139 | |
} |
140 | 1782 | return returnValues; |
141 | |
} |
142 | |
} |