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: */package org.ejb3unit.asm.optimizer;
030:
031: import java.io.File;
032: import java.io.FileInputStream;
033: import java.io.FileOutputStream;
034: import java.io.IOException;
035: import java.io.OutputStream;
036: import java.util.Comparator;
037: import java.util.Iterator;
038: import java.util.Set;
039: import java.util.TreeSet;
040:
041: import org.ejb3unit.asm.ClassReader;
042: import org.ejb3unit.asm.ClassWriter;
043:
044: /**
045: * A class file shrinker utility.
046: *
047: * @author Eric Bruneton
048: */
049: public class Shrinker {
050:
051: public static void main(final String[] args) throws IOException {
052: NameMapping mapping = new NameMapping(args[0]);
053: File f = new File(args[1]);
054: File d = new File(args[2]);
055: optimize(f, d, mapping);
056: Iterator i = mapping.unused.iterator();
057: while (i.hasNext()) {
058: System.out.println("INFO: unused mapping " + i.next());
059: }
060: }
061:
062: static void optimize(final File f, final File d,
063: final NameMapping mapping) throws IOException {
064: if (f.isDirectory()) {
065: File[] files = f.listFiles();
066: for (int i = 0; i < files.length; ++i) {
067: optimize(files[i], d, mapping);
068: }
069: } else if (f.getName().endsWith(".class")) {
070: ConstantPool cp = new ConstantPool();
071: ClassReader cr = new ClassReader(new FileInputStream(f));
072: ClassWriter cw = new ClassWriter(0);
073: ClassConstantsCollector ccc = new ClassConstantsCollector(
074: cw, cp);
075: ClassOptimizer co = new ClassOptimizer(ccc, mapping);
076: cr.accept(co, ClassReader.SKIP_DEBUG);
077:
078: Set constants = new TreeSet(new ConstantComparator());
079: constants.addAll(cp.values());
080:
081: cr = new ClassReader(cw.toByteArray());
082: cw = new ClassWriter(0);
083: Iterator i = constants.iterator();
084: while (i.hasNext()) {
085: Constant c = (Constant) i.next();
086: c.write(cw);
087: }
088: cr.accept(cw, ClassReader.SKIP_DEBUG);
089:
090: String n = mapping.map(co.getClassName());
091: File g = new File(d, n + ".class");
092: if (!g.exists() || g.lastModified() < f.lastModified()) {
093: g.getParentFile().mkdirs();
094: OutputStream os = new FileOutputStream(g);
095: os.write(cw.toByteArray());
096: os.close();
097: }
098: }
099: }
100:
101: static class ConstantComparator implements Comparator {
102:
103: public int compare(final Object o1, final Object o2) {
104: Constant c1 = (Constant) o1;
105: Constant c2 = (Constant) o2;
106: int d = getSort(c1) - getSort(c2);
107: if (d == 0) {
108: switch (c1.type) {
109: case 'I':
110: return new Integer(c1.intVal)
111: .compareTo(new Integer(c2.intVal));
112: case 'J':
113: return new Long(c1.longVal).compareTo(new Long(
114: c2.longVal));
115: case 'F':
116: return new Float(c1.floatVal).compareTo(new Float(
117: c2.floatVal));
118: case 'D':
119: return new Double(c1.doubleVal)
120: .compareTo(new Double(c2.doubleVal));
121: case 's':
122: case 'S':
123: case 'C':
124: return c1.strVal1.compareTo(c2.strVal1);
125: case 'T':
126: d = c1.strVal1.compareTo(c2.strVal1);
127: if (d == 0) {
128: d = c1.strVal2.compareTo(c2.strVal2);
129: }
130: break;
131: default:
132: d = c1.strVal1.compareTo(c2.strVal1);
133: if (d == 0) {
134: d = c1.strVal2.compareTo(c2.strVal2);
135: if (d == 0) {
136: d = c1.strVal3.compareTo(c2.strVal3);
137: }
138: }
139: }
140: }
141: return d;
142: }
143:
144: private int getSort(final Constant c) {
145: switch (c.type) {
146: case 'I':
147: return 0;
148: case 'J':
149: return 1;
150: case 'F':
151: return 2;
152: case 'D':
153: return 3;
154: case 's':
155: return 4;
156: case 'S':
157: return 5;
158: case 'C':
159: return 6;
160: case 'T':
161: return 7;
162: case 'G':
163: return 8;
164: case 'M':
165: return 9;
166: default:
167: return 10;
168: }
169: }
170: }
171: }
|