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 }