KickJava   Java API By Example, From Geeks To Geeks.

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


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 import java.util.zip.*;
31 import java.util.jar.*;
32 import java.security.*;
33 import java.lang.reflect.Modifier JavaDoc;
34
35 import com.yworks.yguard.*;
36 import com.yworks.yguard.obf.classfile.*;
37 import java.util.AbstractMap JavaDoc;
38 import java.util.jar.Attributes JavaDoc;
39 import java.util.jar.Manifest JavaDoc;
40
41 /**
42  * Classfile database for obfuscation.
43  *
44  * @author Mark Welsh
45  */

46 public class GuardDB implements ClassConstants
47 {
48   // Constants -------------------------------------------------------------
49
private static final String JavaDoc STREAM_NAME_MANIFEST = "META-INF/MANIFEST.MF";
50   private static final String JavaDoc MANIFEST_NAME_TAG = "Name";
51   private static final String JavaDoc MANIFEST_DIGESTALG_TAG = "Digest-Algorithms";
52   private static final String JavaDoc CLASS_EXT = ".class";
53   private static final String JavaDoc SIGNATURE_PREFIX = "META-INF/";
54   private static final String JavaDoc SIGNATURE_EXT = ".SF";
55   private static final String JavaDoc LOG_MEMORY_USED = " Memory in use after class data structure built: ";
56   private static final String JavaDoc LOG_MEMORY_TOTAL = " Total memory available : ";
57   private static final String JavaDoc LOG_MEMORY_BYTES = " bytes";
58   private static final String JavaDoc WARNING_SCRIPT_ENTRY_ABSENT = "<!-- WARNING - identifier from script file not found in JAR: ";
59   private static final String JavaDoc ERROR_CORRUPT_CLASS = "<!-- ERROR - corrupt class file: ";
60
61
62   // Fields ----------------------------------------------------------------
63
private JarFile[] inJar; // JAR file for obfuscation
64
private Manifest JavaDoc[] oldManifest; // MANIFEST.MF
65
private Manifest JavaDoc[] newManifest; // MANIFEST.MF
66
private ClassTree classTree; // Tree of packages, classes. methods, fields
67
private boolean hasMap = false;
68
69   /** Utility field holding list of Listeners. */
70   private transient java.util.ArrayList JavaDoc listenerList;
71
72   /** Holds value of property replaceClassNameStrings. */
73   private boolean replaceClassNameStrings;
74
75   /** Holds value of property pedantic. */
76   private boolean pedantic;
77
78   private ResourceHandler resourceHandler;
79   private String JavaDoc[] digestStrings;
80
81   // Has the mapping been generated already?
82

83   // Class Methods ---------------------------------------------------------
84

85   // Instance Methods ------------------------------------------------------
86
/** A classfile database for obfuscation. */
87   public GuardDB(File[] inFile) throws java.io.IOException JavaDoc
88   {
89     inJar = new JarFile[inFile.length];
90     for(int i = 0; i < inFile.length; i++)
91       inJar[i] = new JarFile(inFile[i]);
92   }
93
94   /** Close input JAR file and log-file at GC-time. */
95   protected void finalize() throws java.io.IOException JavaDoc
96   {
97     close();
98   }
99
100   public void setResourceHandler(ResourceHandler handler)
101   {
102     resourceHandler = handler;
103   }
104
105   public String JavaDoc getOutName(String JavaDoc inName)
106   {
107     return classTree.getOutName(inName);
108   }
109
110   /**
111    * Go through database marking certain entities for retention, while
112    * maintaining polymorphic integrity.
113    */

114   public void retain(Collection rgsEntries, PrintWriter log)throws java.io.IOException JavaDoc
115   {
116
117     // Build database if not already done, or if a mapping has already been generated
118
if (classTree == null || hasMap)
119     {
120       hasMap = false;
121       buildClassTree(log);
122     }
123
124
125     // Enumerate the entries in the RGS script
126
for (Iterator it = rgsEntries.iterator(); it.hasNext();)
127     {
128       YGuardRule entry = (YGuardRule)it.next();
129       try
130       {
131         switch (entry.type)
132         {
133           case YGuardRule.TYPE_LINE_NUMBER_MAPPER:
134             classTree.retainLineNumberTable(entry.name, entry.lineNumberTableMapper);
135             break;
136           case YGuardRule.TYPE_SOURCE_ATTRIBUTE_MAP:
137             classTree.retainSourceFileAttributeMap(entry.name, entry.obfName);
138             break;
139           case YGuardRule.TYPE_ATTR:
140             classTree.retainAttribute(entry.name);
141             break;
142           case YGuardRule.TYPE_ATTR2:
143             classTree.retainAttributeForClass(entry.descriptor, entry.name);
144             break;
145           case YGuardRule.TYPE_CLASS:
146             classTree.retainClass(entry.name, entry.retainClasses, entry.retainMethods, entry.retainFields, true);
147             break;
148           case YGuardRule.TYPE_METHOD:
149             classTree.retainMethod(entry.name, entry.descriptor);
150             break;
151           case YGuardRule.TYPE_PACKAGE:
152             classTree.retainPackage(entry.name);
153             break;
154           case YGuardRule.TYPE_FIELD:
155             classTree.retainField(entry.name);
156             break;
157           case YGuardRule.TYPE_PACKAGE_MAP:
158             classTree.retainPackageMap(entry.name, entry.obfName);
159             break;
160           case YGuardRule.TYPE_CLASS_MAP:
161             classTree.retainClassMap(entry.name, entry.obfName);
162             break;
163           case YGuardRule.TYPE_METHOD_MAP:
164             classTree.retainMethodMap(entry.name, entry.descriptor,
165             entry.obfName);
166             break;
167           case YGuardRule.TYPE_FIELD_MAP:
168             classTree.retainFieldMap(entry.name, entry.obfName);
169             break;
170           default:
171             throw new ParseException("Illegal type: " + entry.type);
172         }
173       }
174       catch (RuntimeException JavaDoc e)
175       {
176         // DEBUG
177
// e.printStackTrace();
178
log.println(WARNING_SCRIPT_ENTRY_ABSENT + entry.name + " -->");
179       }
180     }
181   }
182
183   /** Remap each class based on the remap database, and remove attributes. */
184   public void remapTo(File[] out,
185     Filter fileFilter,
186     PrintWriter log,
187     boolean conserveManifest
188     ) throws java.io.IOException JavaDoc, ClassNotFoundException JavaDoc
189   {
190     // Build database if not already done
191
if (classTree == null)
192     {
193       buildClassTree(log);
194     }
195
196     // Generate map table if not already done
197
if (!hasMap)
198     {
199       createMap(log);
200     }
201
202     oldManifest = new Manifest JavaDoc[out.length];
203     newManifest = new Manifest JavaDoc[out.length];
204     parseManifest();
205
206     StringBuffer JavaDoc replaceNameLog = new StringBuffer JavaDoc();
207     StringBuffer JavaDoc replaceContentsLog = new StringBuffer JavaDoc();
208
209     JarOutputStream outJar = null;
210     // Open the entry and prepare to process it
211
DataInputStream inStream = null;
212     OutputStream os = null;
213     for(int i = 0; i < inJar.length; i++)
214     {
215       os = null;
216       outJar = null;
217       //store the whole jar in memory, I known this might be alot, but anyway
218
//this is the best option, if you want to create correct jar files...
219
List jarEntries = new ArrayList();
220       try
221       {
222         // Go through the input Jar, removing attributes and remapping the Constant Pool
223
// for each class file. Other files are copied through unchanged, except for manifest
224
// and any signature files - these are deleted and the manifest is regenerated.
225
Enumeration entries = inJar[i].entries();
226         fireObfuscatingJar(inJar[i].getName(), out[i].getName());
227         ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
228         while (entries.hasMoreElements())
229         {
230           // Get the next entry from the input Jar
231
JarEntry inEntry = (JarEntry)entries.nextElement();
232
233           // Ignore directories
234
if (inEntry.isDirectory())
235           {
236             continue;
237           }
238
239           inStream = new DataInputStream(
240             new BufferedInputStream(
241             inJar[i].getInputStream(inEntry)));
242           String JavaDoc inName = inEntry.getName();
243           if (inName.endsWith(CLASS_EXT))
244           {
245             if (fileFilter == null || fileFilter.accepts(inName)){
246               // Write the obfuscated version of the class to the output Jar
247
ClassFile cf = ClassFile.create(inStream);
248               fireObfuscatingClass(Conversion.toJavaClass(cf.getName()));
249               cf.remap(classTree, replaceClassNameStrings, log);
250               JarEntry outEntry = new JarEntry(cf.getName() + CLASS_EXT);
251
252               DataOutputStream classOutputStream;
253               MessageDigest[] digests;
254               if (digestStrings == null){
255                 digestStrings = new String JavaDoc[]{"SHA-1", "MD5"};
256               }
257               digests = new MessageDigest[digestStrings.length];
258               OutputStream stream = baos;
259               // Create an OutputStream piped through a number of digest generators for the manifest
260

261               for (int j = 0; j < digestStrings.length; j++) {
262                 String JavaDoc digestString = digestStrings[j];
263                 MessageDigest digest = MessageDigest.getInstance(digestString);
264                 digests[j] = digest;
265                 stream = new DigestOutputStream(stream, digest);
266               }
267               classOutputStream = new DataOutputStream(stream);
268
269               // Dump the classfile, while creating the digests
270
cf.write(classOutputStream);
271               classOutputStream.flush();
272               jarEntries.add(new Object JavaDoc[]{outEntry, baos.toByteArray()});
273               baos.reset();
274               // Now update the manifest entry for the class with new name and new digests
275
updateManifest(i, inName, cf.getName() + CLASS_EXT, digests);
276             }
277           }
278           else if (STREAM_NAME_MANIFEST.equals(inName.toUpperCase()) ||
279             (inName.length() > (SIGNATURE_PREFIX.length() + 1 + SIGNATURE_EXT.length()) &&
280             inName.indexOf(SIGNATURE_PREFIX) != -1 &&
281             inName.substring(inName.length() - SIGNATURE_EXT.length(), inName.length()).equals(SIGNATURE_EXT)))
282           {
283             // Don't pass through the manifest or signature files
284
continue;
285           }
286           else
287           {
288             // Copy the non-class entry through unchanged
289
long size = inEntry.getSize();
290             if (size != -1)
291             {
292
293               // Create an OutputStream piped through a number of digest generators for the manifest
294
MessageDigest shaDigest = MessageDigest.getInstance("SHA");
295               MessageDigest md5Digest = MessageDigest.getInstance("MD5");
296               DataOutputStream dataOutputStream =
297               new DataOutputStream(new DigestOutputStream(new DigestOutputStream(baos,
298               shaDigest),
299               md5Digest));
300
301               String JavaDoc outName;
302
303               StringBuffer JavaDoc outNameBuffer = new StringBuffer JavaDoc(80);
304
305               if(resourceHandler != null && resourceHandler.filterName(inName, outNameBuffer))
306               {
307                 outName = outNameBuffer.toString();
308                 if(!outName.equals(inName))
309                 {
310                   replaceNameLog.append(" <resource name=\"");
311                   replaceNameLog.append(ClassTree.toUtf8XmlString(inName));
312                   replaceNameLog.append("\" map=\"");
313                   replaceNameLog.append(ClassTree.toUtf8XmlString(outName));
314                   replaceNameLog.append("\"/>\n");
315                 }
316               }
317               else
318               {
319                 outName = classTree.getOutName(inName);
320               }
321
322               if(resourceHandler == null || !resourceHandler.filterContent(inStream, dataOutputStream, inName))
323               {
324                 byte[] bytes = new byte[(int)size];
325                 inStream.readFully(bytes);
326
327                 // outName = classTree.getOutName(inName);
328
// Dump the data, while creating the digests
329
dataOutputStream.write(bytes, 0, bytes.length);
330               }
331               else
332               {
333                 replaceContentsLog.append(" <resource name=\"");
334                 replaceContentsLog.append(ClassTree.toUtf8XmlString(inName));
335                 replaceContentsLog.append("\"/>\n");
336               }
337
338               dataOutputStream.flush();
339               JarEntry outEntry = new JarEntry(outName);
340
341
342               jarEntries.add(new Object JavaDoc[]{outEntry, baos.toByteArray()});
343               baos.reset();
344               // Now update the manifest entry for the entry with new name and new digests
345
MessageDigest[] digests =
346               {shaDigest, md5Digest};
347               updateManifest(i , inName, outName, digests);
348             }
349           }
350         }
351
352         os = new FileOutputStream(out[i]);
353         if (conserveManifest){
354           outJar = new JarOutputStream(new BufferedOutputStream(os),oldManifest[i]);
355         } else {
356           outJar = new JarOutputStream(new BufferedOutputStream(os),newManifest[i]);
357         }
358         outJar.setComment( Version.getJarComment());
359
360         // sort the entries in ascending order
361
Collections.sort(jarEntries, new Comparator(){
362           public int compare(Object JavaDoc a, Object JavaDoc b){
363                 Object JavaDoc[] array1 = (Object JavaDoc[]) a;
364                 JarEntry entry1 = (JarEntry) array1[0];
365                 Object JavaDoc[] array2 = (Object JavaDoc[]) b;
366                 JarEntry entry2 = (JarEntry) array2[0];
367                 return entry1.getName().compareTo(entry2.getName());
368           }
369         });
370         // Finally, write the big bunch of data
371
Set directoriesWritten = new HashSet();
372         for (int j = 0; j < jarEntries.size(); j++){
373           Object JavaDoc[] array = (Object JavaDoc[]) jarEntries.get(j);
374           JarEntry entry = (JarEntry) array[0];
375           String JavaDoc name = entry.getName();
376           // make sure the directory entries are written to the jar file
377
if (!entry.isDirectory()){
378                 int index = 0;
379                 while ((index = name.indexOf("/", index + 1))>= 0){
380                   String JavaDoc directory = name.substring(0, index+1);
381                   if (!directoriesWritten.contains(directory)){
382                         directoriesWritten.add(directory);
383                         JarEntry directoryEntry = new JarEntry(directory);
384                         outJar.putNextEntry(directoryEntry);
385                         outJar.closeEntry();
386                   }
387                 }
388           }
389           // write the entry itself
390
byte[] bytes = (byte[]) array[1];
391           outJar.putNextEntry(entry);
392           outJar.write(bytes);
393           outJar.closeEntry();
394         }
395
396       }
397       catch (Exception JavaDoc e)
398       {
399         // Log exceptions before exiting
400
log.println();
401         log.println("<!-- An exception has occured.");
402         if (e instanceof java.util.zip.ZipException JavaDoc){
403           log.println("This is most likely due to a duplicate .class file in your jar!");
404           log.println("Please check that there are no out-of-date or backup duplicate .class files in your jar!");
405         }
406         log.println(e.toString());
407         e.printStackTrace(log);
408         log.println("-->");
409         throw new IOException("An error ('"+e.getMessage()+"') occured during the remapping! See the log!)");
410       }
411       finally
412       {
413         inJar[i].close();
414         if (inStream != null)
415         {
416           inStream.close();
417         }
418         if (outJar != null)
419         {
420           outJar.close();
421         }
422         if (os != null){
423           os.close();
424         }
425       }
426     }
427     // Write the mapping table to the log file
428
classTree.dump(log);
429     if(replaceContentsLog.length() > 0 || replaceNameLog.length() > 0)
430     {
431       log.println("<!--");
432       if(replaceNameLog.length() > 0)
433       {
434         log.println("\n<adjust replaceName=\"true\">");
435         log.print(replaceNameLog);
436         log.println("</adjust>");
437       }
438       if(replaceContentsLog.length() > 0)
439       {
440         log.println("\n<adjust replaceContents=\"true\">");
441         log.print(replaceContentsLog);
442         log.println("</adjust>");
443       }
444       log.println("-->");
445     }
446
447   }
448
449   /** Close input JAR file. */
450   public void close() throws java.io.IOException JavaDoc
451   {
452     for(int i = 0; i < inJar.length; i++)
453     {
454       if (inJar[i] != null)
455       {
456         inJar[i].close();
457         inJar[i] = null;
458       }
459     }
460   }
461
462   // Parse the RFC822-style MANIFEST.MF file
463
private void parseManifest()throws java.io.IOException JavaDoc
464   {
465     for(int i = 0; i < oldManifest.length; i++)
466     {
467       // The manifest file is the first in the jar and is called
468
// (case insensitively) 'MANIFEST.MF'
469
oldManifest[i] = inJar[i].getManifest();
470
471       if (oldManifest[i] == null){
472         oldManifest[i] = new Manifest JavaDoc();
473       }
474
475       // Create a fresh manifest, with a version header
476
newManifest[i] = new Manifest JavaDoc();
477
478       // copy all main attributes
479
for (Iterator it = oldManifest[i].getMainAttributes().entrySet().iterator(); it.hasNext();) {
480         Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
481         Attributes.Name JavaDoc name = (Attributes.Name JavaDoc) entry.getKey();
482         String JavaDoc value = (String JavaDoc) entry.getValue();
483         if (resourceHandler != null) {
484           name = new Attributes.Name JavaDoc(resourceHandler.filterString(name.toString(), "META-INF/MANIFEST.MF"));
485           value = resourceHandler.filterString(value, "META-INF/MANIFEST.MF");
486         }
487         newManifest[i].getMainAttributes().putValue(name.toString(), value);
488       }
489
490       newManifest[i].getMainAttributes().putValue("Created-by", "yGuard Bytecode Obfuscator " + Version.getVersion());
491
492       // copy all directory entries
493
for (Iterator it = oldManifest[i].getEntries().entrySet().iterator();
494             it.hasNext();){
495          Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
496          String JavaDoc name = (String JavaDoc) entry.getKey();
497          if (name.endsWith("/")){
498            newManifest[i].getEntries().put(name, (Attributes JavaDoc) entry.getValue());
499          }
500       }
501     }
502   }
503
504   // Update an entry in the manifest file
505
private void updateManifest(int manifestIndex, String JavaDoc inName, String JavaDoc outName, MessageDigest[] digests)
506   {
507     // Create fresh section for entry, and enter "Name" header
508

509     Manifest JavaDoc nm = newManifest[manifestIndex];
510     Manifest JavaDoc om = oldManifest[manifestIndex];
511
512     Attributes JavaDoc oldAtts = om.getAttributes(inName);
513     Attributes JavaDoc newAtts = new Attributes JavaDoc();
514     //newAtts.putValue(MANIFEST_NAME_TAG, outName);
515

516     // copy over non-name and none digest entries
517
if (oldAtts != null){
518       for(Iterator it = oldAtts.entrySet().iterator(); it.hasNext();){
519         Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
520         Object JavaDoc key = entry.getKey();
521         String JavaDoc name = key.toString();
522         if (!name.equalsIgnoreCase(MANIFEST_NAME_TAG) &&
523             name.indexOf("Digest") == -1){
524           newAtts.remove(name);
525           newAtts.putValue(name, (String JavaDoc)entry.getValue());
526         }
527       }
528     }
529
530     // Create fresh digest entries in the new section
531
if (digests != null && digests.length > 0)
532     {
533       // Digest-Algorithms header
534
StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
535       for (int i = 0; i < digests.length; i++)
536       {
537         sb.append(digests[i].getAlgorithm());
538         if (i < digests.length -1){
539           sb.append(", ");
540         }
541       }
542       newAtts.remove(MANIFEST_DIGESTALG_TAG);
543       newAtts.putValue(MANIFEST_DIGESTALG_TAG, sb.toString());
544
545       // *-Digest headers
546
for (int i = 0; i < digests.length; i++)
547       {
548         newAtts.remove(digests[i].getAlgorithm() + "-Digest");
549         newAtts.putValue(digests[i].getAlgorithm() + "-Digest", Tools.toBase64(digests[i].digest()));
550       }
551     }
552
553     if (!newAtts.isEmpty()) {
554       // Append the new section to the new manifest
555
nm.getEntries().put(outName, newAtts);
556     }
557   }
558
559   // Create a classfile database.
560
private void buildClassTree(PrintWriter log)throws java.io.IOException JavaDoc
561   {
562     // Go through the input Jar, adding each class file to the database
563
classTree = new ClassTree();
564     classTree.setPedantic(isPedantic());
565     classTree.setReplaceClassNameStrings(replaceClassNameStrings);
566     ClassFile.resetDangerHeader();
567     
568     Map JavaDoc parsedClasses = new HashMap();
569     for(int i = 0; i < inJar.length; i++)
570     {
571       Enumeration entries = inJar[i].entries();
572       fireParsingJar(inJar[i].getName());
573       while (entries.hasMoreElements())
574       {
575         // Get the next entry from the input Jar
576
ZipEntry inEntry = (ZipEntry)entries.nextElement();
577         String JavaDoc name = inEntry.getName();
578         if (name.endsWith(CLASS_EXT))
579         {
580           fireParsingClass(Conversion.toJavaClass(name));
581           // Create a full internal representation of the class file
582
DataInputStream inStream = new DataInputStream(
583           new BufferedInputStream(
584           inJar[i].getInputStream(inEntry)));
585           ClassFile cf = null;
586           try
587           {
588             cf = ClassFile.create(inStream);
589           }
590           catch (Exception JavaDoc e)
591           {
592             log.println(ERROR_CORRUPT_CLASS + createJarName(inJar[i], name) + " -->");
593             e.printStackTrace(log);
594             throw new ParseException( e );
595           }
596           finally
597           {
598             inStream.close();
599           }
600
601           if (cf != null){
602             Object JavaDoc[] old = (Object JavaDoc[]) parsedClasses.get(cf.getName());
603             if (old != null){
604               int jarIndex = ((Integer JavaDoc)old[0]).intValue();
605               String JavaDoc warning = "yGuard detected a duplicate class definition " +
606                 "for \n " + Conversion.toJavaClass(cf.getName()) +
607               "\n [" + createJarName(inJar[jarIndex], old[1].toString()) + "] in \n [" +
608                 createJarName(inJar[i], name) + "]";
609               log.write("<!-- \n" + warning + "\n-->\n");
610               if (jarIndex == i){
611                 throw new IOException(warning + "\nPlease remove inappropriate duplicates first!");
612               } else {
613                 if (pedantic){
614                   throw new IOException(warning + "\nMake sure these files are of the same version!");
615                 }
616               }
617             } else {
618               parsedClasses.put(cf.getName(), new Object JavaDoc[]{new Integer JavaDoc(i), name});
619             }
620
621             // Check the classfile for references to 'dangerous' methods
622
cf.logDangerousMethods(log, replaceClassNameStrings);
623             classTree.addClassFile(cf);
624           }
625
626         }
627       }
628     }
629
630     // set the java access modifiers from the containing class (muellese)
631
final ClassTree ct = classTree;
632     ct.walkTree(new TreeAction()
633     {
634       public void classAction(Cl cl)
635       {
636         if (cl.isInnerClass())
637         {
638           Cl parent = (Cl) cl.getParent();
639           cl.access = parent.getInnerClassModifier(cl.getInName());
640         }
641       }
642     });
643   }
644
645   private static String JavaDoc createJarName(JarFile jar, String JavaDoc name){
646     return "jar:"+jar.getName() + "|" + name;
647   }
648
649   // Generate a mapping table for obfuscation.
650
private void createMap(PrintWriter log) throws ClassNotFoundException JavaDoc
651   {
652     // Traverse the class tree, generating obfuscated names within
653
// package and class namespaces
654
classTree.generateNames();
655
656     // Resolve the polymorphic dependencies of each class, generating
657
// non-private method and field names for each namespace
658
classTree.resolveClasses();
659
660     // Signal that the namespace maps have been created
661
hasMap = true;
662
663     // Write the memory usage at this point to the log file
664
Runtime JavaDoc rt = Runtime.getRuntime();
665     rt.gc();
666     log.println("<!--");
667     log.println(LOG_MEMORY_USED + Long.toString(rt.totalMemory() - rt.freeMemory()) + LOG_MEMORY_BYTES);
668     log.println(LOG_MEMORY_TOTAL + Long.toString(rt.totalMemory()) + LOG_MEMORY_BYTES);
669     log.println("-->");
670
671   }
672
673   protected void fireParsingJar(String JavaDoc jar){
674     if (listenerList == null) return;
675     for (int i = 0, j = listenerList.size(); i < j; i++){
676       ((ObfuscationListener)listenerList.get(i)).parsingJar(jar);
677     }
678   }
679   protected void fireParsingClass(String JavaDoc className){
680     if (listenerList == null) return;
681     for (int i = 0, j = listenerList.size(); i < j; i++){
682       ((ObfuscationListener)listenerList.get(i)).parsingClass(className);
683     }
684   }
685   protected void fireObfuscatingJar(String JavaDoc inJar, String JavaDoc outJar){
686     if (listenerList == null) return;
687     for (int i = 0, j = listenerList.size(); i < j; i++){
688       ((ObfuscationListener)listenerList.get(i)).obfuscatingJar(inJar, outJar);
689     }
690   }
691   protected void fireObfuscatingClass(String JavaDoc className){
692     if (listenerList == null) return;
693     for (int i = 0, j = listenerList.size(); i < j; i++){
694       ((ObfuscationListener)listenerList.get(i)).obfuscatingClass(className);
695     }
696   }
697
698   /** Registers Listener to receive events.
699    * @param listener The listener to register.
700    */

701   public synchronized void addListener(com.yworks.yguard.ObfuscationListener listener)
702   {
703     if (listenerList == null )
704     {
705       listenerList = new java.util.ArrayList JavaDoc();
706     }
707     listenerList.add(listener);
708   }
709
710   /** Removes Listener from the list of listeners.
711    * @param listener The listener to remove.
712    */

713   public synchronized void removeListener(com.yworks.yguard.ObfuscationListener listener)
714   {
715     if (listenerList != null )
716     {
717       listenerList.remove(listener);
718     }
719   }
720
721   /** Getter for property replaceClassNameStrings.
722    * @return Value of property replaceClassNameStrings.
723    *
724    */

725   public boolean isReplaceClassNameStrings()
726   {
727     return this.replaceClassNameStrings;
728   }
729
730   /** Setter for property replaceClassNameStrings.
731    * @param replaceClassNameStrings New value of property replaceClassNameStrings.
732    *
733    */

734   public void setReplaceClassNameStrings(boolean replaceClassNameStrings)
735   {
736     this.replaceClassNameStrings = replaceClassNameStrings;
737   }
738
739
740   /** Getter for property pedantic.
741    * @return Value of property pedantic.
742    *
743    */

744   public boolean isPedantic()
745   {
746     return this.pedantic;
747   }
748
749   /** Setter for property pedantic.
750    * @param pedantic New value of property pedantic.
751    *
752    */

753   public void setPedantic(boolean pedantic)
754   {
755     this.pedantic = pedantic;
756     Cl.setPedantic(pedantic);
757   }
758
759
760   /**
761    * Returns the obfuscated file name of the java class.
762    * The ending ".class" is omitted.
763    * @param javaClass the fully qualified name of an unobfuscated class.
764    */

765   public String JavaDoc translateJavaFile(String JavaDoc javaClass)
766   {
767     Cl cl = classTree.findClassForName(javaClass.replace('/','.'));
768     if(cl != null)
769     {
770       return cl.getFullOutName();
771     }
772     else
773     {
774       return javaClass;
775     }
776   }
777
778
779   public String JavaDoc translateJavaClass(String JavaDoc javaClass)
780   {
781     Cl cl = classTree.findClassForName(javaClass);
782     if(cl != null)
783     {
784       return cl.getFullOutName().replace('/', '.');
785     }
786     else
787     {
788       return javaClass;
789     }
790   }
791
792   public void setDigests(String JavaDoc[] digestStrings) {
793     this.digestStrings = digestStrings;
794   }
795 }
796
Popular Tags