001: /*
002: * ASM: a very small and fast Java bytecode manipulation framework
003: * Copyright (c) 2000-2005 INRIA, France Telecom
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: * 2. Redistributions in binary form must reproduce the above copyright
012: * notice, this list of conditions and the following disclaimer in the
013: * documentation and/or other materials provided with the distribution.
014: * 3. Neither the name of the copyright holders nor the names of its
015: * contributors may be used to endorse or promote products derived from
016: * this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028: * THE POSSIBILITY OF SUCH DAMAGE.
029: */
030: package org.objectweb.asm.optimizer;
031:
032: import java.io.File;
033: import java.io.FileInputStream;
034: import java.io.FileOutputStream;
035: import java.io.IOException;
036: import java.io.OutputStream;
037: import java.util.Comparator;
038: import java.util.Iterator;
039: import java.util.Set;
040: import java.util.TreeSet;
041:
042: import org.objectweb.asm.ClassReader;
043: import org.objectweb.asm.ClassWriter;
044:
045: /**
046: * A class file shrinker utility.
047: *
048: * @author Eric Bruneton
049: */
050: @SuppressWarnings("unchecked")
051: public class Shrinker {
052:
053: public static void main(final String[] args) throws IOException {
054: NameMapping mapping = new NameMapping(args[0]);
055: File f = new File(args[1]);
056: File d = new File(args[2]);
057: optimize(f, d, mapping);
058: Iterator i = mapping.unused.iterator();
059: while (i.hasNext()) {
060: System.out.println("INFO: unused mapping " + i.next());
061: }
062: }
063:
064: static void optimize(final File f, final File d,
065: final NameMapping mapping) throws IOException {
066: if (f.isDirectory()) {
067: File[] files = f.listFiles();
068: for (int i = 0; i < files.length; ++i) {
069: optimize(files[i], d, mapping);
070: }
071: } else if (f.getName().endsWith(".class")) {
072: ConstantPool cp = new ConstantPool();
073: ClassReader cr = new ClassReader(new FileInputStream(f));
074: ClassWriter cw = new ClassWriter(0);
075: ClassConstantsCollector ccc = new ClassConstantsCollector(
076: cw, cp);
077: ClassOptimizer co = new ClassOptimizer(ccc, mapping);
078: cr.accept(co, ClassReader.SKIP_DEBUG);
079:
080: Set constants = new TreeSet(new ConstantComparator());
081: constants.addAll(cp.values());
082:
083: cr = new ClassReader(cw.toByteArray());
084: cw = new ClassWriter(0);
085: Iterator i = constants.iterator();
086: while (i.hasNext()) {
087: Constant c = (Constant) i.next();
088: c.write(cw);
089: }
090: cr.accept(cw, ClassReader.SKIP_DEBUG);
091:
092: String n = mapping.map(co.getClassName());
093: File g = new File(d, n + ".class");
094: if (!g.exists() || g.lastModified() < f.lastModified()) {
095: g.getParentFile().mkdirs();
096: OutputStream os = new FileOutputStream(g);
097: os.write(cw.toByteArray());
098: os.close();
099: }
100: }
101: }
102:
103: static class ConstantComparator implements Comparator {
104:
105: public int compare(final Object o1, final Object o2) {
106: Constant c1 = (Constant) o1;
107: Constant c2 = (Constant) o2;
108: int d = getSort(c1) - getSort(c2);
109: if (d == 0) {
110: switch (c1.type) {
111: case 'I':
112: return new Integer(c1.intVal)
113: .compareTo(new Integer(c2.intVal));
114: case 'J':
115: return new Long(c1.longVal).compareTo(new Long(
116: c2.longVal));
117: case 'F':
118: return new Float(c1.floatVal).compareTo(new Float(
119: c2.floatVal));
120: case 'D':
121: return new Double(c1.doubleVal)
122: .compareTo(new Double(c2.doubleVal));
123: case 's':
124: case 'S':
125: case 'C':
126: return c1.strVal1.compareTo(c2.strVal1);
127: case 'T':
128: d = c1.strVal1.compareTo(c2.strVal1);
129: if (d == 0) {
130: d = c1.strVal2.compareTo(c2.strVal2);
131: }
132: break;
133: default:
134: d = c1.strVal1.compareTo(c2.strVal1);
135: if (d == 0) {
136: d = c1.strVal2.compareTo(c2.strVal2);
137: if (d == 0) {
138: d = c1.strVal3.compareTo(c2.strVal3);
139: }
140: }
141: }
142: }
143: return d;
144: }
145:
146: private int getSort(final Constant c) {
147: switch (c.type) {
148: case 'I':
149: return 0;
150: case 'J':
151: return 1;
152: case 'F':
153: return 2;
154: case 'D':
155: return 3;
156: case 's':
157: return 4;
158: case 'S':
159: return 5;
160: case 'C':
161: return 6;
162: case 'T':
163: return 7;
164: case 'G':
165: return 8;
166: case 'M':
167: return 9;
168: default:
169: return 10;
170: }
171: }
172: }
173: }
|