1 /* 2 * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package vm.mlvm.share; 25 26 import java.io.File; 27 import java.io.FileOutputStream; 28 import java.io.IOException; 29 30 import nsk.share.ArgumentParser; 31 32 public abstract class ClassfileGenerator { 33 34 public static class Klass { 35 private String pkgName; 36 private String className; 37 private byte[] bytes; 38 private String mainMethodName; 39 private String mainMethodSignature; 40 41 public Klass(String packageName, String className, String mainMethodName, String mainMethodSignature, byte[] bytes) { 42 this.pkgName = packageName; 43 this.className = className; 44 this.mainMethodName = mainMethodName; 45 this.mainMethodSignature = mainMethodSignature; 46 this.bytes = bytes; 47 } 48 49 public String getClassName() { 50 return (this.pkgName != null ? (this.pkgName + ".") : "") + this.className; 51 } 52 53 public String getSimpleClassName() { 54 return this.className; 55 } 56 57 public String getPackageName() { 58 return this.pkgName; 59 } 60 61 public String getMainMethodName() { 62 return mainMethodName; 63 } 64 65 public String getMainMethodSignature() { 66 return mainMethodSignature; 67 } 68 69 public byte[] getBytes() { 70 return this.bytes; 71 } 72 73 public void writeClass(String destDir) throws IOException { 74 boolean wroteOk = false; 75 76 File outDir; 77 if (this.pkgName != null) 78 outDir = new File(destDir, this.pkgName.replace('.', '/')); 79 else 80 outDir = new File("."); 81 82 outDir.mkdirs(); 83 84 File outFile = new File(outDir, this.className.concat(".class")); 85 FileOutputStream outStream = new FileOutputStream(outFile); 86 try { 87 outStream.write(this.bytes); 88 wroteOk = true; 89 } finally { 90 outStream.close(); 91 92 if (!wroteOk) 93 outFile.delete(); 94 } 95 } 96 } 97 98 protected String fullClassName, pkgName, shortClassName; 99 100 public void setClassName(String pkgName, String shortClassName) { 101 this.pkgName = pkgName; 102 this.shortClassName = shortClassName; 103 fullClassName = (pkgName == null ? "" : (pkgName.replace('.', '/') + '/')) 104 + shortClassName; 105 } 106 107 public abstract Klass[] generateBytecodes(); 108 109 public static void main(String[] args) { 110 try { 111 Env.init(new ArgumentParser(args) { 112 @Override 113 protected boolean checkOption(String option, String value) { 114 if (option.equals("d")) 115 return true; 116 117 return super.checkOption(option, value); 118 } 119 }); 120 121 Class<?> caller = Class.forName(Thread.currentThread() 122 .getStackTrace()[2].getClassName()); 123 ClassfileGenerator gen = (ClassfileGenerator) caller.newInstance(); 124 gen.setClassName(caller.getPackage().getName(), caller 125 .getSimpleName().replaceFirst("^GENERATE_", "")); 126 127 String destDir = Env.getArgParser().getOptions().getProperty("d"); 128 129 Klass[] klasses = gen.generateBytecodes(); 130 131 for (Klass k : klasses) 132 k.writeClass(destDir); 133 134 } catch (Exception e) { 135 Env.complain(e, "Generator caught an error"); 136 System.exit(1); 137 } 138 } 139 }