Home | History | Annotate | Download | only in visitor
      1 /*
      2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
      3  *             of Java bytecode.
      4  *
      5  * Copyright (c) 2002-2014 Eric Lafortune (eric (at) graphics.cornell.edu)
      6  *
      7  * This program is free software; you can redistribute it and/or modify it
      8  * under the terms of the GNU General Public License as published by the Free
      9  * Software Foundation; either version 2 of the License, or (at your option)
     10  * any later version.
     11  *
     12  * This program is distributed in the hope that it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
     15  * more details.
     16  *
     17  * You should have received a copy of the GNU General Public License along
     18  * with this program; if not, write to the Free Software Foundation, Inc.,
     19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
     20  */
     21 package proguard.classfile.visitor;
     22 
     23 import proguard.classfile.*;
     24 import proguard.classfile.util.SimplifiedVisitor;
     25 
     26 /**
     27  * This <code>MemberVisitor</code> lets a given <code>MemberVisitor</code>
     28  * travel to all concrete and abstract implementations of the visited methods
     29  * in their class hierarchies.
     30  *
     31  * @author Eric Lafortune
     32  */
     33 public class MethodImplementationTraveler
     34 extends      SimplifiedVisitor
     35 implements   MemberVisitor
     36 {
     37     private final boolean       visitThisMethod;
     38     private final boolean       visitSuperMethods;
     39     private final boolean       visitInterfaceMethods;
     40     private final boolean       visitOverridingMethods;
     41     private final MemberVisitor memberVisitor;
     42 
     43 
     44     /**
     45      * Creates a new MethodImplementationTraveler.
     46      * @param visitThisMethod        specifies whether to visit the originally
     47      *                               visited methods.
     48      * @param visitSuperMethods      specifies whether to visit the method in
     49      *                               the super classes.
     50      * @param visitInterfaceMethods  specifies whether to visit the method in
     51      *                               the interface classes.
     52      * @param visitOverridingMethods specifies whether to visit the method in
     53      *                               the subclasses.
     54      * @param memberVisitor          the <code>MemberVisitor</code> to which
     55      *                               visits will be delegated.
     56      */
     57     public MethodImplementationTraveler(boolean       visitThisMethod,
     58                                         boolean       visitSuperMethods,
     59                                         boolean       visitInterfaceMethods,
     60                                         boolean       visitOverridingMethods,
     61                                         MemberVisitor memberVisitor)
     62     {
     63         this.visitThisMethod        = visitThisMethod;
     64         this.visitSuperMethods      = visitSuperMethods;
     65         this.visitInterfaceMethods  = visitInterfaceMethods;
     66         this.visitOverridingMethods = visitOverridingMethods;
     67         this.memberVisitor          = memberVisitor;
     68     }
     69 
     70 
     71     // Implementations for MemberVisitor.
     72 
     73     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
     74     {
     75         if (visitThisMethod)
     76         {
     77             programMethod.accept(programClass, memberVisitor);
     78         }
     79 
     80         if (!isSpecial(programClass, programMethod))
     81         {
     82             programClass.hierarchyAccept(false,
     83                                          visitSuperMethods,
     84                                          visitInterfaceMethods,
     85                                          visitOverridingMethods,
     86                                          new NamedMethodVisitor(programMethod.getName(programClass),
     87                                                                 programMethod.getDescriptor(programClass),
     88                                          new MemberAccessFilter(0,
     89                                                                 ClassConstants.ACC_PRIVATE |
     90                                                                 ClassConstants.ACC_STATIC,
     91                                          memberVisitor)));
     92         }
     93     }
     94 
     95 
     96     public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
     97     {
     98         if (visitThisMethod)
     99         {
    100             libraryMethod.accept(libraryClass, memberVisitor);
    101         }
    102 
    103         if (!isSpecial(libraryClass, libraryMethod))
    104         {
    105             libraryClass.hierarchyAccept(false,
    106                                          visitSuperMethods,
    107                                          visitInterfaceMethods,
    108                                          visitOverridingMethods,
    109                                          new NamedMethodVisitor(libraryMethod.getName(libraryClass),
    110                                                                 libraryMethod.getDescriptor(libraryClass),
    111                                          new MemberAccessFilter(0,
    112                                                                 ClassConstants.ACC_PRIVATE |
    113                                                                 ClassConstants.ACC_STATIC,
    114                                          memberVisitor)));
    115         }
    116     }
    117 
    118 
    119     // Small utility methods.
    120 
    121     private boolean isSpecial(Clazz clazz, Method method)
    122     {
    123         return (method.getAccessFlags() &
    124                 (ClassConstants.ACC_PRIVATE |
    125                  ClassConstants.ACC_STATIC)) != 0 ||
    126                method.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT);
    127     }
    128 }
    129