1 22 package org.jboss.annotation.factory; 23 24 import org.jboss.annotation.factory.ast.ASTAnnotation; 25 import org.jboss.annotation.factory.ast.ASTChar; 26 import org.jboss.annotation.factory.ast.ASTIdentifier; 27 import org.jboss.annotation.factory.ast.ASTMemberValueArrayInitializer; 28 import org.jboss.annotation.factory.ast.ASTMemberValuePair; 29 import org.jboss.annotation.factory.ast.ASTMemberValuePairs; 30 import org.jboss.annotation.factory.ast.ASTSingleMemberValue; 31 import org.jboss.annotation.factory.ast.ASTStart; 32 import org.jboss.annotation.factory.ast.ASTString; 33 import org.jboss.annotation.factory.ast.AnnotationParser; 34 import org.jboss.annotation.factory.ast.AnnotationParserVisitor; 35 import org.jboss.annotation.factory.ast.Node; 36 import org.jboss.annotation.factory.ast.SimpleNode; 37 import org.jboss.annotation.factory.javassist.DefaultValueAnnotationValidator; 38 39 import java.io.StringReader ; 40 import java.lang.reflect.Array ; 41 import java.lang.reflect.Field ; 42 import java.lang.reflect.InvocationTargetException ; 43 import java.lang.reflect.Method ; 44 import java.security.AccessController ; 45 import java.security.PrivilegedActionException ; 46 import java.security.PrivilegedExceptionAction ; 47 import java.util.HashMap ; 48 49 56 public class AnnotationCreator implements AnnotationParserVisitor 57 { 58 private Class annotation; 59 private Class type; 60 public Object typeValue; 61 62 static final AnnotationValidator defaultAnnotationReader; 63 static 64 { 65 boolean haveJavassist = false; 66 try 67 { 68 Class.forName("javassist.CtClass"); 69 haveJavassist = true; 70 } 71 catch(ClassNotFoundException ignore) 72 { 73 } 74 75 if (haveJavassist) 76 { 77 defaultAnnotationReader = new DefaultValueAnnotationValidator(); 78 } 79 else 80 { 81 defaultAnnotationReader = new SimpleAnnotationValidator(); 82 } 83 84 } 85 86 public AnnotationCreator(Class annotation, Class type) 87 { 88 this.type = type; 89 this.annotation = annotation; 90 } 91 92 93 public Object visit(ASTMemberValuePairs node, Object data) 94 { 95 node.childrenAccept(this, data); 96 return null; 97 } 98 99 public Object visit(ASTMemberValuePair node, Object data) 100 { 101 String name = node.getIdentifier().getValue(); 102 node.getValue().jjtAccept(this, name); 103 return data; 104 } 105 106 public Object visit(ASTSingleMemberValue node, Object data) 107 { 108 node.getValue().jjtAccept(this, "value"); 109 return data; 110 } 111 112 public Object visit(ASTIdentifier node, Object data) 113 { 114 try 115 { 116 if (type.equals(Class .class)) 117 { 118 String classname = node.getValue(); 119 if (classname.endsWith(".class")) 120 { 121 classname = classname.substring(0, classname.indexOf(".class")); 122 } 123 if (classname.equals("void")) 124 { 125 typeValue = void.class; 126 } 127 else if (classname.equals("int")) 128 { 129 typeValue = int.class; 130 } 131 else if (classname.equals("byte")) 132 { 133 typeValue = byte.class; 134 } 135 else if (classname.equals("long")) 136 { 137 typeValue = long.class; 138 } 139 else if (classname.equals("double")) 140 { 141 typeValue = double.class; 142 } 143 else if (classname.equals("float")) 144 { 145 typeValue = float.class; 146 } 147 else if (classname.equals("char")) 148 { 149 typeValue = char.class; 150 } 151 else if (classname.equals("short")) 152 { 153 typeValue = short.class; 154 } 155 else if (classname.equals("boolean")) 156 { 157 typeValue = boolean.class; 158 } 159 else 160 { 161 typeValue = Thread.currentThread().getContextClassLoader().loadClass(classname); 162 } 163 } 164 else if (type.isPrimitive()) 165 { 166 if (type.equals(boolean.class)) 167 { 168 typeValue = new Boolean (node.getValue()); 169 } 170 else if (type.equals(short.class)) 171 { 172 typeValue = Short.valueOf(node.getValue()); 173 } 174 else if (type.equals(float.class)) 175 { 176 typeValue = Float.valueOf(node.getValue()); 177 } 178 else if (type.equals(double.class)) 179 { 180 typeValue = Double.valueOf(node.getValue()); 181 } 182 else if (type.equals(long.class)) 183 { 184 typeValue = Long.valueOf(node.getValue()); 185 } 186 else if (type.equals(byte.class)) 187 { 188 typeValue = new Byte (node.getValue()); 189 } 190 else if (type.equals(int.class)) 191 { 192 typeValue = new Integer (node.getValue()); 193 } 194 } 195 else { 197 int index = node.getValue().lastIndexOf('.'); 198 if (index == -1) throw new RuntimeException ("Enum must be fully qualified: " + node.getValue()); 199 String className = node.getValue().substring(0, index); 200 String en = node.getValue().substring(index + 1); 201 Class enumClass = Thread.currentThread().getContextClassLoader().loadClass(className); 202 203 if (enumClass.getSuperclass().getName().equals("java.lang.Enum")) 204 { 205 Method valueOf = null; 206 Method [] methods = enumClass.getSuperclass().getMethods(); 207 for (int i = 0; i < methods.length; i++) 208 { 209 if (methods[i].getName().equals("valueOf")) 210 { 211 valueOf = methods[i]; 212 break; 213 } 214 } 215 Object [] args = {enumClass, en}; 216 typeValue = valueOf.invoke(null, args); 217 } 218 else 219 { 220 Field field = enumClass.getField(en); 221 typeValue = field.get(null); 222 } 223 } 224 } 225 catch (ClassNotFoundException e) 226 { 227 throw new RuntimeException (e); 228 } 229 catch (IllegalAccessException e) 230 { 231 throw new RuntimeException (e); 232 } 233 catch (InvocationTargetException e) 234 { 235 throw new RuntimeException (e); 236 } 237 catch (NoSuchFieldException e) 238 { 239 throw new RuntimeException (e); 240 } 241 return null; 242 } 243 244 public Object visit(ASTString node, Object data) 245 { 246 if (!type.equals(String .class)) throw new RuntimeException (annotation.getName() + "." + data + " is not an String"); 247 typeValue = node.getValue(); 248 return null; 249 } 250 251 public Object visit(ASTChar node, Object data) 252 { 253 if (!type.equals(char.class)) throw new RuntimeException (annotation.getName() + "." + data + " is not an char"); 254 typeValue = new Character (node.getValue()); 255 return null; 256 } 257 258 259 public Object visit(ASTMemberValueArrayInitializer node, Object data) 260 { 261 if (!type.isArray()) throw new RuntimeException (annotation.getName() + "." + data + " is not an array"); 262 Class baseType = type.getComponentType(); 263 int size = node.jjtGetNumChildren(); 264 typeValue = Array.newInstance(baseType, size); 265 266 for (int i = 0; i < size; i++) 267 { 268 AnnotationCreator creator = new AnnotationCreator(annotation, baseType); 269 node.jjtGetChild(i).jjtAccept(creator, null); 270 Array.set(typeValue, i, creator.typeValue); 271 } 272 return null; 273 } 274 275 public Object visit(ASTAnnotation node, Object data) 276 { 277 try 278 { 279 Class subAnnotation = Thread.currentThread().getContextClassLoader().loadClass(node.getIdentifier()); 280 typeValue = createAnnotation(node, subAnnotation); 281 } 282 catch (Exception e) 283 { 284 throw new RuntimeException (e); 285 } 286 return null; 287 } 288 289 291 public Object visit(SimpleNode node, Object data) 292 { 293 return null; 294 } 295 296 public Object visit(ASTStart node, Object data) 297 { 298 return null; 299 } 300 301 private static Class getMemberType(Class annotation, String member) 302 { 303 Method [] methods = annotation.getMethods(); 304 for (int i = 0; i < methods.length; i++) 305 { 306 if (methods[i].getName().equals(member)) 307 { 308 return methods[i].getReturnType(); 309 } 310 } 311 throw new RuntimeException ("unable to determine member type for annotation: " + annotation.getName() + "." + member); 312 } 313 314 private static ASTAnnotation getRootExpr(final String annotationExpr) throws Exception 315 { 316 try 317 { 318 319 return AccessController.doPrivileged(new PrivilegedExceptionAction <ASTAnnotation>() 320 { 321 public ASTAnnotation run() throws Exception 322 { 323 AnnotationParser parser = new AnnotationParser(new StringReader (annotationExpr)); 324 ASTStart start = parser.Start(); 325 return (ASTAnnotation) start.jjtGetChild(0); 326 } 327 }); 328 } 329 catch (PrivilegedActionException e) 330 { 331 throw new RuntimeException ("Error getting root expression", e.getException()); 332 } 333 } 334 335 336 public static Object createAnnotation(ASTAnnotation node, Class annotation, ClassLoader cl) throws Exception 337 { 338 HashMap <String , Object > map = new HashMap <String , Object >(); 339 if (annotation == null) 340 { 341 ClassLoader loader = (cl != null) ? cl : Thread.currentThread().getContextClassLoader(); 342 annotation = loader.loadClass(node.getIdentifier()); 343 } 344 345 if (node.jjtGetNumChildren() > 0) 346 { 347 Node contained = node.jjtGetChild(0); 348 if (contained instanceof ASTSingleMemberValue) 349 { 350 Class type = getMemberType(annotation, "value"); 351 AnnotationCreator creator = new AnnotationCreator(annotation, type); 352 contained.jjtAccept(creator, "value"); 353 map.put("value", creator.typeValue); 354 } 355 else 356 { 357 ASTMemberValuePairs pairs = (ASTMemberValuePairs) contained; 358 for (int i = 0; i < pairs.jjtGetNumChildren(); i++) 359 { 360 ASTMemberValuePair member = (ASTMemberValuePair) pairs.jjtGetChild(i); 361 Class type = getMemberType(annotation, member.getIdentifier().getValue()); 362 AnnotationCreator creator = new AnnotationCreator(annotation, type); 363 member.jjtAccept(creator, null); 364 map.put(member.getIdentifier().getValue(), creator.typeValue); 365 } 366 } 367 } 368 369 defaultAnnotationReader.validate(map, annotation); 370 return AnnotationProxy.createProxy(map, annotation); 371 } 372 373 public static Object createAnnotation(ASTAnnotation node, Class annotation) throws Exception 374 { 375 return createAnnotation(node, annotation, null); 376 } 377 378 public static Object createAnnotation(final String annotationExpr, final Class annotation) throws Exception 379 { 380 return createAnnotation(getRootExpr(annotationExpr), annotation, null); 381 } 382 383 public static Object createAnnotation(String annotationExpr, ClassLoader cl) throws Exception 384 { 385 return createAnnotation(getRootExpr(annotationExpr), null, cl); 386 } 387 388 389 } 390 | Popular Tags |