001: /* ===========================================================================
002: * $RCSfile: TreeItem.java,v $
003: * ===========================================================================
004: *
005: * RetroGuard -- an obfuscation package for Java classfiles.
006: *
007: * Copyright (c) 1999 Mark Welsh (markw@retrologic.com)
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022: *
023: * The author may be contacted at markw@retrologic.com
024: *
025: *
026: * $Date: 2005/05/19 09:55:11 $
027: * $Revision: 1.3 $
028: */
029: package com.yworks.yguard.obf;
030:
031: import java.io.*;
032: import java.lang.reflect.*;
033: import java.util.*;
034: import com.yworks.yguard.obf.classfile.*;
035:
036: /**
037: * Item that forms a tree structure and can represent a package level, a class,
038: * or a method or field.
039: *
040: * @author Mark Welsh
041: */
042: public class TreeItem {
043: // Constants -------------------------------------------------------------
044:
045: // Fields ----------------------------------------------------------------
046: protected boolean isSynthetic; // Is a method or field Synthetic?
047: protected int access; // Access level (interpret using java.lang.reflect.Modifier)
048: protected ClassTree classTree = null; // Our owner
049: protected TreeItem parent = null; // Our immediate parent
050: protected String sep = ClassFile.SEP_REGULAR; // Separator preceeding this level's name
051: private String inName = null; // Original name of this item
052: private String outName = null; // Output name of this item
053: private boolean isFixed = false; // Has the name been fixed in some way?
054: private boolean isFromScript = false; // Is this script constrained?
055: private boolean isFromScriptMap = false; // Is this script_map constrained?
056:
057: // Class Methods ---------------------------------------------------------
058:
059: /** Do a non-package-recursive wildcard String match. */
060: public static boolean isNRMatch(String pattern, String string) {
061: Enumeration enum1, enum2;
062: try {
063: for (enum1 = ClassTree.getNameEnum(pattern), enum2 = ClassTree
064: .getNameEnum(string); enum1.hasMoreElements()
065: && enum2.hasMoreElements();) {
066: Cons nameSegment1 = (Cons) enum1.nextElement();
067: char tag1 = ((Character) nameSegment1.car).charValue();
068: String name1 = (String) nameSegment1.cdr;
069: Cons nameSegment2 = (Cons) enum2.nextElement();
070: char tag2 = ((Character) nameSegment2.car).charValue();
071: String name2 = (String) nameSegment2.cdr;
072: if (tag1 != tag2 || !isMatch(name1, name2)) {
073: return false;
074: }
075: }
076: if (enum1.hasMoreElements() || enum2.hasMoreElements()) {
077: return false;
078: }
079: } catch (Exception e) {
080: return false;
081: }
082: return true;
083: }
084:
085: /** Do a wildcard String match. */
086: public static boolean isMatch(String pattern, String string) {
087: // Sanity check
088: if (pattern == null || string == null) {
089: return false;
090: }
091:
092: //System.out.println("1) Pattern: " + pattern + " String: " + string);
093:
094: // Not really a wildcard, then check for exact match
095: if (pattern.indexOf('*') == -1) {
096: return pattern.equals(string);
097: }
098:
099: // Check for match of head
100: int pos = -1;
101: if (pattern.charAt(0) != '*') {
102: pos = pattern.indexOf('*');
103: String head = pattern.substring(0, pos);
104: if (string.length() < head.length()) {
105: return false;
106: }
107: if (!string.substring(0, head.length()).equals(head)) {
108: return false;
109: } else {
110: pattern = pattern.substring(pos);
111: string = string.substring(pos);
112: }
113: }
114:
115: //System.out.println("2) Pattern: " + pattern + " String: " + string);
116:
117: // Check for match of tail
118: if (pattern.charAt(pattern.length() - 1) != '*') {
119: pos = pattern.lastIndexOf('*');
120: String tail = pattern.substring(pos + 1);
121: if (string.length() < tail.length()) {
122: return false;
123: }
124: if (!string.substring(string.length() - tail.length())
125: .equals(tail)) {
126: return false;
127: } else {
128: pattern = pattern.substring(0, pos + 1);
129: string = string.substring(0, string.length()
130: - tail.length());
131: }
132: }
133:
134: //System.out.println("3) Pattern: " + pattern + " String: " + string);
135:
136: // Split the pattern at the wildcard positions
137: Vector section = new Vector();
138: pos = pattern.indexOf('*');
139: int rpos = -1;
140: while ((rpos = pattern.indexOf('*', pos + 1)) != -1) {
141: if (rpos != pos + 1) {
142: section.addElement(pattern.substring(pos + 1, rpos));
143: }
144: pos = rpos;
145: }
146: // Check each section for a non-overlapping match in the string
147: for (Enumeration enumeration = section.elements(); enumeration
148: .hasMoreElements();) {
149: String chunk = (String) enumeration.nextElement();
150: //System.out.println("Section: " + chunk + " String: " + string);
151: pos = string.indexOf(chunk);
152: if (pos == -1) {
153: return false;
154: }
155: string = string.substring(pos + chunk.length());
156: }
157: return true;
158: }
159:
160: // Instance Methods ------------------------------------------------------
161: /** Ctor. */
162: public TreeItem(TreeItem parent, String name) {
163: this .parent = parent;
164: this .inName = name;
165: if (parent != null) {
166: classTree = parent.classTree;
167: }
168: }
169:
170: /** Return the modifiers. */
171: public int getModifiers() {
172: return access;
173: }
174:
175: /** Return the original name of the entry. */
176: public String getInName() {
177: return inName;
178: }
179:
180: /** Set the output name of the entry. */
181: public void setOutName(String outName) {
182: // DEBUG
183: //if (isFixed)
184: //{
185: // System.out.println("BIG TROUBLE: " + inName + " -> " + this.outName + " -> " + outName);
186: //}
187: this .outName = outName;
188: isFixed = true;
189: }
190:
191: /** Return the output name of the entry, obfuscated or original. */
192: public String getOutName() {
193: return outName != null ? outName : inName;
194: }
195:
196: /** Return the obfuscated name of the entry. */
197: public String getObfName() {
198: return outName;
199: }
200:
201: /** Signal that this constraint came from a user script line. */
202: public void setFromScript() {
203: isFromScript = true;
204: }
205:
206: /** Signal that this constraint came from a map script line. */
207: public void setFromScriptMap() {
208: isFromScriptMap = true;
209: }
210:
211: /** Has the entry been fixed already? */
212: public boolean isFixed() {
213: return isFixed;
214: }
215:
216: /** Is this constrained by a user script line? */
217: public boolean isFromScript() {
218: return isFromScript;
219: }
220:
221: /** Is this constrained by a map script line? */
222: public boolean isFromScriptMap() {
223: return isFromScriptMap;
224: }
225:
226: /** Is a method or field Synthetic? */
227: public boolean isSynthetic() {
228: return isSynthetic;
229: }
230:
231: /** Set the parent in the tree -- used when stitching in a Cl to replace a PlaceholderCl. */
232: public void setParent(TreeItem parent) {
233: this .parent = parent;
234: }
235:
236: /** Get the parent in the tree. */
237: public TreeItem getParent() {
238: return parent;
239: }
240:
241: /** Construct and return the full original name of the entry. */
242: public String getFullInName() {
243: if (parent == null) {
244: return "";
245: } else if (parent.parent == null) {
246: return getInName();
247: } else {
248: return parent.getFullInName() + sep + getInName();
249: }
250: }
251:
252: /** Construct and return the full obfuscated name of the entry. */
253: public String getFullOutName() {
254: if (parent == null) {
255: return "";
256: } else if (parent.parent == null) {
257: return getOutName();
258: } else {
259: return parent.getFullOutName() + sep + getOutName();
260: }
261: }
262: }
|