1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2009 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 */ 21package proguard; 22 23import 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 */ 33public 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 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