/* * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package com.sun.tools.renamer; import com.sun.tools.classfile.ClassFile; import com.sun.tools.classfile.ClassTranslator; import com.sun.tools.classfile.ClassWriter; import com.sun.tools.classfile.ConstantPool; import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info; import com.sun.tools.classfile.ConstantPool.CPInfo; import com.sun.tools.classfile.ConstantPoolException; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; /** * * @author ksrini */ public class PackageRenamer { private static Logger logger = Logger.getLogger(PackageRenamer.class.getName()); private static Properties config = null; private static HashSet<PatternContainer> renameList = null; private static int renamecount = 0; private static void usage(int exitcode) { System.out.println("Usage: PackageRenamer [-v ] -i input-jar -o output-jar [-c config-file]\n"); System.out.println(" Ex: config file may contain com.sun.tools.javac=com.sun.tools.mjavac\n"); System.exit(exitcode); } static void initConfig(String configfile) throws IOException { renameList = new HashSet<PatternContainer>(); if (configfile == null) { renameList.add(new PatternContainer("com/sun/tools/javac", "com/sun/tools/mjavac")); renameList.add(new PatternContainer("com.sun.tools.javac", "com.sun.tools.mjavac")); } else { config = new Properties(); config.load(new FileReader(configfile)); for (Object o : Collections.list(config.keys())) { String key = (String) o; String value = config.getProperty(key); renameList.add(new PatternContainer(key, value)); } } } /** * @param args the command line arguments */ public static void main(String[] args) { ZipFile zf = null; FileOutputStream fos = null; ZipOutputStream zstream = null; String infile = null; String outfile = null; String configfile = null; if (args == null || args.length < 4) { usage(1); } logger.setLevel(Level.WARNING); for (int n = 0 ; n < args.length ; n++) { if (args[n].equals("-v")) { logger.setLevel(Level.INFO); } if (args[n].equals("-i")) { n++; infile = args[n]; } if (args[n].equals("-o")) { n++; outfile = args[n]; } if (args[n].equals("-c")) { n++; configfile = args[n]; } } try { initConfig(configfile); zf = new ZipFile(infile); fos = new FileOutputStream(outfile); zstream = new ZipOutputStream(fos); RenamedEntry zout = null; for (ZipEntry ze : Collections.list(zf.entries())) { if (ze.isDirectory()) { continue; } logger.info("processing: " + ze); InputStream is = zf.getInputStream(ze); zout = transForm(ze, is); is.close(); zout.finish(); if (zout != null) { zstream.putNextEntry(zout); zstream.write(zout.getByteArray()); zstream.closeEntry(); } } } catch (IOException ex) { Logger.getLogger(PackageRenamer.class.getName()).log(Level.SEVERE, null, ex); System.exit(1); } finally { if (zf != null) { try { zf.close(); } catch (IOException ex) { /* ignore */ } } if (zstream != null) { try { zstream.close(); } catch (IOException ex) { /* ignore */ } } if (fos != null) { try { fos.close(); } catch (IOException ex) { /* ignore */ } } } logger.info("Renamed " + renamecount + " instances."); } private static String replaceString(String in) { for (PatternContainer pc : renameList) { if (in.contains(pc.source)) { renamecount++; String out = pc.getPattern().matcher(in).replaceAll(pc.target); logger.info("renaming: " + in + " to " + out); return out; } } return in; } private static CONSTANT_Utf8_info replaceString(CONSTANT_Utf8_info cinfo) { String s = replaceString(cinfo.value); return new CONSTANT_Utf8_info(s); } private static RenamedEntry transForm(ZipEntry ze, InputStream in) { RenamedEntry re = null; try { if (ze.getName().endsWith(".class")) { ClassFile cf = ClassFile.read(in); CPInfo[] ncpinfos = new CPInfo[cf.constant_pool.size()]; for (int n = 1; n < cf.constant_pool.size(); n++) { CPInfo cinfo = null; try { cinfo = cf.constant_pool.get(n); } catch (ConstantPool.InvalidIndex ii) { /* ignore happens for Long and Doubles*/ } if (cinfo != null && cinfo.getTag() == ConstantPool.CONSTANT_Utf8) { CONSTANT_Utf8_info ncinfo = replaceString((CONSTANT_Utf8_info) cinfo); ncpinfos[n] = ncinfo; } else { ncpinfos[n] = cinfo; } } Map<Object, Object> xmap = new HashMap<Object, Object>(); xmap.put(cf.constant_pool, new ConstantPool(ncpinfos)); ClassTranslator translator = new ClassTranslator(); ClassFile ncf = translator.translate(cf, xmap); String cname = replaceString(ze.getName()); ZipEntry nze = new ZipEntry(cname); nze.setTime(ze.getTime()); nze.setMethod(ze.getMethod()); nze.setSize(ze.getSize()); ClassWriter cw = new ClassWriter(); re = new RenamedEntry(nze); cw.write(ncf, re.getOutputStream()); } else if (ze.getName().toLowerCase().startsWith("meta-inf")) { re = new RenamedEntry(ze); BufferedReader br = new BufferedReader(new InputStreamReader(in)); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(re.getOutputStream())); String line = br.readLine(); while (line != null) { line = replaceString(line); bw.write(line + "\n"); line = br.readLine(); } bw.flush(); } else { re = new RenamedEntry(ze, in); } } catch (IOException ex) { logger.log(Level.SEVERE, null, ex); } catch (ConstantPoolException ex) { logger.log(Level.SEVERE, null, ex); } return re; } }