001    package ca.discotek.feenix.classloader;
002    
003    import java.io.File;
004    import java.io.FileOutputStream;
005    import java.io.IOException;
006    import java.io.InputStream;
007    import java.util.jar.JarFile;
008    import java.util.jar.JarOutputStream;
009    import java.util.zip.ZipEntry;
010    
011    import ca.discotek.feenix.Util;
012    import ca.discotek.feenix.io.IOUtil;
013    import ca.discotek.rebundled.org.objectweb.asm.ClassReader;
014    import ca.discotek.rebundled.org.objectweb.asm.ClassWriter;
015    
016    public class ClassLoaderGenerator {
017    
018        static final String OUTPUT_JAR_NAME = "feenix-classloader.jar";
019        
020        public static void printUsage() {
021            printUsage(null);
022        }
023        
024        public static void printUsage(String message) {
025            StringBuilder buffer = new StringBuilder();
026            if (message != null) {
027                buffer.append(message);
028                buffer.append("\n\n");
029            }
030            buffer.append("Usage:\n\t");
031            buffer.append("java " + ClassLoaderGenerator.class.getName() + " <path to rt.jar> <output directory>");
032            buffer.append("\n\n");
033            buffer.append("or");
034            buffer.append("\n\n");
035            buffer.append("java -jar " + OUTPUT_JAR_NAME + " <path to rt.jar> <output directory>");
036            System.out.println(buffer);
037            System.exit(1);
038        }
039        
040        public static void main(String[] args) {
041            if (args == null || args.length < 2) {
042                printUsage();
043            }
044            else {
045                try {
046                    File directory = new File(args[1]);
047                    if (!directory.exists()) 
048                        printUsage("Directory " + directory.getAbsolutePath() + " does not exist.");
049                    else if (!directory.isDirectory()) 
050                        printUsage("Path " + directory.getAbsolutePath() + " is not a directory.");
051                    
052                    File file = new File(args[0]);
053                    if (!file.exists()) 
054                        printUsage("File " + file.getAbsolutePath() + " does not exist.");
055                    else if (!file.isFile()) 
056                        printUsage("Path " + file.getAbsolutePath() + " is not a file.");
057                        
058                    JarFile jar = new JarFile(file);
059                    ZipEntry entry = jar.getEntry("java/lang/ClassLoader.class");
060                    InputStream is = jar.getInputStream(entry);
061                    byte bytes[] = IOUtil.copy(is);
062                    is.close();
063                    
064                    byte newBytes[] = generate(bytes);
065                    Util.checkBytes(newBytes);
066                    
067                    File outputFile = new File(directory, OUTPUT_JAR_NAME);
068                    FileOutputStream fos = new FileOutputStream(outputFile);
069                    JarOutputStream jos = new JarOutputStream(fos);
070                    entry = new ZipEntry("java/lang/ClassLoader.class");
071                    jos.putNextEntry(entry);
072                    jos.write(newBytes);
073                    jos.close();
074                    fos.close();
075                }
076                catch (IOException e) {
077                    printUsage("A runtime error occured processing rt.jar.");
078                }
079            }
080        }
081        
082        static byte[] generate(byte classLoaderBytes[]) {
083            ClassReader cr = new ClassReader(classLoaderBytes);
084            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
085            ClassLoaderClassVisitor cv = new ClassLoaderClassVisitor(cw);
086            cr.accept(cv, ClassReader.SKIP_FRAMES);
087            return cw.toByteArray();
088        }
089    }