00001 import de.fub.bytecode.*; 00002 import de.fub.bytecode.classfile.*; 00003 import de.fub.bytecode.generic.*; 00004 import java.io.*; 00005 00006 public class GenerateReflection { 00007 private static final int METHOD_COUNT = 0; 00008 private static final int EXECUTE_METHOD = 1; 00009 private static final int IS_METHOD_EXECUTABLE = 2; 00010 private static final int IS_METHOD_DETERMINISTIC = 3; 00011 private static final int STATIC_METHOD_COUNT = 4; 00012 private static final int EXECUTE_STATIC_METHOD = 5; 00013 private static final int IS_STATIC_METHOD_EXECUTABLE = 6; 00014 private static final int IS_STATIC_METHOD_DETERMINISTIC = 7; 00015 00016 private static String packageName = null; 00017 private static boolean forceMethod = false; 00018 private static boolean forceStaticMethod = false; 00019 00020 private static class GenerateVisitor extends EmptyVisitor { 00021 private int phase; 00022 private int counter = 0; 00023 private JavaClass jc; 00024 private PrintStream outfile; 00025 00026 public GenerateVisitor(JavaClass j, int p, PrintStream o) { 00027 jc = j; 00028 phase = p; 00029 outfile = o; 00030 } 00031 00032 public int getCounter() { 00033 return counter; 00034 } 00035 00036 public void visitMethod(Method m) { 00037 if(m.isNative()) { 00038 switch(phase) { 00039 case METHOD_COUNT: 00040 if(m.isStatic()) return; 00041 counter++; 00042 break; 00043 00044 case EXECUTE_METHOD: 00045 if(m.isStatic()) return; 00046 putEquals(m); 00047 putPop(m, false); 00048 putReturnNextPC(); 00049 break; 00050 00051 case IS_METHOD_EXECUTABLE: 00052 if(m.isStatic()) return; 00053 putEquals(m); 00054 putPeek(m); 00055 putReturnTrue(); 00056 break; 00057 00058 case IS_METHOD_DETERMINISTIC: 00059 if(m.isStatic()) return; 00060 putEquals(m); 00061 putPeek(m); 00062 putReturnTrue(); 00063 break; 00064 00065 case STATIC_METHOD_COUNT: 00066 if(!m.isStatic()) return; 00067 counter++; 00068 break; 00069 00070 case EXECUTE_STATIC_METHOD: 00071 if(!m.isStatic()) return; 00072 putEquals(m); 00073 putPop(m, true); 00074 putReturnNextPC(); 00075 break; 00076 00077 case IS_STATIC_METHOD_EXECUTABLE: 00078 if(!m.isStatic()) return; 00079 putEquals(m); 00080 putPeek(m); 00081 putReturnTrue(); 00082 break; 00083 00084 case IS_STATIC_METHOD_DETERMINISTIC: 00085 if(!m.isStatic()) return; 00086 putEquals(m); 00087 putPeek(m); 00088 putReturnTrue(); 00089 break; 00090 } 00091 } 00092 } 00093 00094 private void putEquals(Method m) { 00095 outfile.println(" if(name.equals(\"" + jc.getClassName() + "." + m.getName() + m.getSignature() + "\")) {"); 00096 outfile.println(" // throws a runtime exception for now"); 00097 outfile.println(" throw new NativeMethodException(\"" + jc.getClassName() + "." + m.getName() + m.getSignature() + "\");"); 00098 outfile.println(" // put your code here"); 00099 } 00100 00101 private void putReturnNextPC() { 00102 outfile.println(" // return th.getPC().getNext();"); 00103 outfile.println(" }"); 00104 outfile.println(); 00105 } 00106 00107 private void putReturnTrue() { 00108 outfile.println(" // return true;"); 00109 outfile.println(" }"); 00110 outfile.println(); 00111 } 00112 00113 private void putPop(Method m, boolean isStatic) { 00114 Type[] args = Type.getArgumentTypes(m.getSignature()); 00115 int nargs = args.length; 00116 00117 for(int i = nargs - 1; i >= 0; i--) { 00118 int t = args[i].getType(); 00119 00120 switch(t) { 00121 case Constants.T_BOOLEAN: 00122 outfile.println(" // boolean arg" + i + " = th.popBoolean();"); 00123 break; 00124 00125 case Constants.T_BYTE: 00126 outfile.println(" // byte arg" + i + " = th.popByte();"); 00127 break; 00128 00129 case Constants.T_CHAR: 00130 outfile.println(" // char arg" + i + " = th.popChar();"); 00131 break; 00132 00133 case Constants.T_DOUBLE: 00134 outfile.println(" // double arg" + i + " = th.popDouble();"); 00135 break; 00136 00137 case Constants.T_FLOAT: 00138 outfile.println(" // float arg" + i + " = th.popFloat();"); 00139 break; 00140 00141 case Constants.T_INT: 00142 outfile.println(" // int arg" + i + " = th.popInt();"); 00143 break; 00144 00145 case Constants.T_LONG: 00146 outfile.println(" // long arg" + i + " = th.popLong();"); 00147 break; 00148 00149 case Constants.T_REFERENCE: 00150 case Constants.T_ARRAY: 00151 outfile.println(" // ObjRef arg" + i + " = th.popObjRef();"); 00152 break; 00153 00154 case Constants.T_SHORT: 00155 outfile.println(" // short arg" + i + " = th.popShort();"); 00156 break; 00157 00158 } 00159 00160 if(!isStatic) 00161 outfile.println(" // th.popObjRef(); // this"); 00162 } 00163 00164 int t = Type.getReturnType(m.getSignature()).getType(); 00165 00166 switch(t) { 00167 case Constants.T_BOOLEAN: 00168 outfile.println(" // boolean result;"); 00169 outfile.println(" // th.pushBoolean(result);"); 00170 break; 00171 00172 case Constants.T_BYTE: 00173 outfile.println(" // byte result;"); 00174 outfile.println(" // th.pushByte(result);"); 00175 break; 00176 00177 case Constants.T_CHAR: 00178 outfile.println(" // char result;"); 00179 outfile.println(" // th.pushChar(result);"); 00180 break; 00181 00182 case Constants.T_DOUBLE: 00183 outfile.println(" // double result;"); 00184 outfile.println(" // th.pushDouble(result);"); 00185 break; 00186 00187 case Constants.T_FLOAT: 00188 outfile.println(" // float result;"); 00189 outfile.println(" // th.pushFloat(result);"); 00190 break; 00191 00192 case Constants.T_INT: 00193 outfile.println(" // int result;"); 00194 outfile.println(" // th.pushInt(result);"); 00195 break; 00196 00197 case Constants.T_LONG: 00198 outfile.println(" // long result;"); 00199 outfile.println(" // th.pushLong(result);"); 00200 break; 00201 00202 case Constants.T_REFERENCE: 00203 case Constants.T_ARRAY: 00204 outfile.println(" // ObjRef result;"); 00205 outfile.println(" // th.pushObjRef(result);"); 00206 break; 00207 00208 case Constants.T_SHORT: 00209 outfile.println(" // short result;"); 00210 outfile.println(" // th.pushShort(result);"); 00211 break; 00212 } 00213 } 00214 00215 private void putPeek(Method m) { 00216 Type[] args = Type.getArgumentTypes(m.getSignature()); 00217 int nargs = args.length; 00218 00219 for(int i = nargs - 1; i >= 0; i--) { 00220 int t = args[i].getType(); 00221 00222 switch(t) { 00223 case Constants.T_BOOLEAN: 00224 outfile.println(" // boolean arg" + i + " = th.peekBoolean(" + i + ");"); 00225 break; 00226 00227 case Constants.T_BYTE: 00228 outfile.println(" // byte arg" + i + " = th.peekByte(" + i + ");"); 00229 break; 00230 00231 case Constants.T_CHAR: 00232 outfile.println(" // char arg" + i + " = th.peekChar(" + i + ");"); 00233 break; 00234 00235 case Constants.T_DOUBLE: 00236 outfile.println(" // double arg" + i + " = th.peekDouble(" + i + ");"); 00237 break; 00238 00239 case Constants.T_FLOAT: 00240 outfile.println(" // float arg" + i + " = th.peekFloat(" + i + ");"); 00241 break; 00242 00243 case Constants.T_INT: 00244 outfile.println(" // int arg" + i + " = th.peekInt(" + i + ");"); 00245 break; 00246 00247 case Constants.T_LONG: 00248 outfile.println(" // long arg" + i + " = th.peekLong(" + i + ");"); 00249 break; 00250 00251 case Constants.T_REFERENCE: 00252 case Constants.T_ARRAY: 00253 outfile.println(" // ObjRef arg" + i + " = th.peekObjRef(" + i + ");"); 00254 break; 00255 00256 case Constants.T_SHORT: 00257 outfile.println(" // short arg" + i + " = th.peekShort(" + i + ");"); 00258 break; 00259 00260 } 00261 } 00262 } 00263 } 00264 00265 private static int generate(JavaClass j, int p, PrintStream o) { 00266 GenerateVisitor gv = new GenerateVisitor(j, p, o); 00267 new DefaultVisitor(j, gv).visit(); 00268 00269 return gv.getCounter(); 00270 } 00271 private static String getFileName(String name) { 00272 int index = 0; 00273 int last = 0; 00274 StringBuffer sb = new StringBuffer(); 00275 00276 while((index = name.indexOf(".", last)) != -1) { 00277 sb.append(Character.toUpperCase(name.charAt(last))); 00278 sb.append(name.substring(last + 1, index)); 00279 last = index + 1; 00280 } 00281 sb.append(name.substring(last)); 00282 00283 return sb.toString(); 00284 } 00285 public static void main(String[] args) { 00286 int argc = args.length; 00287 00288 if(argc == 0) { 00289 System.err.println("usage:"); 00290 System.err.println("\tjava GenerateReflection [ -package <package> ] [ -force-methods ] [ -force-static-methods ] <classname> {<classname> ...}"); 00291 System.err.println(); 00292 return; 00293 } 00294 00295 for(int i = 0; i < argc; i++) 00296 if(args[i].startsWith("-")) { 00297 if(args[i].equals("-package")) { 00298 packageName = args[++i]; 00299 } else if(args[i].equals("-force-methods")) { 00300 forceMethod = true; 00301 } else if(args[i].equals("-force-static-methods")) { 00302 forceStaticMethod = true; 00303 } else { 00304 System.err.println("invalid option -- " + args[i]); 00305 System.exit(1); 00306 } 00307 } else 00308 process(args[i]); 00309 } 00310 private static void process(String name) { 00311 try { 00312 System.out.println(name + ":"); 00313 00314 PrintStream outfile = new PrintStream(new FileOutputStream(getFileName(name) + "Reflection.java")); 00315 00316 JavaClass jc; 00317 00318 if((jc = Repository.lookupClass(name)) == null) 00319 jc = new ClassParser(name).parse(); 00320 00321 int nMethods = generate(jc, METHOD_COUNT, null); 00322 int nStaticMethods = generate(jc, STATIC_METHOD_COUNT, null); 00323 00324 if(nMethods != 0 || nStaticMethods != 0 || forceMethod || forceStaticMethod) { 00325 if(packageName != null) { 00326 outfile.println("package " + packageName + ";"); 00327 outfile.println(); 00328 } 00329 outfile.println("import gov.nasa.arc.ase.jpf.jvm.*;"); 00330 outfile.println("import gov.nasa.arc.ase.jpf.jvm.reflection.*;"); 00331 outfile.println("import de.fub.bytecode.generic.InstructionHandle;"); 00332 outfile.println(); 00333 outfile.println("public class " + getFileName(name) + "Reflection extends Reflection {"); 00334 if(nMethods != 0 || forceMethod) { 00335 outfile.println(" public InstructionHandle executeMethod(MethodInfo mi, boolean atomic) {"); 00336 outfile.println(" String name = mi.getFullName();"); 00337 outfile.println(); 00338 00339 generate(jc, EXECUTE_METHOD, outfile); 00340 00341 outfile.println(" return super.executeMethod(mi, atomic);"); 00342 outfile.println(" }"); 00343 outfile.println(); 00344 outfile.println(" public boolean isMethodExecutable(MethodInfo mi) {"); 00345 outfile.println(" String name = mi.getFullName();"); 00346 outfile.println(); 00347 00348 generate(jc, IS_METHOD_EXECUTABLE, outfile); 00349 00350 outfile.println(" return super.isMethodExecutable(mi);"); 00351 outfile.println(" }"); 00352 outfile.println(); 00353 outfile.println(" public boolean isMethodDeterministic(MethodInfo mi) {"); 00354 outfile.println(" String name = mi.getFullName();"); 00355 outfile.println(); 00356 00357 generate(jc, IS_METHOD_DETERMINISTIC, outfile); 00358 00359 outfile.println(" return super.isMethodDeterministic(mi);"); 00360 outfile.println(" }"); 00361 } 00362 if(nStaticMethods != 0 || forceStaticMethod) { 00363 outfile.println(" public InstructionHandle executeStaticMethod(MethodInfo mi, boolean atomic) {"); 00364 outfile.println(" String name = mi.getFullName();"); 00365 outfile.println(); 00366 00367 generate(jc, EXECUTE_STATIC_METHOD, outfile); 00368 00369 outfile.println(" return super.executeStaticMethod(mi, atomic);"); 00370 outfile.println(" }"); 00371 outfile.println(); 00372 outfile.println(" public boolean isStaticMethodExecutable(MethodInfo mi) {"); 00373 outfile.println(" String name = mi.getFullName();"); 00374 outfile.println(); 00375 00376 generate(jc, IS_STATIC_METHOD_EXECUTABLE, outfile); 00377 00378 outfile.println(" return super.isStaticMethodExecutable(mi);"); 00379 outfile.println(" }"); 00380 outfile.println(); 00381 outfile.println(" public boolean isStaticMethodDeterministic(MethodInfo mi) {"); 00382 outfile.println(" String name = mi.getFullName();"); 00383 outfile.println(); 00384 00385 generate(jc, IS_STATIC_METHOD_DETERMINISTIC, outfile); 00386 00387 outfile.println(" return super.isStaticMethodDeterministic(mi);"); 00388 outfile.println(" }"); 00389 } 00390 outfile.println("}"); 00391 } 00392 } catch(IOException e) { 00393 e.printStackTrace(); 00394 System.exit(1); 00395 } 00396 } 00397 }