Home | History | Annotate | Download | only in proguard
      1 /*
      2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
      3  *             of Java bytecode.
      4  *
      5  * Copyright (c) 2002-2009 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;
     22 
     23 import proguard.classfile.*;
     24 import proguard.classfile.util.*;
     25 import proguard.classfile.visitor.*;
     26 import proguard.optimize.KeepMarker;
     27 
     28 import java.util.List;
     29 
     30 
     31 /**
     32  * This class checks whether classes referenced by class members that are
     33  * marked to be kept are marked to be kept too.
     34  *
     35  * @author Eric Lafortune
     36  */
     37 public class DescriptorKeepChecker
     38 extends      SimplifiedVisitor
     39 implements   MemberVisitor,
     40              ClassVisitor
     41 {
     42     private final ClassPool      programClassPool;
     43     private final ClassPool      libraryClassPool;
     44     private final WarningPrinter notePrinter;
     45 
     46     // Some fields acting as parameters for the class visitor.
     47     private Clazz   referencingClass;
     48     private Member  referencingMember;
     49     private boolean isField;
     50 
     51 
     52     /**
     53      * Creates a new DescriptorKeepChecker.
     54      */
     55     public DescriptorKeepChecker(ClassPool      programClassPool,
     56                                  ClassPool      libraryClassPool,
     57                                  WarningPrinter notePrinter)
     58     {
     59         this.programClassPool = programClassPool;
     60         this.libraryClassPool = libraryClassPool;
     61         this.notePrinter      = notePrinter;
     62     }
     63 
     64 
     65     /**
     66      * Checks the classes mentioned in the given keep specifications, printing
     67      * notes if necessary. Returns the number of notes printed.
     68      */
     69     public void checkClassSpecifications(List keepSpecifications)
     70     {
     71         // Clean up any old visitor info.
     72         programClassPool.classesAccept(new ClassCleaner());
     73         libraryClassPool.classesAccept(new ClassCleaner());
     74 
     75         // Create a visitor for marking the seeds.
     76         KeepMarker keepMarker = new KeepMarker();
     77         ClassPoolVisitor classPoolvisitor =
     78             ClassSpecificationVisitorFactory.createClassPoolVisitor(keepSpecifications,
     79                                                                     keepMarker,
     80                                                                     keepMarker,
     81                                                                     false,
     82                                                                     true,
     83                                                                     true);
     84         // Mark the seeds.
     85         programClassPool.accept(classPoolvisitor);
     86         libraryClassPool.accept(classPoolvisitor);
     87 
     88         // Print out notes about argument types that are not being kept.
     89         programClassPool.classesAccept(new AllMemberVisitor(this));
     90     }
     91 
     92 
     93     // Implementations for MemberVisitor.
     94 
     95     public void visitProgramField(ProgramClass programClass, ProgramField programField)
     96     {
     97         if (KeepMarker.isKept(programField))
     98         {
     99             referencingClass  = programClass;
    100             referencingMember = programField;
    101             isField           = true;
    102 
    103             // Don't check the type, because it is not required for introspection.
    104             //programField.referencedClassesAccept(this);
    105         }
    106     }
    107 
    108 
    109     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
    110     {
    111         if (KeepMarker.isKept(programMethod))
    112         {
    113             referencingClass  = programClass;
    114             referencingMember = programMethod;
    115             isField           = false;
    116 
    117             // Don't check the return type, because it is not required for
    118             // introspection (e.g. the return type of the special Enum methods).
    119             //programMethod.referencedClassesAccept(this);
    120 
    121             Clazz[] referencedClasses = programMethod.referencedClasses;
    122             if (referencedClasses != null)
    123             {
    124                 for (int index = 0; index < referencedClasses.length-1; index++)
    125                 {
    126                     if (referencedClasses[index] != null)
    127                     {
    128                         referencedClasses[index].accept(this);
    129                     }
    130                 }
    131             }
    132         }
    133     }
    134 
    135 
    136     // Implementations for ClassVisitor.
    137 
    138     public void visitProgramClass(ProgramClass programClass)
    139     {
    140         if (!KeepMarker.isKept(programClass))
    141         {
    142             notePrinter.print(referencingClass.getName(),
    143                               programClass.getName(),
    144                               "Note: the configuration keeps the entry point '" +
    145                               ClassUtil.externalClassName(referencingClass.getName()) +
    146                               " { " +
    147                               (isField ?
    148                                    ClassUtil.externalFullFieldDescription(0,
    149                                                                           referencingMember.getName(referencingClass),
    150                                                                           referencingMember.getDescriptor(referencingClass)) :
    151                                    ClassUtil.externalFullMethodDescription(referencingClass.getName(),
    152                                                                            0,
    153                                                                            referencingMember.getName(referencingClass),
    154                                                                            referencingMember.getDescriptor(referencingClass))) +
    155                               "; }', but not the descriptor class '" +
    156                               ClassUtil.externalClassName(programClass.getName()) +
    157                               "'");
    158         }
    159     }
    160 
    161 
    162     public void visitLibraryClass(LibraryClass libraryClass) {}
    163 }
    164