001 /*
002 * Licensed under the Apache License, Version 2.0 (the "License");
003 * you may not use this file except in compliance with the License.
004 * You may obtain a copy of the License at
005 *
006 * http://www.apache.org/licenses/LICENSE-2.0
007 *
008 * Unless required by applicable law or agreed to in writing, software
009 * distributed under the License is distributed on an "AS IS" BASIS,
010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011 * See the License for the specific language governing permissions and
012 * limitations under the License.
013 */
014 package org.apache.commons.classscan.bcel;
015
016 import org.apache.bcel.classfile.AnnotationElementValue;
017 import org.apache.bcel.classfile.AnnotationEntry;
018 import org.apache.bcel.classfile.ArrayElementValue;
019 import org.apache.bcel.classfile.ClassElementValue;
020 import org.apache.bcel.classfile.ElementValue;
021 import org.apache.bcel.classfile.ElementValuePair;
022 import org.apache.bcel.classfile.EnumElementValue;
023 import org.apache.bcel.classfile.SimpleElementValue;
024 import org.apache.commons.classscan.builtin.ClassNameHelper;
025 import org.apache.commons.classscan.model.MetaClass;
026 import org.apache.commons.classscan.spi.model.SpiMetaAnnotation.SpiProperty;
027 import org.apache.commons.classscan.spi.model.SpiMetaClassLoader;
028 import org.slf4j.Logger;
029 import org.slf4j.LoggerFactory;
030
031 public class BcelProperty implements SpiProperty {
032
033 private static final Logger logger = LoggerFactory.getLogger(BcelProperty.class);
034
035 private final String propertyName;
036 private Object value;
037
038 public BcelProperty(ElementValuePair evPair) {
039 propertyName = evPair.getNameString();
040 value = evPair.getValue();
041 }
042
043 @Override
044 public boolean resolve(SpiMetaClassLoader classLoader) {
045 value = createObject(classLoader, value);
046 return value!=null;
047 }
048
049 @Override
050 public String getName() {
051 return propertyName;
052 }
053
054 @Override
055 public Object getValue() {
056 return value;
057 }
058
059 private Object createObject(SpiMetaClassLoader classLoader, Object ev) {
060 if (ev instanceof SimpleElementValue) {
061 return createWrapper((SimpleElementValue) ev);
062 }
063 if (ev instanceof EnumElementValue) {
064 return createEnum(classLoader, (EnumElementValue) ev);
065 }
066 if (ev instanceof ClassElementValue) {
067 return createMetaClass(classLoader, (ClassElementValue) ev);
068 }
069 if (ev instanceof ArrayElementValue) {
070 return createArray(classLoader, (ArrayElementValue) ev);
071 }
072 if (ev instanceof AnnotationElementValue) {
073 return createAnnotation((AnnotationElementValue) ev);
074 }
075 logger.info("unknown annotation value type "+ev.getClass().getCanonicalName()+" for annotation property "+propertyName);
076 return null;
077 }
078
079 private Object createWrapper(SimpleElementValue sev) {
080 char primitiveTypeCode = (char) sev.getElementValueType();
081
082 switch (primitiveTypeCode) {
083 case 'B':
084 return sev.getValueByte();
085 case 'C':
086 return sev.getValueChar();
087 case 'D':
088 return sev.getValueDouble();
089 case 'F':
090 return sev.getValueFloat();
091 case 'I':
092 return sev.getValueInt();
093 case 'J':
094 return sev.getValueLong();
095 case 'S':
096 return sev.getValueShort();
097 case 'Z':
098 return sev.getValueBoolean();
099 case 's':
100 return sev.getValueString();
101 default:
102 return null;
103 }
104 }
105
106 private MetaClass createMetaClass(SpiMetaClassLoader classLoader, ClassElementValue ev) {
107 String internalClassName = ev.getClassString();
108 String canonicalName = ClassNameHelper.internalToCanonicalName(internalClassName);
109 return classLoader.resolveMetaClass(canonicalName);
110 }
111
112 private Object createAnnotation(AnnotationElementValue aev) {
113 AnnotationEntry ae = ((AnnotationElementValue) aev).getAnnotationEntry();
114 return new BcelAnnotation(ae);
115 }
116
117 private Object createEnum(SpiMetaClassLoader classLoader, EnumElementValue eev) {
118 String enumTypeString = ClassNameHelper.internalToCanonicalName(eev.getEnumTypeString());
119 MetaClass dmc = classLoader.resolveMetaClass(enumTypeString);
120 if(dmc==null) {
121 logger.info("unknown enum type "+enumTypeString+" for annotation property "+propertyName);
122 return null;
123 }
124 String enumInstanceName = eev.getEnumValueString();
125 return new BcelEnumProperty(dmc, enumInstanceName);
126 }
127
128 private Object[] createArray(SpiMetaClassLoader classLoader, ArrayElementValue ev) {
129 ArrayElementValue aev = (ArrayElementValue) ev;
130 ElementValue[] elementValues = aev.getElementValuesArray();
131 Object[] returnValues = new Object[elementValues.length];
132 int i = 0;
133 for (ElementValue elementValue : elementValues) {
134 Object obj = createObject(classLoader, elementValue);
135 if(obj==null) {
136 return null;
137 }
138 returnValues[i++] = obj;
139 }
140 return returnValues;
141 }
142 }