View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of 
7    * individual contributors. 
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   *
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  package org.modeshape.sequencer.classfile.metadata;
25  
26  import java.util.Collections;
27  import java.util.LinkedList;
28  import java.util.List;
29  import javassist.bytecode.AccessFlag;
30  import javassist.bytecode.AnnotationsAttribute;
31  import javassist.bytecode.AttributeInfo;
32  import javassist.bytecode.ClassFile;
33  import javassist.bytecode.FieldInfo;
34  import javassist.bytecode.MethodInfo;
35  import javassist.bytecode.annotation.Annotation;
36  import net.jcip.annotations.Immutable;
37  
38  @Immutable
39  public class ClassMetadata {
40  
41      private final ClassFile clazz;
42  
43      private final List<AnnotationMetadata> annotations;
44      private final List<FieldMetadata> fields;
45      private final List<MethodMetadata> methods;
46      private final List<MethodMetadata> constructors;
47  
48      ClassMetadata( ClassFile clazz ) {
49          this.clazz = clazz;
50          this.annotations = annotationsFor(clazz);
51          this.fields = fieldsFor(clazz);
52          this.methods = methodsFor(clazz);
53          this.constructors = constructorsFor(clazz);
54      }
55  
56      private List<AnnotationMetadata> annotationsFor( ClassFile clazz ) {
57          List<AnnotationMetadata> annotations = new LinkedList<AnnotationMetadata>();
58  
59          for (Object ob : clazz.getAttributes()) {
60              AttributeInfo att = (AttributeInfo)ob;
61  
62              if (att instanceof AnnotationsAttribute) {
63                  for (Annotation ann : ((AnnotationsAttribute)att).getAnnotations()) {
64                      annotations.add(new AnnotationMetadata(ann));
65                  }
66              }
67          }
68  
69          return Collections.unmodifiableList(annotations);
70      }
71  
72      private List<FieldMetadata> fieldsFor( ClassFile clazz ) {
73          List<FieldMetadata> fields = new LinkedList<FieldMetadata>();
74  
75          for (Object field : clazz.getFields()) {
76              fields.add(new FieldMetadata((FieldInfo)field));
77          }
78  
79          Collections.sort(fields);
80  
81          return Collections.unmodifiableList(fields);
82      }
83  
84      private List<MethodMetadata> methodsFor( ClassFile clazz ) {
85          List<MethodMetadata> methods = new LinkedList<MethodMetadata>();
86  
87          for (Object ob : clazz.getMethods()) {
88              MethodInfo method = (MethodInfo)ob;
89  
90              if (!method.isStaticInitializer() && !method.isConstructor()) {
91                  methods.add(new MethodMetadata(clazz, method));
92              }
93          }
94  
95          Collections.sort(methods);
96  
97          return Collections.unmodifiableList(methods);
98      }
99  
100     private List<MethodMetadata> constructorsFor( ClassFile clazz ) {
101         List<MethodMetadata> ctors = new LinkedList<MethodMetadata>();
102 
103         for (Object ob : clazz.getMethods()) {
104             MethodInfo method = (MethodInfo)ob;
105             if (!method.isStaticInitializer() && method.isConstructor()) {
106                 ctors.add(new MethodMetadata(clazz, method));
107             }
108         }
109 
110         Collections.sort(ctors);
111 
112         return Collections.unmodifiableList(ctors);
113     }
114 
115     public boolean isEnumeration() {
116         return false;
117     }
118 
119     public String getClassName() {
120         return clazz.getName();
121     }
122 
123     public String getSuperclassName() {
124         return clazz.getSuperclass();
125     }
126 
127     public String[] getInterfaces() {
128         return clazz.getInterfaces();
129     }
130 
131     public boolean isAbstract() {
132         return clazz.isAbstract();
133     }
134 
135     public boolean isInterface() {
136         return clazz.isInterface();
137     }
138 
139     public boolean isStrictFp() {
140         return AccessFlag.STRICT == (AccessFlag.STRICT & clazz.getAccessFlags());
141     }
142 
143     public boolean isFinal() {
144         return AccessFlag.FINAL == (AccessFlag.FINAL & clazz.getAccessFlags());
145     }
146 
147     public Visibility getVisibility() {
148         return Visibility.fromAccessFlags(clazz.getAccessFlags());
149     }
150 
151     public List<AnnotationMetadata> getAnnotations() {
152         return annotations;
153     }
154 
155     public List<FieldMetadata> getFields() {
156         return fields;
157     }
158 
159     public List<MethodMetadata> getMethods() {
160         return methods;
161     }
162 
163     public List<MethodMetadata> getConstructors() {
164         return constructors;
165     }
166 
167     @Override
168     public String toString() {
169         StringBuilder buff = new StringBuilder();
170 
171         for (AnnotationMetadata annotation : annotations) {
172             buff.append(annotation).append('\n');
173         }
174 
175         buff.append(getVisibility());
176         if (getVisibility() != Visibility.PACKAGE) {
177             buff.append(' ');
178         }
179 
180         if (isAbstract()) {
181             if (isInterface()) {
182                 buff.append("interface ");
183             } else {
184                 buff.append("abstract class ");
185 
186             }
187         } else {
188             buff.append("class ");
189         }
190 
191         if (getSuperclassName() != null && !Object.class.getName().equals(getSuperclassName())) {
192             buff.append(" extends ").append(getSuperclassName()).append(" ");
193         }
194 
195         if (getInterfaces().length > 0) {
196             boolean first = true;
197             buff.append(" implements ");
198 
199             for (String interfaceName : getInterfaces()) {
200                 if (first) {
201                     first = false;
202                 } else {
203                     buff.append(", ");
204                 }
205                 buff.append(interfaceName);
206             }
207 
208             buff.append(' ');
209         }
210 
211         buff.append(getClassName()).append(" {\n");
212 
213         for (FieldMetadata field : fields) {
214             buff.append('\t').append(field).append('\n');
215         }
216 
217         if (!methods.isEmpty()) {
218             buff.append('\n');
219         }
220 
221         for (MethodMetadata method : methods) {
222             buff.append('\t').append(method).append('\n');
223         }
224 
225         buff.append("}");
226 
227         return buff.toString();
228     }
229 }