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 org.ejb3unit.asm.AnnotationVisitor;
032: import org.ejb3unit.asm.Attribute;
033: import org.ejb3unit.asm.ClassAdapter;
034: import org.ejb3unit.asm.ClassVisitor;
035: import org.ejb3unit.asm.FieldVisitor;
036: import org.ejb3unit.asm.MethodVisitor;
037: import org.ejb3unit.asm.Opcodes;
038:
039: /**
040: * A {@link ClassAdapter} that renames fields and methods, and removes debug
041: * info.
042: *
043: * @author Eric Bruneton
044: */
045: public class ClassOptimizer extends ClassAdapter {
046:
047: private NameMapping mapping;
048:
049: private String className;
050:
051: private String pkgName;
052:
053: public ClassOptimizer(final ClassVisitor cv,
054: final NameMapping mapping) {
055: super (cv);
056: this .mapping = mapping;
057: }
058:
059: public String getClassName() {
060: return className;
061: }
062:
063: // ------------------------------------------------------------------------
064: // Overriden methods
065: // ------------------------------------------------------------------------
066:
067: public void visit(final int version, final int access,
068: final String name, final String signature,
069: final String super Name, final String[] interfaces) {
070: className = name;
071: pkgName = name.substring(0, name.lastIndexOf('/'));
072: cv.visit(version, access, mapping.map(name), null, mapping
073: .map(super Name), interfaces);
074: }
075:
076: public void visitSource(final String source, final String debug) {
077: // remove debug info
078: }
079:
080: public void visitOuterClass(final String owner, final String name,
081: final String desc) {
082: // remove debug info
083: }
084:
085: public AnnotationVisitor visitAnnotation(final String desc,
086: final boolean visible) {
087: throw new UnsupportedOperationException();
088: }
089:
090: public void visitAttribute(final Attribute attr) {
091: // remove non standard attribute
092: }
093:
094: public void visitInnerClass(final String name,
095: final String outerName, final String innerName,
096: final int access) {
097: // remove debug info
098: }
099:
100: public FieldVisitor visitField(final int access, final String name,
101: final String desc, final String signature,
102: final Object value) {
103: String s = className + "." + name;
104: if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
105: if ((access & Opcodes.ACC_FINAL) != 0
106: && (access & Opcodes.ACC_STATIC) != 0
107: && desc.equals("I")) {
108: return null;
109: }
110: if (pkgName.equals("org/objectweb/asm")
111: && mapping.map(s).equals(name)) {
112: System.out.println("INFO: " + s + " could be renamed");
113: }
114: cv.visitField(access, mapping.map(s), mapping.fix(desc),
115: null, value);
116: } else {
117: if (!mapping.map(s).equals(name)) {
118: throw new RuntimeException(
119: "The public or protected field " + s
120: + " must not be renamed.");
121: }
122: cv.visitField(access, name, desc, null, value);
123: }
124: return null; // remove debug info
125: }
126:
127: public MethodVisitor visitMethod(final int access,
128: final String name, final String desc,
129: final String signature, final String[] exceptions) {
130: String s = className + "." + name + desc;
131: if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
132: if (pkgName.equals("org/objectweb/asm")
133: && !name.startsWith("<")
134: && mapping.map(s).equals(name)) {
135: System.out.println("INFO: " + s + " could be renamed");
136: }
137: return new MethodOptimizer(cv.visitMethod(access, mapping
138: .map(s), mapping.fix(desc), null, exceptions),
139: mapping);
140: } else {
141: if (!mapping.map(s).equals(name)) {
142: throw new RuntimeException(
143: "The public or protected method " + s
144: + " must not be renamed.");
145: }
146: return new MethodOptimizer(cv.visitMethod(access, name,
147: desc, null, exceptions), mapping);
148: }
149: }
150: }
|