1 16 17 package org.cojen.classfile; 18 19 import java.io.PrintWriter ; 20 21 import org.cojen.classfile.constant.ConstantClassInfo; 22 import org.cojen.classfile.constant.ConstantDoubleInfo; 23 import org.cojen.classfile.constant.ConstantFieldInfo; 24 import org.cojen.classfile.constant.ConstantFloatInfo; 25 import org.cojen.classfile.constant.ConstantIntegerInfo; 26 import org.cojen.classfile.constant.ConstantInterfaceMethodInfo; 27 import org.cojen.classfile.constant.ConstantLongInfo; 28 import org.cojen.classfile.constant.ConstantMethodInfo; 29 import org.cojen.classfile.constant.ConstantNameAndTypeInfo; 30 import org.cojen.classfile.constant.ConstantStringInfo; 31 32 38 class BuilderStylePrinter implements DisassemblyTool.Printer { 39 private PrintWriter mOut; 40 41 private int mIndent = 0; 42 private boolean mNeedIndent = true; 43 44 public BuilderStylePrinter() { 45 } 46 47 public void disassemble(ClassFile cf, PrintWriter out) { 48 mOut = out; 49 50 println("import java.io.BufferedOutputStream;"); 51 println("import java.io.File;"); 52 println("import java.io.FileOutputStream;"); 53 println("import java.io.OutputStream;"); 54 println(); 55 println("import org.cojen.classfile.ClassFile;"); 56 println("import org.cojen.classfile.CodeBuilder;"); 57 println("import org.cojen.classfile.FieldInfo;"); 58 println("import org.cojen.classfile.Label;"); 59 println("import org.cojen.classfile.LocalVariable;"); 60 println("import org.cojen.classfile.Location;"); 61 println("import org.cojen.classfile.MethodInfo;"); 62 println("import org.cojen.classfile.Modifiers;"); 63 println("import org.cojen.classfile.Opcode;"); 64 println("import org.cojen.classfile.TypeDesc;"); 65 66 disassemble(cf, (String )null); 67 } 68 69 private void disassemble(ClassFile cf, String innerClassSuffix) { 70 println(); 71 if (innerClassSuffix == null) { 72 println("/**"); 73 println(" * Builds ClassFile for " + cf.getClassName()); 74 println(" *"); 75 println(" * @author auto-generated"); 76 println(" */"); 77 println("public class ClassFileBuilder {"); 78 } else { 79 println("/**"); 80 println(" * Builds ClassFile for " + cf.getClassName()); 81 println(" */"); 82 println("private static class InnerBuilder" + innerClassSuffix + " {"); 83 } 84 mIndent += 4; 85 86 if (innerClassSuffix == null) { 87 println("public static void main(String[] args) throws Exception {"); 88 mIndent += 4; 89 println("// " + cf); 90 println("ClassFile cf = createClassFile();"); 91 92 println(); 93 println("if (args.length > 0) {"); 94 mIndent += 4; 95 println("File file = new File(args[0]);"); 96 println("if (file.isDirectory()) {"); 97 mIndent += 4; 98 println("writeClassFiles(cf, file);"); 99 mIndent -= 4; 100 println("} else {"); 101 mIndent += 4; 102 println("OutputStream out = new BufferedOutputStream(new FileOutputStream(file));"); 103 println("cf.writeTo(out);"); 104 println("out.close();"); 105 mIndent -= 4; 106 println("}"); 107 mIndent -= 4; 108 println("}"); 109 mIndent -= 4; 110 println("}"); 111 112 println(); 113 println("private static void writeClassFiles(ClassFile cf, File dir) throws Exception {"); 114 mIndent += 4; 115 println("File file = new File(dir, cf.getClassName().replace('.', '/') + \".class\");"); 116 println("file.getParentFile().mkdirs();"); 117 println("OutputStream out = new BufferedOutputStream(new FileOutputStream(file));"); 118 println("cf.writeTo(out);"); 119 println("out.close();"); 120 121 println(); 122 println("ClassFile[] innerClasses = cf.getInnerClasses();"); 123 println("for (int i=0; i<innerClasses.length; i++) {"); 124 mIndent += 4; 125 println("writeClassFiles(innerClasses[i], dir);"); 126 mIndent -= 4; 127 println("}"); 128 mIndent -= 4; 129 println("}"); 130 131 println(); 132 } 133 134 if (innerClassSuffix == null) { 135 println("public static ClassFile createClassFile() {"); 136 mIndent += 4; 137 println("ClassFile cf = new ClassFile(\"" + escape(cf.getClassName()) 138 + "\", \"" + escape(cf.getSuperClassName()) + "\");"); 139 } else { 140 println("static ClassFile createClassFile(ClassFile cf) {"); 141 mIndent += 4; 142 } 143 144 if (cf.getTarget() != null) { 145 println("cf.setTarget(\"" + escape(cf.getTarget()) + "\");"); 146 } 147 println("cf.setSourceFile(\"" + escape(cf.getSourceFile()) + "\");"); 148 149 if (cf.isSynthetic()) { 150 println("cf.markSynthetic();"); 151 } 152 if (cf.isDeprecated()) { 153 println("cf.markDeprecated();"); 154 } 155 156 if (!cf.getModifiers().equals(Modifiers.PUBLIC)) { 157 print("cf.setModifiers("); 158 printModifiers(cf); 159 println(");"); 160 } 161 162 String [] interfaces = cf.getInterfaces(); 163 for (int i=0; i<interfaces.length; i++) { 164 println("cf.addInterface(\"" + escape(interfaces[i]) + "\");"); 165 } 166 167 if (cf.getInitializer() != null) { 168 println(); 169 println("createStaticInitializer(cf);"); 170 } 171 172 FieldInfo[] fields = cf.getFields(); 173 boolean createdFieldVariable = false; 174 175 for (int i=0; i<fields.length; i++) { 176 if (i == 0) { 177 println(); 178 println("//"); 179 println("// Create fields"); 180 println("//"); 181 } 182 183 println(); 184 185 FieldInfo fi = fields[i]; 186 if (fi.isSynthetic() || fi.isDeprecated() || fi.getConstantValue() != null) { 187 if (!createdFieldVariable) { 188 print("FieldInfo "); 189 createdFieldVariable = true; 190 } 191 print("fi = "); 192 } 193 194 print("cf.addField("); 195 printModifiers(fi); 196 print(", "); 197 print('\"' + escape(fi.getName()) + "\", "); 198 print(fi.getType()); 199 println(");"); 200 201 if (fi.getConstantValue() != null) { 202 ConstantInfo constant = fi.getConstantValue(); 203 print("fi.setConstantValue("); 204 if (constant instanceof ConstantStringInfo) { 205 print("\""); 206 String value = ((ConstantStringInfo)constant).getValue(); 207 print(escape(value)); 208 print("\""); 209 } else if (constant instanceof ConstantIntegerInfo) { 210 print(String.valueOf(((ConstantIntegerInfo)constant).getValue())); 211 } else if (constant instanceof ConstantLongInfo) { 212 print(String.valueOf(((ConstantLongInfo)constant).getValue())); 213 print("L"); 214 } else if (constant instanceof ConstantFloatInfo) { 215 float value = ((ConstantFloatInfo)constant).getValue(); 216 if (value != value) { 217 print("0.0f/0.0f"); 218 } else if (value == Float.NEGATIVE_INFINITY) { 219 print("-1.0f/0.0f"); 220 } else if (value == Float.POSITIVE_INFINITY) { 221 print("1.0f/0.0f"); 222 } else { 223 print(String.valueOf(value)); 224 print("f"); 225 } 226 } else if (constant instanceof ConstantDoubleInfo) { 227 double value = ((ConstantDoubleInfo)constant).getValue(); 228 if (value != value) { 229 print("0.0d/0.0d"); 230 } else if (value == Float.NEGATIVE_INFINITY) { 231 print("-1.0d/0.0d"); 232 } else if (value == Float.POSITIVE_INFINITY) { 233 print("1.0d/0.0d"); 234 } else { 235 print(String.valueOf(value)); 236 print("d"); 237 } 238 } 239 println(");"); 240 } 241 if (fi.isSynthetic()) { 242 println("fi.markSynthetic();"); 243 } 244 if (fi.isDeprecated()) { 245 println("fi.markDeprecated();"); 246 } 247 } 248 249 MethodInfo[] methods = cf.getConstructors(); 250 for (int i=0; i<methods.length; i++) { 251 if (i == 0) { 252 println(); 253 println("//"); 254 println("// Create constructors"); 255 println("//"); 256 } 257 println(); 258 println("// " + methods[i]); 259 println("createConstructor_" + (i + 1) + "(cf);"); 260 } 261 262 methods = cf.getMethods(); 263 for (int i=0; i<methods.length; i++) { 264 if (i == 0) { 265 println(); 266 println("//"); 267 println("// Create methods"); 268 println("//"); 269 } 270 271 println(); 272 println("// " + methods[i]); 273 println("createMethod_" + (i + 1) + "(cf);"); 274 } 275 276 final ClassFile[] innerClasses = cf.getInnerClasses(); 277 278 for (int i=0; i<innerClasses.length; i++) { 279 if (i == 0) { 280 println(); 281 println("//"); 282 println("// Create inner classes"); 283 println("//"); 284 } 285 286 println(); 287 println("// " + innerClasses[i]); 288 289 if (i == 0) { 290 print("ClassFile "); 291 } 292 print("innerClass = "); 293 String name = innerClasses[i].getClassName(); 294 String innerName = innerClasses[i].getInnerClassName(); 295 if (innerName != null) { 296 if ((cf.getClassName() + '$' + innerName).equals(name)) { 297 name = null; 298 } 299 innerName = '"' + escape(innerName) + '"'; 300 } 301 if (name != null) { 302 name = '"' + escape(name) + '"'; 303 } 304 println("cf.addInnerClass(" + name + ", " + innerName + ", \"" + 305 escape(innerClasses[i].getSuperClassName()) + "\");"); 306 String suffix = "_" + (i + 1); 307 if (innerClassSuffix != null) { 308 suffix = innerClassSuffix + suffix; 309 } 310 println("InnerBuilder" + suffix + ".createClassFile(innerClass);"); 311 } 312 313 println(); 314 println("return cf;"); 315 316 mIndent -= 4; 317 println("}"); 318 319 if (cf.getInitializer() != null) { 320 println(); 321 println("private static void createStaticInitializer(ClassFile cf) {"); 322 mIndent += 4; 323 disassemble(cf.getInitializer()); 324 mIndent -= 4; 325 println("}"); 326 } 327 328 methods = cf.getConstructors(); 329 for (int i=0; i<methods.length; i++) { 330 println(); 331 println("// " + methods[i]); 332 println("private static void createConstructor_" + (i + 1) + "(ClassFile cf) {"); 333 mIndent += 4; 334 disassemble(methods[i]); 335 mIndent -= 4; 336 println("}"); 337 } 338 339 methods = cf.getMethods(); 340 for (int i=0; i<methods.length; i++) { 341 println(); 342 println("// " + methods[i]); 343 println("private static void createMethod_" + (i + 1) + "(ClassFile cf) {"); 344 mIndent += 4; 345 disassemble(methods[i]); 346 mIndent -= 4; 347 println("}"); 348 } 349 350 for (int i=0; i<innerClasses.length; i++) { 351 String suffix = "_" + (i + 1); 352 if (innerClassSuffix != null) { 353 suffix = innerClassSuffix + suffix; 354 } 355 disassemble(innerClasses[i], suffix); 356 } 357 358 mIndent -= 4; 359 println("}"); 360 } 361 362 private void disassemble(MethodInfo mi) { 363 print("MethodInfo mi = cf.add"); 364 365 if (mi.getName().equals("<clinit>")) { 366 println("Initializer();"); 367 } else if (mi.getName().equals("<init>")) { 368 print("Constructor("); 369 printModifiers(mi); 370 print(", "); 371 print(mi.getMethodDescriptor().getParameterTypes()); 372 println(");"); 373 } else { 374 print("Method("); 375 printModifiers(mi); 376 print(", "); 377 print("\"" + escape(mi.getName()) + "\", "); 378 print(mi.getMethodDescriptor().getReturnType()); 379 print(", "); 380 print(mi.getMethodDescriptor().getParameterTypes()); 381 println(");"); 382 } 383 384 if (mi.isSynthetic()) { 385 println("mi.markSynthetic();"); 386 } 387 if (mi.isDeprecated()) { 388 println("mi.markDeprecated();"); 389 } 390 TypeDesc[] exceptions = mi.getExceptions(); 391 for (int j=0; j<exceptions.length; j++) { 392 print("mi.addException("); 393 print(exceptions[j]); 394 println(");"); 395 } 396 397 if (mi.getCodeAttr() != null) { 398 println("CodeBuilder b = new CodeBuilder(mi);"); 399 println(); 400 401 TypeDesc[] paramTypes = mi.getMethodDescriptor().getParameterTypes(); 402 boolean isStatic = mi.getModifiers().isStatic(); 403 String indentStr = generateIndent(mIndent); 404 405 new CodeDisassembler(mi).disassemble 406 (new CodeAssemblerPrinter(paramTypes, isStatic, 407 mOut, indentStr, ";", "b.")); 408 } 409 } 410 411 private String escape(String str) { 412 return CodeAssemblerPrinter.escape(str); 413 } 414 415 private void printModifiers(ClassFile cf) { 416 printModifiers(cf.getModifiers()); 417 } 418 419 private void printModifiers(FieldInfo fi) { 420 printModifiers(fi.getModifiers()); 421 } 422 423 private void printModifiers(MethodInfo mi) { 424 printModifiers(mi.getModifiers()); 425 } 426 427 private void printModifiers(Modifiers modifiers) { 428 print("Modifiers."); 429 430 if (modifiers.isPublic()) { 431 if (modifiers.isAbstract()) { 432 print("PUBLIC_ABSTRACT"); 433 modifiers = modifiers.toAbstract(false); 434 } else if (modifiers.isStatic()) { 435 print("PUBLIC_STATIC"); 436 modifiers = modifiers.toStatic(false); 437 } else { 438 print("PUBLIC"); 439 } 440 modifiers = modifiers.toPublic(false); 441 } else if (modifiers.isProtected()) { 442 print("PROTECTED"); 443 modifiers = modifiers.toProtected(false); 444 } else if (modifiers.isPrivate()) { 445 print("PRIVATE"); 446 modifiers = modifiers.toPrivate(false); 447 } else { 448 print("NONE"); 449 } 450 451 if (modifiers.isStatic()) { 452 print(".toStatic(true)"); 453 } 454 if (modifiers.isFinal()) { 455 print(".toFinal(true)"); 456 } 457 if (modifiers.isSynchronized()) { 458 print(".toSynchronized(true)"); 459 } 460 if (modifiers.isVolatile()) { 461 print(".toVolatile(true)"); 462 } 463 if (modifiers.isTransient()) { 464 print(".toTransient(true)"); 465 } 466 if (modifiers.isNative()) { 467 print(".toNative(true)"); 468 } 469 if (modifiers.isInterface()) { 470 print(".toInterface(true)"); 471 } 472 if (modifiers.isAbstract() && !modifiers.isInterface()) { 473 print(".toAbstract(true)"); 474 } 475 if (modifiers.isStrict()) { 476 print(".toStrict(true)"); 477 } 478 } 479 480 private void print(TypeDesc type) { 481 if (type == null || type == TypeDesc.VOID) { 482 print("null"); 483 return; 484 } 485 486 if (type.isPrimitive()) { 487 print("TypeDesc.".concat(type.getFullName().toUpperCase())); 488 return; 489 } else if (type == TypeDesc.OBJECT) { 490 print("TypeDesc.OBJECT"); 491 return; 492 } else if (type == TypeDesc.STRING) { 493 print("TypeDesc.STRING"); 494 return; 495 } 496 497 TypeDesc componentType = type.getComponentType(); 498 if (componentType != null) { 499 print(componentType); 500 print(".toArrayType()"); 501 } else { 502 print("TypeDesc.forClass(\""); 503 print(escape(type.getRootName())); 504 print("\")"); 505 } 506 } 507 508 private void print(TypeDesc[] params) { 509 if (params == null || params.length == 0) { 510 print("null"); 511 return; 512 } 513 514 print("new TypeDesc[] {"); 515 516 for (int i=0; i<params.length; i++) { 517 if (i > 0) { 518 print(", "); 519 } 520 print(params[i]); 521 } 522 523 print("}"); 524 } 525 526 private void print(String text) { 527 indent(); 528 mOut.print(text); 529 } 530 531 private void println(String text) { 532 print(text); 533 println(); 534 } 535 536 private void println() { 537 mOut.println(); 538 mNeedIndent = true; 539 } 540 541 private void indent() { 542 if (mNeedIndent) { 543 for (int i=mIndent; --i>= 0; ) { 544 mOut.print(' '); 545 } 546 mNeedIndent = false; 547 } 548 } 549 550 private String generateIndent(int amount) { 551 StringBuffer buf = new StringBuffer (amount); 552 for (int i=0; i<amount; i++) { 553 buf.append(' '); 554 } 555 return buf.toString(); 556 } 557 } 558 | Popular Tags |