Home | History | Annotate | Download | only in optimizer
      1 /***
      2  * ASM: a very small and fast Java bytecode manipulation framework
      3  * Copyright (c) 2000-2005 INRIA, France Telecom
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. Neither the name of the copyright holders nor the names of its
     15  *    contributors may be used to endorse or promote products derived from
     16  *    this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     28  * THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 package org.objectweb.asm.optimizer;
     31 
     32 import org.objectweb.asm.AnnotationVisitor;
     33 import org.objectweb.asm.Attribute;
     34 import org.objectweb.asm.ClassAdapter;
     35 import org.objectweb.asm.ClassVisitor;
     36 import org.objectweb.asm.FieldVisitor;
     37 import org.objectweb.asm.MethodVisitor;
     38 import org.objectweb.asm.Opcodes;
     39 
     40 /**
     41  * A {@link ClassAdapter} that renames fields and methods, and removes debug
     42  * info.
     43  *
     44  * @author Eric Bruneton
     45  */
     46 public class ClassOptimizer extends ClassAdapter {
     47 
     48     private NameMapping mapping;
     49 
     50     private String className;
     51 
     52     private String pkgName;
     53 
     54     public ClassOptimizer(final ClassVisitor cv, final NameMapping mapping) {
     55         super(cv);
     56         this.mapping = mapping;
     57     }
     58 
     59     public String getClassName() {
     60         return className;
     61     }
     62 
     63     // ------------------------------------------------------------------------
     64     // Overriden methods
     65     // ------------------------------------------------------------------------
     66 
     67     public void visit(
     68         final int version,
     69         final int access,
     70         final String name,
     71         final String signature,
     72         final String superName,
     73         final String[] interfaces)
     74     {
     75         className = name;
     76         pkgName = name.substring(0, name.lastIndexOf('/'));
     77         cv.visit(version,
     78                 access,
     79                 mapping.map(name),
     80                 null,
     81                 mapping.map(superName),
     82                 interfaces);
     83     }
     84 
     85     public void visitSource(final String source, final String debug) {
     86         // remove debug info
     87     }
     88 
     89     public void visitOuterClass(
     90         final String owner,
     91         final String name,
     92         final String desc)
     93     {
     94         // remove debug info
     95     }
     96 
     97     public AnnotationVisitor visitAnnotation(
     98         final String desc,
     99         final boolean visible)
    100     {
    101         throw new UnsupportedOperationException();
    102     }
    103 
    104     public void visitAttribute(final Attribute attr) {
    105         // remove non standard attribute
    106     }
    107 
    108     public void visitInnerClass(
    109         final String name,
    110         final String outerName,
    111         final String innerName,
    112         final int access)
    113     {
    114         // remove debug info
    115     }
    116 
    117     public FieldVisitor visitField(
    118         final int access,
    119         final String name,
    120         final String desc,
    121         final String signature,
    122         final Object value)
    123     {
    124         String s = className + "." + name;
    125         if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
    126             if ((access & Opcodes.ACC_FINAL) != 0
    127                     && (access & Opcodes.ACC_STATIC) != 0 && desc.equals("I"))
    128             {
    129                 return null;
    130             }
    131             if (pkgName.equals("org/objectweb/asm")
    132                     && mapping.map(s).equals(name))
    133             {
    134                 System.out.println("INFO: " + s + " could be renamed");
    135             }
    136             cv.visitField(access,
    137                     mapping.map(s),
    138                     mapping.fix(desc),
    139                     null,
    140                     value);
    141         } else {
    142             if (!mapping.map(s).equals(name)) {
    143                 throw new RuntimeException("The public or protected field " + s
    144                         + " must not be renamed.");
    145             }
    146             cv.visitField(access, name, desc, null, value);
    147         }
    148         return null; // remove debug info
    149     }
    150 
    151     public MethodVisitor visitMethod(
    152         final int access,
    153         final String name,
    154         final String desc,
    155         final String signature,
    156         final String[] exceptions)
    157     {
    158         String s = className + "." + name + desc;
    159         if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
    160             if (pkgName.equals("org/objectweb/asm") && !name.startsWith("<")
    161                     && mapping.map(s).equals(name))
    162             {
    163                 System.out.println("INFO: " + s + " could be renamed");
    164             }
    165             return new MethodOptimizer(cv.visitMethod(access,
    166                     mapping.map(s),
    167                     mapping.fix(desc),
    168                     null,
    169                     exceptions), mapping);
    170         } else {
    171             if (!mapping.map(s).equals(name)) {
    172                 throw new RuntimeException("The public or protected method "
    173                         + s + " must not be renamed.");
    174             }
    175             return new MethodOptimizer(cv.visitMethod(access,
    176                     name,
    177                     desc,
    178                     null,
    179                     exceptions), mapping);
    180         }
    181     }
    182 }
    183