KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > yworks > yguard > obf > KeywordNameMaker


1 /**
2  * YGuard -- an obfuscation library for Java(TM) classfiles.
3  *
4  * Original Copyright (c) 1999 Mark Welsh (markw@retrologic.com)
5  * Modifications Copyright (c) 2002 yWorks GmbH (yguard@yworks.com)
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  *
21  * The author may be contacted at yguard@yworks.com
22  *
23  * Java and all Java-based marks are trademarks or registered
24  * trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
25  */

26 package com.yworks.yguard.obf;
27
28 import java.io.*;
29 import java.util.*;
30
31 /**
32  * Name generator that uses (almost) the full Java identifier namespace,
33  * and chooses to put some of the keyword names (legal in JVM, illegal in
34  * Java language) out front in sequence.
35  *
36  * @author Mark Welsh
37  */

38 public class KeywordNameMaker implements NameMaker
39 {
40     // Constants -------------------------------------------------------------
41
private static final String JavaDoc DUMMY_ARG_LIST = "dummy";
42
43
44     // Fields ----------------------------------------------------------------
45
private int skipped = 0; // Names skipped in the sequence
46
private Vector namesToDate = new Vector();
47     private Hashtable argCount = new Hashtable();
48     private String JavaDoc[] noObfNames = null; // List of names not to be obfuscated
49
private String JavaDoc[] keywordsToUse;
50     private String JavaDoc[] keywordsToExclude;
51     private String JavaDoc[] firstLetter;
52     private String JavaDoc[] nextLetter;
53     private String JavaDoc[] noKeywords = {};
54     private String JavaDoc[] someKeywords = {
55         "a", "if", "do", "for", "int", "new", "try", "byte", "case", "char",
56         "else", "goto", "long", "null", "void"
57     };
58     private String JavaDoc[] allKeywords = {
59         "if", "do", "for", "int", "new", "try", "byte", "case", "char",
60         "else", "goto", "long", "null", "this", "void", "true", "false",
61         "break", "catch", "class", "const", "float", "final", "short",
62         "super", "throw", "while", "double", "import", "native", "public",
63         "return", "static", "switch", "throws", "boolean", "default",
64         "extends", "finally", "package", "private", "abstract", "continue",
65         "volatile", "interface", "protected", "transient", "implements",
66         "instanceof", "synchronized"
67     };
68     private String JavaDoc[] firstLetterLower = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
69                                     "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x",
70                                     "y", "z"};
71     private String JavaDoc[] nextLetterLower = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
72                                     "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x",
73                                     "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
74     private String JavaDoc[] firstLetterAll = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
75                                     "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x",
76                                     "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
77                                     "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
78                                     "W", "X", "Y", "Z"};
79     private String JavaDoc[] nextLetterAll = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
80                                     "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x",
81                                     "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
82                                     "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
83                                     "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
84
85
86     // Class Methods ---------------------------------------------------------
87
/** Main method for testing. */
88 /* public static void main(String[] args)
89     {
90         PrintWriter pw = new PrintWriter(
91                          new BufferedOutputStream(
92                          new FileOutputStream("keywordnamemaker.tst")));
93         try
94         {
95             NameMaker nmk = new KeywordNameMaker();
96             for (int i = 0; i < 1000000; i++)
97             {
98                 pw.println(nmk.nextName(null));
99             }
100         }
101         finally
102         {
103             pw.close();
104         }
105     }
106 */

107
108     // Instance Methods ------------------------------------------------------
109
/** Ctor. */
110     public KeywordNameMaker()
111     {
112         this(null);
113     }
114
115     /** Ctor - block names not to be obfuscated from the mapping target space. */
116     public KeywordNameMaker(String JavaDoc[] noObfNames)
117     {
118         this(noObfNames, true);
119     }
120
121     /** Ctor - block names not to be obfuscated from the mapping target space. */
122     public KeywordNameMaker(String JavaDoc[] noObfNames, boolean useKeywords)
123     {
124         this(noObfNames, true, false);
125     }
126
127     /** Ctor - block names not to be obfuscated from the mapping target space. */
128     public KeywordNameMaker(String JavaDoc[] noObfNames, boolean useKeywords, boolean lowerCaseOnly)
129     {
130         this.noObfNames = noObfNames == null ? new String JavaDoc[0] : noObfNames;
131         if (useKeywords)
132         {
133             keywordsToUse = someKeywords;
134             keywordsToExclude = someKeywords;
135         }
136         else
137         {
138             keywordsToUse = noKeywords;
139             keywordsToExclude = allKeywords;
140         }
141         if (lowerCaseOnly)
142         {
143             firstLetter = firstLetterLower;
144             nextLetter = nextLetterLower;
145         }
146         else
147         {
148             firstLetter = firstLetterAll;
149             nextLetter = nextLetterAll;
150         }
151     }
152
153     /** Return the next unique name for this namespace. */
154     public String JavaDoc nextName(String JavaDoc descriptor)
155     {
156         // Check for arg-list in hashtable
157
String JavaDoc argList = DUMMY_ARG_LIST;
158         if (descriptor != null)
159         {
160             argList = getArgList(descriptor);
161         }
162         Integer JavaDoc intCount = (Integer JavaDoc)argCount.get(argList);
163         int theCount = 0;
164         if (intCount == null)
165         {
166             argCount.put(argList, new Integer JavaDoc(theCount));
167         }
168         else
169         {
170             theCount = intCount.intValue() + 1;
171             argCount.remove(argList);
172             argCount.put(argList, new Integer JavaDoc(theCount));
173         }
174         return getName(theCount);
175     }
176
177     // Extract the arg-list from a descriptor
178
private String JavaDoc getArgList(String JavaDoc descriptor)
179     {
180         int pos = descriptor.indexOf(')');
181         return descriptor.substring(1, pos);
182     }
183
184     // Generate i'th allowed, unique name
185
private String JavaDoc getName(int index)
186     {
187         // If we have previously computed this name, just return it
188
String JavaDoc name = null;
189         if (index < namesToDate.size())
190         {
191             name = (String JavaDoc)namesToDate.elementAt(index);
192         }
193         else
194         {
195             // Generate a new valid name for the sequence
196
for (;;)
197             {
198                 name = getNewName(index + skipped);
199                 if (!Tools.isInArray(name, noObfNames) &&
200                     (index + skipped < keywordsToUse.length ||
201                      !Tools.isInArray(name, keywordsToExclude)))
202                 {
203                     break;
204                 }
205                 skipped++;
206             }
207             namesToDate.addElement(name);
208         }
209         return name;
210     }
211
212     // Generate j'th name in sequence (can repeat keywords)
213
private String JavaDoc getNewName(int index)
214     {
215         String JavaDoc name = null;
216
217         // Check if we are in the 'keyword' part of the namespace
218
if (index < keywordsToUse.length)
219         {
220             name = keywordsToUse[index];
221         }
222         else
223         {
224             // Check if we are in the single letter part of the namespace
225
index -= keywordsToUse.length;
226             if (index < firstLetter.length)
227             {
228                 name = firstLetter[index];
229             }
230             else
231             {
232                 // We are in the >=2 letter part of namespace
233
index -= firstLetter.length;
234                 int nextLetters = 1;
235                 int subspaceSize = nextLetter.length;
236                 while (index >= firstLetter.length * subspaceSize)
237                 {
238                     index -= firstLetter.length * subspaceSize;
239                     nextLetters++;
240                     subspaceSize *= nextLetter.length;
241                 }
242
243                 // Pull out the name
244
StringBuffer JavaDoc sb = new StringBuffer JavaDoc(firstLetter[index / subspaceSize]);
245                 while (subspaceSize != 1)
246                 {
247                     index %= subspaceSize;
248                     subspaceSize /= nextLetter.length;
249                     sb.append(nextLetter[index / subspaceSize]);
250                 }
251
252                 // Check for collision with keywords
253
name = sb.toString();
254             }
255         }
256         return name;
257     }
258 }
259
260
Popular Tags