View Javadoc
1   /*
2    * Copyright (C) 2008 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.codehaus.plexus.metadata.ann;
18  
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.util.ArrayList;
22  
23  import org.objectweb.asm.AnnotationVisitor;
24  import org.objectweb.asm.ClassReader;
25  import org.objectweb.asm.ClassVisitor;
26  import org.objectweb.asm.FieldVisitor;
27  import org.objectweb.asm.MethodVisitor;
28  import org.objectweb.asm.Opcodes;
29  
30  /**
31   * @author Eugene Kuleshov
32   */
33  public class AnnReader extends ClassVisitor {
34  
35    private final AnnClass annClass;
36  
37    private AnnReader(AnnClass annClass) {
38      super(Opcodes.ASM5);
39      this.annClass = annClass;
40    }
41  
42    public static AnnClass read(InputStream is, ClassLoader cl) throws IOException {
43      AnnClass annClass = new AnnClass(cl);
44      AnnReader cv = new AnnReader(annClass);
45      ClassReader r = new ClassReader(is);
46      r.accept(cv, ClassReader.SKIP_FRAMES | ClassReader.SKIP_CODE);
47      return annClass;
48    }
49  
50    public void visit(int version, int access, String name, String signature,
51        String superName, String[] interfaces) {
52      annClass.setName(name);
53      annClass.setAccess(access);
54      annClass.setSuperName(superName);
55      annClass.setInterfaces(interfaces);
56    }
57    
58    public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
59      Ann ann = new Ann(desc);
60      annClass.addAnn(ann);
61      return new AnnAnnReader(ann);
62    }
63    
64    public FieldVisitor visitField(int access, final String name, final String desc, String signature, Object value) {
65      final AnnField field = new AnnField(annClass, access, name, desc);
66      annClass.addField(field);
67      return new FieldVisitor(Opcodes.ASM5) {
68  
69        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
70          Ann ann = new Ann(desc);
71          field.addAnn(ann);
72          return new AnnAnnReader(ann);
73        }
74      };
75    }
76  
77    public MethodVisitor visitMethod(int access, final String mname, final String mdesc,
78        String signature, String[] exceptions) {
79      final AnnMethod method = new AnnMethod(annClass, access, mname, mdesc);
80      annClass.addMethod(method);
81      
82      return new MethodVisitor(Opcodes.ASM5) {
83  
84        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
85          Ann ann = new Ann(desc);
86          method.addAnn(ann);
87          return new AnnAnnReader(ann);
88        }
89  
90        public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
91          Ann ann = new Ann(desc);
92          method.addParamAnn(parameter, ann);
93          return new AnnAnnReader(ann);
94        }
95      };
96    }
97  
98    static class AnnAnnReader extends AnnotationVisitor {
99      private Ann ann;
100 
101     public AnnAnnReader(Ann ann) {
102       super(Opcodes.ASM5);
103       this.ann = ann;
104     }
105 
106     public void visit(String name, Object value) {
107       ann.addParam(name, value);
108     }
109 
110     public void visitEnum(String name, String desc, String value) {
111       ann.addParam(name, new AnnEnum(desc, value));
112     }
113     
114     public AnnotationVisitor visitAnnotation(String name, String desc) {
115       Ann ann = new Ann(desc);
116       this.ann.addParam(name, ann);
117       return new AnnAnnReader(ann);
118     }
119 
120     public AnnotationVisitor visitArray(String name) {
121       return new AnnAnnArrayReader(ann, name);
122     }
123   }
124   
125   static class AnnAnnArrayReader extends AnnotationVisitor {
126 
127     private Ann ann;
128 
129     private String name;
130 
131     // TODO good enough for now, but does not cover general case
132     private ArrayList<String> array = new ArrayList<String>();
133 
134     public AnnAnnArrayReader(Ann ann, String name) {
135       super(Opcodes.ASM5);
136       this.ann = ann;
137       this.name = name;
138     }
139 
140     public void visit(String name, Object value) {
141       if(value instanceof String) {
142         array.add((String) value);
143       }
144     }
145 
146     public void visitEnd() {
147       ann.addParam(name, array.toArray(new String[array.size()]));
148     }
149   }
150 }