KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > annotation > factory > AnnotationCreator


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

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 JavaDoc;
40 import java.lang.reflect.Array JavaDoc;
41 import java.lang.reflect.Field JavaDoc;
42 import java.lang.reflect.InvocationTargetException JavaDoc;
43 import java.lang.reflect.Method JavaDoc;
44 import java.security.AccessController JavaDoc;
45 import java.security.PrivilegedActionException JavaDoc;
46 import java.security.PrivilegedExceptionAction JavaDoc;
47 import java.util.HashMap JavaDoc;
48
49 /**
50  * Comment
51  *
52  * @author <a HREF="mailto:bill@jboss.org">Bill Burke</a>
53  * @author <a HREF="mailto:kabir.khan@jboss.org">Kabir Khan</a>
54  * @version $Revision: 57306 $
55  */

56 public class AnnotationCreator implements AnnotationParserVisitor
57 {
58    private Class JavaDoc annotation;
59    private Class JavaDoc type;
60    public Object JavaDoc 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 JavaDoc 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 JavaDoc annotation, Class JavaDoc type)
87    {
88       this.type = type;
89       this.annotation = annotation;
90    }
91
92
93    public Object JavaDoc visit(ASTMemberValuePairs node, Object JavaDoc data)
94    {
95       node.childrenAccept(this, data);
96       return null;
97    }
98
99    public Object JavaDoc visit(ASTMemberValuePair node, Object JavaDoc data)
100    {
101       String JavaDoc name = node.getIdentifier().getValue();
102       node.getValue().jjtAccept(this, name);
103       return data;
104    }
105
106    public Object JavaDoc visit(ASTSingleMemberValue node, Object JavaDoc data)
107    {
108       node.getValue().jjtAccept(this, "value");
109       return data;
110    }
111
112    public Object JavaDoc visit(ASTIdentifier node, Object JavaDoc data)
113    {
114       try
115       {
116          if (type.equals(Class JavaDoc.class))
117          {
118             String JavaDoc 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 JavaDoc(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 JavaDoc(node.getValue());
189             }
190             else if (type.equals(int.class))
191             {
192                typeValue = new Integer JavaDoc(node.getValue());
193             }
194          }
195          else // its an enum
196
{
197             int index = node.getValue().lastIndexOf('.');
198             if (index == -1) throw new RuntimeException JavaDoc("Enum must be fully qualified: " + node.getValue());
199             String JavaDoc className = node.getValue().substring(0, index);
200             String JavaDoc en = node.getValue().substring(index + 1);
201             Class JavaDoc enumClass = Thread.currentThread().getContextClassLoader().loadClass(className);
202
203             if (enumClass.getSuperclass().getName().equals("java.lang.Enum"))
204             {
205                Method JavaDoc valueOf = null;
206                Method JavaDoc[] 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 JavaDoc[] args = {enumClass, en};
216                typeValue = valueOf.invoke(null, args);
217             }
218             else
219             {
220                Field JavaDoc field = enumClass.getField(en);
221                typeValue = field.get(null);
222             }
223          }
224       }
225       catch (ClassNotFoundException JavaDoc e)
226       {
227          throw new RuntimeException JavaDoc(e);
228       }
229       catch (IllegalAccessException JavaDoc e)
230       {
231          throw new RuntimeException JavaDoc(e);
232       }
233       catch (InvocationTargetException JavaDoc e)
234       {
235          throw new RuntimeException JavaDoc(e);
236       }
237       catch (NoSuchFieldException JavaDoc e)
238       {
239          throw new RuntimeException JavaDoc(e);
240       }
241       return null;
242    }
243
244    public Object JavaDoc visit(ASTString node, Object JavaDoc data)
245    {
246       if (!type.equals(String JavaDoc.class)) throw new RuntimeException JavaDoc(annotation.getName() + "." + data + " is not an String");
247       typeValue = node.getValue();
248       return null;
249    }
250
251    public Object JavaDoc visit(ASTChar node, Object JavaDoc data)
252    {
253       if (!type.equals(char.class)) throw new RuntimeException JavaDoc(annotation.getName() + "." + data + " is not an char");
254       typeValue = new Character JavaDoc(node.getValue());
255       return null;
256    }
257
258
259    public Object JavaDoc visit(ASTMemberValueArrayInitializer node, Object JavaDoc data)
260    {
261       if (!type.isArray()) throw new RuntimeException JavaDoc(annotation.getName() + "." + data + " is not an array");
262       Class JavaDoc 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 JavaDoc visit(ASTAnnotation node, Object JavaDoc data)
276    {
277       try
278       {
279          Class JavaDoc subAnnotation = Thread.currentThread().getContextClassLoader().loadClass(node.getIdentifier());
280          typeValue = createAnnotation(node, subAnnotation);
281       }
282       catch (Exception JavaDoc e)
283       {
284          throw new RuntimeException JavaDoc(e);
285       }
286       return null;
287    }
288
289    // Unneeded
290

291    public Object JavaDoc visit(SimpleNode node, Object JavaDoc data)
292    {
293       return null;
294    }
295
296    public Object JavaDoc visit(ASTStart node, Object JavaDoc data)
297    {
298       return null;
299    }
300
301    private static Class JavaDoc getMemberType(Class JavaDoc annotation, String JavaDoc member)
302    {
303       Method JavaDoc[] 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 JavaDoc("unable to determine member type for annotation: " + annotation.getName() + "." + member);
312    }
313    
314    private static ASTAnnotation getRootExpr(final String JavaDoc annotationExpr) throws Exception JavaDoc
315    {
316       try
317       {
318
319          return AccessController.doPrivileged(new PrivilegedExceptionAction JavaDoc<ASTAnnotation>()
320          {
321            public ASTAnnotation run() throws Exception JavaDoc
322            {
323               AnnotationParser parser = new AnnotationParser(new StringReader JavaDoc(annotationExpr));
324               ASTStart start = parser.Start();
325               return (ASTAnnotation) start.jjtGetChild(0);
326            }
327          });
328       }
329       catch (PrivilegedActionException JavaDoc e)
330       {
331          throw new RuntimeException JavaDoc("Error getting root expression", e.getException());
332       }
333    }
334    
335    
336    public static Object JavaDoc createAnnotation(ASTAnnotation node, Class JavaDoc annotation, ClassLoader JavaDoc cl) throws Exception JavaDoc
337    {
338       HashMap JavaDoc<String JavaDoc, Object JavaDoc> map = new HashMap JavaDoc<String JavaDoc, Object JavaDoc>();
339       if (annotation == null)
340       {
341          ClassLoader JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc createAnnotation(ASTAnnotation node, Class JavaDoc annotation) throws Exception JavaDoc
374    {
375       return createAnnotation(node, annotation, null);
376    }
377    
378    public static Object JavaDoc createAnnotation(final String JavaDoc annotationExpr, final Class JavaDoc annotation) throws Exception JavaDoc
379    {
380       return createAnnotation(getRootExpr(annotationExpr), annotation, null);
381    }
382
383    public static Object JavaDoc createAnnotation(String JavaDoc annotationExpr, ClassLoader JavaDoc cl) throws Exception JavaDoc
384    {
385       return createAnnotation(getRootExpr(annotationExpr), null, cl);
386    }
387
388    
389 }
390
Popular Tags