/* * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package proguard; import java.util.*; /** * This class stores a specification of classes and possibly class members. * The specification is template-based: the class names and class member names * and descriptors can contain wildcards. Classes can be specified explicitly, * or as extensions or implementations in the class hierarchy. * * @author Eric Lafortune */ public class ClassSpecification implements Cloneable { public final String comments; public int requiredSetAccessFlags; public int requiredUnsetAccessFlags; public final String annotationType; public String className; public final String extendsAnnotationType; public final String extendsClassName; public List fieldSpecifications; public List methodSpecifications; /** * Creates a new ClassSpecification for all possible classes, without * comments or class members. */ public ClassSpecification() { this(null, 0, 0, null, null, null, null); } /** * Creates a new ClassSpecification that is a copy of the given specification. */ public ClassSpecification(ClassSpecification classSpecification) { this(classSpecification.comments, classSpecification.requiredSetAccessFlags, classSpecification.requiredUnsetAccessFlags, classSpecification.annotationType, classSpecification.className, classSpecification.extendsAnnotationType, classSpecification.extendsClassName, classSpecification.fieldSpecifications, classSpecification.methodSpecifications); } /** * Creates a new ClassSpecification for the specified class(es), without * class members. * * @param comments provides optional comments on this * specification. * @param requiredSetAccessFlags the class access flags that must be set * in order for the class to apply. * @param requiredUnsetAccessFlags the class access flags that must be * unset in order for the class to apply. * @param annotationType the name of the class that must be an * annotation of the class in order for it * to apply. The name may be null to * specify that no annotation is required. * @param className the class name. The name may be null to * specify any class, or it may contain * "**", "*", or "?" wildcards. * @param extendsAnnotationType the name of the class of that must be * an annotation of the class that the * class must extend or implement in order * to apply. The name may be null to * specify that no annotation is required. * @param extendsClassName the name of the class that the class * must extend or implement in order to * apply. The name may be null to specify * any class. */ public ClassSpecification(String comments, int requiredSetAccessFlags, int requiredUnsetAccessFlags, String annotationType, String className, String extendsAnnotationType, String extendsClassName) { this(comments, requiredSetAccessFlags, requiredUnsetAccessFlags, annotationType, className, extendsAnnotationType, extendsClassName, null, null); } /** * Creates a new ClassSpecification for the specified classes and class * members. * * @param comments provides optional comments on this * specification. * @param requiredSetAccessFlags the class access flags that must be set * in order for the class to apply. * @param requiredUnsetAccessFlags the class access flags that must be * unset in order for the class to apply. * @param annotationType the name of the class that must be an * annotation of the class in order for it * to apply. The name may be null to * specify that no annotation is required. * @param className the class name. The name may be null to * specify any class, or it may contain * "**", "*", or "?" wildcards. * @param extendsAnnotationType the name of the class of that must be * an annotation of the class that the * class must extend or implement in order * to apply. The name may be null to * specify that no annotation is required. * @param extendsClassName the name of the class that the class * must extend or implement in order to * apply. The name may be null to specify * any class. * @param fieldSpecifications the field specifications. * @param methodSpecifications the method specifications. */ public ClassSpecification(String comments, int requiredSetAccessFlags, int requiredUnsetAccessFlags, String annotationType, String className, String extendsAnnotationType, String extendsClassName, List fieldSpecifications, List methodSpecifications) { this.comments = comments; this.requiredSetAccessFlags = requiredSetAccessFlags; this.requiredUnsetAccessFlags = requiredUnsetAccessFlags; this.annotationType = annotationType; this.className = className; this.extendsAnnotationType = extendsAnnotationType; this.extendsClassName = extendsClassName; this.fieldSpecifications = fieldSpecifications; this.methodSpecifications = methodSpecifications; } /** * Specifies to keep the specified field(s) of this option's class(es). * * @param fieldSpecification the field specification. */ public void addField(MemberSpecification fieldSpecification) { if (fieldSpecifications == null) { fieldSpecifications = new ArrayList(); } fieldSpecifications.add(fieldSpecification); } /** * Specifies to keep the specified method(s) of this option's class(es). * * @param methodSpecification the method specification. */ public void addMethod(MemberSpecification methodSpecification) { if (methodSpecifications == null) { methodSpecifications = new ArrayList(); } methodSpecifications.add(methodSpecification); } // Implementations for Object. public boolean equals(Object object) { if (object == null || this.getClass() != object.getClass()) { return false; } ClassSpecification other = (ClassSpecification)object; return // (this.comments == null ? other.comments == null : this.comments.equals(other.comments) ) && (this.requiredSetAccessFlags == other.requiredSetAccessFlags ) && (this.requiredUnsetAccessFlags == other.requiredUnsetAccessFlags ) && (this.annotationType == null ? other.annotationType == null : this.annotationType.equals(other.annotationType) ) && (this.className == null ? other.className == null : this.className.equals(other.className) ) && (this.extendsAnnotationType == null ? other.extendsAnnotationType == null : this.extendsAnnotationType.equals(other.extendsAnnotationType)) && (this.extendsClassName == null ? other.extendsClassName == null : this.extendsClassName.equals(other.extendsClassName) ) && (this.fieldSpecifications == null ? other.fieldSpecifications == null : this.fieldSpecifications.equals(other.fieldSpecifications) ) && (this.methodSpecifications == null ? other.methodSpecifications == null : this.methodSpecifications.equals(other.methodSpecifications) ); } public int hashCode() { return // (comments == null ? 0 : comments.hashCode() ) ^ (requiredSetAccessFlags ) ^ (requiredUnsetAccessFlags ) ^ (annotationType == null ? 0 : annotationType.hashCode() ) ^ (className == null ? 0 : className.hashCode() ) ^ (extendsAnnotationType == null ? 0 : extendsAnnotationType.hashCode()) ^ (extendsClassName == null ? 0 : extendsClassName.hashCode() ) ^ (fieldSpecifications == null ? 0 : fieldSpecifications.hashCode() ) ^ (methodSpecifications == null ? 0 : methodSpecifications.hashCode() ); } public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { return null; } } }