OSDN Git Service

adding.
[jcfa/jcfa.git] / jcfa / src / jp / igapyon / jcfa / JavaClassFileAnalyzer.java
1 package jp.igapyon.jcfa;\r
2 \r
3 import java.io.File;\r
4 import java.io.IOException;\r
5 \r
6 import jp.igapyon.jcfa.util.JcfaUtil;\r
7 import jp.igapyon.jcfa.vo.JcfaClass;\r
8 import jp.igapyon.jcfa.vo.JcfaField;\r
9 import jp.igapyon.jcfa.vo.JcfaMethod;\r
10 import jp.igapyon.jcfa.vo.JcfaUnit;\r
11 \r
12 import org.apache.bcel.Constants;\r
13 import org.apache.bcel.classfile.ClassFormatException;\r
14 import org.apache.bcel.classfile.ClassParser;\r
15 import org.apache.bcel.classfile.Code;\r
16 import org.apache.bcel.classfile.ConstantValue;\r
17 import org.apache.bcel.classfile.Field;\r
18 import org.apache.bcel.classfile.JavaClass;\r
19 import org.apache.bcel.classfile.Method;\r
20 \r
21 public class JavaClassFileAnalyzer {\r
22         protected JcfaUnit jcfaUnit = new JcfaUnit();\r
23 \r
24         public static final void main(final String[] args) {\r
25                 new JavaClassFileAnalyzer().process(new File(\r
26                                 "./bin/test/TestJavaClass002.class"), new File(\r
27                                 "./testJavaClass/output"));\r
28         }\r
29 \r
30         private final void process(final File inputFile, final File outputDir) {\r
31                 try {\r
32                         final JavaClass jc = new ClassParser(inputFile.getCanonicalPath())\r
33                                         .parse();\r
34                         final JcfaClass jcfaClass = new JcfaClass();\r
35                         jcfaUnit.getClassList().add(jcfaClass);\r
36 \r
37                         jcfaClass.setName(jc.getClassName());\r
38                         jcfaClass.setExtendsName(jc.getSuperclassName());\r
39 \r
40                         System.out.println("Classname   : " + jc.getClassName());\r
41                         System.out.println("Parent class: " + jc.getSuperclassName());\r
42 \r
43                         final String[] split = jc.getClassName().split("\\.");\r
44                         File actualyTargetDir = outputDir;\r
45                         if (split.length > 1) {\r
46                                 for (int index = 0; index < split.length - 1; index++) {\r
47                                         actualyTargetDir = new File(outputDir, split[index]);\r
48                                         actualyTargetDir.mkdirs();\r
49                                 }\r
50                         }\r
51 \r
52                         analyzeFields(jc, jcfaClass);\r
53                         analyzeMethods(jc, jcfaClass);\r
54 \r
55                         new File(actualyTargetDir, split[split.length - 1] + ".jcfa")\r
56                                         .createNewFile();\r
57                 } catch (ClassFormatException e) {\r
58                         e.printStackTrace();\r
59                 } catch (IOException e) {\r
60                         e.printStackTrace();\r
61                 }\r
62         }\r
63 \r
64         private void analyzeFields(final JavaClass jc, final JcfaClass jcfaClass) {\r
65                 final org.apache.bcel.classfile.Field[] fields = jc.getFields();\r
66                 for (int indexField = 0; indexField < fields.length; indexField++) {\r
67                         final Field field = fields[indexField];\r
68                         analyzeField(jc, field, jcfaClass);\r
69                 }\r
70         }\r
71 \r
72         private void analyzeField(final JavaClass jc, final Field field,\r
73                         final JcfaClass jcfaClass) {\r
74                 final JcfaField jcfaField = new JcfaField();\r
75                 jcfaField.setName(field.getName());\r
76                 jcfaClass.getFieldList().add(jcfaField);\r
77 \r
78                 String access = "";\r
79                 access += field.isPublic() ? "public " : "";\r
80                 access += field.isProtected() ? "protected " : "";\r
81                 access += field.isPrivate() ? "private " : "";\r
82                 access += field.isAbstract() ? "abstract " : "";\r
83                 access += field.isStatic() ? "static " : "";\r
84                 access += field.isVolatile() ? "volatile " : "";\r
85                 access += field.isFinal() ? "final " : "";\r
86                 jcfaField.setAccess(access);\r
87 \r
88                 String constValue = null;\r
89                 final ConstantValue cv = field.getConstantValue();\r
90                 if (cv != null) {\r
91                         jcfaField.setConstantValue(jc.getConstantPool().getConstantString(\r
92                                         cv.getConstantValueIndex(), Constants.CONSTANT_String));\r
93                         // FIXME other type support add.\r
94                         jcfaField.setConstantValueType(Constants.CONSTANT_String);\r
95                 }\r
96 \r
97                 System.out.println("    " + access + field.getType().toString() + " "\r
98                                 + field.getName()\r
99                                 + (constValue == null ? "" : " = \"" + constValue + "\""));\r
100         }\r
101 \r
102         private void analyzeMethods(final JavaClass jc, final JcfaClass jcfaClass)\r
103                         throws IOException {\r
104                 final org.apache.bcel.classfile.Method[] methods = jc.getMethods();\r
105                 for (int indexMethod = 0; indexMethod < methods.length; indexMethod++) {\r
106                         final Method method = methods[indexMethod];\r
107                         analyzeMethod(jc, method, jcfaClass);\r
108 \r
109                 }\r
110         }\r
111 \r
112         private void analyzeMethod(final JavaClass jc, final Method method,\r
113                         final JcfaClass jcfaClass) throws IOException {\r
114                 final JcfaMethod jcfaMethod = new JcfaMethod();\r
115                 jcfaClass.getMethodList().add(jcfaMethod);\r
116 \r
117                 jcfaMethod.setName(method.getName());\r
118 \r
119                 final Code code = method.getCode();\r
120                 if (code == null) {\r
121                         return;\r
122                 }\r
123 \r
124                 final byte[] codes = code.getCode();\r
125                 for (int pc = 0; pc < codes.length; pc++) {\r
126                         final short opcode = JcfaUtil.byte2UnsignedByte(codes[pc]);\r
127                         short operands = Constants.NO_OF_OPERANDS[opcode];\r
128                         if (operands < 0) {\r
129                                 System.out.println("  TODO negative value:"\r
130                                                 + Constants.OPCODE_NAMES[opcode] + ": " + operands);\r
131                                 // break;\r
132                         }\r
133 \r
134                         switch (opcode) {\r
135                         case Constants.RETURN: {\r
136                                 System.out.println("    " + pc + ": "\r
137                                                 + Constants.OPCODE_NAMES[opcode]);\r
138                                 break;\r
139                         }\r
140                         case Constants.GETSTATIC: {\r
141                                 System.out.println("    "\r
142                                                 + pc\r
143                                                 + ": "\r
144                                                 + Constants.OPCODE_NAMES[opcode]\r
145                                                 + ": "\r
146                                                 + JcfaUtil.getConstantFieldrefString(jc, codes[pc + 1],\r
147                                                                 codes[pc + 2]));\r
148                                 break;\r
149                         }\r
150                         case Constants.LDC: {\r
151                                 System.out.println("    " + pc + ": "\r
152                                                 + Constants.OPCODE_NAMES[opcode] + ": "\r
153                                                 + JcfaUtil.getConstantString(jc, codes[pc + 1]));\r
154                         }\r
155                                 break;\r
156                         case Constants.INVOKEVIRTUAL:\r
157                         case Constants.INVOKESPECIAL: {\r
158                                 final int operand = JcfaUtil.byte2UnsignedShort(codes[pc + 1],\r
159                                                 codes[pc + 2]);\r
160                                 System.out.println("    " + pc + ": "\r
161                                                 + Constants.OPCODE_NAMES[opcode] + ": "\r
162                                                 + JcfaUtil.getConstantMethodRefString(jc, operand));\r
163                         }\r
164                                 break;\r
165                         case Constants.LOOKUPSWITCH:\r
166                                 int result = JcfaUtil.byte2Int(codes[pc + 1], codes[pc + 2],\r
167                                                 codes[pc + 3], codes[pc + 4]);\r
168                                 System.out.println("  TODO skipping bytes: " + (result));\r
169 \r
170                                 int lookupOp = pc + 5;\r
171 \r
172                                 short diff = JcfaUtil.byte2UnsignedByte(codes[lookupOp++]);\r
173                                 System.out.println("  TODO skipping bytes: " + (diff));\r
174 \r
175                                 int loopCount = JcfaUtil\r
176                                                 .byte2Int(codes[lookupOp++], codes[lookupOp++],\r
177                                                                 codes[lookupOp++], codes[lookupOp++]);\r
178                                 for (int index = 0; index < loopCount; index++) {\r
179                                         System.out.println("      "\r
180                                                         + JcfaUtil.byte2Int(codes[lookupOp++],\r
181                                                                         codes[lookupOp++], codes[lookupOp++],\r
182                                                                         codes[lookupOp++])\r
183                                                         + ":"\r
184                                                         + (JcfaUtil.byte2Int(codes[lookupOp++],\r
185                                                                         codes[lookupOp++], codes[lookupOp++],\r
186                                                                         codes[lookupOp++]) + pc));\r
187                                 }\r
188 \r
189                                 short diff2 = JcfaUtil.byte2UnsignedByte(codes[lookupOp++]);\r
190                                 System.out.println("  TODO skipping bytes: " + (diff2));\r
191 \r
192                                 operands += (lookupOp - pc);\r
193 \r
194                                 break;\r
195                         default: {\r
196                                 System.out.println("    " + pc + ": "\r
197                                                 + Constants.OPCODE_NAMES[opcode] + " (" + operands\r
198                                                 + ")");\r
199                         }\r
200                                 break;\r
201                         }\r
202                         pc += operands;\r
203                 }\r
204         }\r
205 }