OSDN Git Service

save
[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.util.JcfaWriteUtil;\r
8 import jp.igapyon.jcfa.vo.JcfaClass;\r
9 import jp.igapyon.jcfa.vo.JcfaCode;\r
10 import jp.igapyon.jcfa.vo.JcfaField;\r
11 import jp.igapyon.jcfa.vo.JcfaMethod;\r
12 import jp.igapyon.jcfa.vo.JcfaUnit;\r
13 \r
14 import org.apache.bcel.Constants;\r
15 import org.apache.bcel.classfile.ClassFormatException;\r
16 import org.apache.bcel.classfile.ClassParser;\r
17 import org.apache.bcel.classfile.Code;\r
18 import org.apache.bcel.classfile.ConstantValue;\r
19 import org.apache.bcel.classfile.Field;\r
20 import org.apache.bcel.classfile.JavaClass;\r
21 import org.apache.bcel.classfile.Method;\r
22 import org.apache.bcel.generic.Type;\r
23 \r
24 public class JavaClassFileAnalyzer {\r
25         protected JcfaUnit jcfaUnit = new JcfaUnit();\r
26 \r
27         public static final void main(final String[] args) {\r
28                 new JavaClassFileAnalyzer().parseDir(new File("./bin/test"));\r
29                 new JavaClassFileAnalyzer().parseDir(new File(\r
30                                 "./bin/jp/igapyon/jcfa/vo"));\r
31         }\r
32 \r
33         private void parseDir(final File dir) {\r
34                 final File[] files = dir.listFiles();\r
35                 if (files == null) {\r
36                         return;\r
37                 }\r
38                 for (File file : files) {\r
39                         if (file.isDirectory()) {\r
40                                 parseDir(file);\r
41                         }\r
42                         if (file.isFile()) {\r
43                                 if (file.getName().endsWith(".class")) {\r
44                                         new JavaClassFileAnalyzer().process(file, new File(\r
45                                                         "./testJavaClass/output"));\r
46                                 }\r
47                         }\r
48                 }\r
49         }\r
50 \r
51         private final void process(final File inputFile, final File outputDir) {\r
52                 try {\r
53                         final JavaClass jc = new ClassParser(inputFile.getCanonicalPath())\r
54                                         .parse();\r
55                         final JcfaClass jcfaClass = new JcfaClass();\r
56                         jcfaUnit.getClassList().add(jcfaClass);\r
57 \r
58                         jcfaClass.setName(jc.getClassName());\r
59                         jcfaClass.setExtendsName(jc.getSuperclassName());\r
60 \r
61                         jcfaClass.getComment().getCommentList()\r
62                                         .add("TODO import func. is missing.");\r
63                         jcfaClass.getComment().setJavaDoc(true);\r
64 \r
65                         final String[] split = jc.getClassName().split("\\.");\r
66                         File actualyTargetDir = outputDir;\r
67                         if (split.length > 1) {\r
68                                 for (int index = 0; index < split.length - 1; index++) {\r
69                                         actualyTargetDir = new File(actualyTargetDir, split[index]);\r
70                                         actualyTargetDir.mkdirs();\r
71                                 }\r
72                         }\r
73 \r
74                         analyzeFields(jc, jcfaClass);\r
75                         analyzeMethods(jc, jcfaClass);\r
76 \r
77                         jcfaUnit.setTargetFile(new File(actualyTargetDir,\r
78                                         split[split.length - 1] + ".jcfa"));\r
79 \r
80                         JcfaWriteUtil.writeToFile(jcfaUnit);\r
81                 } catch (ClassFormatException e) {\r
82                         e.printStackTrace();\r
83                 } catch (IOException e) {\r
84                         e.printStackTrace();\r
85                 }\r
86         }\r
87 \r
88         private void analyzeFields(final JavaClass jc, final JcfaClass jcfaClass) {\r
89                 final org.apache.bcel.classfile.Field[] fields = jc.getFields();\r
90                 for (int indexField = 0; indexField < fields.length; indexField++) {\r
91                         final Field field = fields[indexField];\r
92                         analyzeField(jc, field, jcfaClass);\r
93                 }\r
94         }\r
95 \r
96         private void analyzeField(final JavaClass jc, final Field field,\r
97                         final JcfaClass jcfaClass) {\r
98                 final JcfaField jcfaField = new JcfaField();\r
99                 jcfaField.setName(field.getName());\r
100                 jcfaClass.getFieldList().add(jcfaField);\r
101 \r
102                 jcfaField.getComment().setJavaDoc(true);\r
103 \r
104                 // TODO type should be more collect.\r
105                 jcfaField.setType(field.getType().toString());\r
106 \r
107                 String access = "";\r
108                 access += field.isPublic() ? "public " : "";\r
109                 access += field.isProtected() ? "protected " : "";\r
110                 access += field.isPrivate() ? "private " : "";\r
111                 access += field.isAbstract() ? "abstract " : "";\r
112                 access += field.isStatic() ? "static " : "";\r
113                 access += field.isVolatile() ? "volatile " : "";\r
114                 access += field.isFinal() ? "final " : "";\r
115                 jcfaField.setAccess(access);\r
116 \r
117                 final ConstantValue cv = field.getConstantValue();\r
118                 if (cv != null) {\r
119                         jcfaField.setConstantValue("\""\r
120                                         + jc.getConstantPool().getConstantString(\r
121                                                         cv.getConstantValueIndex(),\r
122                                                         Constants.CONSTANT_String) + "\"");\r
123 \r
124                         jcfaField\r
125                                         .getComment()\r
126                                         .getCommentList()\r
127                                         .add("FIXME other type support is missing. <br />Now only String.");\r
128                 }\r
129         }\r
130 \r
131         private void analyzeMethods(final JavaClass jc, final JcfaClass jcfaClass)\r
132                         throws IOException {\r
133                 final org.apache.bcel.classfile.Method[] methods = jc.getMethods();\r
134                 for (int indexMethod = 0; indexMethod < methods.length; indexMethod++) {\r
135                         final Method method = methods[indexMethod];\r
136                         analyzeMethod(jc, method, jcfaClass);\r
137 \r
138                 }\r
139         }\r
140 \r
141         /**\r
142          * Analyze method.\r
143          * \r
144          * @param jc\r
145          * @param method\r
146          * @param jcfaClass\r
147          * @throws IOException\r
148          */\r
149         private void analyzeMethod(final JavaClass jc, final Method method,\r
150                         final JcfaClass jcfaClass) throws IOException {\r
151                 final JcfaMethod jcfaMethod = new JcfaMethod();\r
152                 jcfaClass.getMethodList().add(jcfaMethod);\r
153 \r
154                 jcfaMethod.setName(method.getName());\r
155                 jcfaMethod.getComment().setJavaDoc(true);\r
156                 if (jcfaMethod.getName().equals("<init>")) {\r
157                         jcfaMethod.getComment().getCommentList()\r
158                                         .add("Default constructor.");\r
159                 } else {\r
160                         jcfaMethod.getComment().getCommentList().add("Method.");\r
161                 }\r
162 \r
163                 for (Type type : method.getArgumentTypes()) {\r
164                         jcfaMethod.getComment().getCommentList().add(type.toString());\r
165                         jcfaMethod.getArugumentTypeList().add(type.toString());\r
166                 }\r
167                 jcfaMethod.setType(method.getReturnType().toString());\r
168 \r
169                 final Code code = method.getCode();\r
170                 if (code == null) {\r
171                         return;\r
172                 }\r
173 \r
174                 final byte[] codes = code.getCode();\r
175                 for (int pc = 0; pc < codes.length; pc++) {\r
176                         final JcfaCode jcfaCode = new JcfaCode();\r
177                         jcfaMethod.getCodeList().add(jcfaCode);\r
178 \r
179                         jcfaCode.setOpcode(JcfaUtil.byte2UnsignedByte(codes[pc]));\r
180                         jcfaCode.getComment()\r
181                                         .getCommentList()\r
182                                         .add("" + pc + ": "\r
183                                                         + Constants.OPCODE_NAMES[jcfaCode.getOpcode()]);\r
184 \r
185                         short operands = Constants.NO_OF_OPERANDS[jcfaCode.getOpcode()];\r
186                         if (operands < 0) {\r
187                                 jcfaCode.getComment()\r
188                                                 .getCommentList()\r
189                                                 .add("TODO negative value:"\r
190                                                                 + Constants.OPCODE_NAMES[jcfaCode.getOpcode()]\r
191                                                                 + ": " + operands);\r
192                                 break;\r
193                         }\r
194 \r
195                         switch (jcfaCode.getOpcode()) {\r
196                         case Constants.RETURN: {\r
197                                 System.out.println("    " + pc + ": "\r
198                                                 + Constants.OPCODE_NAMES[jcfaCode.getOpcode()]);\r
199                                 break;\r
200                         }\r
201                         case Constants.GETSTATIC: {\r
202                                 System.out.println("    "\r
203                                                 + pc\r
204                                                 + ": "\r
205                                                 + Constants.OPCODE_NAMES[jcfaCode.getOpcode()]\r
206                                                 + ": "\r
207                                                 + JcfaUtil.getConstantFieldrefString(jc, codes[pc + 1],\r
208                                                                 codes[pc + 2]));\r
209                                 break;\r
210                         }\r
211                         case Constants.LDC: {\r
212                                 System.out.println("    " + pc + ": "\r
213                                                 + Constants.OPCODE_NAMES[jcfaCode.getOpcode()] + ": "\r
214                                                 + JcfaUtil.getConstantString(jc, codes[pc + 1]));\r
215                         }\r
216                                 break;\r
217                         case Constants.INVOKEVIRTUAL:\r
218                         case Constants.INVOKESPECIAL: {\r
219                                 final int operand = JcfaUtil.byte2UnsignedShort(codes[pc + 1],\r
220                                                 codes[pc + 2]);\r
221                                 System.out.println("    " + pc + ": "\r
222                                                 + Constants.OPCODE_NAMES[jcfaCode.getOpcode()] + ": "\r
223                                                 + JcfaUtil.getConstantMethodRefString(jc, operand));\r
224                         }\r
225                                 break;\r
226                         case Constants.LOOKUPSWITCH:\r
227                                 int result = JcfaUtil.byte2Int(codes[pc + 1], codes[pc + 2],\r
228                                                 codes[pc + 3], codes[pc + 4]);\r
229                                 System.out.println("  TODO skipping bytes: " + (result));\r
230 \r
231                                 int lookupOp = pc + 5;\r
232 \r
233                                 short diff = JcfaUtil.byte2UnsignedByte(codes[lookupOp++]);\r
234                                 System.out.println("  TODO skipping bytes: " + (diff));\r
235 \r
236                                 int loopCount = JcfaUtil\r
237                                                 .byte2Int(codes[lookupOp++], codes[lookupOp++],\r
238                                                                 codes[lookupOp++], codes[lookupOp++]);\r
239                                 for (int index = 0; index < loopCount; index++) {\r
240                                         System.out.println("      "\r
241                                                         + JcfaUtil.byte2Int(codes[lookupOp++],\r
242                                                                         codes[lookupOp++], codes[lookupOp++],\r
243                                                                         codes[lookupOp++])\r
244                                                         + ":"\r
245                                                         + (JcfaUtil.byte2Int(codes[lookupOp++],\r
246                                                                         codes[lookupOp++], codes[lookupOp++],\r
247                                                                         codes[lookupOp++]) + pc));\r
248                                 }\r
249 \r
250                                 short diff2 = JcfaUtil.byte2UnsignedByte(codes[lookupOp++]);\r
251                                 System.out.println("  TODO skipping bytes: " + (diff2));\r
252 \r
253                                 operands += (lookupOp - pc);\r
254 \r
255                                 break;\r
256                         default: {\r
257                                 System.out.println("    " + pc + ": "\r
258                                                 + Constants.OPCODE_NAMES[jcfaCode.getOpcode()] + " ("\r
259                                                 + operands + ")");\r
260                         }\r
261                                 break;\r
262                         }\r
263                         pc += operands;\r
264                 }\r
265         }\r
266 }