001: /**
002: * YGuard -- an obfuscation library for Java(TM) classfiles.
003: *
004: * Original Copyright (c) 1999 Mark Welsh (markw@retrologic.com)
005: * Modifications Copyright (c) 2002 yWorks GmbH (yguard@yworks.com)
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: * The author may be contacted at yguard@yworks.com
022: *
023: * Java and all Java-based marks are trademarks or registered
024: * trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
025: */package com.yworks.yguard.obf;
026:
027: import com.yworks.yguard.obf.classfile.Logger;
028:
029: import java.io.*;
030: import java.lang.reflect.*;
031: import java.util.*;
032:
033: /**
034: * Base to package and class tree item.
035: *
036: * @author Mark Welsh
037: */
038: abstract public class PkCl extends TreeItem {
039: // Constants -------------------------------------------------------------
040:
041: // Fields ----------------------------------------------------------------
042: /** Owns a list of classes. */
043: protected Hashtable cls = new Hashtable();
044:
045: // Class Methods ---------------------------------------------------------
046:
047: // Instance Methods ------------------------------------------------------
048: /** Ctor. */
049: public PkCl(TreeItem parent, String name) {
050: super (parent, name);
051: }
052:
053: /** Get a class by name. */
054: public Cl getClass(String name) {
055: return (Cl) cls.get(name);
056: }
057:
058: /** Get an Enumeration of classes directly beneath this PkCl. */
059: public Enumeration getClassEnum() {
060: return cls.elements();
061: }
062:
063: /** Get an Enumeration of all classes (outer and inner) in the tree beneath this PkCl. */
064: public Enumeration getAllClassEnum() {
065: Vector allClasses = new Vector();
066: addAllClasses(allClasses);
067: return allClasses.elements();
068: }
069:
070: /** List classes and recursively compose a list of all inner classes. */
071: protected void addAllClasses(Vector allClasses) {
072: for (Enumeration enumeration = cls.elements(); enumeration
073: .hasMoreElements();) {
074: Cl cl = (Cl) enumeration.nextElement();
075: allClasses.addElement(cl);
076: cl.addAllClasses(allClasses);
077: }
078: }
079:
080: /** Return number of classes. */
081: public int getClassCount() {
082: return cls.size();
083: }
084:
085: /** Add a class to the list of owned classes. */
086: abstract public Cl addClass(String name, String super Name,
087: String[] interfaceNames, int modifiers);
088:
089: /** Add a class to the list of owned classes. */
090: public Cl addClass(boolean isInnerClass, String name,
091: String super Name, String[] interfaceNames, int modifiers) {
092: Cl cl = getClass(name);
093:
094: // Remove placeholder if present
095: PlaceholderCl plClassItem = null;
096: if (cl instanceof PlaceholderCl) {
097: plClassItem = (PlaceholderCl) cl;
098: cls.remove(name);
099: cl = null;
100: }
101:
102: // Add the class, if not already present
103: if (cl == null) {
104: cl = new Cl(this , isInnerClass, name, super Name,
105: interfaceNames, modifiers);
106: cls.put(name, cl);
107: }
108:
109: // Copy over the inner class data from the placeholder, if any
110: if (plClassItem != null) {
111: for (Enumeration enumeration = plClassItem.getClassEnum(); enumeration
112: .hasMoreElements();) {
113: Cl innerCl = (Cl) enumeration.nextElement();
114: innerCl.setParent(cl);
115: cl.addClass(innerCl);
116: }
117: }
118: return cl;
119: }
120:
121: /** Add a placeholder class to our list of owned classes, to be replaced later by the full class. */
122: abstract public Cl addPlaceholderClass(String name);
123:
124: /** Add a placeholder class to our list of owned classes, to be replaced later by the full class. */
125: public Cl addPlaceholderClass(boolean isInnerClass, String name) {
126: Cl cl = getClass(name);
127: if (cl == null) {
128: cl = new PlaceholderCl(this , isInnerClass, name);
129: cls.put(name, cl);
130: }
131: return cl;
132: }
133:
134: /** Generate unique obfuscated names for this namespace. */
135: public void generateNames() {
136: generateNames(cls);
137: }
138:
139: /** Generate unique obfuscated names for a given namespace. */
140: protected void generateNames(Hashtable hash) {
141: Vector vec = new Vector();
142: for (Enumeration enumeration = hash.elements(); enumeration
143: .hasMoreElements();) {
144: TreeItem ti = (TreeItem) enumeration.nextElement();
145: if (ti.isFixed()) {
146: vec.addElement(ti.getOutName());
147: }
148: }
149: String[] noObfNames = new String[vec.size()];
150: for (int i = 0; i < noObfNames.length; i++) {
151: noObfNames[i] = (String) vec.elementAt(i);
152: }
153: NameMakerFactory nmf = NameMakerFactory.getInstance();
154: for (Enumeration enumeration = hash.elements(); enumeration
155: .hasMoreElements();) {
156: TreeItem ti = (TreeItem) enumeration.nextElement();
157: if (!ti.isFixed()) {
158: if (ti instanceof Cl && ((Cl) ti).isInnerClass()) {
159: NameMaker innerClassNameMaker = nmf
160: .getInnerClassNameMaker(noObfNames,
161: getFullInName());
162: ti.setOutName(innerClassNameMaker.nextName(null));
163: } else if (ti instanceof Pk) {
164: NameMaker packageNameMaker = nmf
165: .getPackageNameMaker(noObfNames,
166: getFullInName());
167: ti.setOutName(packageNameMaker.nextName(null));
168: } else {
169: NameMaker classNameMaker = nmf.getClassNameMaker(
170: noObfNames, getFullInName());
171: boolean newNameFound = true;
172: Cl.ClassResolver resolver = Cl.getClassResolver();
173: do {
174: ti.setOutName(classNameMaker.nextName(null));
175: String newName = ti.getFullOutName();
176: try {
177: resolver.resolve(newName);
178: newNameFound = false;
179: } catch (ClassNotFoundException cnfe) {
180: newNameFound = true;
181: }
182: } while (!newNameFound);
183: }
184: }
185: }
186: }
187: }
|