|
|
|
@ -19,27 +19,36 @@ |
|
|
|
|
|
|
|
|
|
package jode.obfuscator; |
|
|
|
|
import jode.GlobalOptions; |
|
|
|
|
import jode.Obfuscator; |
|
|
|
|
import jode.bytecode.*; |
|
|
|
|
|
|
|
|
|
///#ifdef JDK12
|
|
|
|
|
///import java.util.Comparator;
|
|
|
|
|
///import java.util.Collection;
|
|
|
|
|
///import java.util.Collections;
|
|
|
|
|
///import java.util.Arrays;
|
|
|
|
|
///import java.util.Iterator;
|
|
|
|
|
///import java.util.List;
|
|
|
|
|
///import java.util.LinkedList;
|
|
|
|
|
///import java.util.Map;
|
|
|
|
|
///#else
|
|
|
|
|
import jode.util.Comparator; |
|
|
|
|
import jode.util.Collection; |
|
|
|
|
import jode.util.Collections; |
|
|
|
|
import jode.util.Arrays; |
|
|
|
|
import jode.util.Iterator; |
|
|
|
|
import jode.util.List; |
|
|
|
|
import jode.util.LinkedList; |
|
|
|
|
import jode.util.Map; |
|
|
|
|
///#endif
|
|
|
|
|
|
|
|
|
|
import java.lang.reflect.Modifier; |
|
|
|
|
import java.security.MessageDigest; |
|
|
|
|
import java.security.NoSuchAlgorithmException; |
|
|
|
|
import java.io.OutputStream; |
|
|
|
|
import java.io.DataOutputStream; |
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.util.Random; |
|
|
|
|
import java.util.Hashtable; |
|
|
|
|
import java.util.Vector; |
|
|
|
|
import java.util.Enumeration; |
|
|
|
|
|
|
|
|
|
public class ClassIdentifier extends Identifier { |
|
|
|
|
ClassBundle bundle; |
|
|
|
|
PackageIdentifier pack; |
|
|
|
|
String name; |
|
|
|
|
ClassInfo info; |
|
|
|
@ -52,23 +61,21 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
* are MethodIdentifier |
|
|
|
|
*/ |
|
|
|
|
Identifier[] identifiers; |
|
|
|
|
Vector knownSubClasses = new Vector(); |
|
|
|
|
Vector virtualReachables = new Vector(); |
|
|
|
|
List knownSubClasses = new LinkedList(); |
|
|
|
|
List virtualReachables = new LinkedList(); |
|
|
|
|
|
|
|
|
|
public ClassIdentifier(ClassBundle bundle, PackageIdentifier pack, |
|
|
|
|
public ClassIdentifier(PackageIdentifier pack, |
|
|
|
|
String name, ClassInfo info) { |
|
|
|
|
super(name); |
|
|
|
|
this.bundle = bundle; |
|
|
|
|
this.pack = pack; |
|
|
|
|
this.name = name; |
|
|
|
|
this.info = info; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void addSubClass(ClassIdentifier ci) { |
|
|
|
|
knownSubClasses.addElement(ci); |
|
|
|
|
Enumeration enum = virtualReachables.elements(); |
|
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
|
String[] method = (String[]) enum.nextElement(); |
|
|
|
|
knownSubClasses.add(ci); |
|
|
|
|
for(Iterator i = virtualReachables.iterator(); i.hasNext(); ) { |
|
|
|
|
String[] method = (String[]) i.next(); |
|
|
|
|
ci.reachableIdentifier(method[0], method[1], true); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -96,15 +103,6 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void applyPreserveRule(int preserveRule) { |
|
|
|
|
if ((preserveRule & (info.getModifiers() ^ Modifier.PRIVATE)) != 0) { |
|
|
|
|
setReachable(); |
|
|
|
|
setPreserved(); |
|
|
|
|
} |
|
|
|
|
for (int i=0; i< identifiers.length; i++) |
|
|
|
|
identifiers[i].applyPreserveRule(preserveRule); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void reachableIdentifier(String name, String typeSig, |
|
|
|
|
boolean isVirtual) { |
|
|
|
|
boolean found = false; |
|
|
|
@ -119,12 +117,10 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
/*XXXXXXXX super reachableIdentifier */ |
|
|
|
|
} /*ELSE*/ |
|
|
|
|
if (isVirtual) { |
|
|
|
|
Enumeration enum = knownSubClasses.elements(); |
|
|
|
|
while (enum.hasMoreElements()) |
|
|
|
|
((ClassIdentifier)enum.nextElement()) |
|
|
|
|
for (Iterator i = knownSubClasses.iterator(); i.hasNext(); ) |
|
|
|
|
((ClassIdentifier)i.next()) |
|
|
|
|
.reachableIdentifier(name, typeSig, false); |
|
|
|
|
virtualReachables.addElement |
|
|
|
|
(new String[] { name, typeSig }); |
|
|
|
|
virtualReachables.add(new String[] { name, typeSig }); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -138,6 +134,120 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* This is partly taken from the classpath project. |
|
|
|
|
*/ |
|
|
|
|
public long calcSerialVersionUID() { |
|
|
|
|
final MessageDigest md; |
|
|
|
|
try { |
|
|
|
|
md = MessageDigest.getInstance("SHA"); |
|
|
|
|
} catch (NoSuchAlgorithmException ex) { |
|
|
|
|
ex.printStackTrace(); |
|
|
|
|
GlobalOptions.err.println("Can't calculate serialVersionUID"); |
|
|
|
|
return 0L; |
|
|
|
|
} |
|
|
|
|
OutputStream digest = new OutputStream() { |
|
|
|
|
|
|
|
|
|
public void write(int b) { |
|
|
|
|
md.update((byte) b); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void write(byte[] data, int offset, int length) { |
|
|
|
|
md.update(data, offset, length); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
DataOutputStream out = new DataOutputStream(digest); |
|
|
|
|
try { |
|
|
|
|
out.writeUTF(info.getName()); |
|
|
|
|
|
|
|
|
|
int modifiers = info.getModifiers(); |
|
|
|
|
// just look at interesting bits
|
|
|
|
|
modifiers = modifiers & ( Modifier.ABSTRACT | Modifier.FINAL |
|
|
|
|
| Modifier.INTERFACE | Modifier.PUBLIC ); |
|
|
|
|
out.writeInt(modifiers); |
|
|
|
|
|
|
|
|
|
ClassInfo[] interfaces |
|
|
|
|
= (ClassInfo[]) info.getInterfaces().clone(); |
|
|
|
|
Arrays.sort(interfaces, new Comparator() { |
|
|
|
|
public int compare( Object o1, Object o2 ) { |
|
|
|
|
return ((ClassInfo)o1).getName() |
|
|
|
|
.compareTo(((ClassInfo)o2).getName()); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
for( int i=0; i < interfaces.length; i++ ) { |
|
|
|
|
out.writeUTF(interfaces[i].getName()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Comparator identCmp = new Comparator() { |
|
|
|
|
public int compare(Object o1, Object o2) { |
|
|
|
|
Identifier i1 = (Identifier)o1; |
|
|
|
|
Identifier i2 = (Identifier)o2; |
|
|
|
|
boolean special1 = (i1.equals("<init>") |
|
|
|
|
|| i1.equals("<clinit>")); |
|
|
|
|
boolean special2 = (i2.equals("<init>") |
|
|
|
|
|| i2.equals("<clinit>")); |
|
|
|
|
// Put constructors at the beginning
|
|
|
|
|
if (special1 != special2) { |
|
|
|
|
return special1 ? -1 : 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int comp = i1.getName().compareTo(i2.getName()); |
|
|
|
|
if (comp != 0) { |
|
|
|
|
return comp; |
|
|
|
|
} else { |
|
|
|
|
return i1.getType().compareTo(i2.getType()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
List idents = Arrays.asList((Object[]) identifiers.clone()); |
|
|
|
|
List fields = idents.subList(0, fieldCount); |
|
|
|
|
List methods = idents.subList(fieldCount, idents.size()); |
|
|
|
|
Collections.sort(fields, identCmp); |
|
|
|
|
Collections.sort(methods, identCmp); |
|
|
|
|
|
|
|
|
|
for (Iterator i = fields.iterator(); i.hasNext();) { |
|
|
|
|
FieldIdentifier field = (FieldIdentifier) i.next(); |
|
|
|
|
modifiers = field.info.getModifiers(); |
|
|
|
|
if ((modifiers & Modifier.PRIVATE) != 0 |
|
|
|
|
&& (modifiers & (Modifier.STATIC |
|
|
|
|
| Modifier.TRANSIENT)) != 0) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
out.writeUTF(field.getName()); |
|
|
|
|
out.writeInt(modifiers); |
|
|
|
|
out.writeUTF(field.getType()); |
|
|
|
|
} |
|
|
|
|
for(Iterator i = methods.iterator(); i.hasNext(); ) { |
|
|
|
|
MethodIdentifier method = (MethodIdentifier) i.next(); |
|
|
|
|
modifiers = method.info.getModifiers(); |
|
|
|
|
if( Modifier.isPrivate(modifiers)) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
out.writeUTF(method.getName()); |
|
|
|
|
out.writeInt(modifiers); |
|
|
|
|
|
|
|
|
|
// the replacement of '/' with '.' was needed to make computed
|
|
|
|
|
// SUID's agree with those computed by JDK
|
|
|
|
|
out.writeUTF(method.getType().replace('/', '.')); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
out.close(); |
|
|
|
|
|
|
|
|
|
byte[] sha = md.digest(); |
|
|
|
|
long result = 0; |
|
|
|
|
for (int i=0; i < 8; i++) { |
|
|
|
|
result += (long)(sha[i] & 0xFF) << (8 * i); |
|
|
|
|
} |
|
|
|
|
return result; |
|
|
|
|
} catch (IOException ex) { |
|
|
|
|
ex.printStackTrace(); |
|
|
|
|
GlobalOptions.err.println("Can't calculate serialVersionUID"); |
|
|
|
|
return 0L; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Preserve all fields, that are necessary, to serialize |
|
|
|
|
* a compatible class. |
|
|
|
@ -145,16 +255,46 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
public void preserveSerializable() { |
|
|
|
|
preserveIdentifier("writeObject", "(Ljava.io.ObjectOutputStream)V"); |
|
|
|
|
preserveIdentifier("readObject", "(Ljava.io.ObjectOutputStream)V"); |
|
|
|
|
if (Obfuscator.preserveSerial) { |
|
|
|
|
/* XXX - add a field serializableVersionUID if not existent */ |
|
|
|
|
preserveIdentifier("serializableVersionUID", "I"); |
|
|
|
|
if ((Main.options & Main.OPTION_PRESERVESERIAL) != 0) { |
|
|
|
|
setPreserved(); |
|
|
|
|
boolean hasSerialUID = false; |
|
|
|
|
for (int i=0; i< fieldCount; i++) { |
|
|
|
|
if ("serialVersionUID".equals(identifiers[i].getName()) |
|
|
|
|
&& "J".equals(identifiers[i].getType())) { |
|
|
|
|
identifiers[i].setReachable(); |
|
|
|
|
identifiers[i].setPreserved(); |
|
|
|
|
hasSerialUID = true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!hasSerialUID) { |
|
|
|
|
/* add a field serializableVersionUID if not existent */ |
|
|
|
|
long serialVersion = calcSerialVersionUID(); |
|
|
|
|
Identifier[] newIdents = new Identifier[identifiers.length+1]; |
|
|
|
|
System.arraycopy(identifiers, 0, newIdents, 0, fieldCount); |
|
|
|
|
System.arraycopy(identifiers, fieldCount, |
|
|
|
|
newIdents, fieldCount + 1, |
|
|
|
|
identifiers.length - fieldCount); |
|
|
|
|
FieldInfo UIDField = new FieldInfo |
|
|
|
|
(info, "serialVersionUID", "J", |
|
|
|
|
Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL); |
|
|
|
|
UIDField.setConstant(new Long(serialVersion)); |
|
|
|
|
FieldIdentifier fident = new FieldIdentifier(this, UIDField); |
|
|
|
|
fident.setPreserved(); |
|
|
|
|
fident.setReachable(); |
|
|
|
|
newIdents[fieldCount++] = fident; |
|
|
|
|
identifiers = newIdents; |
|
|
|
|
} |
|
|
|
|
for (int i=0; i < fieldCount; i++) { |
|
|
|
|
FieldIdentifier ident = (FieldIdentifier) identifiers[i]; |
|
|
|
|
if ((ident.info.getModifiers() |
|
|
|
|
& (Modifier.TRANSIENT | Modifier.STATIC)) == 0) |
|
|
|
|
identifiers[i].setPreserved(); |
|
|
|
|
& (Modifier.TRANSIENT | Modifier.STATIC)) == 0) { |
|
|
|
|
ident.setPreserved(); |
|
|
|
|
ident.setNotConstant(); |
|
|
|
|
} |
|
|
|
|
/* XXX - only preserve them if writeObject not existent |
|
|
|
|
* or if writeObject calls defaultWriteObject |
|
|
|
|
* or if writeObject calls defaultWriteObject, and similar |
|
|
|
|
* for readObject |
|
|
|
|
*/ |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -169,16 +309,16 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
|
|
|
|
|
public void setSingleReachable() { |
|
|
|
|
super.setSingleReachable(); |
|
|
|
|
bundle.analyzeIdentifier(this); |
|
|
|
|
Main.getClassBundle().analyzeIdentifier(this); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void analyzeSuperClasses(ClassInfo superclass) { |
|
|
|
|
while (superclass != null) { |
|
|
|
|
if (superclass.getName().equals("java.lang.Serializable")) |
|
|
|
|
if (superclass.getName().equals("java.io.Serializable")) |
|
|
|
|
preserveSerializable(); |
|
|
|
|
|
|
|
|
|
ClassIdentifier superident |
|
|
|
|
= bundle.getClassIdentifier(superclass.getName()); |
|
|
|
|
ClassIdentifier superident = Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(superclass.getName()); |
|
|
|
|
if (superident != null) { |
|
|
|
|
superident.addSubClass(this); |
|
|
|
|
} else { |
|
|
|
@ -217,8 +357,8 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
if (superclass.getName().equals("java.lang.Serializable")) |
|
|
|
|
preserveSerializable(); |
|
|
|
|
|
|
|
|
|
ClassIdentifier superident |
|
|
|
|
= bundle.getClassIdentifier(superclass.getName()); |
|
|
|
|
ClassIdentifier superident = Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(superclass.getName()); |
|
|
|
|
if (superident != null) { |
|
|
|
|
for (int i=superident.fieldCount; |
|
|
|
|
i < superident.identifiers.length; i++) { |
|
|
|
@ -261,7 +401,7 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
|
|
|
|
|
FieldInfo[] finfos = info.getFields(); |
|
|
|
|
MethodInfo[] minfos = info.getMethods(); |
|
|
|
|
if (Obfuscator.swapOrder) { |
|
|
|
|
if (Main.swapOrder) { |
|
|
|
|
Random rand = new Random(); |
|
|
|
|
Collections.shuffle(Arrays.asList(finfos), rand); |
|
|
|
|
Collections.shuffle(Arrays.asList(minfos), rand); |
|
|
|
@ -275,7 +415,7 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
identifiers[fieldCount + i] |
|
|
|
|
= new MethodIdentifier(this, minfos[i]); |
|
|
|
|
if (identifiers[fieldCount + i].getName().equals("<clinit>")) { |
|
|
|
|
/* If there is a static initializer, it is automagically |
|
|
|
|
/* If there is a static initializer, it is automatically |
|
|
|
|
* reachable (even if this class wouldn't be otherwise). |
|
|
|
|
*/ |
|
|
|
|
identifiers[fieldCount + i].setPreserved(); |
|
|
|
@ -289,18 +429,26 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
ifaceNames = new String[ifaces.length]; |
|
|
|
|
for (int i=0; i < ifaces.length; i++) { |
|
|
|
|
ifaceNames[i] = ifaces[i].getName(); |
|
|
|
|
ClassIdentifier ifaceident |
|
|
|
|
= bundle.getClassIdentifier(ifaceNames[i]); |
|
|
|
|
ClassIdentifier ifaceident = Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(ifaceNames[i]); |
|
|
|
|
initSuperClasses(ifaces[i]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (info.getSuperclass() != null) { |
|
|
|
|
superName = info.getSuperclass().getName(); |
|
|
|
|
ClassIdentifier superident |
|
|
|
|
= bundle.getClassIdentifier(superName); |
|
|
|
|
ClassIdentifier superident = Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(superName); |
|
|
|
|
initSuperClasses(info.getSuperclass()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ((Main.stripping & Main.STRIP_SOURCE) != 0) { |
|
|
|
|
info.setSourceFile(null); |
|
|
|
|
} |
|
|
|
|
if ((Main.stripping & Main.STRIP_INNERINFO) != 0) { |
|
|
|
|
info.setInnerClasses(new InnerClassInfo[0]); |
|
|
|
|
info.setOuterClasses(new InnerClassInfo[0]); |
|
|
|
|
info.setExtraClasses(new InnerClassInfo[0]); |
|
|
|
|
} |
|
|
|
|
// load inner classes
|
|
|
|
|
InnerClassInfo[] innerClasses = info.getInnerClasses(); |
|
|
|
|
InnerClassInfo[] outerClasses = info.getOuterClasses(); |
|
|
|
@ -308,53 +456,69 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
if (outerClasses != null) { |
|
|
|
|
for (int i=0; i < outerClasses.length; i++) { |
|
|
|
|
if (outerClasses[i].outer != null) { |
|
|
|
|
bundle.getClassIdentifier(outerClasses[i].outer); |
|
|
|
|
Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(outerClasses[i].outer); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (innerClasses != null) { |
|
|
|
|
for (int i=0; i < innerClasses.length; i++) { |
|
|
|
|
bundle.getClassIdentifier(innerClasses[i].inner); |
|
|
|
|
Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(innerClasses[i].inner); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (extraClasses != null) { |
|
|
|
|
for (int i=0; i < extraClasses.length; i++) { |
|
|
|
|
bundle.getClassIdentifier(extraClasses[i].inner); |
|
|
|
|
Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(extraClasses[i].inner); |
|
|
|
|
if (extraClasses[i].outer != null) |
|
|
|
|
bundle.getClassIdentifier(extraClasses[i].outer); |
|
|
|
|
Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(extraClasses[i].outer); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void buildTable(int renameRule) { |
|
|
|
|
public void buildTable(Renamer renameRule) { |
|
|
|
|
super.buildTable(renameRule); |
|
|
|
|
for (int i=0; i < identifiers.length; i++) |
|
|
|
|
if (!Obfuscator.shouldStrip || identifiers[i].isReachable()) |
|
|
|
|
if ((Main.stripping & Main.STRIP_UNREACH) == 0 |
|
|
|
|
|| identifiers[i].isReachable()) |
|
|
|
|
identifiers[i].buildTable(renameRule); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void readTable(Hashtable table) { |
|
|
|
|
public void readTable(Map table) { |
|
|
|
|
super.readTable(table); |
|
|
|
|
for (int i=0; i < identifiers.length; i++) |
|
|
|
|
if (!Obfuscator.shouldStrip || identifiers[i].isReachable()) |
|
|
|
|
if ((Main.stripping & Main.STRIP_UNREACH) == 0 |
|
|
|
|
|| identifiers[i].isReachable()) |
|
|
|
|
identifiers[i].readTable(table); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void writeTable(Hashtable table) { |
|
|
|
|
public void writeTable(Map table) { |
|
|
|
|
super.writeTable(table); |
|
|
|
|
for (int i=0; i < identifiers.length; i++) |
|
|
|
|
if (!Obfuscator.shouldStrip || identifiers[i].isReachable()) |
|
|
|
|
if ((Main.stripping & Main.STRIP_UNREACH) == 0 |
|
|
|
|
|| identifiers[i].isReachable()) |
|
|
|
|
identifiers[i].writeTable(table); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void addIfaces(Vector result, String[] ifaces) { |
|
|
|
|
/** |
|
|
|
|
* Add the ClassInfo objects of the interfaces of ancestor. But if |
|
|
|
|
* an interface of ancestor is not reachable it will add its interfaces |
|
|
|
|
* instead. |
|
|
|
|
* @param result The Collection where the interfaces should be added to. |
|
|
|
|
* @param ancestor The ancestor whose interfaces should be added. |
|
|
|
|
*/ |
|
|
|
|
public void addIfaces(Collection result, ClassIdentifier ancestor) { |
|
|
|
|
String[] ifaces = ancestor.ifaceNames; |
|
|
|
|
ClassInfo[] ifaceInfos = ancestor.info.getInterfaces(); |
|
|
|
|
for (int i=0; i < ifaces.length; i++) { |
|
|
|
|
ClassIdentifier ifaceident |
|
|
|
|
= bundle.getClassIdentifier(ifaces[i]); |
|
|
|
|
= Main.getClassBundle().getClassIdentifier(ifaces[i]); |
|
|
|
|
if (ifaceident != null && !ifaceident.isReachable()) |
|
|
|
|
addIfaces(result, ifaceident.ifaceNames); |
|
|
|
|
addIfaces(result, ifaceident); |
|
|
|
|
else |
|
|
|
|
result.addElement(ClassInfo.forName(ifaces[i])); |
|
|
|
|
result.add(ifaceInfos[i]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -366,24 +530,23 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
* other entries are the interfaces. |
|
|
|
|
*/ |
|
|
|
|
public void transformSuperIfaces() { |
|
|
|
|
if (!Obfuscator.shouldStrip) |
|
|
|
|
if ((Main.stripping & Main.STRIP_UNREACH) == 0) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
Vector newIfaces = new Vector(); |
|
|
|
|
addIfaces(newIfaces, ifaceNames); |
|
|
|
|
String nameOfSuper = superName; |
|
|
|
|
while (true) { |
|
|
|
|
Collection newIfaces = new LinkedList(); |
|
|
|
|
ClassIdentifier ancestor = this; |
|
|
|
|
while(true) { |
|
|
|
|
addIfaces(newIfaces, ancestor); |
|
|
|
|
ClassIdentifier superident |
|
|
|
|
= bundle.getClassIdentifier(nameOfSuper); |
|
|
|
|
= Main.getClassBundle().getClassIdentifier(ancestor.superName); |
|
|
|
|
if (superident == null || superident.isReachable()) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
addIfaces(newIfaces, superident.ifaceNames); |
|
|
|
|
nameOfSuper = superident.superName; |
|
|
|
|
ancestor = superident; |
|
|
|
|
} |
|
|
|
|
ClassInfo[] ifaces = new ClassInfo[newIfaces.size()]; |
|
|
|
|
newIfaces.copyInto(ifaces); |
|
|
|
|
info.setSuperclass(ClassInfo.forName(nameOfSuper)); |
|
|
|
|
ClassInfo superInfo = ancestor.info.getSuperclass(); |
|
|
|
|
ClassInfo[] ifaces = (ClassInfo[]) |
|
|
|
|
newIfaces.toArray(new ClassInfo[newIfaces.size()]); |
|
|
|
|
info.setSuperclass(superInfo); |
|
|
|
|
info.setInterfaces(ifaces); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -391,11 +554,11 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
InnerClassInfo[] outerClasses = info.getOuterClasses(); |
|
|
|
|
if (outerClasses != null) { |
|
|
|
|
int newOuterCount = outerClasses.length; |
|
|
|
|
if (Obfuscator.shouldStrip) { |
|
|
|
|
if ((Main.stripping & Main.STRIP_UNREACH) != 0) { |
|
|
|
|
for (int i=0; i < outerClasses.length; i++) { |
|
|
|
|
if (outerClasses[i].outer != null) { |
|
|
|
|
ClassIdentifier outerIdent |
|
|
|
|
= bundle.getClassIdentifier(outerClasses[i].outer); |
|
|
|
|
ClassIdentifier outerIdent = Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(outerClasses[i].outer); |
|
|
|
|
if (outerIdent != null && !outerIdent.isReachable()) |
|
|
|
|
newOuterCount--; |
|
|
|
|
} |
|
|
|
@ -409,7 +572,8 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
String lastClass = getFullAlias(); |
|
|
|
|
for (int i=0; i<outerClasses.length; i++) { |
|
|
|
|
ClassIdentifier outerIdent = outerClasses[i].outer != null |
|
|
|
|
? bundle.getClassIdentifier(outerClasses[i].outer) |
|
|
|
|
? (Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(outerClasses[i].outer)) |
|
|
|
|
: null; |
|
|
|
|
|
|
|
|
|
if (outerIdent != null && !outerIdent.isReachable()) |
|
|
|
@ -435,10 +599,10 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
InnerClassInfo[] innerClasses = info.getInnerClasses(); |
|
|
|
|
if (innerClasses != null) { |
|
|
|
|
int newInnerCount = innerClasses.length; |
|
|
|
|
if (Obfuscator.shouldStrip) { |
|
|
|
|
if ((Main.stripping & Main.STRIP_UNREACH) != 0) { |
|
|
|
|
for (int i=0; i < innerClasses.length; i++) { |
|
|
|
|
ClassIdentifier innerIdent |
|
|
|
|
= bundle.getClassIdentifier(innerClasses[i].inner); |
|
|
|
|
ClassIdentifier innerIdent = Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(innerClasses[i].inner); |
|
|
|
|
if (innerIdent != null && !innerIdent.isReachable()) |
|
|
|
|
newInnerCount--; |
|
|
|
|
} |
|
|
|
@ -449,10 +613,11 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
InnerClassInfo[] newInners = new InnerClassInfo[newInnerCount]; |
|
|
|
|
int pos = 0; |
|
|
|
|
for (int i=0; i<innerClasses.length; i++) { |
|
|
|
|
ClassIdentifier innerIdent |
|
|
|
|
= bundle.getClassIdentifier(innerClasses[i].inner); |
|
|
|
|
ClassIdentifier innerIdent = Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(innerClasses[i].inner); |
|
|
|
|
if (innerIdent != null |
|
|
|
|
&& Obfuscator.shouldStrip && !innerIdent.isReachable()) |
|
|
|
|
&& (Main.stripping & Main.STRIP_UNREACH) != 0 |
|
|
|
|
&& !innerIdent.isReachable()) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
String inner = innerIdent == null |
|
|
|
@ -474,13 +639,14 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
InnerClassInfo[] extraClasses = info.getExtraClasses(); |
|
|
|
|
if (extraClasses != null) { |
|
|
|
|
int newExtraCount = extraClasses.length; |
|
|
|
|
if (Obfuscator.shouldStrip) { |
|
|
|
|
if ((Main.stripping & Main.STRIP_UNREACH) != 0) { |
|
|
|
|
for (int i=0; i < extraClasses.length; i++) { |
|
|
|
|
ClassIdentifier outerIdent = extraClasses[i].outer != null |
|
|
|
|
? bundle.getClassIdentifier(extraClasses[i].outer) |
|
|
|
|
? (Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(extraClasses[i].outer)) |
|
|
|
|
: null; |
|
|
|
|
ClassIdentifier innerIdent |
|
|
|
|
= bundle.getClassIdentifier(extraClasses[i].inner); |
|
|
|
|
ClassIdentifier innerIdent = Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(extraClasses[i].inner); |
|
|
|
|
if ((outerIdent != null && !outerIdent.isReachable()) |
|
|
|
|
|| (innerIdent != null && !innerIdent.isReachable())) |
|
|
|
|
newExtraCount--; |
|
|
|
@ -496,10 +662,11 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
int pos = 0; |
|
|
|
|
for (int i=0; i<extraClasses.length; i++) { |
|
|
|
|
ClassIdentifier outerIdent = extraClasses[i].outer != null |
|
|
|
|
? bundle.getClassIdentifier(extraClasses[i].outer) |
|
|
|
|
? (Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(extraClasses[i].outer)) |
|
|
|
|
: null; |
|
|
|
|
ClassIdentifier innerIdent |
|
|
|
|
= bundle.getClassIdentifier(extraClasses[i].inner); |
|
|
|
|
ClassIdentifier innerIdent = Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(extraClasses[i].inner); |
|
|
|
|
|
|
|
|
|
if (innerIdent != null && !innerIdent.isReachable()) |
|
|
|
|
continue; |
|
|
|
@ -534,7 +701,7 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
transformInnerClasses(); |
|
|
|
|
|
|
|
|
|
int newFieldCount = 0, newMethodCount = 0; |
|
|
|
|
if (Obfuscator.shouldStrip) { |
|
|
|
|
if ((Main.stripping & Main.STRIP_UNREACH) != 0) { |
|
|
|
|
for (int i=0; i < fieldCount; i++) |
|
|
|
|
if (identifiers[i].isReachable()) |
|
|
|
|
newFieldCount++; |
|
|
|
@ -551,14 +718,16 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
newFieldCount = newMethodCount = 0; |
|
|
|
|
|
|
|
|
|
for (int i=0; i < fieldCount; i++) { |
|
|
|
|
if (!Obfuscator.shouldStrip || identifiers[i].isReachable()) { |
|
|
|
|
if ((Main.stripping & Main.STRIP_UNREACH) == 0 |
|
|
|
|
|| identifiers[i].isReachable()) { |
|
|
|
|
((FieldIdentifier)identifiers[i]).doTransformations(); |
|
|
|
|
newFields[newFieldCount++] |
|
|
|
|
= ((FieldIdentifier)identifiers[i]).info; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
for (int i=fieldCount; i < identifiers.length; i++) { |
|
|
|
|
if (!Obfuscator.shouldStrip || identifiers[i].isReachable()) { |
|
|
|
|
if ((Main.stripping & Main.STRIP_UNREACH) == 0 |
|
|
|
|
|| identifiers[i].isReachable()) { |
|
|
|
|
((MethodIdentifier)identifiers[i]).doTransformations(); |
|
|
|
|
newMethods[newMethodCount++] |
|
|
|
|
= ((MethodIdentifier)identifiers[i]).info; |
|
|
|
@ -609,6 +778,10 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
return "Ljava/lang/Class;"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public Iterator getChilds() { |
|
|
|
|
return Arrays.asList(identifiers).iterator(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public String toString() { |
|
|
|
|
return "ClassIdentifier "+getFullName(); |
|
|
|
|
} |
|
|
|
@ -621,8 +794,8 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (int i=0; i < ifaceNames.length; i++) { |
|
|
|
|
ClassIdentifier ifaceident |
|
|
|
|
= bundle.getClassIdentifier(ifaceNames[i]); |
|
|
|
|
ClassIdentifier ifaceident = Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(ifaceNames[i]); |
|
|
|
|
if (ifaceident != null) { |
|
|
|
|
Identifier ident |
|
|
|
|
= ifaceident.getIdentifier(fieldName, typeSig); |
|
|
|
@ -632,8 +805,8 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (superName != null) { |
|
|
|
|
ClassIdentifier superident |
|
|
|
|
= bundle.getClassIdentifier(superName); |
|
|
|
|
ClassIdentifier superident = Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(superName); |
|
|
|
|
if (superident != null) { |
|
|
|
|
Identifier ident |
|
|
|
|
= superident.getIdentifier(fieldName, typeSig); |
|
|
|
@ -644,78 +817,209 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static boolean containFieldAlias(ClassInfo clazz, |
|
|
|
|
String fieldName, String typeSig) { |
|
|
|
|
public static boolean containsField |
|
|
|
|
(ClassInfo clazz, String name, String type, ModifierMatcher modMatch) { |
|
|
|
|
FieldInfo[] finfos = clazz.getFields(); |
|
|
|
|
for (int i=0; i< finfos.length; i++) { |
|
|
|
|
if (finfos[i].getName().equals(fieldName) |
|
|
|
|
&& finfos[i].getType().startsWith(typeSig)) |
|
|
|
|
if (finfos[i].getName().equals(name) |
|
|
|
|
&& finfos[i].getType().startsWith(type) |
|
|
|
|
&& modMatch.matches(finfos[i].getModifiers())) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ClassInfo[] ifaces = clazz.getInterfaces(); |
|
|
|
|
for (int i=0; i < ifaces.length; i++) { |
|
|
|
|
if (containFieldAlias(ifaces[i], fieldName, typeSig)) |
|
|
|
|
if (containsField(ifaces[i], name, type, modMatch)) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (clazz.getSuperclass() != null) { |
|
|
|
|
if (containFieldAlias(clazz.getSuperclass(), |
|
|
|
|
fieldName, typeSig)) |
|
|
|
|
if (containsField(clazz.getSuperclass(), |
|
|
|
|
name, type, modMatch)) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public boolean containsFieldAliasDirectly(String fieldName, |
|
|
|
|
String typeSig) { |
|
|
|
|
for (int i=0; i < fieldCount; i++) { |
|
|
|
|
if ((!Obfuscator.shouldStrip || identifiers[i].isReachable()) |
|
|
|
|
&& identifiers[i].getAlias().equals(fieldName) |
|
|
|
|
&& identifiers[i].getType().startsWith(typeSig)) |
|
|
|
|
public static boolean containsMethod |
|
|
|
|
(ClassInfo clazz, String name, String type, ModifierMatcher modMatch) { |
|
|
|
|
MethodInfo[] minfos = clazz.getMethods(); |
|
|
|
|
for (int i=0; i< minfos.length; i++) { |
|
|
|
|
if (minfos[i].getName().equals(name) |
|
|
|
|
&& minfos[i].getType().startsWith(type) |
|
|
|
|
&& modMatch.matches(minfos[i].getModifiers())) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ClassInfo[] ifaces = clazz.getInterfaces(); |
|
|
|
|
for (int i=0; i < ifaces.length; i++) { |
|
|
|
|
if (containsMethod(ifaces[i], name, type, modMatch)) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (clazz.getSuperclass() != null) { |
|
|
|
|
if (containsMethod(clazz.getSuperclass(), |
|
|
|
|
name, type, modMatch)) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public boolean containFieldAlias(String fieldName, String typeSig) { |
|
|
|
|
if (containsFieldAliasDirectly(fieldName,typeSig)) |
|
|
|
|
return true; |
|
|
|
|
public boolean containsFieldAliasDirectly(String fieldName, String typeSig, |
|
|
|
|
ModifierMatcher matcher) { |
|
|
|
|
for (int i=0; i < fieldCount; i++) { |
|
|
|
|
if ((!Obfuscator.shouldStrip || identifiers[i].isReachable()) |
|
|
|
|
if (((Main.stripping & Main.STRIP_UNREACH) == 0 |
|
|
|
|
|| identifiers[i].isReachable()) |
|
|
|
|
&& identifiers[i].wasAliased() |
|
|
|
|
&& identifiers[i].getAlias().equals(fieldName) |
|
|
|
|
&& identifiers[i].getType().startsWith(typeSig)) |
|
|
|
|
&& identifiers[i].getType().startsWith(typeSig) |
|
|
|
|
&& matcher.matches(identifiers[i])) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public boolean containsMethodAliasDirectly(String methodName, |
|
|
|
|
String paramType, |
|
|
|
|
ModifierMatcher matcher) { |
|
|
|
|
for (int i=fieldCount; i< identifiers.length; i++) { |
|
|
|
|
if (((Main.stripping & Main.STRIP_UNREACH) == 0 |
|
|
|
|
|| identifiers[i].isReachable()) |
|
|
|
|
&& identifiers[i].wasAliased() |
|
|
|
|
&& identifiers[i].getAlias().equals(methodName) |
|
|
|
|
&& identifiers[i].getType().startsWith(paramType) |
|
|
|
|
&& matcher.matches(identifiers[i])) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public boolean containsFieldAlias(String fieldName, String typeSig, |
|
|
|
|
ModifierMatcher matcher) { |
|
|
|
|
if (containsFieldAliasDirectly(fieldName, typeSig, matcher)) |
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
ModifierMatcher packMatcher = matcher.forceAccess(0, true); |
|
|
|
|
ClassInfo[] ifaces = info.getInterfaces(); |
|
|
|
|
for (int i=0; i < ifaces.length; i++) { |
|
|
|
|
ClassIdentifier ifaceident |
|
|
|
|
= bundle.getClassIdentifier(ifaces[i].getName()); |
|
|
|
|
ClassIdentifier ifaceident = Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(ifaces[i].getName()); |
|
|
|
|
if (ifaceident != null) { |
|
|
|
|
if (ifaceident.containFieldAlias(fieldName, typeSig)) |
|
|
|
|
if (ifaceident.containsFieldAlias(fieldName, typeSig, |
|
|
|
|
packMatcher)) |
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
if (containFieldAlias(ifaces[i], fieldName, typeSig)) |
|
|
|
|
if (containsField(ifaces[i], fieldName, typeSig, |
|
|
|
|
packMatcher)) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (info.getSuperclass() != null) { |
|
|
|
|
ClassIdentifier superident |
|
|
|
|
= bundle.getClassIdentifier(info.getSuperclass().getName()); |
|
|
|
|
ClassIdentifier superident = Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(info.getSuperclass().getName()); |
|
|
|
|
if (superident != null) { |
|
|
|
|
if (superident.containsFieldAlias(fieldName, typeSig, |
|
|
|
|
packMatcher)) |
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
if (containsField(info.getSuperclass(), |
|
|
|
|
fieldName, typeSig, packMatcher)) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public boolean containsMethodAlias(String methodName, String typeSig, |
|
|
|
|
ModifierMatcher matcher) { |
|
|
|
|
if (containsMethodAliasDirectly(methodName,typeSig, matcher)) |
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
ModifierMatcher packMatcher = matcher.forceAccess(0, true); |
|
|
|
|
ClassInfo[] ifaces = info.getInterfaces(); |
|
|
|
|
for (int i=0; i < ifaces.length; i++) { |
|
|
|
|
ClassIdentifier ifaceident = Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(ifaces[i].getName()); |
|
|
|
|
if (ifaceident != null) { |
|
|
|
|
if (ifaceident.containsMethodAlias(methodName, typeSig, |
|
|
|
|
packMatcher)) |
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
if (containsMethod(ifaces[i], methodName, typeSig, |
|
|
|
|
packMatcher)) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (info.getSuperclass() != null) { |
|
|
|
|
ClassIdentifier superident = Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(info.getSuperclass().getName()); |
|
|
|
|
if (superident != null) { |
|
|
|
|
if (superident.containFieldAlias(fieldName, typeSig)) |
|
|
|
|
if (superident.containsMethodAlias(methodName, typeSig, |
|
|
|
|
packMatcher)) |
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
if (containFieldAlias(info.getSuperclass(), |
|
|
|
|
fieldName, typeSig)) |
|
|
|
|
if (containsMethod(info.getSuperclass(), |
|
|
|
|
methodName, typeSig, packMatcher)) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public boolean fieldConflicts(FieldIdentifier field, String newAlias) { |
|
|
|
|
String typeSig = (Main.options & Main.OPTION_STRONGOVERLOAD) != 0 |
|
|
|
|
? field.getType() : ""; |
|
|
|
|
|
|
|
|
|
/* Fields are special: They are not overriden but hidden. We |
|
|
|
|
* must only take care, that the reference of every |
|
|
|
|
* getfield/putfield opcode points to the exact class, afterwards |
|
|
|
|
* we can use doubled name as much as we want. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ModifierMatcher mm = ModifierMatcher.allowAll; |
|
|
|
|
if (containsFieldAliasDirectly(newAlias, typeSig, mm)) |
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// boolean isPublic = (field.info.getModifier()
|
|
|
|
|
// & (Modifier.PROTECTED | Modifier.PUBLIC)) == 0;
|
|
|
|
|
// if (field.info.getModifier() & Modifier.PRIVATE != 0) {
|
|
|
|
|
// for (Iterator i = clazz.knownSubClasses.iterator();
|
|
|
|
|
// i.hasNext(); ) {
|
|
|
|
|
// ClassIdentifier ci = (ClassIdentifier) i.next();
|
|
|
|
|
// if ((isPublic || ci.getParent() == getParent())
|
|
|
|
|
// && ci.containsFieldAliasDirectly(newAlias, typeSig, mm))
|
|
|
|
|
// return true;
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public boolean methodConflicts(MethodIdentifier method, String newAlias) { |
|
|
|
|
String paramType = method.getType(); |
|
|
|
|
if ((Main.options & Main.OPTION_STRONGOVERLOAD) == 0) |
|
|
|
|
paramType = paramType.substring(0, paramType.indexOf(')')+1); |
|
|
|
|
|
|
|
|
|
ModifierMatcher matcher = ModifierMatcher.allowAll; |
|
|
|
|
if (containsMethodAlias(newAlias, paramType, matcher)) |
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
ModifierMatcher packMatcher = matcher.forceAccess(0, true); |
|
|
|
|
if (packMatcher.matches(method)) { |
|
|
|
|
for (Iterator i = knownSubClasses.iterator(); i.hasNext(); ) { |
|
|
|
|
ClassIdentifier ci = (ClassIdentifier) i.next(); |
|
|
|
|
if (ci.containsMethodAliasDirectly(newAlias, paramType, |
|
|
|
|
matcher)) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static Object getMethod(ClassInfo clazz, |
|
|
|
|
String methodName, String paramType) { |
|
|
|
|
MethodInfo[] minfos = clazz.getMethods(); |
|
|
|
@ -741,27 +1045,18 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public boolean hasMethod(String methodName, String paramType) { |
|
|
|
|
for (int i=fieldCount; i< identifiers.length; i++) { |
|
|
|
|
if ((!Obfuscator.shouldStrip || identifiers[i].isReachable()) |
|
|
|
|
&& identifiers[i].getAlias().equals(methodName) |
|
|
|
|
&& identifiers[i].getType().startsWith(paramType)) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public Object getMethod(String methodName, String paramType) { |
|
|
|
|
for (int i=fieldCount; i< identifiers.length; i++) { |
|
|
|
|
if ((!Obfuscator.shouldStrip || identifiers[i].isReachable()) |
|
|
|
|
if (((Main.stripping & Main.STRIP_UNREACH) == 0 |
|
|
|
|
|| identifiers[i].isReachable()) |
|
|
|
|
&& identifiers[i].getAlias().equals(methodName) |
|
|
|
|
&& identifiers[i].getType().startsWith(paramType)) |
|
|
|
|
return identifiers[i]; |
|
|
|
|
} |
|
|
|
|
ClassInfo[] ifaces = info.getInterfaces(); |
|
|
|
|
for (int i=0; i < ifaces.length; i++) { |
|
|
|
|
ClassIdentifier ifaceident |
|
|
|
|
= bundle.getClassIdentifier(ifaces[i].getName()); |
|
|
|
|
ClassIdentifier ifaceident = Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(ifaces[i].getName()); |
|
|
|
|
if (ifaceident != null) { |
|
|
|
|
Object result = ifaceident.getMethod(methodName, paramType); |
|
|
|
|
if (result != null) |
|
|
|
@ -774,8 +1069,8 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (info.getSuperclass() != null) { |
|
|
|
|
ClassIdentifier superident |
|
|
|
|
= bundle.getClassIdentifier(info.getSuperclass().getName()); |
|
|
|
|
ClassIdentifier superident = Main.getClassBundle() |
|
|
|
|
.getClassIdentifier(info.getSuperclass().getName()); |
|
|
|
|
if (superident != null) { |
|
|
|
|
Object result = superident.getMethod(methodName, paramType); |
|
|
|
|
if (result != null) |
|
|
|
@ -790,7 +1085,7 @@ public class ClassIdentifier extends Identifier { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public boolean conflicting(String newAlias, boolean strong) { |
|
|
|
|
return pack.contains(newAlias); |
|
|
|
|
public boolean conflicting(String newAlias) { |
|
|
|
|
return pack.contains(newAlias, this); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|