KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > obfuscator > ClassBundle


1 /* ClassBundle Copyright (C) 1998-2002 Jochen Hoenicke.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; see the file COPYING. If not, write to
15  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16  *
17  * $Id: ClassBundle.java.in,v 1.8.2.4 2002/05/28 17:34:14 hoenicke Exp $
18  */

19
20 package jode.obfuscator;
21 import jode.GlobalOptions;
22 import jode.bytecode.SearchPath;
23 import jode.bytecode.ClassInfo;
24 import jode.bytecode.Reference;
25 import jode.obfuscator.modules.WildCard;
26 import jode.obfuscator.modules.MultiIdentifierMatcher;
27 import jode.obfuscator.modules.SimpleAnalyzer;
28 import java.io.*;
29 import java.util.zip.ZipOutputStream JavaDoc;
30
31 import java.util.Collection JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.Set JavaDoc;
34 import java.util.HashSet JavaDoc;
35 import java.util.Map JavaDoc;
36 import java.util.HashMap JavaDoc;
37 import java.util.TreeMap JavaDoc;
38 import java.lang.UnsupportedOperationException JavaDoc;
39
40 ///#ifdef JDK12
41
import java.util.WeakHashMap JavaDoc;
42 ///#endif
43

44 public class ClassBundle implements OptionHandler {
45     PackageIdentifier basePackage;
46
47     /**
48      * the identifiers that must be analyzed.
49      */

50     Set JavaDoc toAnalyze = new HashSet JavaDoc();
51
52     String JavaDoc classPath;
53     String JavaDoc destDir;
54
55     String JavaDoc inTableFile;
56     String JavaDoc outTableFile;
57     String JavaDoc outRevTableFile;
58
59     IdentifierMatcher loading;
60     IdentifierMatcher preserving;
61     IdentifierMatcher reaching;
62     CodeTransformer[] preTrafos;
63     CodeAnalyzer analyzer;
64     CodeTransformer[] postTrafos;
65     Renamer renamer;
66
67
68     public ClassBundle() {
69     classPath = System.getProperty("java.class.path")
70         .replace(File.pathSeparatorChar, SearchPath.altPathSeparatorChar);
71     destDir = ".";
72     basePackage = new PackageIdentifier(this, null, "", "");
73     basePackage.setReachable();
74     basePackage.setPreserved();
75     }
76
77 ///#ifdef JDK12
78
private static final Map JavaDoc aliasesHash = new WeakHashMap JavaDoc();
79 ///#else
80
/// private static final Map aliasesHash = new HashMap();
81
///#endif
82
private static final Map JavaDoc clazzCache = new HashMap JavaDoc();
83     private static final Map JavaDoc referenceCache = new HashMap JavaDoc();
84
85     public static void setStripOptions(Collection JavaDoc stripString) {
86     }
87     public void setOption(String JavaDoc option, Collection JavaDoc values) {
88     if (option.equals("classpath")) {
89         Iterator JavaDoc i = values.iterator();
90         StringBuffer JavaDoc sb = new StringBuffer JavaDoc((String JavaDoc) i.next());
91         while (i.hasNext()) {
92         sb.append(SearchPath.altPathSeparatorChar)
93             .append((String JavaDoc)i.next());
94         }
95         ClassInfo.setClassPath(sb.toString());
96         return;
97     }
98         
99     if (option.equals("dest")) {
100         if (values.size() != 1)
101         throw new IllegalArgumentException JavaDoc
102             ("Only one destination path allowed");
103         destDir = (String JavaDoc) values.iterator().next();
104         return;
105     }
106
107     if (option.equals("verbose")) {
108         if (values.size() != 1)
109         throw new IllegalArgumentException JavaDoc
110             ("Verbose takes one int parameter");
111         GlobalOptions.verboseLevel
112         = ((Integer JavaDoc) values.iterator().next()).intValue();
113         return;
114     }
115
116     if (option.equals("intable") || option.equals("table")) {
117         if (values.size() != 1)
118         throw new IllegalArgumentException JavaDoc
119             ("Only one destination path allowed");
120         inTableFile = (String JavaDoc) values.iterator().next();
121         return;
122     }
123
124     if (option.equals("outtable")) {
125         if (values.size() != 1)
126         throw new IllegalArgumentException JavaDoc
127             ("Only one destination path allowed");
128         outTableFile = (String JavaDoc) values.iterator().next();
129         return;
130     }
131
132     if (option.equals("outrevtable") || option.equals("revtable")) {
133         if (values.size() != 1)
134         throw new IllegalArgumentException JavaDoc
135             ("Only one destination path allowed");
136         outRevTableFile = (String JavaDoc) values.iterator().next();
137         return;
138     }
139
140     if (option.equals("strip")) {
141     next_token:
142         for (Iterator JavaDoc iter = values.iterator(); iter.hasNext(); ) {
143         String JavaDoc token = (String JavaDoc) iter.next();
144         for (int i=0; i < Main.stripNames.length; i++) {
145             if (token.equals(Main.stripNames[i])) {
146             Main.stripping |= 1 << i;
147             continue next_token;
148             }
149         }
150         throw new IllegalArgumentException JavaDoc("Unknown strip option: `"
151                            +token+"'");
152         }
153         return;
154     }
155
156     if (option.equals("load")) {
157         if (values.size() == 1) {
158         Object JavaDoc value = values.iterator().next();
159         if (value instanceof String JavaDoc)
160             loading = new WildCard((String JavaDoc)value);
161         else
162             loading = (IdentifierMatcher) value;
163         } else {
164         IdentifierMatcher[] matchers
165             = new IdentifierMatcher[values.size()];
166         int j = 0;
167         for (Iterator JavaDoc i = values.iterator(); i.hasNext(); ) {
168             Object JavaDoc value = i.next();
169             matchers[j++] = (value instanceof String JavaDoc
170                      ? new WildCard((String JavaDoc)value)
171                      : (IdentifierMatcher) value);
172         }
173         loading = new MultiIdentifierMatcher
174             (MultiIdentifierMatcher.OR, matchers);
175         }
176         return;
177     }
178
179     if (option.equals("preserve")) {
180         if (values.size() == 1) {
181         Object JavaDoc value = values.iterator().next();
182         if (value instanceof String JavaDoc)
183             preserving = new WildCard((String JavaDoc)value);
184         else
185             preserving = (IdentifierMatcher) value;
186         } else {
187         IdentifierMatcher[] matchers
188             = new IdentifierMatcher[values.size()];
189         int j = 0;
190         for (Iterator JavaDoc i = values.iterator(); i.hasNext(); ) {
191             Object JavaDoc value = i.next();
192             matchers[j++] = (value instanceof String JavaDoc
193                      ? new WildCard((String JavaDoc)value)
194                      : (IdentifierMatcher) value);
195         }
196         preserving = new MultiIdentifierMatcher
197             (MultiIdentifierMatcher.OR, matchers);
198         }
199         return;
200     }
201
202     if (option.equals("reach")) {
203         // NOT IMPLEMENTED YET
204
if (values.size() == 1) {
205         Object JavaDoc value = values.iterator().next();
206         if (value instanceof String JavaDoc)
207             reaching = new WildCard((String JavaDoc)value);
208         else
209             reaching = (IdentifierMatcher) value;
210         } else {
211         IdentifierMatcher[] matchers
212             = new IdentifierMatcher[values.size()];
213         int j = 0;
214         for (Iterator JavaDoc i = values.iterator(); i.hasNext(); ) {
215             Object JavaDoc value = i.next();
216             matchers[j++] = (value instanceof String JavaDoc
217                      ? new WildCard((String JavaDoc)value)
218                      : (IdentifierMatcher) value);
219         }
220         reaching = new MultiIdentifierMatcher
221             (MultiIdentifierMatcher.OR, matchers);
222         }
223     }
224
225     if (option.equals("pre")) {
226         preTrafos = (CodeTransformer[])
227         values.toArray(new CodeTransformer[values.size()]);
228         return;
229     }
230     if (option.equals("analyzer")) {
231         if (values.size() != 1)
232         throw new IllegalArgumentException JavaDoc
233             ("Only one analyzer is allowed");
234         analyzer = (CodeAnalyzer) values.iterator().next();
235         return;
236     }
237     if (option.equals("post")) {
238         postTrafos = (CodeTransformer[])
239         values.toArray(new CodeTransformer[values.size()]);
240         return;
241     }
242
243     if (option.equals("renamer")) {
244         if (values.size() != 1)
245         throw new IllegalArgumentException JavaDoc
246             ("Only one renamer allowed");
247         renamer = (Renamer) values.iterator().next();
248         return;
249     }
250     throw new IllegalArgumentException JavaDoc("Invalid option `"+option+"'.");
251     }
252
253     public Reference getReferenceAlias(Reference ref) {
254     Reference alias = (Reference) aliasesHash.get(ref);
255     if (alias == null) {
256         Identifier ident = getIdentifier(ref);
257         String JavaDoc newType = getTypeAlias(ref.getType());
258         if (ident == null)
259         alias = Reference.getReference
260             (ref.getClazz(), ref.getName(), newType);
261         else
262         alias = Reference.getReference
263             ("L"+ident.getParent().getFullAlias().replace('.','/')+';',
264              ident.getAlias(), newType);
265         aliasesHash.put(ref, alias);
266     }
267     return alias;
268     }
269
270     public String JavaDoc getClassAlias(String JavaDoc className) {
271     ClassIdentifier classIdent = getClassIdentifier(className);
272     if (classIdent == null)
273         return className;
274     return classIdent.getFullAlias();
275     }
276
277     public String JavaDoc getTypeAlias(String JavaDoc typeSig) {
278     String JavaDoc alias = (String JavaDoc) aliasesHash.get(typeSig);
279     if (alias == null) {
280         StringBuffer JavaDoc newSig = new StringBuffer JavaDoc();
281         int index = 0, nextindex;
282         while ((nextindex = typeSig.indexOf('L', index)) != -1) {
283         newSig.append(typeSig.substring(index, nextindex+1));
284         index = typeSig.indexOf(';', nextindex);
285         String JavaDoc typeAlias = getClassAlias
286             (typeSig.substring(nextindex+1, index).replace('/','.'));
287         newSig.append(typeAlias.replace('.', '/'));
288         }
289         alias = newSig.append(typeSig.substring(index))
290         .toString().intern();
291         aliasesHash.put(typeSig, alias);
292     }
293     return alias;
294     }
295
296     public void addClassIdentifier(Identifier ident) {
297     }
298
299     public ClassIdentifier getClassIdentifier(String JavaDoc name) {
300     if (clazzCache.containsKey(name))
301         return (ClassIdentifier) clazzCache.get(name);
302     ClassIdentifier ident
303         = (ClassIdentifier) basePackage.getIdentifier(name);
304     clazzCache.put(name, ident);
305     return ident;
306     }
307
308     public Identifier getIdentifier(Reference ref) {
309     if (referenceCache.containsKey(ref))
310         return (Identifier) referenceCache.get(ref);
311
312     String JavaDoc clName = ref.getClazz();
313     if (clName.charAt(0) == '[')
314         /* Can't represent arrays */
315         return null;
316     ClassIdentifier clazzIdent =
317         getClassIdentifier(clName.substring(1, clName.length()-1)
318                    .replace('/','.'));
319     Identifier ident =
320         clazzIdent == null ? null
321         : clazzIdent.getIdentifier(ref.getName(), ref.getType());
322     referenceCache.put(ref, ident);
323     return ident;
324     }
325
326     public void reachableClass(String JavaDoc clazzName) {
327     ClassIdentifier ident = getClassIdentifier(clazzName);
328     if (ident != null)
329         ident.setReachable();
330     }
331
332     public void reachableReference(Reference ref, boolean isVirtual) {
333     String JavaDoc clName = ref.getClazz();
334     if (clName.charAt(0) == '[')
335         /* Can't represent arrays */
336         return;
337     ClassIdentifier ident =
338         getClassIdentifier(clName.substring(1, clName.length()-1)
339                    .replace('/','.'));
340     if (ident != null)
341         ident.reachableReference(ref, isVirtual);
342     }
343
344     public void analyzeIdentifier(Identifier ident) {
345     if (ident == null)
346         throw new NullPointerException JavaDoc();
347     toAnalyze.add(ident);
348     }
349
350     public void analyze() {
351     while(!toAnalyze.isEmpty()) {
352         Identifier ident = (Identifier) toAnalyze.iterator().next();
353         toAnalyze.remove(ident);
354         ident.analyze();
355     }
356     }
357
358     public IdentifierMatcher getPreserveRule() {
359     return preserving;
360     }
361
362     public CodeAnalyzer getCodeAnalyzer() {
363     return analyzer;
364     }
365
366     public CodeTransformer[] getPreTransformers() {
367     return preTrafos;
368     }
369     
370     public CodeTransformer[] getPostTransformers() {
371     return postTrafos;
372     }
373     
374     public void buildTable(Renamer renameRule) {
375     basePackage.buildTable(renameRule);
376     }
377
378     public void readTable() {
379     try {
380         TranslationTable table = new TranslationTable();
381         InputStream input = new FileInputStream(inTableFile);
382         table.load(input);
383         input.close();
384         basePackage.readTable(table);
385     } catch (java.io.IOException JavaDoc ex) {
386         GlobalOptions.err.println("Can't read rename table "
387                       + inTableFile);
388         ex.printStackTrace(GlobalOptions.err);
389     }
390     }
391
392     public void writeTable() {
393     TranslationTable table = new TranslationTable();
394     basePackage.writeTable(table, false);
395     try {
396         OutputStream JavaDoc out = new FileOutputStream(outTableFile);
397         table.store(out);
398         out.close();
399     } catch (java.io.IOException JavaDoc ex) {
400         GlobalOptions.err.println("Can't write rename table "
401                       + outTableFile);
402         ex.printStackTrace(GlobalOptions.err);
403     }
404     }
405
406     public void writeRevTable() {
407     TranslationTable revtable = new TranslationTable();
408     basePackage.writeTable(revtable, true);
409     try {
410         OutputStream JavaDoc out = new FileOutputStream(outRevTableFile);
411         revtable.store(out);
412         out.close();
413     } catch (java.io.IOException JavaDoc ex) {
414         GlobalOptions.err.println("Can't write rename table "
415                       + outRevTableFile);
416         ex.printStackTrace(GlobalOptions.err);
417     }
418     }
419
420     public void doTransformations() {
421     basePackage.doTransformations();
422     }
423     
424     public void storeClasses() {
425     if (destDir.endsWith(".jar") ||
426         destDir.endsWith(".zip")) {
427         try {
428         ZipOutputStream JavaDoc zip = new ZipOutputStream JavaDoc
429             (new FileOutputStream(destDir));
430         basePackage.storeClasses(zip);
431         zip.close();
432         } catch (IOException ex) {
433         GlobalOptions.err.println
434             ("Can't write zip file: "+destDir);
435         ex.printStackTrace(GlobalOptions.err);
436         }
437     } else {
438         File directory = new File(destDir);
439         if (!directory.exists()) {
440         GlobalOptions.err.println("Destination directory "
441                       +directory.getPath()
442                       +" doesn't exists.");
443         return;
444         }
445         basePackage.storeClasses(new File(destDir));
446     }
447     }
448
449     public void run() {
450     if (analyzer == null)
451         analyzer = new SimpleAnalyzer();
452     if (preTrafos == null)
453         preTrafos = new CodeTransformer[0];
454     if (postTrafos == null)
455         postTrafos = new CodeTransformer[0];
456     if (renamer == null)
457         renamer = new Renamer() {
458         public Iterator JavaDoc generateNames(Identifier ident) {
459             final String JavaDoc base = ident.getName();
460             return new Iterator JavaDoc() {
461             int last = 0;
462             
463             public boolean hasNext() {
464                 return true;
465             }
466             
467             public Object JavaDoc next() {
468                 return (last++ == 0 ? base : base + last);
469             }
470             
471             public void remove() {
472                 throw new UnsupportedOperationException JavaDoc();
473             }
474             };
475         }
476         };
477
478
479     Runtime JavaDoc runtime = Runtime.getRuntime();
480     long free = runtime.freeMemory();
481     long last;
482     do {
483         last = free;
484         runtime.gc();
485         runtime.runFinalization();
486         free = runtime.freeMemory();
487     } while (free < last);
488     System.err.println("used before: "+(runtime.totalMemory()- free));
489
490     GlobalOptions.err.println("Loading and preserving classes");
491
492     long time = System.currentTimeMillis();
493     basePackage.loadMatchingClasses(loading);
494     basePackage.applyPreserveRule(preserving);
495     System.err.println("Time used: "+(System.currentTimeMillis() - time));
496
497
498     GlobalOptions.err.println("Computing reachability");
499     time = System.currentTimeMillis();
500     analyze();
501     System.err.println("Time used: "+(System.currentTimeMillis() - time));
502
503     free = runtime.freeMemory();
504     do {
505         last = free;
506         runtime.gc();
507         runtime.runFinalization();
508         free = runtime.freeMemory();
509     } while (free < last);
510     System.err.println("used after analyze: "
511                + (runtime.totalMemory() - free));
512
513     GlobalOptions.err.println("Renaming methods");
514     time = System.currentTimeMillis();
515     if (inTableFile != null)
516             readTable();
517     buildTable(renamer);
518         if (outTableFile != null)
519             writeTable();
520         if (outRevTableFile != null)
521             writeRevTable();
522     System.err.println("Time used: "+(System.currentTimeMillis() - time));
523
524     GlobalOptions.err.println("Transforming the classes");
525     time = System.currentTimeMillis();
526     doTransformations();
527     System.err.println("Time used: "+(System.currentTimeMillis() - time));
528
529     free = runtime.freeMemory();
530     do {
531         last = free;
532         runtime.gc();
533         runtime.runFinalization();
534         free = runtime.freeMemory();
535     } while (free < last);
536     System.err.println("used after transform: "
537                + (runtime.totalMemory() - free));
538
539     GlobalOptions.err.println("Writing new classes");
540     time = System.currentTimeMillis();
541         storeClasses();
542     System.err.println("Time used: "+(System.currentTimeMillis() - time));
543     }
544 }
545
Popular Tags