1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 }