KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > Obfuscator


1
2 /*
3  * Copyright © 2002 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
4  * California 95054, U.S.A. All rights reserved. Sun Microsystems, Inc. has
5  * intellectual property rights relating to technology embodied in the product
6  * that is described in this document. In particular, and without limitation,
7  * these intellectual property rights may include one or more of the U.S.
8  * patents listed at http://www.sun.com/patents and one or more additional
9  * patents or pending patent applications in the U.S. and in other countries.
10  * U.S. Government Rights - Commercial software. Government users are subject
11  * to the Sun Microsystems, Inc. standard license agreement and applicable
12  * provisions of the FAR and its supplements. Use is subject to license terms.
13  * Sun, Sun Microsystems, the Sun logo and Java are trademarks or registered
14  * trademarks of Sun Microsystems, Inc. in the U.S. and other countries. This
15  * product is covered and controlled by U.S. Export Control laws and may be
16  * subject to the export or import laws in other countries. Nuclear, missile,
17  * chemical biological weapons or nuclear maritime end uses or end users,
18  * whether direct or indirect, are strictly prohibited. Export or reexport
19  * to countries subject to U.S. embargo or to entities identified on U.S.
20  * export exclusion lists, including, but not limited to, the denied persons
21  * and specially designated nationals lists is strictly prohibited.
22  */

23
24
25 import java.io.*;
26 import java.util.*;
27
28 public class Obfuscator extends Globals {
29
30   // These data structures implement a stack that is used to recursively
31
// walk the input directory structure looking for Java files.
32

33   static String JavaDoc[][] dirStack = new String JavaDoc[100][];
34   static int[] dirStackIndex = new int[100];
35   static int dirStackSize;
36   static File[] dirFile = new File[100];
37
38   static {
39     dirFile[0] = inpDir;
40     dirStackSize = 1;
41     dirStack[dirStackSize] = dirFile[dirStackSize-1].list();
42     dirStackIndex[dirStackSize] = 0;
43   }
44
45   // Returns true if this is a Java file.
46
static boolean javaFile(String JavaDoc name) {
47     if (name.length() < 6) {
48       return false;
49     }
50     if (name.substring(name.length() - 5).equals(".java")) {
51       return true;
52     }
53     return false;
54   }
55
56   // The iterator. This uses the above datastructures to walk the input
57
// directory tree. Everytime it finds a Java file or when it cannot find
58
// any more Java file, it returns to the caller.
59
static void nextJavaFile() {
60     while (true) {
61       if (dirStackIndex[dirStackSize] == dirStack[dirStackSize].length) {
62         dirStackSize--;
63         if (dirStackSize == 0) {
64           return;
65         } else {
66           dirStackIndex[dirStackSize]++;
67         }
68       } else {
69         dirFile[dirStackSize] = new File(dirFile[dirStackSize-1],
70                                          dirStack[dirStackSize][dirStackIndex[dirStackSize]]);
71         if (dirStack[dirStackSize][dirStackIndex[dirStackSize]].equals("SCCS")) {
72           dirStackIndex[dirStackSize]++;
73         } else if (dirFile[dirStackSize].isDirectory()) {
74           dirStackSize++;
75           dirStack[dirStackSize] = dirFile[dirStackSize-1].list();
76           dirStackIndex[dirStackSize] = 0;
77         } else if (javaFile(dirStack[dirStackSize][dirStackIndex[dirStackSize]])) {
78           dirStackIndex[dirStackSize]++;
79           return;
80         } else {
81           dirStackIndex[dirStackSize]++;
82         }
83       }
84     }
85   }
86
87   // The main Obfuscator routine. It calls the iterator for each Java file to
88
// work on. It then creates the output file, then parses the input Java file
89
// to determine whether or not it has a main program and also to collect the
90
// tokens that make up this file. It then calls printOutputFile that takes
91
// first token and walks the next field chain printing tokens as it goes along.
92
// Finally a main program is created if necessary.
93
static public void start() {
94     boolean parserInitialized = false;
95     JavaParser parser = null;
96     Token first;
97     while (true) {
98       nextJavaFile();
99       if (dirStackSize == 0) {
100         break;
101       }
102       createOutputFile();
103       System.out.println("Obfuscating " + dirFile[dirStackSize].getPath());
104       System.out.println(" into " + outFile.getPath());
105       try {
106     if (parserInitialized) {
107       parser.ReInit(new FileInputStream(dirFile[dirStackSize]));
108     } else {
109       parser = new JavaParser(new FileInputStream(dirFile[dirStackSize]));
110       parserInitialized = true;
111     }
112         first = parser.CompilationUnit(dirStack[dirStackSize][dirStackIndex[dirStackSize]-1]);
113       } catch (ParseException e1) {
114         System.out.println("Parse error in file " + dirFile[dirStackSize].getPath());
115         throw new Error JavaDoc();
116       } catch (IOException e2) {
117         System.out.println("Could not open file " + dirFile[dirStackSize].getPath());
118         throw new Error JavaDoc();
119       }
120       printOutputFile(first);
121       if (mainExists) {
122         createMainClass();
123       }
124     }
125   }
126
127   static File outFile;
128   static PrintWriter ostr;
129
130   static void createOutputFile() {
131     // sets outFile and ostr
132
outFile = outDir;
133     for (int i = 1; i < dirStackSize; i++) {
134       outFile = new File(outFile, map(dirStack[i][dirStackIndex[i]]));
135       if (outFile.exists()) {
136         if (!outFile.isDirectory()) {
137           System.out.println("Unexpected error!");
138           throw new Error JavaDoc();
139         }
140       } else {
141         if (!outFile.mkdir()) {
142           System.out.println("Could not create directory " + outFile.getPath());
143           throw new Error JavaDoc();
144         }
145       }
146     }
147     String JavaDoc origFileName = dirStack[dirStackSize][dirStackIndex[dirStackSize]-1];
148     String JavaDoc newFileName = map(origFileName.substring(0, origFileName.length() - 5)) + ".java";
149     outFile = new File(outFile, newFileName);
150     try {
151       ostr = new PrintWriter(new FileWriter(outFile));
152     } catch (IOException e) {
153       System.out.println("Could not create file " + outFile.getPath());
154       throw new Error JavaDoc();
155     }
156   }
157
158   static void printOutputFile(Token first) {
159     Token t = first;
160     for (int i = 1; i < t.beginColumn; i++) {
161       ostr.print(" ");
162     }
163     while (true) {
164       if (t.kind == JavaParserConstants.IDENTIFIER) {
165         t.image = map(t.image);
166       }
167       ostr.print(addUnicodeEscapes(t.image));
168       if (t.next == null) {
169         ostr.println("");
170         break;
171       }
172       if (t.endLine != t.next.beginLine) {
173         for (int i = t.endLine; i < t.next.beginLine; i++) {
174           ostr.println("");
175         }
176         for (int i = 1; i < t.next.beginColumn; i++) {
177           ostr.print(" ");
178         }
179       } else {
180         for (int i = t.endColumn+1; i < t.next.beginColumn; i++) {
181           ostr.print(" ");
182         }
183       }
184       t = t.next;
185     }
186     ostr.close();
187   }
188
189   static String JavaDoc addUnicodeEscapes(String JavaDoc str) {
190     String JavaDoc retval = "";
191     char ch;
192     for (int i = 0; i < str.length(); i++) {
193       ch = str.charAt(i);
194       if (ch < 0x20 || ch > 0x7e) {
195     String JavaDoc s = "0000" + Integer.toString(ch, 16);
196     retval += "\\u" + s.substring(s.length() - 4, s.length());
197       } else {
198         retval += ch;
199       }
200     }
201     return retval;
202   }
203
204   // This creates a main program if there was one in the original file. This
205
// main program has the same name and resides in the same package as the original
206
// file and it simply calls the obfuscated main program. This allows scripts
207
// to continue to work.
208
static void createMainClass() {
209     PrintWriter mstr;
210     boolean mustCreate = false;
211     File mFile = outDir;
212     for (int i = 1; i < dirStackSize; i++) {
213       mFile = new File(mFile, dirStack[i][dirStackIndex[i]]);
214       mustCreate = mustCreate || !map(dirStack[i][dirStackIndex[i]]).equals(dirStack[i][dirStackIndex[i]]);
215       if (mFile.exists()) {
216         if (!mFile.isDirectory()) {
217           System.out.println("Error: Created file " + mFile.getPath() + ", but need to create a main program with the same path prefix. Please remove identifiers from the path prefix from your <useidsfile> and run again.");
218           throw new Error JavaDoc();
219         }
220       }
221     }
222     String JavaDoc origFileName = dirStack[dirStackSize][dirStackIndex[dirStackSize]-1];
223     String JavaDoc newFileName = map(origFileName.substring(0, origFileName.length() - 5)) + ".java";
224     if (!mustCreate && origFileName.equals(newFileName)) {
225       return; // this main program has not been obfuscated.
226
}
227     if (!mFile.exists() && !mFile.mkdirs()) {
228       System.out.println("Could not create " + mFile.getPath());
229       throw new Error JavaDoc();
230     }
231     mFile = new File(mFile, origFileName);
232     try {
233       mstr = new PrintWriter(new FileWriter(mFile));
234     } catch (IOException e) {
235       System.out.println("Could not create " + mFile.getPath());
236       throw new Error JavaDoc();
237     }
238     System.out.print("Generating main program ");
239     String JavaDoc pname = "";
240     if (dirStackSize > 1) {
241       for (int i = 1; i < dirStackSize; i++) {
242         pname += "." + dirStack[i][dirStackIndex[i]];
243       }
244       mstr.println("package " + pname.substring(1) + ";");
245       System.out.print(pname.substring(1) + ".");
246       mstr.println("");
247     }
248     System.out.println(origFileName.substring(0, origFileName.length() - 5));
249     mstr.println("public class " + origFileName.substring(0, origFileName.length() - 5) + " {");
250     mstr.println("");
251     mstr.println(" public static void main(String[] args) {");
252     pname = "";
253     for (int i = 1; i < dirStackSize; i++) {
254       pname += map(dirStack[i][dirStackIndex[i]]) + ".";
255     }
256     mstr.println(" " + pname + map(origFileName.substring(0, origFileName.length() - 5)) + ".main(args);");
257     mstr.println(" }");
258     mstr.println("");
259     mstr.println("}");
260     mstr.close();
261   }
262
263 }
264
Popular Tags