The unexclude Statement
The ZKM Script unexclude statement acts only on the set of excluded names created by an exclude statement.
The statement removes the names of specified objects from the set of excluded names so that they become available once more for renaming by the
ZKM Script obfuscate statement.
The unexclude statement is intended to be used in conjunction with a exclude statement to specify
a final set of excluded names that would have been difficult to achieve using a exclude statement alone.
Typically, in such cases, an initial exclude statement would set the broad exclusions and then the unexclude
statement would specify the exceptions to those broad exclusions.
Successive unexclude statements have a cumulative effect. The effect of all exclusions and unexclusions that have been set is removed
by a resetExclusions statement.
The remainder of this page is organized into the following sections.
The syntax of the unexclude statement is the same as that of the exclude statement except that the
unexclude statement has no class prefix and suffix (ie. <link> ) syntax.
unexclude statement parameters may be loosely categorized into the following groups
Any package name matching a package unexclusion parameter is unexcluded. If a package level is specified by a simple "*" wildcard then it matches one or more levels.
If the package parameter is a component of a class, field, method or class suffix unexclude parameter and the package parameter is followed by a "^"
then the name of the enclosing package is also unexcluded. Note that a package name specification always ends with a "." .
If a package name specification ends with ".." then it specifies that package and all of its sub-packages.
unexclude pack1.pack2. and //unexclude the package "pack1.pack2"
*. and //unexclude all packages
p*1.*.p*1. and //unexclude any package matching "p*1.*.p1"
pack2.*. and //unexclude all the sub-packages of "pack2"
pack3.. and //unexclude "pack3" and all sub-packages of "pack3"
(pack4.*. && !(pack3.pack0. || pack3.pack2.)); //unexclude all the sub-packages of "pack4" except for "pack0" and "pack2"
Put informally (with mandatory components in bold), the syntax is:
<classAnnotations> <classModifiers> "<archiveQualifier>"!<packageQualifiers>.<className> <containingClause> <extendsClause> <implementsClause>;
For a class name to be unexcluded, all of the following must be true:
- Its annotations must match any specified annotations.
- Its modifiers (e.g.
public final ) must match all parameter modifiers.
So if the parameters are public abstract !interface then the class must be
public , abstract and NOT an interface to be unexcluded.
- If the parameter has an archive qualifier then the class must be contained in an archive which matches that archive qualifier.
- Its package qualifiers must match any specified package parameter component.
If there is no package parameter component then the class must be in the default package.
- Its unqualified name must match the specified class name specification.
- If the parameter has a containing clause then the class must contain members which match the specified class
- If the parameter has an extends clause then the class must be a subclass of the specified class
- If the parameter has an implements clause then the class must directly or indirectly implement all of the specified interfaces
If the class parameter is a component of a field or method unexclude parameter then
a final "^" tag after the class name specification causes the enclosing class to be unexcluded.
If a class unexclusion parameter's class name specification is followed by
a "+" tag then the parameter also causes the names of all the fields and methods of the class to be unexcluded as well.
unexclude * and //unexclude all classes in the default package
*.Class1 and //unexclude all classes with the unqualified class name "Class1"
pack1..* and //unexclude all classes in "pack1" ot any of its sub-packages
public !final *.* and //unexclude all public non-final classes
//unexclude all "public abstract" classes that have an unqualified name matching "C*s" and extend "pack1.Class1".
package abstract *.C*s extends pack1.Class1 and
//unexclude all classes in packages that start with the character "p" and also exclude the names of the enclosing packages.
p*.^* and
//unexclude all classes that implement Serializable and also exclude all field and method names
*.* + implements java.io.Serializable and
//unexclude names of all classes that start with "Class" except for "Class0" and "Class1"
*.(Class* && !(Class0 || Class1)) and
"MyJar*.jar"!*.* and //unexclude all classes contained in a JAR file with a name matching "MyJar*.jar"
@*.MyAnnotation0 *.*; //unexclude all classes annotated which an annotation matching *.MyAnnotation0
Put informally (with mandatory components in bold), the syntax is:
<classAnnotations> <classModifiers> "<archiveQualifier>"!<packageQualifiers>.<className> <extendsClause> <implementsClause>
<fieldAnnotations> <fieldModifiers> <fieldType> <fieldName>;
For a field name to be unexcluded, all of the following must be true:
- Its containing class must match any class unexclude parameter component (see Class unexclude parameters).
- Its annotations must match any specified field level annotations.
- Its modifiers (e.g.
public volatile ) must match all parameter field modifiers.
So if the parameters are public static !transient then the field must be
public , static and NOT transient to be unexcluded.
- Its type (e.g. int[] or java.lang.String) must match the parameter field type if it exists.
- Its name must match the parameter field name.
unexclude *.* * and //unexclude all field names
*.Class1 !transient int f* and //unexclude all non-transient "int" field names matching "f*"
//in classes with the unqualified name "Class1"
public *.*^ public volatile * and //unexclude all "public volatile" fields in
//public classes.
//Also unexclude the containing class names.
*.* @*.MyAnnotation0 *; //Exclude all fields annotated with a class matching *.MyAnnotation0.
Put informally (with mandatory components in bold), the syntax is:
<classAnnotations> <classModifiers> "<archiveQualifier>"!<packageQualifiers>.<className> <extendsClause> <implementsClause>
<methodAnnotations> <methodModifiers> <methodName>(<argumentTypes>) <throwsClause> +signatureClasses;
For a method name to be unexcluded, all of the following must be true:
- Its containing class must match any class unexclude parameter component (see Class unexclude parameters).
- Its annotations must match any specified method or method parameter level annotations.
- Its modifiers (e.g.
public native ) must match all parameter method modifiers.
So if the parameters are public static !synchronized then the method must be
public , static and NOT synchronized to be unexcluded.
- Its name must match the parameter method name.
- Its argument types (e.g.
int[], java.lang.String ) must match the parameter argument types if they exist.
(A single parameter argument type of "*" matches any method argument types including no arguments.)
If the parameter has no argument type then the method must take no arguments.
- Its throws clause must contain all the classes specified in the unexclude parameter's throw clause.
So, if the unexclude parameter's throws clause is
throws java.io.IOException then the method
must throw java.io.IOException or one of its subclasses to be unexcluded.
For consistency, the unexclude statement supports the special method names <init> and <clinit>
which represent constructor and class initializer method names respectively. However, because constructor and class initializer names cannot be
obfuscated, the syntax has no practical application for this statement.
If a method unexclude parameter ends with the keyword +signatureClasses then, for each matching method,
the fully qualified class names of the method's return and parameter types are also unexcluded from obfuscation. Types
which are primitive are ignored. So, if a matching method has the signature pack1.Class1 method1(pack2.Class2)
then the +signatureClasses flag has the effect of excluding the fully qualified names:
- pack1.Class1 (because it is the return type of a matching method) and
- pack2.Class2 (because it is a parameter type of a matching method)
unexclude *.* *(*) and //unexclude all method names
*.* !static m*() and //unexclude all non-static methods taking no parameters with names matching "m*"
//unexclude all "native" methods. Also exclude the containing package and class names.
*.^*^ native *(*) and
*.* *(*) throws java.io.IOException and //unexclude all methods that throw java.io.IOException.
//unexclude the names of all "abstract" methods that take a single String.
*.* abstract *(java.lang.String) and
pack1.Class1 *(*) +signatureClasses and //unexclude all method names in pack1.Class1 along with
//the matching methods' return and parameter types
//unexclude all the methods of any class implementing "Serializable" in a package that matches "pack1.*"
pack1.* implements java.io.Serializable *(*) and
//unexclude all methods annotated with a class matching *.MyAnnotation0.
*.* @*.MyAnnotation0 *(*);
"unexclude" unexcludeParameter ("and" unexcludeParameter)* ";"
annotationSpecifier ::= ("@" [packageExcludeParameter] nameSpecifier) | annotationSpecifierAndList
annotationSpecifierAndList ::= ["!"] "(" annotationSpecifierOrList ("&&" annotationSpecifierOrList)* ")"
annotationSpecifierOrList ::= annotationSpecifier ("||" annotationSpecifier)*
classUnexcludeParameter ::=
[annotationSpecifier] [["!"] "public" | "package"]
[["!"] "abstract"] [["!"] "final"] [["!"] "interface"] [["!"] "synthetic"] [["!"] "enum"] [["!"] "annotation"]
["\"" archiveQualifier "\"" "!"] [packageExcludeParameter ["."]] nameSpecifier ["^"] ["+"] [containingClause]
[extendsClause] [implementsClause]
containingClause ::= "containing" "{" "memberAndList" "}"
unexcludeParameter ::=
|
classUnexcludeParameter
|
|
|
|
fieldUnexcludeParameter
|
|
|
|
methodUnexcludeParameter
|
|
extendsClause ::= "extends" [annotationSpecifier] wildcardClassName
fieldUnexcludeParameter ::=
classUnexcludeParameter [annotationSpecifier] [["!"] "public" | "protected"| "package"| "private"]
[["!"] "static"] [["!"] "final"] [["!"] "transient"] [["!"] "volatile"] [["!"] "synthetic"] [["!"] "enum"]
[type] nameSpecifier
fullyQualifiedClassName ::= name ("." name)*
implementsClause ::= "implements" [annotationSpecifier] wildcardClassName ("," [annotationSpecifier] wildcardClassName)*
methodUnexcludeParameter ::=
classUnexcludeParameter [["!"] "public" | "protected"| "package"| "private"]
[["!"] "abstract"] [["!"] "static"] [["!"] "final"] [["!"] "native"] [["!"] "synchronized"] [["!"] "synthetic"] [["!"] "bridge"]
nameSpecifier "(" [ "*" | (parameter ("," parameter)*)] ")" ["throws" wildcardClassName] ["+signatureClasses"]
memberAndList ::= ["!"] "(" memberOrList ("&&" memberOrList)* ")"
memberOrList ::= memberSpecifier ("||" memberSpecifier)*
memberSpecifier ::= fieldExcludeParameter | methodExcludeParameter
nameAndList ::= ["!"] "(" nameOrList ("&&" nameOrList)* ")"
name ::= (["0"-"9","a"-"z","A"-"Z","$","_"])+
i.e. a Java identifer (e.g. a package, class, field or method name) with no wildcards allowed
nameAndList ::= ["!"] "(" nameOrList ("&&" nameOrList)* ")"
nameOrList ::= nameSpecifier ("||" nameSpecifier)*
nameSpecifier ::= wildcardName | nameAndList
packageUnexcludeParameter ::= packageName | packageNameAndList
packageName ::= wildcardName ("." wildcardName)* "."
NB: the final "." is part of the package name
packageNameAndList ::= ["!"] "(" packageNameOrList ("&&" packageNameOrList)* ")"
packageNameOrList ::= packageUnexcludeParameter ("||" packageUnexcludeParameter)*
parameter ::= [annotationSpecifier] ("*" | "?" | type)
type ::=
("byte" | "short" | "char" | "int" | "long" | "float" | "double"| "boolean" |
fullyQualifiedClassName) ("[]")*
wildcardClassName ::= wildcardName ("." wildcardName)*
wildcardName ::= (["*","0"-"9","a"-"z","A"-"Z","$","_"])+
i.e. a Java identifer (e.g. a package, class, field or method name) with the "*" wildcard allowed
|