1 /* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2014 Eric Lafortune (eric@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 java.util.*; 24 25 /** 26 * This class stores a specification of classes and possibly class members. 27 * The specification is template-based: the class names and class member names 28 * and descriptors can contain wildcards. Classes can be specified explicitly, 29 * or as extensions or implementations in the class hierarchy. 30 * 31 * @author Eric Lafortune 32 */ 33 public class ClassSpecification implements Cloneable 34 { 35 public final String comments; 36 public int requiredSetAccessFlags; 37 public int requiredUnsetAccessFlags; 38 public final String annotationType; 39 public String className; 40 public final String extendsAnnotationType; 41 public final String extendsClassName; 42 43 public List fieldSpecifications; 44 public List methodSpecifications; 45 46 47 /** 48 * Creates a new ClassSpecification for all possible classes, without 49 * comments or class members. 50 */ ClassSpecification()51 public ClassSpecification() 52 { 53 this(null, 54 0, 55 0, 56 null, 57 null, 58 null, 59 null); 60 } 61 62 63 /** 64 * Creates a new ClassSpecification that is a copy of the given specification. 65 */ ClassSpecification(ClassSpecification classSpecification)66 public ClassSpecification(ClassSpecification classSpecification) 67 { 68 this(classSpecification.comments, 69 classSpecification.requiredSetAccessFlags, 70 classSpecification.requiredUnsetAccessFlags, 71 classSpecification.annotationType, 72 classSpecification.className, 73 classSpecification.extendsAnnotationType, 74 classSpecification.extendsClassName, 75 classSpecification.fieldSpecifications, 76 classSpecification.methodSpecifications); 77 } 78 79 80 /** 81 * Creates a new ClassSpecification for the specified class(es), without 82 * class members. 83 * 84 * @param comments provides optional comments on this 85 * specification. 86 * @param requiredSetAccessFlags the class access flags that must be set 87 * in order for the class to apply. 88 * @param requiredUnsetAccessFlags the class access flags that must be 89 * unset in order for the class to apply. 90 * @param annotationType the name of the class that must be an 91 * annotation of the class in order for it 92 * to apply. The name may be null to 93 * specify that no annotation is required. 94 * @param className the class name. The name may be null to 95 * specify any class, or it may contain 96 * "**", "*", or "?" wildcards. 97 * @param extendsAnnotationType the name of the class of that must be 98 * an annotation of the class that the 99 * class must extend or implement in order 100 * to apply. The name may be null to 101 * specify that no annotation is required. 102 * @param extendsClassName the name of the class that the class 103 * must extend or implement in order to 104 * apply. The name may be null to specify 105 * any class. 106 */ ClassSpecification(String comments, int requiredSetAccessFlags, int requiredUnsetAccessFlags, String annotationType, String className, String extendsAnnotationType, String extendsClassName)107 public ClassSpecification(String comments, 108 int requiredSetAccessFlags, 109 int requiredUnsetAccessFlags, 110 String annotationType, 111 String className, 112 String extendsAnnotationType, 113 String extendsClassName) 114 { 115 this(comments, 116 requiredSetAccessFlags, 117 requiredUnsetAccessFlags, 118 annotationType, 119 className, 120 extendsAnnotationType, 121 extendsClassName, 122 null, 123 null); 124 } 125 126 127 /** 128 * Creates a new ClassSpecification for the specified classes and class 129 * members. 130 * 131 * @param comments provides optional comments on this 132 * specification. 133 * @param requiredSetAccessFlags the class access flags that must be set 134 * in order for the class to apply. 135 * @param requiredUnsetAccessFlags the class access flags that must be 136 * unset in order for the class to apply. 137 * @param annotationType the name of the class that must be an 138 * annotation of the class in order for it 139 * to apply. The name may be null to 140 * specify that no annotation is required. 141 * @param className the class name. The name may be null to 142 * specify any class, or it may contain 143 * "**", "*", or "?" wildcards. 144 * @param extendsAnnotationType the name of the class of that must be 145 * an annotation of the class that the 146 * class must extend or implement in order 147 * to apply. The name may be null to 148 * specify that no annotation is required. 149 * @param extendsClassName the name of the class that the class 150 * must extend or implement in order to 151 * apply. The name may be null to specify 152 * any class. 153 * @param fieldSpecifications the field specifications. 154 * @param methodSpecifications the method specifications. 155 */ ClassSpecification(String comments, int requiredSetAccessFlags, int requiredUnsetAccessFlags, String annotationType, String className, String extendsAnnotationType, String extendsClassName, List fieldSpecifications, List methodSpecifications)156 public ClassSpecification(String comments, 157 int requiredSetAccessFlags, 158 int requiredUnsetAccessFlags, 159 String annotationType, 160 String className, 161 String extendsAnnotationType, 162 String extendsClassName, 163 List fieldSpecifications, 164 List methodSpecifications) 165 { 166 this.comments = comments; 167 this.requiredSetAccessFlags = requiredSetAccessFlags; 168 this.requiredUnsetAccessFlags = requiredUnsetAccessFlags; 169 this.annotationType = annotationType; 170 this.className = className; 171 this.extendsAnnotationType = extendsAnnotationType; 172 this.extendsClassName = extendsClassName; 173 this.fieldSpecifications = fieldSpecifications; 174 this.methodSpecifications = methodSpecifications; 175 } 176 177 178 /** 179 * Specifies to keep the specified field(s) of this option's class(es). 180 * 181 * @param fieldSpecification the field specification. 182 */ addField(MemberSpecification fieldSpecification)183 public void addField(MemberSpecification fieldSpecification) 184 { 185 if (fieldSpecifications == null) 186 { 187 fieldSpecifications = new ArrayList(); 188 } 189 190 fieldSpecifications.add(fieldSpecification); 191 } 192 193 194 /** 195 * Specifies to keep the specified method(s) of this option's class(es). 196 * 197 * @param methodSpecification the method specification. 198 */ addMethod(MemberSpecification methodSpecification)199 public void addMethod(MemberSpecification methodSpecification) 200 { 201 if (methodSpecifications == null) 202 { 203 methodSpecifications = new ArrayList(); 204 } 205 206 methodSpecifications.add(methodSpecification); 207 } 208 209 210 211 // Implementations for Object. 212 equals(Object object)213 public boolean equals(Object object) 214 { 215 if (object == null || 216 this.getClass() != object.getClass()) 217 { 218 return false; 219 } 220 221 ClassSpecification other = (ClassSpecification)object; 222 return 223 // (this.comments == null ? other.comments == null : this.comments.equals(other.comments) ) && 224 (this.requiredSetAccessFlags == other.requiredSetAccessFlags ) && 225 (this.requiredUnsetAccessFlags == other.requiredUnsetAccessFlags ) && 226 (this.annotationType == null ? other.annotationType == null : this.annotationType.equals(other.annotationType) ) && 227 (this.className == null ? other.className == null : this.className.equals(other.className) ) && 228 (this.extendsAnnotationType == null ? other.extendsAnnotationType == null : this.extendsAnnotationType.equals(other.extendsAnnotationType)) && 229 (this.extendsClassName == null ? other.extendsClassName == null : this.extendsClassName.equals(other.extendsClassName) ) && 230 (this.fieldSpecifications == null ? other.fieldSpecifications == null : this.fieldSpecifications.equals(other.fieldSpecifications) ) && 231 (this.methodSpecifications == null ? other.methodSpecifications == null : this.methodSpecifications.equals(other.methodSpecifications) ); 232 } 233 hashCode()234 public int hashCode() 235 { 236 return 237 // (comments == null ? 0 : comments.hashCode() ) ^ 238 (requiredSetAccessFlags ) ^ 239 (requiredUnsetAccessFlags ) ^ 240 (annotationType == null ? 0 : annotationType.hashCode() ) ^ 241 (className == null ? 0 : className.hashCode() ) ^ 242 (extendsAnnotationType == null ? 0 : extendsAnnotationType.hashCode()) ^ 243 (extendsClassName == null ? 0 : extendsClassName.hashCode() ) ^ 244 (fieldSpecifications == null ? 0 : fieldSpecifications.hashCode() ) ^ 245 (methodSpecifications == null ? 0 : methodSpecifications.hashCode() ); 246 } 247 clone()248 public Object clone() 249 { 250 try 251 { 252 return super.clone(); 253 } 254 catch (CloneNotSupportedException e) 255 { 256 return null; 257 } 258 } 259 } 260