package org.python.debug; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import dalvik.system.DexClassLoader; import com.android.dx.dex.cf.CfOptions; import com.android.dx.dex.cf.CfTranslator; import com.android.dx.dex.file.ClassDefItem; import com.android.dx.dex.file.DexFile; import com.android.dx.dex.DexOptions; /** * That's the main Code that fix the differences between the dalvik and standard * jvm * * @author Administrator */ public class FixMe { public static String tmpdirpath = "/data/data/jackpal.androidterm/jythonroid/"; public static boolean isinitialized = false; public static boolean initialize() { // create the tmp dir File tdp = new File(tmpdirpath); if (!tdp.exists()) { tdp.mkdir(); } else { if (!tdp.isDirectory()) { return false; } } isinitialized = true; return true; } /** * the Class.getDeclaringClass() is missing in Android, so it will try * the official method, and use the fix code when failed * * @param Class c * @return Class cls * @throws ClassNotFoundException */ public static Class getDeclaringClass(Class c) throws ClassNotFoundException { try { // this will work when google fix the bug Class result = c.getDeclaringClass(); return result; } catch (Exception e) { String[] elements = c.getName().replace('.', '/').split("\\$"); String name = elements[0]; for (int i = 1; i < elements.length - 1; i++) { name += "$" + elements[i]; } if (elements.length == 1) { return null; } else { return getClassByName(name); } } } /** * get class by name from the default apk file * * @param classname * @return */ public static Class getClassByName(String classname) { try { return Class.forName(classname.replace('/', '.')); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } /** * get a class by apk file name and class name need recursion as the * Class instance can not get when the super class is not inferred; * Example: * <code> * Class<c>=getClassByName("/tmp/fuck.apk","org/freehust/pystring"); * </code> * * @param String * filename,String classname * @return Class */ public static Class getClassByName(String filename, String classname) { try { DexClassLoader cl = new DexClassLoader(filename, tmpdirpath, null, ClassLoader.getSystemClassLoader()); Class s = cl.loadClass(classname); return s; } catch (ClassNotFoundException e) { throw new RuntimeException(classname + " in " + filename, e); } } /** * need recursion as the Class instance can not get when the super * class is not infered; * <code> * method dothis(): * if Class.hasSuperClass: * dothis(Class.getSuperClass) * else: * Class.forname(); * </code> * * @param classname * @return * @throws ClassNotFoundException */ // public static Class classForName(String classname) // throws ClassNotFoundException { // Class b = Class.forName(classname); // Class tmp = b.getSuperclass(); // while (tmp != null) { // tmp = tmp.getSuperclass(); // } // return b; // } /** * get inner class by name example: * getInnerClassByName(Shit,"org.freehust.Shit$shit"); * * @param c * @param name * @return Class */ public static Class getInnerClassByName(Class c, String name) { Class[] inners = c.getClasses(); for (int i = 0; i < inners.length; i++) { if (inners[i].getName().equals(name)) { return inners[i]; } } return null; } /** * detect whether Class an Inner one * * @param c * @return boolean */ public static boolean isInnerClass(Class c) { String name = c.getName(); if (name.contains("$")) { return true; } else { return false; } } /** * whether it is an outer class * * @param c * @return boolean */ public static boolean isOuterClass(Class c) { Class[] inners = c.getClasses(); if (inners.length == 0) { return false; } else { return true; } } public static Class getClass(byte[] bytecode) { return null; } public static Class getClass(File apkFile) { return null; } private static String fixPath(String path) { if (File.separatorChar == '\\') path = path.replace('\\', '/'); int index = path.lastIndexOf("/./"); if (index != -1) return path.substring(index + 3); if (path.startsWith("./")) return path.substring(2); else return path; } /** * return the dalvik Class object from the java bytecode stream * @param String name * @param byte[] data * @return Class cls * @throws IOException */ public static Class getDexClass(String name, byte[] data) throws IOException { //translate the java bytecode to dalvik bytecode DexOptions opt = new DexOptions(); DexFile outputDex = new DexFile(opt); CfOptions cf = new CfOptions(); ClassDefItem clazz = CfTranslator.translate(fixPath(name.replace('.', '/') + ".class"), data, cf, opt); outputDex.add(clazz); //create the zip file name.apk String apkn = tmpdirpath + name + ".apk"; File apk = new File(apkn); if (!apk.exists()) apk.createNewFile(); ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(apk)); ZipEntry classeszip = new ZipEntry("classes.dex"); zos.putNextEntry(classeszip); outputDex.writeTo(zos, null, false); zos.closeEntry(); zos.close(); //load the name.apk file Class c = getClassByName(apkn, name.replace('.', '/')); return c; } public static Object newInstance(Constructor cst, Object[] objects) { Thread.currentThread().setContextClassLoader( ClassLoader.getSystemClassLoader()); Class a = null; try { a = Class.forName("org.python.core.PyObject"); Constructor cs = a.getConstructor(new Class[] {}); cs.newInstance(new Object() { }); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } // DexClassLoader a=new DexClassLoader(); // try { // Class o=a.findClass("org.python.core.PyObject"); // o.getClasses(); // } catch (ClassNotFoundException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } return a; } public static void resolveClass(Class c) { // TODO Auto-generated method stub // DexClassLoader dcl=new DexClassLoader(); // dcl.resolveClass(c); } }