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    }