OSDN Git Service

save
authoriga <tosiki.iga@nifty.ne.jp>
Tue, 1 Apr 2014 14:14:52 +0000 (23:14 +0900)
committeriga <tosiki.iga@nifty.ne.jp>
Tue, 1 Apr 2014 14:14:52 +0000 (23:14 +0900)
jcfa/src/jp/igapyon/jcfa/JavaClassFileAnalyzer.java
jcfa/src/jp/igapyon/jcfa/JcfaParser.java [new file with mode: 0644]

index d5c9c11..235996b 100644 (file)
@@ -1,30 +1,10 @@
 package jp.igapyon.jcfa;\r
 \r
-import java.io.ByteArrayOutputStream;\r
 import java.io.File;\r
-import java.io.IOException;\r
 \r
-import jp.igapyon.jcfa.util.JcfaUtil;\r
-import jp.igapyon.jcfa.util.JcfaWriteUtil;\r
-import jp.igapyon.jcfa.vo.JcfaClass;\r
-import jp.igapyon.jcfa.vo.JcfaCode;\r
-import jp.igapyon.jcfa.vo.JcfaField;\r
-import jp.igapyon.jcfa.vo.JcfaMethod;\r
 import jp.igapyon.jcfa.vo.JcfaUnit;\r
 \r
-import org.apache.bcel.Constants;\r
-import org.apache.bcel.classfile.ClassFormatException;\r
-import org.apache.bcel.classfile.ClassParser;\r
-import org.apache.bcel.classfile.Code;\r
-import org.apache.bcel.classfile.ConstantValue;\r
-import org.apache.bcel.classfile.Field;\r
-import org.apache.bcel.classfile.JavaClass;\r
-import org.apache.bcel.classfile.Method;\r
-import org.apache.bcel.generic.Type;\r
-\r
 public class JavaClassFileAnalyzer {\r
-       protected JcfaUnit jcfaUnit = new JcfaUnit();\r
-\r
        public static final void main(final String[] args) {\r
                new JavaClassFileAnalyzer().parseDir(new File("./bin/test"));\r
                new JavaClassFileAnalyzer().parseDir(new File(\r
@@ -50,207 +30,8 @@ public class JavaClassFileAnalyzer {
        }\r
 \r
        private final void process(final File inputFile, final File outputDir) {\r
-               parseUnit(inputFile, outputDir);\r
-       }\r
-\r
-       private void parseUnit(final File inputFile, final File outputDir) {\r
-               try {\r
-                       final JavaClass jc = new ClassParser(inputFile.getCanonicalPath())\r
-                                       .parse();\r
-                       final JcfaClass jcfaClass = new JcfaClass();\r
-                       jcfaUnit.getClassList().add(jcfaClass);\r
-\r
-                       jcfaClass.setName(jc.getClassName());\r
-                       jcfaClass.setExtendsName(jc.getSuperclassName());\r
-\r
-                       jcfaClass.getComment().getCommentList()\r
-                                       .add("TODO import func. is missing.");\r
-                       jcfaClass.getComment().setJavaDoc(true);\r
-\r
-                       final String[] split = jc.getClassName().split("\\.");\r
-                       File actualyTargetDir = outputDir;\r
-                       if (split.length > 1) {\r
-                               for (int index = 0; index < split.length - 1; index++) {\r
-                                       actualyTargetDir = new File(actualyTargetDir, split[index]);\r
-                                       actualyTargetDir.mkdirs();\r
-                               }\r
-                       }\r
-\r
-                       parseFields(jc, jcfaClass);\r
-                       parseMethods(jc, jcfaClass);\r
-\r
-                       jcfaUnit.setTargetFile(new File(actualyTargetDir,\r
-                                       split[split.length - 1] + ".jcfa"));\r
-\r
-                       JcfaWriteUtil.writeToFile(jcfaUnit);\r
-               } catch (ClassFormatException e) {\r
-                       e.printStackTrace();\r
-               } catch (IOException e) {\r
-                       e.printStackTrace();\r
-               }\r
-       }\r
-\r
-       private void parseFields(final JavaClass jc, final JcfaClass jcfaClass) {\r
-               final org.apache.bcel.classfile.Field[] fields = jc.getFields();\r
-               for (int indexField = 0; indexField < fields.length; indexField++) {\r
-                       final Field field = fields[indexField];\r
-                       parseField(jc, field, jcfaClass);\r
-               }\r
-       }\r
-\r
-       private void parseField(final JavaClass jc, final Field field,\r
-                       final JcfaClass jcfaClass) {\r
-               final JcfaField jcfaField = new JcfaField();\r
-               jcfaField.setName(field.getName());\r
-               jcfaClass.getFieldList().add(jcfaField);\r
-\r
-               jcfaField.getComment().setJavaDoc(true);\r
-\r
-               // TODO type should be more collect.\r
-               jcfaField.setType(field.getType().toString());\r
-\r
-               String access = "";\r
-               access += field.isPublic() ? "public " : "";\r
-               access += field.isProtected() ? "protected " : "";\r
-               access += field.isPrivate() ? "private " : "";\r
-               access += field.isAbstract() ? "abstract " : "";\r
-               access += field.isStatic() ? "static " : "";\r
-               access += field.isVolatile() ? "volatile " : "";\r
-               access += field.isFinal() ? "final " : "";\r
-               jcfaField.setAccess(access);\r
-\r
-               final ConstantValue cv = field.getConstantValue();\r
-               if (cv != null) {\r
-                       jcfaField.setConstantValue("\""\r
-                                       + jc.getConstantPool().getConstantString(\r
-                                                       cv.getConstantValueIndex(),\r
-                                                       Constants.CONSTANT_String) + "\"");\r
-\r
-                       jcfaField\r
-                                       .getComment()\r
-                                       .getCommentList()\r
-                                       .add("FIXME other type support is missing. <br />Now only String.");\r
-               }\r
-       }\r
-\r
-       private void parseMethods(final JavaClass jc, final JcfaClass jcfaClass)\r
-                       throws IOException {\r
-               final org.apache.bcel.classfile.Method[] methods = jc.getMethods();\r
-               for (int indexMethod = 0; indexMethod < methods.length; indexMethod++) {\r
-                       final Method method = methods[indexMethod];\r
-                       parseMethod(jc, method, jcfaClass);\r
-\r
-               }\r
+               final JcfaUnit jcfaUnit = new JcfaParser().parseUnit(inputFile,\r
+                               outputDir);\r
        }\r
 \r
-       /**\r
-        * Analyze method.\r
-        * \r
-        * @param jc\r
-        * @param method\r
-        * @param jcfaClass\r
-        * @throws IOException\r
-        */\r
-       private void parseMethod(final JavaClass jc, final Method method,\r
-                       final JcfaClass jcfaClass) throws IOException {\r
-               final JcfaMethod jcfaMethod = new JcfaMethod();\r
-               jcfaClass.getMethodList().add(jcfaMethod);\r
-\r
-               jcfaMethod.setName(method.getName());\r
-               jcfaMethod.getComment().setJavaDoc(true);\r
-               if (jcfaMethod.getName().equals("<init>")) {\r
-                       jcfaMethod.getComment().getCommentList()\r
-                                       .add("Default constructor.");\r
-               } else {\r
-                       jcfaMethod.getComment().getCommentList().add("Method.");\r
-               }\r
-\r
-               for (Type type : method.getArgumentTypes()) {\r
-                       jcfaMethod.getComment().getCommentList().add(type.toString());\r
-                       jcfaMethod.getArugumentTypeList().add(type.toString());\r
-               }\r
-               jcfaMethod.setType(method.getReturnType().toString());\r
-\r
-               final Code code = method.getCode();\r
-               if (code == null) {\r
-                       return;\r
-               }\r
-\r
-               final byte[] codes = code.getCode();\r
-               for (int pc = 0; pc < codes.length; pc++) {\r
-                       final int operands = parseCodes(jc, method, jcfaClass, jcfaMethod,\r
-                                       pc, codes);\r
-                       if (operands < 0) {\r
-                               break;\r
-                       }\r
-\r
-                       pc += operands;\r
-               }\r
-       }\r
-\r
-       private int parseCodes(final JavaClass jc, final Method method,\r
-                       final JcfaClass jcfaClass, final JcfaMethod jcfaMethod,\r
-                       final int pc, final byte[] codes) throws IOException {\r
-               final JcfaCode jcfaCode = new JcfaCode();\r
-               jcfaMethod.getCodeList().add(jcfaCode);\r
-               jcfaCode.setJavaClass(jc);\r
-\r
-               jcfaCode.setOpcode(JcfaUtil.byte2UnsignedByte(codes[pc]));\r
-               jcfaCode.getComment()\r
-                               .getCommentList()\r
-                               .add("" + pc + ": "\r
-                                               + Constants.OPCODE_NAMES[jcfaCode.getOpcode()]);\r
-\r
-               short operands = Constants.NO_OF_OPERANDS[jcfaCode.getOpcode()];\r
-               if (operands < 0) {\r
-                       jcfaCode.getComment()\r
-                                       .getCommentList()\r
-                                       .add("FIXME NO_OF_OPERANDS has negative value:"\r
-                                                       + Constants.OPCODE_NAMES[jcfaCode.getOpcode()]\r
-                                                       + ": " + operands);\r
-                       return operands;\r
-               }\r
-\r
-               switch (jcfaCode.getOpcode()) {\r
-               case Constants.RETURN:\r
-                       break;\r
-               case Constants.GETSTATIC:\r
-                       break;\r
-               case Constants.LDC:\r
-                       break;\r
-               case Constants.INVOKEVIRTUAL:\r
-               case Constants.INVOKESPECIAL:\r
-                       break;\r
-               case Constants.LOOKUPSWITCH: {\r
-                       int result = JcfaUtil.byte2Int(codes[pc + 1], codes[pc + 2],\r
-                                       codes[pc + 3], codes[pc + 4]);\r
-                       System.out.println("  TODO skipping bytes: " + (result));\r
-\r
-                       int lookupOp = pc + 5;\r
-\r
-                       short diff = JcfaUtil.byte2UnsignedByte(codes[lookupOp++]);\r
-                       System.out.println("  TODO skipping bytes: " + (diff));\r
-\r
-                       int loopCount = JcfaUtil.byte2Int(codes[lookupOp++],\r
-                                       codes[lookupOp++], codes[lookupOp++], codes[lookupOp++]);\r
-\r
-                       short diff2 = JcfaUtil.byte2UnsignedByte(codes[lookupOp++]);\r
-                       jcfaCode.getComment().getCommentList()\r
-                                       .add("  TODO skipping bytes: " + (diff2));\r
-\r
-                       operands += (lookupOp - pc);\r
-               }\r
-                       break;\r
-               default:\r
-                       break;\r
-               }\r
-\r
-               {\r
-                       final ByteArrayOutputStream outStream = new ByteArrayOutputStream();\r
-                       outStream.write(codes, pc, operands + 1);\r
-                       outStream.flush();\r
-                       jcfaCode.setCodes(outStream.toByteArray());\r
-               }\r
-               return operands;\r
-       }\r
 }
\ No newline at end of file
diff --git a/jcfa/src/jp/igapyon/jcfa/JcfaParser.java b/jcfa/src/jp/igapyon/jcfa/JcfaParser.java
new file mode 100644 (file)
index 0000000..315676d
--- /dev/null
@@ -0,0 +1,229 @@
+package jp.igapyon.jcfa;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+
+import jp.igapyon.jcfa.util.JcfaUtil;
+import jp.igapyon.jcfa.util.JcfaWriteUtil;
+import jp.igapyon.jcfa.vo.JcfaClass;
+import jp.igapyon.jcfa.vo.JcfaCode;
+import jp.igapyon.jcfa.vo.JcfaField;
+import jp.igapyon.jcfa.vo.JcfaMethod;
+import jp.igapyon.jcfa.vo.JcfaUnit;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.classfile.ClassFormatException;
+import org.apache.bcel.classfile.ClassParser;
+import org.apache.bcel.classfile.Code;
+import org.apache.bcel.classfile.ConstantValue;
+import org.apache.bcel.classfile.Field;
+import org.apache.bcel.classfile.JavaClass;
+import org.apache.bcel.classfile.Method;
+import org.apache.bcel.generic.Type;
+
+public class JcfaParser {
+       protected JcfaUnit jcfaUnit = new JcfaUnit();
+
+       public JcfaUnit parseUnit(final File inputFile, final File outputDir) {
+               try {
+                       final JavaClass jc = new ClassParser(inputFile.getCanonicalPath())
+                                       .parse();
+                       final JcfaClass jcfaClass = new JcfaClass();
+                       jcfaUnit.getClassList().add(jcfaClass);
+
+                       jcfaClass.setName(jc.getClassName());
+                       jcfaClass.setExtendsName(jc.getSuperclassName());
+
+                       jcfaClass.getComment().getCommentList()
+                                       .add("TODO import func. is missing.");
+                       jcfaClass.getComment().setJavaDoc(true);
+
+                       final String[] split = jc.getClassName().split("\\.");
+                       File actualyTargetDir = outputDir;
+                       if (split.length > 1) {
+                               for (int index = 0; index < split.length - 1; index++) {
+                                       actualyTargetDir = new File(actualyTargetDir, split[index]);
+                                       actualyTargetDir.mkdirs();
+                               }
+                       }
+
+                       parseFields(jc, jcfaClass);
+                       parseMethods(jc, jcfaClass);
+
+                       jcfaUnit.setTargetFile(new File(actualyTargetDir,
+                                       split[split.length - 1] + ".jcfa"));
+
+                       JcfaWriteUtil.writeToFile(jcfaUnit);
+               } catch (ClassFormatException e) {
+                       e.printStackTrace();
+               } catch (IOException e) {
+                       e.printStackTrace();
+               }
+               return jcfaUnit;
+       }
+
+       private void parseFields(final JavaClass jc, final JcfaClass jcfaClass) {
+               final org.apache.bcel.classfile.Field[] fields = jc.getFields();
+               for (int indexField = 0; indexField < fields.length; indexField++) {
+                       final Field field = fields[indexField];
+                       parseField(jc, field, jcfaClass);
+               }
+       }
+
+       private void parseField(final JavaClass jc, final Field field,
+                       final JcfaClass jcfaClass) {
+               final JcfaField jcfaField = new JcfaField();
+               jcfaField.setName(field.getName());
+               jcfaClass.getFieldList().add(jcfaField);
+
+               jcfaField.getComment().setJavaDoc(true);
+
+               // TODO type should be more collect.
+               jcfaField.setType(field.getType().toString());
+
+               String access = "";
+               access += field.isPublic() ? "public " : "";
+               access += field.isProtected() ? "protected " : "";
+               access += field.isPrivate() ? "private " : "";
+               access += field.isAbstract() ? "abstract " : "";
+               access += field.isStatic() ? "static " : "";
+               access += field.isVolatile() ? "volatile " : "";
+               access += field.isFinal() ? "final " : "";
+               jcfaField.setAccess(access);
+
+               final ConstantValue cv = field.getConstantValue();
+               if (cv != null) {
+                       jcfaField.setConstantValue("\""
+                                       + jc.getConstantPool().getConstantString(
+                                                       cv.getConstantValueIndex(),
+                                                       Constants.CONSTANT_String) + "\"");
+
+                       jcfaField
+                                       .getComment()
+                                       .getCommentList()
+                                       .add("FIXME other type support is missing. <br />Now only String.");
+               }
+       }
+
+       private void parseMethods(final JavaClass jc, final JcfaClass jcfaClass)
+                       throws IOException {
+               final org.apache.bcel.classfile.Method[] methods = jc.getMethods();
+               for (int indexMethod = 0; indexMethod < methods.length; indexMethod++) {
+                       final Method method = methods[indexMethod];
+                       parseMethod(jc, method, jcfaClass);
+
+               }
+       }
+
+       /**
+        * Analyze method.
+        * 
+        * @param jc
+        * @param method
+        * @param jcfaClass
+        * @throws IOException
+        */
+       private void parseMethod(final JavaClass jc, final Method method,
+                       final JcfaClass jcfaClass) throws IOException {
+               final JcfaMethod jcfaMethod = new JcfaMethod();
+               jcfaClass.getMethodList().add(jcfaMethod);
+
+               jcfaMethod.setName(method.getName());
+               jcfaMethod.getComment().setJavaDoc(true);
+               if (jcfaMethod.getName().equals("<init>")) {
+                       jcfaMethod.getComment().getCommentList()
+                                       .add("Default constructor.");
+               } else {
+                       jcfaMethod.getComment().getCommentList().add("Method.");
+               }
+
+               for (Type type : method.getArgumentTypes()) {
+                       jcfaMethod.getComment().getCommentList().add(type.toString());
+                       jcfaMethod.getArugumentTypeList().add(type.toString());
+               }
+               jcfaMethod.setType(method.getReturnType().toString());
+
+               final Code code = method.getCode();
+               if (code == null) {
+                       return;
+               }
+
+               final byte[] codes = code.getCode();
+               for (int pc = 0; pc < codes.length; pc++) {
+                       final int operands = parseCodes(jc, method, jcfaClass, jcfaMethod,
+                                       pc, codes);
+                       if (operands < 0) {
+                               break;
+                       }
+
+                       pc += operands;
+               }
+       }
+
+       private int parseCodes(final JavaClass jc, final Method method,
+                       final JcfaClass jcfaClass, final JcfaMethod jcfaMethod,
+                       final int pc, final byte[] codes) throws IOException {
+               final JcfaCode jcfaCode = new JcfaCode();
+               jcfaMethod.getCodeList().add(jcfaCode);
+               jcfaCode.setJavaClass(jc);
+
+               jcfaCode.setOpcode(JcfaUtil.byte2UnsignedByte(codes[pc]));
+               jcfaCode.getComment()
+                               .getCommentList()
+                               .add("" + pc + ": "
+                                               + Constants.OPCODE_NAMES[jcfaCode.getOpcode()]);
+
+               short operands = Constants.NO_OF_OPERANDS[jcfaCode.getOpcode()];
+               if (operands < 0) {
+                       jcfaCode.getComment()
+                                       .getCommentList()
+                                       .add("FIXME NO_OF_OPERANDS has negative value:"
+                                                       + Constants.OPCODE_NAMES[jcfaCode.getOpcode()]
+                                                       + ": " + operands);
+                       return operands;
+               }
+
+               switch (jcfaCode.getOpcode()) {
+               case Constants.RETURN:
+                       break;
+               case Constants.GETSTATIC:
+                       break;
+               case Constants.LDC:
+                       break;
+               case Constants.INVOKEVIRTUAL:
+               case Constants.INVOKESPECIAL:
+                       break;
+               case Constants.LOOKUPSWITCH: {
+                       int result = JcfaUtil.byte2Int(codes[pc + 1], codes[pc + 2],
+                                       codes[pc + 3], codes[pc + 4]);
+                       System.out.println("  TODO skipping bytes: " + (result));
+
+                       int lookupOp = pc + 5;
+
+                       short diff = JcfaUtil.byte2UnsignedByte(codes[lookupOp++]);
+                       System.out.println("  TODO skipping bytes: " + (diff));
+
+                       int loopCount = JcfaUtil.byte2Int(codes[lookupOp++],
+                                       codes[lookupOp++], codes[lookupOp++], codes[lookupOp++]);
+
+                       short diff2 = JcfaUtil.byte2UnsignedByte(codes[lookupOp++]);
+                       jcfaCode.getComment().getCommentList()
+                                       .add("  TODO skipping bytes: " + (diff2));
+
+                       operands += (lookupOp - pc);
+               }
+                       break;
+               default:
+                       break;
+               }
+
+               {
+                       final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+                       outStream.write(codes, pc, operands + 1);
+                       outStream.flush();
+                       jcfaCode.setCodes(outStream.toByteArray());
+               }
+               return operands;
+       }
+}