001 package net.sourceforge.retroweaver; 002 003 import java.io.File; 004 import java.util.ArrayList; 005 import java.util.List; 006 import java.util.ResourceBundle; 007 import java.util.StringTokenizer; 008 009 import net.sourceforge.retroweaver.translator.NameSpace; 010 011 import org.objectweb.asm.commons.EmptyVisitor; 012 013 014 /** 015 * Applies the RetroWeaver against a set of classes. 016 * 017 */ 018 public class Weaver { 019 020 private static final String VERSION; 021 022 private static final String BUILD_NUMBER_STRING; 023 024 private static final int BUILD_NUMBER; 025 026 private static final int UNKNOWN_BUILD_NUMBER = -1; 027 028 public static final String getVersion() { 029 return VERSION + " (build " + BUILD_NUMBER_STRING + ')'; 030 } 031 032 public static final int getBuildNumber() { 033 return BUILD_NUMBER; 034 } 035 036 static { 037 ResourceBundle bundle = ResourceBundle.getBundle("retroweaver"); 038 VERSION = bundle.getString("retroweaver.version"); 039 BUILD_NUMBER_STRING = bundle.getString("retroweaver.buildNumber"); 040 int n; 041 try { 042 n = Integer.parseInt(BUILD_NUMBER_STRING); 043 } catch (NumberFormatException e) { 044 n = UNKNOWN_BUILD_NUMBER; 045 } 046 BUILD_NUMBER = n; 047 } 048 049 // Read the new class file format spec for how the version is computed. 050 public static final int VERSION_1_5 = 49; 051 052 public static final int VERSION_1_4 = 48; 053 054 public static final int VERSION_1_3 = 47; 055 056 public static final int VERSION_1_2 = 46; 057 058 private static final String nl = System.getProperty("line.separator"); 059 060 public static void main(String[] args) { 061 062 String source = null; 063 String sourceJar = null; 064 String destJar = null; 065 int target = VERSION_1_4; 066 int currentArg = 0; 067 boolean lazy = false; 068 boolean stripSignatures = false; 069 boolean stripAttributes = false; 070 boolean verbose = false; 071 String verifyPath = null; 072 List<NameSpace> namespaces = new ArrayList<NameSpace>(); 073 074 while (currentArg < args.length) { 075 String command = args[currentArg]; 076 ++currentArg; 077 078 if (command.equals("-source")) { 079 source = args[currentArg++]; 080 } else if (command.equals("-jar")) { 081 sourceJar = args[currentArg++]; 082 destJar = args[currentArg++]; 083 084 if (sourceJar.equals(destJar)) { 085 System.out.println("source and destination jar files can not be identical"); // NOPMD by xlv 086 System.out.println(); // NOPMD by xlv 087 System.exit(1); 088 } 089 } else if (command.equals("-namespace")) { 090 String oldPrefix = args[currentArg++]; 091 String newPrefix = args[currentArg++]; 092 NameSpace n = new NameSpace(oldPrefix, newPrefix); 093 namespaces.add(n); 094 } else if (command.equals("-version")) { 095 System.out.println("Retroweaver version " + getVersion()); // NOPMD by xlv 096 System.exit(0); 097 } else if (command.equals("-target")) { 098 String verStr = args[currentArg++]; 099 if (verStr.equals("1.4")) { 100 target = VERSION_1_4; 101 } else if (verStr.equals("1.3")) { 102 target = VERSION_1_3; 103 } else if (verStr.equals("1.2")) { 104 target = VERSION_1_2; 105 } else { 106 System.out.println("Invalid target version: " + verStr); // NOPMD by xlv 107 System.out.println(); // NOPMD by xlv 108 System.out.println(getUsage()); // NOPMD by xlv 109 System.exit(1); 110 } 111 } else if (command.equals("-lazy")) { 112 lazy = true; 113 } else if (command.equals("-stripSignatures")) { 114 stripSignatures = true; 115 } else if (command.equals("-stripAttributes")) { 116 stripAttributes = true; 117 } else if (command.equals("-verbose")) { 118 verbose = true; 119 } else if (command.equals("-verifyrefs")) { 120 verifyPath = args[currentArg++]; 121 } else { 122 System.out.println("I don't understand the command: " + command); // NOPMD by xlv 123 System.out.println(); // NOPMD by xlv 124 System.out.println(getUsage()); // NOPMD by xlv 125 System.exit(1); 126 } 127 } 128 129 if (source == null && sourceJar == null) { 130 System.out.println("Option \"-source\" or \"-jar\" is required."); // NOPMD by xlv 131 System.out.println(); // NOPMD by xlv 132 System.out.println(getUsage()); // NOPMD by xlv 133 System.exit(1); 134 } 135 136 if (source != null && sourceJar != null) { 137 System.out.println("Only one of \"-source\" or \"-jar\" can be specified."); // NOPMD by xlv 138 System.out.println(); // NOPMD by xlv 139 System.out.println(getUsage()); // NOPMD by xlv 140 System.exit(1); 141 } 142 143 File sourcePath = null; 144 145 RetroWeaver weaver = new RetroWeaver(target); 146 weaver.setListener(new DefaultWeaveListener(verbose)); 147 weaver.setLazy(lazy); 148 weaver.setStripSignatures(stripSignatures); 149 weaver.setStripAttributes(stripAttributes); 150 weaver.addNameSpaces(namespaces); 151 152 if (verifyPath != null) { 153 List<String> paths = new ArrayList<String>(); 154 StringTokenizer st = new StringTokenizer(verifyPath, 155 File.pathSeparator); 156 while (st.hasMoreTokens()) { 157 paths.add(st.nextToken()); 158 } 159 RefVerifier rv = new RefVerifier(target, new EmptyVisitor(), paths, 160 new RefVerifier.DefaultListener(verbose)); 161 weaver.setVerifier(rv); 162 } 163 164 try { 165 if (source != null) { 166 sourcePath = new File(source); 167 168 weaver.weave(sourcePath); 169 } else { 170 weaver.weaveJarFile(sourceJar, destJar); 171 } 172 } catch (Exception e) { 173 throw new RetroWeaverException("Weaving failed", e); 174 } 175 } 176 177 private static String getUsage() { 178 return "Usage: Weaver <options>" 179 + nl 180 + " Options: " 181 + nl 182 + " -source <source dir>" 183 + nl 184 + " -jar <source jar> <target jar>" 185 + nl 186 + " -target <target VM version> (one of {1.4, 1.3, 1.2}, default is 1.4)" 187 + nl + " -verifyrefs <classpath>" + nl 188 + " -stripSignatures (strip generic signatures, off by default)" + nl 189 + " -stripAttributes (strip custom attributes, off by default)" + nl 190 + " -verbose (message for each processed class)" + nl 191 + " -version (display version number and exit)" + nl + nl 192 + "One of \"-source\" or \"-jar\" is required."; 193 } 194 195 }