aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/java/proguard/proguard5.3.3/src/proguard/ClassSpecificationVisitorFactory.java
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/java/proguard/proguard5.3.3/src/proguard/ClassSpecificationVisitorFactory.java')
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ClassSpecificationVisitorFactory.java529
1 files changed, 529 insertions, 0 deletions
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ClassSpecificationVisitorFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ClassSpecificationVisitorFactory.java
new file mode 100644
index 0000000000..e13000388b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ClassSpecificationVisitorFactory.java
@@ -0,0 +1,529 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * 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 proguard.classfile.ClassConstants;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.visitor.*;
+
+import java.util.List;
+
+/**
+ * This factory creates visitors to efficiently travel to specified classes and
+ * class members.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassSpecificationVisitorFactory
+{
+ /**
+ * Constructs a ClassPoolVisitor to efficiently travel to the specified
+ * classes and class members.
+ *
+ * @param keepClassSpecifications the list of KeepClassSpecification
+ * instances that specify the classes and
+ * class members to visit.
+ * @param classVisitor the ClassVisitor to be applied to matching
+ * classes.
+ * @param memberVisitor the MemberVisitor to be applied to matching
+ * class members.
+ * @param shrinking a flag that specifies whether the visitors
+ * are intended for the shrinking step.
+ * @param optimizing a flag that specifies whether the visitors
+ * are intended for the optimization step.
+ * @param obfuscating a flag that specifies whether the visitors
+ * are intended for the obfuscation step.
+ */
+ public static ClassPoolVisitor createClassPoolVisitor(List keepClassSpecifications,
+ ClassVisitor classVisitor,
+ MemberVisitor memberVisitor,
+ boolean shrinking,
+ boolean optimizing,
+ boolean obfuscating)
+ {
+ MultiClassPoolVisitor multiClassPoolVisitor = new MultiClassPoolVisitor();
+
+ if (keepClassSpecifications != null)
+ {
+ for (int index = 0; index < keepClassSpecifications.size(); index++)
+ {
+ KeepClassSpecification keepClassSpecification =
+ (KeepClassSpecification)keepClassSpecifications.get(index);
+
+ if ((shrinking && !keepClassSpecification.allowShrinking) ||
+ (optimizing && !keepClassSpecification.allowOptimization) ||
+ (obfuscating && !keepClassSpecification.allowObfuscation))
+ {
+ multiClassPoolVisitor.addClassPoolVisitor(
+ createClassPoolVisitor(keepClassSpecification,
+ classVisitor,
+ memberVisitor));
+ }
+ }
+ }
+
+ return multiClassPoolVisitor;
+ }
+
+
+ /**
+ * Constructs a ClassPoolVisitor to efficiently travel to the specified
+ * classes and class members.
+ *
+ * @param classSpecifications the list of ClassSpecification instances
+ * that specify the classes and class members
+ * to visit.
+ * @param classVisitor the ClassVisitor to be applied to matching
+ * classes.
+ * @param memberVisitor the MemberVisitor to be applied to matching
+ * class members.
+ */
+ public static ClassPoolVisitor createClassPoolVisitor(List classSpecifications,
+ ClassVisitor classVisitor,
+ MemberVisitor memberVisitor)
+ {
+ MultiClassPoolVisitor multiClassPoolVisitor = new MultiClassPoolVisitor();
+
+ if (classSpecifications != null)
+ {
+ for (int index = 0; index < classSpecifications.size(); index++)
+ {
+ ClassSpecification classSpecification =
+ (ClassSpecification)classSpecifications.get(index);
+
+ multiClassPoolVisitor.addClassPoolVisitor(
+ createClassPoolVisitor(classSpecification,
+ classVisitor,
+ memberVisitor));
+ }
+ }
+
+ return multiClassPoolVisitor;
+ }
+
+
+ /**
+ * Constructs a ClassPoolVisitor to efficiently travel to the specified
+ * classes and class members.
+ *
+ * @param keepClassSpecification the specifications of the class(es) and
+ * class members to visit.
+ * @param classVisitor the ClassVisitor to be applied to
+ * matching classes.
+ * @param memberVisitor the MemberVisitor to be applied to
+ * matching class members.
+ */
+ public static ClassPoolVisitor createClassPoolVisitor(KeepClassSpecification keepClassSpecification,
+ ClassVisitor classVisitor,
+ MemberVisitor memberVisitor)
+ {
+ // If specified, let the class visitor also visit the descriptor
+ // classes and the signature classes.
+ if (keepClassSpecification.markDescriptorClasses &&
+ classVisitor != null)
+ {
+ memberVisitor = memberVisitor == null ?
+ new MemberDescriptorReferencedClassVisitor(classVisitor) :
+ new MultiMemberVisitor(new MemberVisitor[]
+ {
+ memberVisitor,
+
+ new MemberDescriptorReferencedClassVisitor(classVisitor),
+
+ new AllAttributeVisitor(
+ new AttributeNameFilter(ClassConstants.ATTR_Signature,
+ new ReferencedClassVisitor(classVisitor)))
+ });
+ }
+
+ // Don't visit the classes if not specified.
+ if (!keepClassSpecification.markClasses &&
+ !keepClassSpecification.markConditionally)
+ {
+ classVisitor = null;
+ }
+
+ // If specified, let the marker visit the class and its class
+ // members conditionally.
+ if (keepClassSpecification.markConditionally)
+ {
+ // Combine both visitors.
+ ClassVisitor composedClassVisitor =
+ createCombinedClassVisitor(keepClassSpecification,
+ classVisitor,
+ memberVisitor);
+
+ // Replace the class visitor.
+ classVisitor =
+ createClassMemberTester(keepClassSpecification,
+ composedClassVisitor);
+
+ // Discard the member visitor, because it has already been included.
+ memberVisitor = null;
+ }
+
+ return createClassPoolVisitor((ClassSpecification)keepClassSpecification,
+ classVisitor,
+ memberVisitor);
+ }
+
+
+ /**
+ * Constructs a ClassPoolVisitor to efficiently travel to the specified
+ * classes and class members.
+ *
+ * @param classSpecification the specifications of the class(es) and class
+ * members to visit.
+ * @param classVisitor the ClassVisitor to be applied to matching
+ * classes.
+ * @param memberVisitor the MemberVisitor to be applied to matching
+ * class members.
+ */
+ public static ClassPoolVisitor createClassPoolVisitor(ClassSpecification classSpecification,
+ ClassVisitor classVisitor,
+ MemberVisitor memberVisitor)
+ {
+ // Combine both visitors.
+ ClassVisitor composedClassVisitor =
+ createCombinedClassVisitor(classSpecification,
+ classVisitor,
+ memberVisitor);
+
+ // By default, start visiting from the named class name, if specified.
+ String className = classSpecification.className;
+
+ // Although we may have to start from the extended class.
+ String extendsAnnotationType = classSpecification.extendsAnnotationType;
+ String extendsClassName = classSpecification.extendsClassName;
+
+ // If wildcarded, only visit classes with matching names.
+ if (className != null &&
+ (extendsAnnotationType != null ||
+ extendsClassName != null ||
+ containsWildCards(className)))
+ {
+ composedClassVisitor =
+ new ClassNameFilter(className, composedClassVisitor);
+
+ // We'll have to visit all classes now.
+ className = null;
+ }
+
+ // If specified, only visit classes with the right annotation.
+ String annotationType = classSpecification.annotationType;
+
+ if (annotationType != null)
+ {
+ composedClassVisitor =
+ new AllAttributeVisitor(
+ new AllAnnotationVisitor(
+ new AnnotationTypeFilter(annotationType,
+ new AnnotatedClassVisitor(composedClassVisitor))));
+ }
+
+ // If specified, only visit classes with the right access flags.
+ if (classSpecification.requiredSetAccessFlags != 0 ||
+ classSpecification.requiredUnsetAccessFlags != 0)
+ {
+ composedClassVisitor =
+ new ClassAccessFilter(classSpecification.requiredSetAccessFlags,
+ classSpecification.requiredUnsetAccessFlags,
+ composedClassVisitor);
+ }
+
+ // If it's specified, start visiting from the extended class.
+ if (extendsAnnotationType != null ||
+ extendsClassName != null)
+ {
+ // Start visiting from the extended class.
+ composedClassVisitor =
+ new ClassHierarchyTraveler(false, false, false, true,
+ composedClassVisitor);
+
+ // If specified, only visit extended classes with the right annotation.
+ if (extendsAnnotationType != null)
+ {
+ composedClassVisitor =
+ new AllAttributeVisitor(
+ new AllAnnotationVisitor(
+ new AnnotationTypeFilter(extendsAnnotationType,
+ new AnnotatedClassVisitor(composedClassVisitor))));
+ }
+
+ // If specified, only visit extended classes with matching names.
+ if (extendsClassName != null)
+ {
+ // If wildcarded, only visit extended classes with matching names.
+ if (containsWildCards(extendsClassName))
+ {
+ composedClassVisitor =
+ new ClassNameFilter(extendsClassName,
+ composedClassVisitor);
+ }
+ else
+ {
+ // Start visiting from the named extended class.
+ className = extendsClassName;
+ }
+ }
+ }
+
+ // If specified, visit a single named class, otherwise visit all classes.
+ return className != null ?
+ (ClassPoolVisitor)new NamedClassVisitor(composedClassVisitor, className) :
+ (ClassPoolVisitor)new AllClassVisitor(composedClassVisitor);
+ }
+
+
+ /**
+ * Constructs a ClassVisitor to efficiently travel to the specified
+ * classes and class members.
+ *
+ * @param classSpecification the specifications of the class(es) and class
+ * members to visit.
+ * @param classVisitor the ClassVisitor to be applied to matching
+ * classes.
+ * @param memberVisitor the MemberVisitor to be applied to matching
+ * class members.
+ */
+ private static ClassVisitor createCombinedClassVisitor(ClassSpecification classSpecification,
+ ClassVisitor classVisitor,
+ MemberVisitor memberVisitor)
+ {
+ // Don't visit any members if there aren't any member specifications.
+ if (classSpecification.fieldSpecifications == null &&
+ classSpecification.methodSpecifications == null)
+ {
+ memberVisitor = null;
+ }
+
+ // The class visitor for classes and their members.
+ MultiClassVisitor multiClassVisitor = new MultiClassVisitor();
+
+ // If specified, let the class visitor visit the class itself.
+ if (classVisitor != null)
+ {
+ // This class visitor may be the only one.
+ if (memberVisitor == null)
+ {
+ return classVisitor;
+ }
+
+ multiClassVisitor.addClassVisitor(classVisitor);
+ }
+
+ // If specified, let the member info visitor visit the class members.
+ if (memberVisitor != null)
+ {
+ ClassVisitor memberClassVisitor =
+ createClassVisitor(classSpecification, memberVisitor);
+
+ // This class visitor may be the only one.
+ if (classVisitor == null)
+ {
+ return memberClassVisitor;
+ }
+
+ multiClassVisitor.addClassVisitor(memberClassVisitor);
+ }
+
+ return multiClassVisitor;
+ }
+
+
+ /**
+ * Constructs a ClassVisitor to efficiently travel to the specified class
+ * members.
+ *
+ * @param classSpecification the specifications of the class members to visit.
+ * @param memberVisitor the MemberVisitor to be applied to matching
+ * class members.
+ */
+ private static ClassVisitor createClassVisitor(ClassSpecification classSpecification,
+ MemberVisitor memberVisitor)
+ {
+ MultiClassVisitor multiClassVisitor = new MultiClassVisitor();
+
+ addMemberVisitors(classSpecification.fieldSpecifications, true, multiClassVisitor, memberVisitor);
+ addMemberVisitors(classSpecification.methodSpecifications, false, multiClassVisitor, memberVisitor);
+
+ // Mark the class member in this class and in super classes.
+ return new ClassHierarchyTraveler(true, true, false, false,
+ multiClassVisitor);
+ }
+
+
+ /**
+ * Adds elements to the given MultiClassVisitor, to apply the given
+ * MemberVisitor to all class members that match the given List
+ * of options (of the given type).
+ */
+ private static void addMemberVisitors(List memberSpecifications,
+ boolean isField,
+ MultiClassVisitor multiClassVisitor,
+ MemberVisitor memberVisitor)
+ {
+ if (memberSpecifications != null)
+ {
+ for (int index = 0; index < memberSpecifications.size(); index++)
+ {
+ MemberSpecification memberSpecification =
+ (MemberSpecification)memberSpecifications.get(index);
+
+ multiClassVisitor.addClassVisitor(
+ createClassVisitor(memberSpecification,
+ isField,
+ memberVisitor));
+ }
+ }
+ }
+
+
+ /**
+ * Constructs a ClassVisitor that conditionally applies the given
+ * ClassVisitor to all classes that contain the given class members.
+ */
+ private static ClassVisitor createClassMemberTester(ClassSpecification classSpecification,
+ ClassVisitor classVisitor)
+ {
+ // Create a linked list of conditional visitors, for fields and for
+ // methods.
+ return createClassMemberTester(classSpecification.fieldSpecifications,
+ true,
+ createClassMemberTester(classSpecification.methodSpecifications,
+ false,
+ classVisitor));
+ }
+
+
+ /**
+ * Constructs a ClassVisitor that conditionally applies the given
+ * ClassVisitor to all classes that contain the given List of class
+ * members (of the given type).
+ */
+ private static ClassVisitor createClassMemberTester(List memberSpecifications,
+ boolean isField,
+ ClassVisitor classVisitor)
+ {
+ // Create a linked list of conditional visitors.
+ if (memberSpecifications != null)
+ {
+ for (int index = 0; index < memberSpecifications.size(); index++)
+ {
+ MemberSpecification memberSpecification =
+ (MemberSpecification)memberSpecifications.get(index);
+
+ classVisitor =
+ createClassVisitor(memberSpecification,
+ isField,
+ new MemberToClassVisitor(classVisitor));
+ }
+ }
+
+ return classVisitor;
+ }
+
+
+ /**
+ * Creates a new ClassVisitor to efficiently travel to the specified class
+ * members.
+ *
+ * @param memberSpecification the specification of the class member(s) to
+ * visit.
+ * @param memberVisitor the MemberVisitor to be applied to matching
+ * class member(s).
+ */
+ private static ClassVisitor createClassVisitor(MemberSpecification memberSpecification,
+ boolean isField,
+ MemberVisitor memberVisitor)
+ {
+ String name = memberSpecification.name;
+ String descriptor = memberSpecification.descriptor;
+
+ // If name or descriptor are not fully specified, only visit matching
+ // class members.
+ boolean fullySpecified =
+ name != null &&
+ descriptor != null &&
+ !containsWildCards(name) &&
+ !containsWildCards(descriptor);
+
+ if (!fullySpecified)
+ {
+ if (descriptor != null)
+ {
+ memberVisitor =
+ new MemberDescriptorFilter(descriptor, memberVisitor);
+ }
+
+ if (name != null)
+ {
+ memberVisitor =
+ new MemberNameFilter(name, memberVisitor);
+ }
+ }
+
+ // If specified, only visit class members with the right annotation.
+ if (memberSpecification.annotationType != null)
+ {
+ memberVisitor =
+ new AllAttributeVisitor(
+ new AllAnnotationVisitor(
+ new AnnotationTypeFilter(memberSpecification.annotationType,
+ new AnnotationToMemberVisitor(memberVisitor))));
+ }
+
+ // If any access flags are specified, only visit matching class members.
+ if (memberSpecification.requiredSetAccessFlags != 0 ||
+ memberSpecification.requiredUnsetAccessFlags != 0)
+ {
+ memberVisitor =
+ new MemberAccessFilter(memberSpecification.requiredSetAccessFlags,
+ memberSpecification.requiredUnsetAccessFlags,
+ memberVisitor);
+ }
+
+ // Depending on what's specified, visit a single named class member,
+ // or all class members, filtering the matching ones.
+ return isField ?
+ fullySpecified ?
+ (ClassVisitor)new NamedFieldVisitor(name, descriptor, memberVisitor) :
+ (ClassVisitor)new AllFieldVisitor(memberVisitor) :
+ fullySpecified ?
+ (ClassVisitor)new NamedMethodVisitor(name, descriptor, memberVisitor) :
+ (ClassVisitor)new AllMethodVisitor(memberVisitor);
+ }
+
+
+ // Small utility methods.
+
+ private static boolean containsWildCards(String string)
+ {
+ return string != null &&
+ (string.indexOf('!') >= 0 ||
+ string.indexOf('*') >= 0 ||
+ string.indexOf('?') >= 0 ||
+ string.indexOf('%') >= 0 ||
+ string.indexOf(',') >= 0 ||
+ string.indexOf("///") >= 0);
+ }
+}