Initial revision

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@246 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 9ce9535622
commit a38890be6a
  1. 40
      jode/jode/expr/ClassFieldOperator.java
  2. 391
      jode/jode/obfuscator/ClassIdentifier.java
  3. 56
      jode/jode/obfuscator/FieldIdentifier.java
  4. 28
      jode/jode/obfuscator/LoadedClassIdentifier.java
  5. 141
      jode/jode/obfuscator/MethodIdentifier.java
  6. 301
      jode/jode/obfuscator/PackageIdentifier.java

@ -0,0 +1,40 @@
/*
* ClassFieldOperator (c) 1998 Jochen Hoenicke
*
* You may distribute under the terms of the GNU General Public License.
*
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* $Id$
*/
package jode.decompiler;
import jode.Type;
import jode.CodeAnalyzer;
public class ClassFieldOperator extends NoArgOperator {
Type classType;
public ClassFieldOperator(Type classType) {
super(Type.tJavaLangClass);
this.classType = classType;
classType.useType();
}
public int getPriority() {
return 950;
}
public String toString(String[] operands) {
return classType.toString() + ".class";
}
}

@ -0,0 +1,391 @@
/*
* ClassIdentifier (c) 1998 Jochen Hoenicke
*
* You may distribute under the terms of the GNU General Public License.
*
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* $Id$
*/
package jode.obfuscator;
import jode.Obfuscator;
import jode.bytecode.ClassInfo;
import jode.bytecode.FieldInfo;
import jode.bytecode.MethodInfo;
import java.lang.reflect.Modifier;
import java.util.*;
import java.io.*;
public class ClassIdentifier extends Identifier {
ClassBundle bundle;
PackageIdentifier pack;
String name;
ClassInfo info;
int preserveRule;
Identifier[] identifiers;
Vector knownSubClasses = new Vector();
Vector virtualReachables = new Vector();
public ClassIdentifier(ClassBundle bundle, PackageIdentifier pack,
String name, ClassInfo info) {
super(name);
this.bundle = bundle;
this.pack = pack;
this.name = name;
this.info = info;
preserveRule = bundle.preserveRule;
if ((preserveRule & (info.getModifiers() ^ Modifier.PRIVATE)) != 0) {
setReachable();
setPreserved();
}
}
public void addSubClass(ClassIdentifier ci) {
knownSubClasses.addElement(ci);
Enumeration enum = virtualReachables.elements();
while (enum.hasMoreElements()) {
String[] method = (String[]) enum.nextElement();
ci.reachableIdentifier(method[0], method[1], true);
}
}
public void preserveIdentifier(String name, String typeSig) {
for (int i=0; i< identifiers.length; i++) {
if (identifiers[i].getName().equals(name)
&& (typeSig == null
|| identifiers[i] .getType().equals(typeSig)))
identifiers[i].setPreserved();
}
}
public void reachableIdentifier(String name, String typeSig,
boolean isVirtual) {
for (int i=0; i < identifiers.length; i++) {
if (identifiers[i].getName().equals(name)
&& (typeSig == null
|| identifiers[i] .getType().equals(typeSig)))
identifiers[i].setReachable();
}
if (isVirtual) {
Enumeration enum = knownSubClasses.elements();
while (enum.hasMoreElements())
((ClassIdentifier)enum.nextElement())
.reachableIdentifier(name, typeSig, isVirtual);
virtualReachables.addElement
(new String[] { name, typeSig });
}
}
public void chainIdentifier(Identifier ident) {
String name = ident.getName();
String typeSig = ident.getType();
for (int i=0; i< identifiers.length; i++) {
if (identifiers[i].getName().equals(ident.getName())
&& (identifiers[i].getType().equals(typeSig)))
ident.addShadow(identifiers[i]);
}
}
/**
* Preserve all fields, that are necessary, to serialize
* a compatible class.
*/
public void preserveSerializable() {
/*XXX*/
/* add a field serializableVersionUID if not existent */
}
public void initSuperClasses(ClassInfo superclass) {
while (superclass != null) {
if (superclass.getName().equals("java.lang.Serializable"))
preserveSerializable();
ClassIdentifier superident = (ClassIdentifier)
bundle.getIdentifier(superclass.getName());
if (superident != null) {
for (int i=0; i < superident.identifiers.length; i++)
if (superident.identifiers[i]
instanceof MethodIdentifier) {
MethodIdentifier mid = (MethodIdentifier)
superident.identifiers[i];
// all virtual methods in superclass must be chained.
int modif = mid.info.getModifiers();
if (((Modifier.PRIVATE
| Modifier.STATIC
| Modifier.FINAL) & modif) == 0
&& !(mid.getName().equals("<init>"))) {
// chain the preserved/same name lists.
chainIdentifier(superident.identifiers[i]);
}
}
} else {
// all methods and fields in superclass are preserved!
MethodInfo[] topmethods = superclass.getMethods();
FieldInfo[] topfields = superclass.getFields();
for (int i=0; i< topmethods.length; i++) {
// all virtual methods in superclass may be
// virtually reachable
int modif = topmethods[i].getModifiers();
if (((Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL)
& modif) == 0
&& !topmethods[i].getName().equals("<init>")) {
reachableIdentifier
(topmethods[i].getName(),
topmethods[i].getType().getTypeSignature(),
true);
preserveIdentifier
(topmethods[i].getName(),
topmethods[i].getType().getTypeSignature());
}
}
}
ClassInfo[] ifaces = superclass.getInterfaces();
for (int i=0; i < ifaces.length; i++)
initSuperClasses(ifaces[i]);
superclass = superclass.getSuperclass();
}
}
public void setSingleReachable() {
info.loadInfo(info.FULLINFO);
if (Obfuscator.isVerbose)
Obfuscator.err.println(this);
FieldInfo[] finfos = info.getFields();
MethodInfo[] minfos = info.getMethods();
identifiers = new Identifier[finfos.length + minfos.length];
for (int i=0; i< finfos.length; i++) {
identifiers[i] = new FieldIdentifier(this, finfos[i]);
if ((preserveRule & (finfos[i].getModifiers() ^ Modifier.PRIVATE))
!= 0) {
identifiers[i].setReachable();
identifiers[i].setPreserved();
}
}
for (int i=0; i< minfos.length; i++) {
identifiers[finfos.length + i]
= new MethodIdentifier(this, minfos[i]);
if ((preserveRule & (minfos[i].getModifiers() ^ Modifier.PRIVATE))
!= 0) {
identifiers[i].setReachable();
identifiers[i].setPreserved();
}
if (identifiers[i].getName().equals("<init>"))
identifiers[i].setPreserved();
}
ClassInfo[] ifaces = info.getInterfaces();
for (int i=0; i < ifaces.length; i++) {
ClassIdentifier ifaceident = (ClassIdentifier)
bundle.getIdentifier(ifaces[i].getName());
if (ifaceident != null) {
ifaceident.setReachable();
ifaceident.addSubClass(this);
}
initSuperClasses(ifaces[i]);
}
if (info.getSuperclass() != null) {
ClassIdentifier superident = (ClassIdentifier)
bundle.getIdentifier(info.getSuperclass().getName());
if (superident != null) {
superident.setReachable();
superident.addSubClass(this);
}
initSuperClasses(info.getSuperclass());
}
preserveIdentifier("<clinit>", "()V");
}
public void strip() {
int newLength = 0;
for (int i=0; i < identifiers.length; i++) {
if (identifiers[i].isReachable())
newLength++;
else {
if (Obfuscator.isDebugging)
Obfuscator.err.println(identifiers[i].toString()
+ " is stripped");
}
}
Identifier[] newIdents = new Identifier[newLength];
int index = 0;
for (int i=0; i < identifiers.length; i++) {
if (identifiers[i].isReachable())
newIdents[index++] = identifiers[i];
}
identifiers = newIdents;
}
public void buildTable(int renameRule) {
super.buildTable(renameRule);
for (int i=0; i < identifiers.length; i++)
identifiers[i].buildTable(renameRule);
}
public void writeTable(PrintWriter out) throws IOException {
if (getName() != getAlias())
out.println("" + getFullAlias() + " = " + getName());
for (int i=0; i < identifiers.length; i++)
identifiers[i].writeTable(out);
}
public void storeClass(OutputStream out) throws IOException {
/*XXX*/
}
/**
* @return the full qualified name, excluding trailing dot.
*/
public String getFullName() {
return pack.getFullName() + getName();
}
/**
* @return the full qualified alias, excluding trailing dot.
*/
public String getFullAlias() {
return pack.getFullAlias() + getAlias();
}
public String getName() {
return name;
}
public String getType() {
return "Ljava/lang/Class;";
}
public String toString() {
return "ClassIdentifier "+getFullName();
}
public static boolean containsField(ClassInfo clazz, String newAlias) {
FieldInfo[] finfos = clazz.getFields();
for (int i=0; i< finfos.length; i++) {
if (finfos[i].getName().equals(newAlias))
return true;
}
ClassInfo[] ifaces = clazz.getInterfaces();
for (int i=0; i < ifaces.length; i++) {
if (containsField(ifaces[i], newAlias))
return true;
}
if (clazz.getSuperclass() != null) {
if (containsField(clazz.getSuperclass(), newAlias))
return true;
}
return false;
}
public boolean containsField(String newAlias) {
for (int i=0; i< identifiers.length; i++) {
if (identifiers[i] instanceof FieldIdentifier
&& identifiers[i].getAlias().equals(newAlias))
return true;
}
ClassInfo[] ifaces = info.getInterfaces();
for (int i=0; i < ifaces.length; i++) {
ClassIdentifier ifaceident = (ClassIdentifier)
bundle.getIdentifier(ifaces[i].getName());
if (ifaceident != null) {
if (ifaceident.containsField(newAlias))
return true;
} else {
if (containsField(ifaces[i], newAlias))
return true;
}
}
if (info.getSuperclass() != null) {
ClassIdentifier superident = (ClassIdentifier)
bundle.getIdentifier(info.getSuperclass().getName());
if (superident != null) {
if (superident.containsField(newAlias))
return true;
} else {
if (containsField(info.getSuperclass(), newAlias))
return true;
}
}
return false;
}
public static boolean containsMethod(ClassInfo clazz,
String newAlias, String paramType) {
MethodInfo[] minfos = clazz.getMethods();
for (int i=0; i< minfos.length; i++) {
if (minfos[i].getName().equals(newAlias)
&& minfos[i].getType().getTypeSignature()
.startsWith(paramType))
return true;
}
ClassInfo[] ifaces = clazz.getInterfaces();
for (int i=0; i < ifaces.length; i++) {
if (containsMethod(ifaces[i], newAlias, paramType))
return true;
}
if (clazz.getSuperclass() != null) {
if (containsMethod(clazz.getSuperclass(), newAlias, paramType))
return true;
}
return false;
}
public boolean containsMethod(String newAlias, String paramType) {
for (int i=0; i< identifiers.length; i++) {
if (identifiers[i] instanceof MethodIdentifier
&& identifiers[i].getAlias().equals(newAlias)
&& identifiers[i].getType().startsWith(paramType))
return true;
}
ClassInfo[] ifaces = info.getInterfaces();
for (int i=0; i < ifaces.length; i++) {
ClassIdentifier ifaceident = (ClassIdentifier)
bundle.getIdentifier(ifaces[i].getName());
if (ifaceident != null) {
if (ifaceident.containsMethod(newAlias, paramType))
return true;
} else {
if (containsMethod(ifaces[i], newAlias, paramType))
return true;
}
}
if (info.getSuperclass() != null) {
ClassIdentifier superident = (ClassIdentifier)
bundle.getIdentifier(info.getSuperclass().getName());
if (superident != null) {
if (superident.containsMethod(newAlias, paramType))
return true;
} else {
if (containsMethod(info.getSuperclass(), newAlias, paramType))
return true;
}
}
return false;
}
public boolean conflicting(String newAlias) {
return pack.contains(newAlias);
}
}

@ -0,0 +1,56 @@
/*
* jode.obfuscator.FieldIdentifier (c) 1998 Jochen Hoenicke
*
* You may distribute under the terms of the GNU General Public License.
*
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* $Id$
*/
package jode.obfuscator;
import jode.bytecode.FieldInfo;
public class FieldIdentifier extends Identifier{
FieldInfo info;
ClassIdentifier clazz;
public FieldIdentifier(ClassIdentifier clazz, FieldInfo info) {
super(info.getName());
this.info = info;
this.clazz = clazz;
}
public String getFullName() {
return clazz.getFullName() + "." + getName();
}
public String getFullAlias() {
return clazz.getFullAlias() + "." + getAlias();
}
public String getName() {
return info.getName();
}
public String getType() {
return info.getType().getTypeSignature();
}
public String toString() {
return "MethodIdentifier "+getFullName()+"."+getType();
}
public boolean conflicting(String newAlias) {
return clazz.containsField(newAlias)
|| clazz.containsMethod(newAlias, "");
}
}

@ -0,0 +1,28 @@
/*
* LoadedClassIdentifier (c) 1998 Jochen Hoenicke
*
* You may distribute under the terms of the GNU General Public License.
*
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* $Id$
*/
package jode.obfuscator;
import jode.Obfuscator;
import jode.bytecode.ClassInfo;
import jode.bytecode.FieldInfo;
import jode.bytecode.MethodInfo;
import java.lang.reflect.Modifier;
import java.util.*;
import java.io.*;

@ -0,0 +1,141 @@
/*
* MethodIdentifier (c) 1998 Jochen Hoenicke
*
* You may distribute under the terms of the GNU General Public License.
*
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* $Id$
*/
package jode.obfuscator;
import jode.Obfuscator;
import jode.bytecode.*;
import java.io.*;
import java.util.Vector;
import java.util.Enumeration;
public class MethodIdentifier extends Identifier {
ClassIdentifier clazz;
MethodInfo info;
public MethodIdentifier(ClassIdentifier clazz, MethodInfo info) {
super(info.getName());
this.clazz = clazz;
this.info = info;
}
public Vector analyzeCode(CodeInfo codeinfo) {
Vector references = new Vector();
byte[] code = codeinfo.getCode();
try {
DataInputStream stream =
new DataInputStream(new ByteArrayInputStream(code));
Opcodes.getReferences(stream, references);
} catch (IOException ex) {
ex.printStackTrace();
throw new ClassFormatError(ex.getMessage());
}
return references;
}
public void setSingleReachable() {
super.setSingleReachable();
if (Obfuscator.isDebugging)
Obfuscator.err.println("Reachable: "+this);
ConstantPool cp = clazz.info.getConstantPool();
AttributeInfo codeattr = info.findAttribute("Code");
if (codeattr == null)
return;
DataInputStream stream = new DataInputStream
(new ByteArrayInputStream(codeattr.getContents()));
CodeInfo codeinfo = new CodeInfo();
try {
codeinfo.read(clazz.info.getConstantPool(), stream);
Vector references = analyzeCode(codeinfo);
Enumeration enum = references.elements();
while (enum.hasMoreElements()) {
int[] ref = (int[]) enum.nextElement();
int tag = cp.getTag(ref[0]);
switch (tag) {
case ConstantPool.FIELDREF:
case ConstantPool.METHODREF:
case ConstantPool.INTERFACEMETHODREF: {
String[] names = cp.getRef(ref[0]);
clazz.bundle.reachableIdentifier
(names[0].replace('/','.')+"."+names[1]+"."+names[2],
ref[1] == 1);
break;
}
case ConstantPool.CLASS: {
String clName = cp.getClassName(ref[0]).replace('/','.');
if (clName.charAt(0) == '[') {
int i;
for (i=0; i< clName.length(); i++)
if (clName.charAt(i) != '[')
break;
if (i >= clName.length() || clName.charAt(i) != 'L')
break;
int index = clName.indexOf(';', i);
if (index != clName.length()-1)
break;
clName = clName.substring(i+1, index);
}
clazz.bundle.reachableIdentifier(clName, false);
break;
}
default:
throw new jode.AssertError
("Unknown reference: "+ref+" tag: "+tag);
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void writeTable(PrintWriter out) throws IOException {
if (getName() != getAlias())
out.println("" + getFullAlias()
+ "." + clazz.bundle.getTypeAlias(getType())
+ " = " + getName());
}
public String getFullName() {
return clazz.getFullName() + "." + getName();
}
public String getFullAlias() {
return clazz.getFullAlias() + "." + getAlias();
}
public String getName() {
return info.getName();
}
public String getType() {
return info.getType().getTypeSignature();
}
public boolean conflicting(String newAlias) {
String type = getType();
String paramType = type.substring(0, type.indexOf(')')+1);
return clazz.containsMethod(newAlias, paramType)
|| clazz.containsField(newAlias);
}
public String toString() {
return "MethodIdentifier "+getFullName()+"."+getType();
}
}

@ -0,0 +1,301 @@
/*
* PackageIdentifier (c) 1998 Jochen Hoenicke
*
* You may distribute under the terms of the GNU General Public License.
*
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* $Id$
*/
package jode.obfuscator;
import jode.Obfuscator;
import jode.bytecode.ClassInfo;
import jode.bytecode.FieldInfo;
import jode.bytecode.MethodInfo;
import java.lang.reflect.Modifier;
import java.util.*;
import java.io.*;
public class PackageIdentifier extends Identifier {
ClassBundle bundle;
PackageIdentifier parent;
String name;
boolean loadOnDemand;
Hashtable loadedClasses;
public PackageIdentifier(ClassBundle bundle,
PackageIdentifier parent,
String name, boolean loadOnDemand) {
super(name);
this.bundle = bundle;
this.parent = parent;
this.name = name;
this.loadOnDemand = loadOnDemand;
this.loadedClasses = new Hashtable();
}
public Identifier getIdentifier(String name) {
if (loadOnDemand)
return loadClass(name);
int index = name.indexOf('.');
if (index == -1)
return (Identifier) loadedClasses.get(name);
else {
PackageIdentifier pack = (PackageIdentifier)
loadedClasses.get(name.substring(0, index));
if (pack != null)
return pack.getIdentifier(name.substring(index+1));
else
return null;
}
}
public Identifier loadClass(String name) {
int index = name.indexOf('.');
if (index == -1) {
Identifier ident = (Identifier) loadedClasses.get(name);
if (ident == null) {
String fullname = getFullName() + name;
if (ClassInfo.isPackage(fullname)) {
ident = new PackageIdentifier(bundle, this, name, true);
} else if (!ClassInfo.exists(fullname)) {
throw new IllegalArgumentException
("Can't find class"+fullname);
} else {
ident = new ClassIdentifier(bundle, this, name,
ClassInfo.forName(fullname));
}
loadedClasses.put(name, ident);
}
return ident;
} else {
String subpack = name.substring(0, index);
PackageIdentifier pack =
(PackageIdentifier) loadedClasses.get(subpack);
if (pack == null) {
pack = new PackageIdentifier(bundle, this,
subpack, loadOnDemand);
loadedClasses.put(subpack, pack);
}
if (pack != null)
return pack.getIdentifier(name.substring(index+1));
else
return null;
}
}
public Identifier loadClasses(String packageOrClass) {
int index = packageOrClass.indexOf('.');
if (index == -1) {
return loadClass(packageOrClass);
} else {
String subpack = packageOrClass.substring(0, index);
PackageIdentifier pack = (PackageIdentifier)
loadedClasses.get(subpack);
if (pack == null) {
pack = new PackageIdentifier(bundle, this,
subpack, loadOnDemand);
loadedClasses.put(subpack, pack);
}
return pack.loadClasses(packageOrClass.substring(index+1));
}
}
public void reachableIdentifier(String fqn, boolean isVirtual) {
int index = fqn.indexOf('.');
String component = index == -1 ? fqn : fqn.substring(0, index);
Identifier ident = getIdentifier(component);
if (ident == null)
return;
ident.setReachable();
if (index == -1)
return;
if (ident instanceof PackageIdentifier)
((PackageIdentifier) ident).reachableIdentifier
(fqn.substring(index+1), isVirtual);
else {
String method = fqn.substring(index+1);
index = method.indexOf('.');
if (index == -1) {
((ClassIdentifier) ident).reachableIdentifier
(method, null, isVirtual);
} else {
((ClassIdentifier) ident).reachableIdentifier
(method.substring(0, index), method.substring(index+1),
isVirtual);
}
}
}
public void preserveIdentifier(String fqn) {
int index = fqn.indexOf('.');
String component = index == -1 ? fqn : fqn.substring(0, index);
Identifier ident = getIdentifier(component);
if (ident == null)
return;
ident.setReachable();
ident.setPreserved();
if (index == -1)
return;
if (ident instanceof PackageIdentifier)
((PackageIdentifier) ident).preserveIdentifier
(fqn.substring(index+1));
else {
String method = fqn.substring(index+1);
index = method.indexOf('.');
if (index == -1) {
((ClassIdentifier) ident).reachableIdentifier
(method, null, false);
((ClassIdentifier) ident).preserveIdentifier
(method, null);
} else {
((ClassIdentifier) ident).reachableIdentifier
(method.substring(0, index), method.substring(index+1),
false);
((ClassIdentifier) ident).preserveIdentifier
(method.substring(0, index), method.substring(index+1));
}
}
}
/**
* @return the full qualified name, including trailing dot.
*/
public String getFullName() {
if (parent != null)
return parent.getFullName() + getName() + ".";
else
return "";
}
/**
* @return the full qualified alias, including trailing dot.
*/
public String getFullAlias() {
if (parent != null)
return parent.getFullAlias() + getAlias() + ".";
else
return "";
}
public String findAlias(String className) {
int index = className.indexOf('.');
if (index == -1) {
Identifier ident = getIdentifier(className);
if (ident != null)
return ident.getFullAlias();
} else {
Identifier pack = getIdentifier(className.substring(0, index));
if (pack != null)
return ((PackageIdentifier)pack)
.findAlias(className.substring(index+1));
}
return className;
}
public void strip() {
Hashtable ht = new Hashtable();
Enumeration enum = loadedClasses.elements();
while (enum.hasMoreElements()) {
Identifier ident = (Identifier) enum.nextElement();
if (ident.isReachable()) {
ht.put(ident.getName(), ident);
if (ident instanceof ClassIdentifier) {
((ClassIdentifier) ident).strip();
} else
((PackageIdentifier) ident).strip();
} else {
if (Obfuscator.isDebugging)
Obfuscator.err.println("Class/Package "
+ ident.getFullName()
+ " is not reachable");
}
}
loadedClasses = ht;
}
public void buildTable(int renameRule) {
super.buildTable(renameRule);
Enumeration enum = loadedClasses.elements();
while (enum.hasMoreElements()) {
Identifier ident = (Identifier) enum.nextElement();
if (ident instanceof ClassIdentifier) {
((ClassIdentifier) ident).buildTable(renameRule);
} else
((PackageIdentifier) ident).buildTable(renameRule);
}
}
public void writeTable(PrintWriter out) throws IOException {
if (parent != null && getName() != getAlias())
out.println("" + parent.getFullAlias() + getAlias()
+ " = " + getName());
Enumeration enum = loadedClasses.elements();
while (enum.hasMoreElements()) {
((Identifier)enum.nextElement()).writeTable(out);
}
}
public String getName() {
return name;
}
public String getType() {
return "package";
}
public void storeClasses(File destination) {
File newDest = (parent == null) ? destination
: new File(destination, getName());
Enumeration enum = loadedClasses.elements();
while (enum.hasMoreElements()) {
Identifier ident = (Identifier) enum.nextElement();
if (ident instanceof PackageIdentifier)
((PackageIdentifier) ident)
.storeClasses(newDest);
else {
try {
((ClassIdentifier) ident).storeClass(null);
} catch (java.io.IOException ex) {
Obfuscator.err.println("Can't write Class "
+ ident.getName());
ex.printStackTrace();
}
}
}
}
public String toString() {
return (parent == null) ? "base package"
: parent.getFullName()+getName();
}
public boolean contains(String newAlias) {
Enumeration enum = loadedClasses.elements();
while (enum.hasMoreElements()) {
if (((Identifier)enum.nextElement()).getAlias().equals(newAlias))
return true;
}
return false;
}
public boolean conflicting(String newAlias) {
return parent.contains(newAlias);
}
}
Loading…
Cancel
Save