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 }