KickJava   Java API By Example, From Geeks To Geeks.

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


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 com.yworks.yguard.Conversion;
29 import com.yworks.yguard.ParseException;
30 import com.yworks.yguard.obf.classfile.ClassConstants;
31 import com.yworks.yguard.obf.classfile.ClassFile;
32 import com.yworks.yguard.obf.classfile.LineNumberTableAttrInfo;
33 import com.yworks.yguard.obf.classfile.Logger;
34 import com.yworks.yguard.obf.classfile.NameMapper;
35
36 import java.io.PrintWriter JavaDoc;
37 import java.lang.reflect.Modifier JavaDoc;
38 import java.util.ArrayList JavaDoc;
39 import java.util.Enumeration JavaDoc;
40 import java.util.HashSet JavaDoc;
41 import java.util.List JavaDoc;
42 import java.util.Set JavaDoc;
43 import java.util.StringTokenizer JavaDoc;
44 import java.util.Vector JavaDoc;
45
46 /**
47  * Tree structure of package levels, classes, methods and fields used for obfuscation.
48  *
49  * @author Mark Welsh
50  */

51 public class ClassTree implements NameMapper
52 {
53     // Constants -------------------------------------------------------------
54
public static final char PACKAGE_LEVEL = '/';
55     public static final char CLASS_LEVEL = '$';
56     public static final char METHOD_FIELD_LEVEL = '/';
57
58     // Fields ----------------------------------------------------------------
59
private Vector JavaDoc retainAttrs = new Vector JavaDoc(); // List of attributes to retain
60
private Pk root = null; // Root package in database (Java default package)
61

62     // Class methods ---------------------------------------------------------
63
/** Return a fully qualified name broken into package/class segments. */
64     public static Enumeration JavaDoc getNameEnum(String JavaDoc name)
65     {
66         Vector JavaDoc vec = new Vector JavaDoc();
67         String JavaDoc nameOrig = name;
68         while (!name.equals(""))
69         {
70             int posP = name.indexOf(PACKAGE_LEVEL);
71             int posC = name.indexOf(CLASS_LEVEL);
72             Cons cons = null;
73             if (posP == -1 && posC == -1)
74             {
75                 cons = new Cons(new Character JavaDoc(CLASS_LEVEL), name);
76                 name = "";
77             }
78             if (posP == -1 && posC != -1)
79             {
80                 cons = new Cons(new Character JavaDoc(CLASS_LEVEL), name.substring(0, posC));
81                 //fixes retroguard bug, where
82
// 'ClassName$$InnerClassName' leads to a runtimeerror
83
while ((posC+1 < name.length()) && (name.charAt(posC+1) == CLASS_LEVEL)) posC++;
84                 name = name.substring(posC + 1, name.length());
85             }
86             if (posP != -1 && posC == -1)
87             {
88                 cons = new Cons(new Character JavaDoc(PACKAGE_LEVEL), name.substring(0, posP));
89                 name = name.substring(posP + 1, name.length());
90             }
91             if (posP != -1 && posC != -1)
92             {
93                 if (posP < posC)
94                 {
95                     cons = new Cons(new Character JavaDoc(PACKAGE_LEVEL), name.substring(0, posP));
96                     name = name.substring(posP + 1, name.length());
97                 }
98                 else
99                 {
100                     throw new IllegalArgumentException JavaDoc("Invalid fully qualified name (a): " +
101                                           nameOrig);
102                 }
103             }
104             if (((String JavaDoc)cons.cdr).equals(""))
105             {
106                 throw new IllegalArgumentException JavaDoc("Invalid fully qualified name (b): " +
107                                       nameOrig);
108             }
109             vec.addElement(cons);
110         }
111         return vec.elements();
112     }
113
114
115     // Instance Methods ------------------------------------------------------
116
/** Ctor. */
117     public ClassTree()
118     {
119         root = Pk.createRoot(this);
120     }
121
122     /** Return the root node. */
123     public Pk getRoot() {return root;}
124     
125     /**
126      * finds tree items by looking for name components only...
127      */

128     public TreeItem findTreeItem(String JavaDoc[] nameParts){
129       TreeItem tmp = root;
130       for (int i = 0; tmp != null && i < nameParts.length; i++){
131         String JavaDoc name = nameParts[i];
132         tmp = findSubItem(tmp, name);
133       }
134       return tmp;
135     }
136
137     /**
138      * walks the tree of TreeItems in order to find a class forName
139      */

140     public Cl findClassForName(String JavaDoc name){
141       int dindex = name.indexOf('$');
142       String JavaDoc innerClass = null;
143       if (dindex>0){
144         innerClass = name.substring(dindex+1);
145         name = name.substring(0, dindex);
146       }
147       int pindex = name.lastIndexOf('.');
148       String JavaDoc packageName = null;
149       if (pindex>0){
150         packageName = name.substring(0, pindex);
151         name = name.substring(pindex+1);
152       }
153       Pk pk = root;
154       if (packageName != null){
155         for (StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(packageName, ".", false); st.hasMoreTokens();){
156           String JavaDoc token = st.nextToken();
157           pk = findPackage(pk, token);
158           if (pk == null) return null;
159         }
160       }
161       Cl cl = findClass(pk, name);
162       if (cl != null && innerClass != null){
163         for (StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(innerClass, "$", false); st.hasMoreTokens();){
164           String JavaDoc token = st.nextToken();
165           cl = findClass(cl, token);
166           if (cl == null) return null;
167         }
168       }
169       return cl;
170     }
171     
172     private Pk findPackage(TreeItem parent, String JavaDoc pName){
173       if (parent instanceof Pk){
174         for (Enumeration JavaDoc enumeration = ((Pk)parent).getPackageEnum(); enumeration.hasMoreElements();){
175           Pk subPk = (Pk) enumeration.nextElement();
176           if (subPk.getInName().equals(pName)){
177             return subPk;
178           }
179         }
180       }
181       return null;
182     }
183
184     private Cl findClass(PkCl parent, String JavaDoc pName){
185       for (Enumeration JavaDoc enumeration = ((PkCl)parent).getClassEnum(); enumeration.hasMoreElements();){
186         Cl cl = (Cl) enumeration.nextElement();
187         if (cl.getInName().equals(pName)){
188           return cl;
189         }
190       }
191       return null;
192     }
193     
194     private TreeItem findSubItem(TreeItem parent, String JavaDoc childName){
195       if (parent instanceof Pk){
196         for (Enumeration JavaDoc enumeration = ((Pk)parent).getPackageEnum(); enumeration.hasMoreElements();){
197           Pk subPk = (Pk) enumeration.nextElement();
198           if (subPk.getInName().equals(childName)){
199             return subPk;
200           }
201         }
202         for (Enumeration JavaDoc enumeration = ((Pk)parent).getClassEnum(); enumeration.hasMoreElements();){
203           Cl cl = (Cl) enumeration.nextElement();
204           if (cl.getInName().equals(childName)){
205             return cl;
206           }
207         }
208       }
209       if (parent instanceof Cl){
210         for (Enumeration JavaDoc enumeration = ((Cl)parent).getClassEnum(); enumeration.hasMoreElements();){
211           Cl cl = (Cl) enumeration.nextElement();
212           if (cl.getInName().equals(childName)){
213             return cl;
214           }
215         }
216         return null;
217       }
218       return null;
219     }
220
221     /** Update the path of the passed filename, if that path corresponds to a package. */
222     public String JavaDoc getOutName(String JavaDoc inName)
223     {
224         try
225         {
226             TreeItem ti = root;
227             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
228             for (Enumeration JavaDoc nameEnum = getNameEnum(inName); nameEnum.hasMoreElements(); )
229             {
230                 Cons nameSegment = (Cons)nameEnum.nextElement();
231                 char tag = ((Character JavaDoc)nameSegment.car).charValue();
232                 String JavaDoc name = (String JavaDoc)nameSegment.cdr;
233                 switch (tag)
234                 {
235                 case PACKAGE_LEVEL:
236                     if (ti != null)
237                     {
238                         ti = ((Pk)ti).getPackage(name);
239                         if (ti != null)
240                         {
241                             sb.append(ti.getOutName());
242                         }
243                         else
244                         {
245                             sb.append(name);
246                         }
247                     }
248                     else
249                     {
250                         sb.append(name);
251                     }
252                     sb.append(PACKAGE_LEVEL);
253                     break;
254                     
255                 case CLASS_LEVEL:
256                     sb.append(name);
257                     return sb.toString();
258                     
259                 default:
260                     throw new RuntimeException JavaDoc("Internal error: illegal package/class name tag");
261                 }
262             }
263         }
264         catch (Exception JavaDoc e)
265         {
266             // Just drop through and return the original name
267
}
268         return inName;
269     }
270
271     /** Add a classfile's package, class, method and field entries to database. */
272     public void addClassFile(ClassFile cf)
273     {
274         // Add the fully qualified class name
275
TreeItem ti = root;
276         char parentTag = PACKAGE_LEVEL;
277         for (Enumeration JavaDoc nameEnum = getNameEnum(cf.getName()); nameEnum.hasMoreElements(); )
278         {
279             Cons nameSegment = (Cons)nameEnum.nextElement();
280             char tag = ((Character JavaDoc)nameSegment.car).charValue();
281             String JavaDoc name = (String JavaDoc)nameSegment.cdr;
282             switch (tag)
283             {
284             case PACKAGE_LEVEL:
285                 ti = ((Pk)ti).addPackage(name);
286                 break;
287
288             case CLASS_LEVEL:
289                 // If this is an inner class, just add placeholder classes up the tree
290
if (nameEnum.hasMoreElements())
291                 {
292                     ti = ((PkCl)ti).addPlaceholderClass(name);
293                 }
294                 else
295                 {
296                   Cl cl =((PkCl)ti).addClass(name, cf.getSuper(), cf.getInterfaces(), cf.getModifiers());
297                   cl.setInnerClassModifiers(cf.getInnerClassModifiers());
298                   cl.setClassFileAccess(cf.getClassFileAccess());
299                   ti = cl;
300                 }
301                 break;
302
303             default:
304                 throw new ParseException("Internal error: illegal package/class name tag");
305             }
306             parentTag = tag;
307         }
308
309         // We must have a class before adding methods and fields
310
if (ti instanceof Cl)
311         {
312             Cl cl = (Cl)ti;
313             cl.access = cf.getModifiers();
314
315             // Add the class's methods to the database
316
for (Enumeration JavaDoc enumeration = cf.getMethodEnum(); enumeration.hasMoreElements(); )
317             {
318                 Cons cons = (Cons)enumeration.nextElement();
319                 cl.addMethod(((Boolean JavaDoc)((Cons)cons.car).car).booleanValue(), (String JavaDoc)((Cons)cons.car).cdr, (String JavaDoc)((Cons)cons.cdr).car, ((Integer JavaDoc)((Cons)cons.cdr).cdr).intValue());
320             }
321
322             // Add the class's fields to the database
323
for (Enumeration JavaDoc enumeration = cf.getFieldEnum(); enumeration.hasMoreElements(); )
324             {
325                 Cons cons = (Cons)enumeration.nextElement();
326                 cl.addField(((Boolean JavaDoc)((Cons)cons.car).car).booleanValue(), (String JavaDoc)((Cons)cons.car).cdr, (String JavaDoc)((Cons)cons.cdr).car, ((Integer JavaDoc)((Cons)cons.cdr).cdr).intValue());
327             }
328         }
329         else
330         {
331             throw new ParseException("Inconsistent class file.");
332         }
333     }
334
335     /** Mark an attribute type for retention. */
336     public void retainAttribute(String JavaDoc name)
337     {
338         retainAttrs.addElement(name);
339     }
340
341     private boolean modifierMatch(int level, int mods){
342         if (level == YGuardRule.LEVEL_NONE) return false;
343         if (Modifier.isPublic(mods)){
344             return (level & YGuardRule.PUBLIC) == YGuardRule.PUBLIC;
345         }
346         if (Modifier.isProtected(mods)){
347             return (level & YGuardRule.PROTECTED) == YGuardRule.PROTECTED;
348         }
349         if (Modifier.isPrivate(mods)){
350             return (level & YGuardRule.PRIVATE) == YGuardRule.PRIVATE;
351         }
352         // package friendly left only
353
return (level & YGuardRule.FRIENDLY) == YGuardRule.FRIENDLY;
354     }
355
356     /** Mark a class/interface type (and possibly methods and fields defined in class) for retention. */
357     public void retainClass(String JavaDoc name, int classLevel, int methodLevel, int fieldLevel, boolean retainHierarchy)
358     {
359
360         // Mark the class (or classes, if this is a wildcarded specifier)
361
for (Enumeration JavaDoc clEnum = getClEnum(name, classLevel); clEnum.hasMoreElements(); )
362         {
363             Cl classItem = (Cl)clEnum.nextElement();
364             if(retainHierarchy && classLevel != YGuardRule.LEVEL_NONE) retainHierarchy(classItem);
365             // Retain methods if requested
366
if (methodLevel != YGuardRule.LEVEL_NONE)
367             {
368                 for (Enumeration JavaDoc enumeration = classItem.getMethodEnum(); enumeration.hasMoreElements(); )
369                 {
370                     Md md = (Md)enumeration.nextElement();
371                     if (modifierMatch(methodLevel, md.getModifiers()))
372                     {
373                         md.setOutName(md.getInName());
374                         md.setFromScript();
375                     }
376                 }
377                 // do super classes and interfaces...
378
if ((methodLevel & (YGuardRule.PUBLIC | YGuardRule.PROTECTED | YGuardRule.FRIENDLY)) != 0
379                   ||(fieldLevel & (YGuardRule.PUBLIC | YGuardRule.PROTECTED | YGuardRule.FRIENDLY)) != 0){
380                   int mask = YGuardRule.PRIVATE;
381                   int ml = methodLevel & ~mask;
382                   int fl = fieldLevel & ~mask;
383                   int cl = classLevel & ~mask;
384                   String JavaDoc[] interfaces = classItem.getInterfaces();
385                   if (interfaces != null){
386                     for (int i = 0; i < interfaces.length; i++){
387                       String JavaDoc interfaceClass = interfaces[i];
388                       retainClass(interfaceClass, cl, ml, fl, false);
389                     }
390                   }
391                   String JavaDoc superClass = classItem.getSuperClass();
392                   if (superClass != null){
393                     // staying in package?!
394
if (!superClass.startsWith(classItem.getParent().getFullInName())){
395                       mask |= YGuardRule.FRIENDLY;
396                       ml = methodLevel & ~mask;
397                       fl = fieldLevel & ~mask;
398                       cl = classLevel & ~mask;
399                     }
400                     retainClass(superClass, cl, ml, fl, false);
401                   }
402                 }
403             }
404
405             // Retain fields if requested
406
if (fieldLevel != YGuardRule.LEVEL_NONE)
407             {
408                 for (Enumeration JavaDoc enumeration = classItem.getFieldEnum(); enumeration.hasMoreElements(); )
409                 {
410                     Fd fd = (Fd)enumeration.nextElement();
411                     if (modifierMatch(fieldLevel, fd.getModifiers()))
412                     {
413                         fd.setOutName(fd.getInName());
414                         fd.setFromScript();
415                     }
416                 }
417             }
418         }
419     }
420
421     /** Mark a method type for retention. */
422     public void retainMethod(String JavaDoc name, String JavaDoc descriptor)
423     {
424         for (Enumeration JavaDoc enumeration = getMdEnum(name, descriptor);
425              enumeration.hasMoreElements(); ) {
426             Md md = (Md)enumeration.nextElement();
427             md.setOutName(md.getInName());
428             md.setFromScript();
429         }
430     }
431
432     /** Mark a field type for retention. */
433     public void retainField(String JavaDoc name)
434     {
435         for (Enumeration JavaDoc enumeration = getFdEnum(name); enumeration.hasMoreElements(); ) {
436             Fd fd = (Fd)enumeration.nextElement();
437             fd.setOutName(fd.getInName());
438             fd.setFromScript();
439         }
440     }
441
442     /** Mark a package for retention, and specify its new name. */
443     public void retainPackageMap(String JavaDoc name, String JavaDoc obfName)
444     {
445         retainItemMap(getPk(name), obfName);
446     }
447
448     /** Mark a class/interface type for retention, and specify its new name. */
449     public void retainClassMap(String JavaDoc name, String JavaDoc obfName)
450     {
451         retainItemMap(getCl(name), obfName);
452     }
453
454     /** Mark a method type for retention, and specify its new name. */
455     public void retainMethodMap(String JavaDoc name, String JavaDoc descriptor,
456                                 String JavaDoc obfName)
457     {
458         retainItemMap(getMd(name, descriptor), obfName);
459     }
460
461     /** Mark a field type for retention, and specify its new name. */
462     public void retainFieldMap(String JavaDoc name, String JavaDoc obfName)
463     {
464         retainItemMap(getFd(name), obfName);
465     }
466
467     // Mark an item for retention, and specify its new name.
468
private void retainItemMap(TreeItem item, String JavaDoc obfName)
469     {
470         if (!item.isFixed())
471         {
472             item.setOutName(obfName);
473             item.setFromScriptMap();
474         } else {
475           if (!item.getOutName().equals(obfName)){
476             item.setOutName(obfName);
477             item.setFromScriptMap();
478             // do warning
479
Logger.getInstance().warning("'" + item.getFullInName() + "' will be remapped to '" + obfName + "' according to mapping rule!");
480           }
481         }
482 // if (!item.isFixed())
483
// {
484
// item.setFromScriptMap();
485
// }
486
// item.setOutName(obfName);
487
}
488
489     /** Traverse the class tree, generating obfuscated names within each namespace. */
490     public void generateNames()
491     {
492         walkTree(new TreeAction() {
493             public void packageAction(Pk pk) {pk.generateNames();}
494             public void classAction(Cl cl) {cl.generateNames();}
495         });
496     }
497
498     /** Resolve the polymorphic dependencies of each class. */
499     public void resolveClasses() throws ClassNotFoundException JavaDoc
500     {
501         walkTree(new TreeAction() {
502             public void classAction(Cl cl) {cl.resetResolve();}
503         });
504         walkTree(new TreeAction() {
505             public void classAction(Cl cl) {cl.setupNameListDowns();}
506         });
507         Cl.nameSpace = 0;
508         final ClassNotFoundException JavaDoc[] ex = new ClassNotFoundException JavaDoc[1];
509         try{
510           walkTree(new TreeAction() {
511               public void classAction(Cl cl) {
512                 try{
513                   cl.resolveOptimally();
514                 } catch (ClassNotFoundException JavaDoc cnfe){
515                   ex[0] = cnfe;
516                   throw new RuntimeException JavaDoc();
517                 }
518               }
519           });
520         } catch (RuntimeException JavaDoc rte){
521           if (ex[0] != null){
522             throw ex[0];
523           } else {
524             throw rte;
525           }
526         }
527     }
528
529     /** Return a list of attributes marked to keep. */
530     public String JavaDoc[] getAttrsToKeep()
531     {
532         String JavaDoc[] attrs = new String JavaDoc[retainAttrs.size()];
533         for (int i = 0; i < attrs.length; i++)
534         {
535             attrs[i] = (String JavaDoc)retainAttrs.elementAt(i);
536         }
537         return attrs;
538     }
539
540     /** Get classes in tree from the fully qualified name
541         (can be wildcarded). */

542     public Enumeration JavaDoc getClEnum(String JavaDoc fullName)
543     {
544        return getClEnum(fullName, YGuardRule.LEVEL_PRIVATE);
545     }
546
547     /** Get classes in tree from the fully qualified name
548         (can be wildcarded). */

549     public Enumeration JavaDoc getClEnum(String JavaDoc fullName, final int classMode)
550     {
551         final Vector JavaDoc vec = new Vector JavaDoc();
552
553         // Wildcarded?
554
// Then return list of all classes (including inner classes) in package
555
if (fullName.indexOf('*') != -1) {
556             // Recursive?
557
if (fullName.indexOf('!') == 0) {
558                 final String JavaDoc fName = fullName.substring(1);
559                 walkTree(new TreeAction() {
560                     public void classAction(Cl cl) {
561                         if (cl.isWildcardMatch(fName) && modifierMatch(classMode, cl.getModifiers())) {
562                             vec.addElement(cl);
563                         }
564                     }
565                 });
566             }
567             else
568             {
569                 // non-recursive
570
final String JavaDoc fName = fullName;
571                 walkTree(new TreeAction() {
572                     public void classAction(Cl cl) {
573                         if (cl.isNRWildcardMatch(fName) && modifierMatch(classMode, cl.getModifiers())) {
574                             vec.addElement(cl);
575                         }
576                     }
577                 });
578             }
579         }
580         else
581         {
582             // Single class
583
Cl cl = getCl(fullName);
584             if (cl != null )
585             {
586               int mods = cl.getModifiers();
587               if (cl.isInnerClass()){
588                 Cl outer = (Cl) cl.getParent();
589               }
590               boolean match = modifierMatch(classMode, cl.getModifiers());
591               if (match || classMode == YGuardRule.LEVEL_NONE ){ //(RW)
592
vec.addElement(cl);
593               }
594             }
595         }
596         return vec.elements();
597     }
598
599     /** Get methods in tree from the fully qualified, and possibly
600         wildcarded, name. */

601     public Enumeration JavaDoc getMdEnum(String JavaDoc fullName,
602                                  String JavaDoc descriptor)
603     {
604         final Vector JavaDoc vec = new Vector JavaDoc();
605         final String JavaDoc fDesc = descriptor;
606         if (fullName.indexOf('*') != -1 ||
607             descriptor.indexOf('*') != -1) {
608             // Recursive?
609
if (fullName.indexOf('!') == 0) {
610                 final String JavaDoc fName = fullName.substring(1);
611                 // recursive wildcarding
612
walkTree(new TreeAction() {
613                     public void methodAction(Md md) {
614                         if (md.isWildcardMatch(fName, fDesc)) {
615                             vec.addElement(md);
616                         }
617                     }
618                 });
619             }
620             else
621             {
622                 final String JavaDoc fName = fullName;
623                 // non-recursive wildcarding
624
walkTree(new TreeAction() {
625                     public void methodAction(Md md) {
626                         if (md.isNRWildcardMatch(fName, fDesc)) {
627                             vec.addElement(md);
628                         }
629                     }
630                 });
631             }
632         } else {
633             Md md = getMd(fullName, descriptor);
634             if (md != null) {
635                 vec.addElement(md);
636             }
637         }
638         return vec.elements();
639     }
640
641     /** Get fields in tree from the fully qualified, and possibly
642         wildcarded, name. */

643     public Enumeration JavaDoc getFdEnum(String JavaDoc fullName)
644     {
645         final Vector JavaDoc vec = new Vector JavaDoc();
646         if (fullName.indexOf('*') != -1) {
647             // Recursive?
648
if (fullName.indexOf('!') == 0) {
649                 // recursive wildcarding
650
final String JavaDoc fName = fullName.substring(1);
651                 walkTree(new TreeAction() {
652                     public void fieldAction(Fd fd) {
653                         if (fd.isWildcardMatch(fName)) {
654                             vec.addElement(fd);
655                         }
656                     }
657                 });
658             }
659             else
660             {
661                 // non-recursive wildcarding
662
final String JavaDoc fName = fullName;
663                 walkTree(new TreeAction() {
664                     public void fieldAction(Fd fd) {
665                         if (fd.isNRWildcardMatch(fName)) {
666                             vec.addElement(fd);
667                         }
668                     }
669                 });
670             }
671         } else {
672             Fd fd = getFd(fullName);
673             if (fd != null) {
674                 vec.addElement(fd);
675             }
676         }
677         return vec.elements();
678     }
679
680     /** Get class in tree from the fully qualified name, returning null if name not found. */
681     public Cl getCl(String JavaDoc fullName)
682     {
683         TreeItem ti = root;
684         for (Enumeration JavaDoc nameEnum = getNameEnum(fullName); nameEnum.hasMoreElements(); )
685         {
686             Cons nameSegment = (Cons)nameEnum.nextElement();
687             char tag = ((Character JavaDoc)nameSegment.car).charValue();
688             String JavaDoc name = (String JavaDoc)nameSegment.cdr;
689             switch (tag)
690             {
691             case PACKAGE_LEVEL:
692                 ti = ((Pk)ti).getPackage(name);
693                 break;
694
695             case CLASS_LEVEL:
696                 ti = ((PkCl)ti).getClass(name);
697                 break;
698
699             default:
700                 throw new ParseException("Internal error: illegal package/class name tag");
701             }
702
703             // If the name is not in the database, return null
704
if (ti == null)
705             {
706                 return null;
707             }
708         }
709
710         // It is an error if we do not end up with a class or interface
711
if (!(ti instanceof Cl))
712         {
713             throw new ParseException("Inconsistent class or interface name.");
714         }
715         return (Cl)ti;
716     }
717
718     /** Get package in tree from the fully qualified name, returning null if name not found. */
719     public Pk getPk(String JavaDoc fullName)
720     {
721         TreeItem ti = root;
722         for (Enumeration JavaDoc nameEnum = getNameEnum(fullName); nameEnum.hasMoreElements(); )
723         {
724             Cons nameSegment = (Cons)nameEnum.nextElement();
725             String JavaDoc name = (String JavaDoc)nameSegment.cdr;
726             ti = ((Pk)ti).getPackage(name);
727
728             // If the name is not in the database, return null
729
if (ti == null)
730             {
731                 return null;
732             }
733             // It is an error if we do not end up with a package
734
if (!(ti instanceof Pk))
735             {
736                 throw new ParseException("Inconsistent package.");
737             }
738         }
739         return (Pk)ti;
740     }
741
742     /** Get method in tree from the fully qualified name. */
743     public Md getMd(String JavaDoc fullName, String JavaDoc descriptor)
744     {
745         // Split into class and method names
746
int pos = fullName.lastIndexOf(METHOD_FIELD_LEVEL);
747         Cl cl = getCl(fullName.substring(0, pos));
748         return cl.getMethod(fullName.substring(pos + 1), descriptor);
749     }
750
751     /** Get field in tree from the fully qualified name. */
752     public Fd getFd(String JavaDoc fullName)
753     {
754         // Split into class and field names
755
int pos = fullName.lastIndexOf(METHOD_FIELD_LEVEL);
756         Cl cl = getCl(fullName.substring(0, pos));
757         return cl.getField(fullName.substring(pos + 1));
758     }
759
760     public String JavaDoc[] getAttrsToKeep(String JavaDoc className) {
761       Cl cl = getCl(className);
762       if (cl != null){
763         Set JavaDoc attrs = cl.getAttributesToKeep();
764         if (attrs != null && attrs.size() > 0){
765           String JavaDoc[] other = getAttrsToKeep();
766           Set JavaDoc tmp = new HashSet JavaDoc(attrs);
767           for (int i = 0; i < other.length; i++) {
768             tmp.add(other[i]);
769           }
770           return (String JavaDoc[]) tmp.toArray(new String JavaDoc[tmp.size()]);
771         } else {
772           return getAttrsToKeep();
773         }
774       } else {
775         return getAttrsToKeep();
776       }
777     }
778
779     public String JavaDoc mapLocalVariable(String JavaDoc thisClassName, String JavaDoc methodName, String JavaDoc descriptor, String JavaDoc string) {
780       return string;
781     }
782
783     /** Mapping for fully qualified class name.
784      * @see NameMapper#mapClass */

785     public String JavaDoc mapClass(String JavaDoc className)
786     {
787 // System.out.println("map class " + className);
788
// Check for array -- requires special handling
789
if (className.length() > 0 && className.charAt(0) == '[') {
790             StringBuffer JavaDoc newName = new StringBuffer JavaDoc();
791             int i = 0;
792             while (i < className.length()) {
793                 char ch = className.charAt(i++);
794                 switch (ch) {
795                 case '[':
796                 case ';':
797                     newName.append(ch);
798                     break;
799
800                 case 'L':
801                     newName.append(ch);
802                     int pos = className.indexOf(';', i);
803                     if (pos < 0) {
804                         throw new ParseException("Invalid class name encountered: " + className);
805                     }
806                     newName.append(mapClass(className.substring(i, pos)));
807                     i = pos;
808                     break;
809
810                 default:
811                     return className;
812                 }
813             }
814             return newName.toString();
815         } else {
816             Cl cl = getCl(className);
817             if (cl == null){
818               try {
819                 Class JavaDoc aClass = Cl.getClassResolver().resolve(Conversion.toJavaClass(className));
820                 // ok class exists...
821
return className;
822               } catch (ClassNotFoundException JavaDoc e) {
823                 if (pedantic){
824                   throw new NoSuchMappingException("Class "+Conversion.toJavaClass(className));
825                 } else {
826                   Logger.getInstance().warningToLogfile("Unresolved external dependency: "+Conversion.toJavaClass(className)+
827                                      " not found!");
828                   Logger.getInstance().setUnresolved();
829                   return className;
830                 }
831               }
832             }
833             return cl.getFullOutName();
834         }
835     }
836
837     /** Mapping for method name, of fully qualified class.
838      * @see NameMapper#mapMethod */

839     public String JavaDoc mapMethod(String JavaDoc className, String JavaDoc methodName, String JavaDoc descriptor)
840     {
841       // check if the className is an array...
842
if (className.startsWith("[") && className.endsWith(";")){
843         int count = 0;
844         while (className.charAt(count) == '['){
845           count++;
846         }
847         if (className.charAt(count) == 'L'){
848           className = className.substring(count + 1, className.length() - 1);
849         }
850       }
851       Cl cl = getCl(className);
852       if (cl != null && cl.getMethod(methodName, descriptor) != null)
853       {
854         return cl.getMethod(methodName, descriptor).getOutName();
855       }
856       else
857       {
858         if (cl == null)
859         {
860           try {
861             Class JavaDoc aClass = Cl.getClassResolver().resolve(Conversion.toJavaClass(className));
862           } catch (ClassNotFoundException JavaDoc e) {
863             if (pedantic){
864               throw new NoSuchMappingException("Class "+Conversion.toJavaClass(className));
865             } else {
866               Logger.getInstance().warningToLogfile( "No mapping found: " + Conversion.toJavaClass( className ) );
867             }
868           }
869           // method is not in database use unobfuscated name...
870
return methodName;
871         }
872         else
873         {
874           try
875           {
876 // System.out.println("Try: "+cl.getFieldObfNameUp(fieldName));
877
String JavaDoc result = cl.getMethodOutNameUp(methodName,descriptor);
878             if (result != null)
879               return result;
880           }
881           catch (Exception JavaDoc ex)
882           {
883             System.out.println(ex);
884             //System.out.println("ME: Error: Try not succeeded");
885
}
886           if ((!methodName.equals("<init>") &&
887                (!methodName.equals("<clinit>")))){
888             if (pedantic){
889               throw new NoSuchMappingException("Method "+Conversion.toJavaClass(className)+"."+methodName);
890             } else {
891               Logger.getInstance().error("Method "+Conversion.toJavaClass(className)+"."+methodName+
892                                  " could not be mapped !\n Probably broken code! Try rebuilding from source!");
893               return methodName;
894             }
895           }
896           return methodName;
897         }
898       }
899     }
900
901     /** Mapping for annotation field/method name, of fully qualified class.
902      * @see NameMapper#mapAnnotationField */

903     public String JavaDoc mapAnnotationField(String JavaDoc className, String JavaDoc methodName)
904     {
905         Cl cl = getCl(className);
906         if (cl != null)
907         {
908           for (Enumeration JavaDoc enumeration = cl.getMethodEnum(); enumeration.hasMoreElements();){
909             Md md = (Md) enumeration.nextElement();
910             if (md.getInName().equals(methodName)){
911               return md.getOutName();
912             }
913           }
914           // actually this should not happen - is this an exception?!
915
return methodName;
916         }
917         else
918         {
919           // method is not in database use unobfuscated name...
920
return methodName;
921         }
922     }
923
924     /** Mapping for field name, of fully qualified class.
925      * @see NameMapper#mapField */

926     public String JavaDoc mapField(String JavaDoc className, String JavaDoc fieldName)
927     {
928 // System.out.println("Map "+className+"."+fieldName);
929
Cl cl = getCl(className);
930         if ((cl != null) && (cl.getField(fieldName) != null))
931         {
932           //special .class construct name mapping....
933
if (fieldName.startsWith("class$") && isReplaceClassNameStrings()){
934             String JavaDoc realClassName = fieldName.substring(6);
935             List JavaDoc nameParts = new ArrayList JavaDoc(20);
936             for (StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(realClassName, "$", false); st.hasMoreTokens();){
937               nameParts.add(st.nextToken());
938             }
939             String JavaDoc[] names = new String JavaDoc[nameParts.size()];
940             nameParts.toArray(names);
941             TreeItem ti = findTreeItem(names);
942             if (ti instanceof Cl){
943               Fd fd = cl.getField(fieldName);
944               String JavaDoc newClassName = mapClass(ti.getFullInName());
945               String JavaDoc outName = "class$"+newClassName.replace('/','$');
946               fd.setOutName(outName);
947               return outName;
948             }
949           }
950 // System.out.println("Standard Field Map");
951
return cl.getField(fieldName).getOutName();
952         }
953         else
954         {
955           if (cl == null)
956           {
957 // System.out.println("Error: "+className+
958
// " class not found !");
959
return fieldName;
960           }
961           else
962           {
963 // System.out.println("ERROR: "+className+"."+fieldName+
964
// " cannot be mapped !");
965
try
966             {
967 // System.out.println("Try: "+cl.getFieldObfNameUp(fieldName));
968
String JavaDoc result = cl.getFieldOutNameUp(fieldName);
969               if (result != null)
970                 return result;
971             }
972             catch (Exception JavaDoc ex)
973             {
974 // System.out.println("Try not succeeded");
975
}
976             if (!fieldName.equals("this")) {
977               if (pedantic){
978                 throw new NoSuchMappingException("Field "+className+"."+fieldName);
979               } else {
980                 Logger.getInstance().error("Field "+className+"."+fieldName+
981                    " could not be mapped !\n Probably broken code! Try rebuilding from source!");
982               }
983             }
984             return fieldName;
985           }
986         }
987         
988
989 // return cl != null && cl.getField(fieldName) != null ?
990
// cl.getField(fieldName).getOutName() :
991
// fieldName;
992
}
993     
994     /** Mapping for signatures (used for generics in 1.5).
995      * @see NameMapper#mapSignature
996      */

997     public String JavaDoc mapSignature(String JavaDoc signature){
998         // Pass everything through unchanged, except for the String between
999
// 'L' and ';' -- this is passed through mapClass(String)
1000

1001// System.out.println( "signature: "+signature );
1002

1003        StringBuffer JavaDoc classString = new StringBuffer JavaDoc();
1004
1005        StringBuffer JavaDoc newSignature = new StringBuffer JavaDoc();
1006        int i = 0;
1007        while (i < signature.length())
1008        {
1009            char ch = signature.charAt(i++);
1010            switch (ch)
1011            {
1012            case '[':
1013            case 'B':
1014            case 'C':
1015            case 'D':
1016            case 'F':
1017            case 'I':
1018            case 'J':
1019            case 'S':
1020            case 'Z':
1021            case 'V':
1022            case '(':
1023            case ')':
1024              case '+':
1025              case ':':
1026              case '-':
1027              case '*':
1028                newSignature.append(ch);
1029                break;
1030            case ';':
1031                newSignature.append(ch);
1032                classString.setLength( 0 );
1033              break;
1034            case 'T':
1035            { // Template name
1036
newSignature.append(ch);
1037                int pos = signature.indexOf(';', i);
1038                if (pos < 0)
1039                {
1040                    throw new ParseException("Invalid signature string encountered.");
1041                }
1042                newSignature.append(signature.substring(i, pos));
1043                i = pos;
1044                break;
1045            }
1046            case '<':
1047            {
1048              // formal parameters
1049
newSignature.append(ch);
1050              while (true){
1051                int first = i;
1052                while (signature.charAt(i) != ':'){
1053                  i++;
1054                }
1055                String JavaDoc templateName = signature.substring(first, i);
1056                newSignature.append(templateName);
1057
1058                while (signature.charAt(i) == ':'){
1059                  newSignature.append(':');
1060                  i++;
1061                  int firstPos = i;
1062                  int bracketCount = 0;
1063                  while (!(bracketCount == 0 && signature.charAt(i) == ';')){
1064                    if (signature.charAt(i) == '<') {
1065                      bracketCount++;
1066                    } else if (signature.charAt(i) == '>'){
1067                      bracketCount--;
1068                    }
1069                    i++;
1070                  }
1071                  i++;
1072                  newSignature.append(mapSignature(signature.substring(firstPos, i)));
1073                }
1074                if (signature.charAt(i) == '>'){
1075                  newSignature.append('>');
1076                  i++;
1077                  break;
1078                }
1079              }
1080                break;
1081            }
1082
1083              case '^':
1084              {
1085                newSignature.append(ch);
1086                if (signature.charAt(i) == 'T'){
1087                  // identifier
1088
while (signature.charAt(i) != ';'){
1089                    newSignature.append(signature.charAt(i));
1090                    i++;
1091                  }
1092                  continue;
1093                } else if (signature.charAt(i) == 'L'){
1094                  // class
1095
int first = i;
1096                  int bracketCount = 0;
1097                  while (signature.charAt(i) != ';' || bracketCount != 0){
1098                    char c = signature.charAt(i);
1099                    if (c == '<'){
1100                      bracketCount++;
1101                    } else if (c == '>'){
1102                      bracketCount--;
1103                    }
1104                    i++;
1105                  }
1106                  i++;
1107                  String JavaDoc classSig = signature.substring(first, i);
1108                  newSignature.append(mapSignature(classSig));
1109                } else {
1110                  throw new IllegalStateException JavaDoc("Could not map signature " + signature);
1111                }
1112              }
1113              break;
1114            case 'L':
1115            case '.': // inner class
1116
{
1117                newSignature.append(ch);
1118                int pos = signature.indexOf(';', i);
1119                int bracketPos = signature.indexOf('<', i);
1120                if (bracketPos >= i && bracketPos < pos){
1121                  // found a bracket - find the matching one..
1122
int bracketCount = 0;
1123                  int closingBracket = signature.length();
1124                  for (int walker = bracketPos + 1; walker < signature.length(); walker++){
1125                    char c = signature.charAt(walker);
1126                    if (c == '<'){
1127                      bracketCount++;
1128                    } else if (c == '>'){
1129                      if (bracketCount == 0){
1130                        closingBracket = walker;
1131                        break;
1132                      } else {
1133                        bracketCount--;
1134                      }
1135                    }
1136                  }
1137                  // TODO check!!!!
1138
pos = closingBracket + 1;
1139// pos = signature.indexOf(';', closingBracket);
1140
String JavaDoc templateArg = signature.substring(bracketPos + 1, closingBracket);
1141                  String JavaDoc classNamePart = signature.substring( i, bracketPos );
1142                  if (ch == '.'){ // inner class part - translate to class file name
1143
classString.append( '$' );
1144                    classString.append( classNamePart );
1145                    String JavaDoc className = classString.toString();
1146                    String JavaDoc result;
1147
1148                    // do basically the same that mapClass() does, but return the last part only.
1149
Cl cl = getCl(className);
1150                    if (cl == null){
1151                      try {
1152                        Class JavaDoc aClass = Cl.getClassResolver().resolve(Conversion.toJavaClass(className));
1153                        // ok class exists...
1154
result = classNamePart;
1155                      } catch (ClassNotFoundException JavaDoc e) {
1156                        if (pedantic){
1157                          throw new NoSuchMappingException("Class "+Conversion.toJavaClass(className));
1158                        } else {
1159                          Logger.getInstance().warningToLogfile("Unresolved external dependency: "+Conversion.toJavaClass(className)+
1160                                             " not found!");
1161                          Logger.getInstance().setUnresolved();
1162                          result = classNamePart;
1163                        }
1164                      }
1165                    } else {
1166                      result = cl.getOutName();
1167                    }
1168                    newSignature.append(result);
1169                  } else { // toplevel class 'L'
1170
classString.append( classNamePart );
1171                    newSignature.append(mapClass( classString.toString() ));
1172                  }
1173                  newSignature.append('<');
1174                  newSignature.append(mapSignature(templateArg));
1175                  newSignature.append('>');
1176                  i = pos;
1177                } else {
1178                  if (pos < 0)
1179                  {
1180                      throw new ParseException("Invalid signature string encountered: " + signature);
1181                  }
1182                  String JavaDoc classNamePart = signature.substring( i, pos );
1183                  if (ch == '.'){ // inner class part - translate to class file name
1184
classString.append( '$' );
1185                  }
1186                  classString.append( classNamePart );
1187                  newSignature.append(mapClass( classString.toString() ));
1188                  i = pos;
1189                }
1190                break;
1191            }
1192            default:
1193                throw new ParseException("Invalid signature string encountered: " +signature + " parsing char " + ch);
1194            }
1195        }
1196        return newSignature.toString();
1197    }
1198    
1199  public String JavaDoc mapSourceFile(String JavaDoc className, String JavaDoc sourceFileName){
1200    final Cl cl = getCl(className);
1201    if (cl.isSourceFileMappingSet()){
1202      return cl.getSourceFileMapping();
1203    } else {
1204      return sourceFileName;
1205    }
1206  }
1207
1208  public boolean mapLineNumberTable(String JavaDoc className, String JavaDoc methodName, String JavaDoc methodSignature, LineNumberTableAttrInfo info) {
1209    final Cl cl = getCl(className);
1210    if (cl.getLineNumberTableMapper() != null){
1211      return cl.getLineNumberTableMapper().mapLineNumberTable(className, methodName, methodSignature, info);
1212    } else {
1213      return true;
1214    }
1215  }
1216
1217  /** Mapping for descriptor of field or method.
1218     * @see NameMapper#mapDescriptor */

1219    public String JavaDoc mapDescriptor(String JavaDoc descriptor)
1220    {
1221        // Pass everything through unchanged, except for the String between
1222
// 'L' and ';' -- this is passed through mapClass(String)
1223
StringBuffer JavaDoc newDesc = new StringBuffer JavaDoc();
1224        int i = 0;
1225        while (i < descriptor.length())
1226        {
1227            char ch = descriptor.charAt(i++);
1228            switch (ch)
1229            {
1230            case '[':
1231            case 'B':
1232            case 'C':
1233            case 'D':
1234            case 'F':
1235            case 'I':
1236            case 'J':
1237            case 'S':
1238            case 'Z':
1239            case 'V':
1240            case '(':
1241            case ')':
1242            case ';':
1243                newDesc.append(ch);
1244                break;
1245
1246            case 'L':
1247                newDesc.append(ch);
1248                int pos = descriptor.indexOf(';', i);
1249                if (pos < 0)
1250                {
1251                    throw new ParseException("Invalid descriptor string encountered.");
1252                }
1253                newDesc.append(mapClass(descriptor.substring(i, pos)));
1254                i = pos;
1255                break;
1256
1257            default:
1258                throw new ParseException("Invalid descriptor string encountered.");
1259            }
1260        }
1261        return newDesc.toString();
1262    }
1263
1264    /** Dump the content of the class tree to the specified file (used for logging). */
1265    public void dump(final PrintWriter JavaDoc log)
1266    {
1267        log.println("<expose>");
1268        walkTree(new TreeAction() {
1269            public void classAction(Cl cl) {
1270                if (cl.isFromScript()) {
1271                    String JavaDoc cla = toUtf8XmlString(Conversion.toJavaClass(cl.getFullInName()));
1272                    log.println(" <class name=\"" + cla + "\"/>");
1273                }
1274            }
1275            public void methodAction(Md md) {
1276                if (md.isFromScript()) {
1277                    String JavaDoc cla = toUtf8XmlString(Conversion.toJavaClass(md.getParent().getFullInName()));
1278                    String JavaDoc method = toUtf8XmlString(Conversion.toJavaMethod(md.getInName(), md.getDescriptor()));
1279                    log.println(" <method class=\""+cla+"\" name=\"" + method + "\"/>");
1280                }
1281            }
1282            public void fieldAction(Fd fd) {
1283                if (fd.isFromScript()) {
1284                    String JavaDoc cla = toUtf8XmlString(Conversion.toJavaClass(fd.getParent().getFullInName()));
1285                    log.println(" <field class=\""+cla+"\" name=\"" + toUtf8XmlString(fd.getInName()) + "\"/>");
1286                }
1287            }
1288            public void packageAction(Pk pk) {
1289                // No action
1290
}
1291        });
1292        log.println("</expose>");
1293        log.println("<map>");
1294        walkTree(new TreeAction() {
1295            public void classAction(Cl cl) {
1296                if (!cl.isFromScript()) {
1297                  String JavaDoc cla = toUtf8XmlString(Conversion.toJavaClass(cl.getFullInName()));
1298                    log.println(" <class name=\"" + toUtf8XmlString(cla) + "\" map=\"" + toUtf8XmlString(cl.getOutName()) + "\"/>");
1299                }
1300            }
1301            public void methodAction(Md md) {
1302                if (!md.isFromScript()) {
1303                    String JavaDoc cla = toUtf8XmlString(Conversion.toJavaClass(md.getParent().getFullInName()));
1304                    String JavaDoc method = toUtf8XmlString(Conversion.toJavaMethod(md.getInName(), md.getDescriptor()));
1305                    log.println(" <method class=\""+cla+"\" name=\"" + method + "\" map=\"" + toUtf8XmlString(md.getOutName()) + "\"/>");
1306                }
1307            }
1308            public void fieldAction(Fd fd) {
1309                if (!fd.isFromScript()) {
1310                    String JavaDoc cla = toUtf8XmlString(Conversion.toJavaClass(fd.getParent().getFullInName()));
1311                    log.println(" <field class=\""+cla+"\" name=\"" + toUtf8XmlString(fd.getInName()) + "\" map=\"" + toUtf8XmlString(fd.getOutName()) + "\"/>");
1312                }
1313            }
1314            public void packageAction(Pk pk) {
1315                if (!pk.isFromScript() && pk.getFullInName().length() > 0) {
1316                    String JavaDoc pa = toUtf8XmlString(Conversion.toJavaClass(pk.getFullInName()));
1317                    log.println(" <package name=\""+pa +"\" map=\"" + toUtf8XmlString(pk.getOutName()) + "\"/>");
1318                }
1319            }
1320        });
1321        log.println("</map>");
1322    }
1323    
1324    public static final String JavaDoc toUtf8XmlString(String JavaDoc s){
1325      boolean bad = false;
1326      for (int i = 0; i< s.length(); i++){
1327        char c = s.charAt(i);
1328        if ((c >= 0x80) || (c =='"') || (c == '<')){
1329          bad = true;
1330          break;
1331        }
1332      }
1333      if (bad){
1334        StringBuffer JavaDoc buf = new StringBuffer JavaDoc(s.length());
1335        for (int i = 0; i < s.length(); i++){
1336          buf.append(toUtf8XmlChar(s.charAt(i)));
1337        }
1338        return buf.toString();
1339      } else {
1340        return s;
1341      }
1342    }
1343    
1344    private static final String JavaDoc toUtf8XmlChar(char c){
1345      if (c < 0x80){
1346        if (c == '"'){
1347          return "&#x22;";
1348        } else if (c == '<'){
1349          return "&#x3c;";
1350        }
1351        return new String JavaDoc(new char[]{c});
1352      }
1353      else if (c < 0x800)
1354      {
1355        StringBuffer JavaDoc buf = new StringBuffer JavaDoc(8);
1356        buf.append("&#x");
1357        buf.append(hex[(c >> 8) & 0xff]);
1358        buf.append(hex[c & 0xff]);
1359        buf.append(';');
1360        return buf.toString();
1361      }
1362      else
1363      {
1364        StringBuffer JavaDoc buf = new StringBuffer JavaDoc(10);
1365        buf.append("&#x");
1366        buf.append(hex[(c >> 16) & 0xff]);
1367        buf.append(hex[(c >> 8) & 0xff]);
1368        buf.append(hex[c & 0xff]);
1369        buf.append(';');
1370        return buf.toString();
1371      }
1372    }
1373    
1374    private static final String JavaDoc[] hex;
1375    static {
1376      hex = new String JavaDoc[256];
1377      for (int i = 0; i < 256; i++){
1378        hex[i] = toHex(i);
1379      }
1380    }
1381    
1382    private static final String JavaDoc hexChars = "0123456789abcdef";
1383    
1384    /** Holds value of property replaceClassNameStrings. */
1385    private boolean replaceClassNameStrings;
1386    
1387    /** Holds value of property pedantic. */
1388    private boolean pedantic;
1389    
1390    private static String JavaDoc toHex(int i){
1391      StringBuffer JavaDoc buf = new StringBuffer JavaDoc(2);
1392      buf.append(hexChars.charAt((i/16)&15));
1393      buf.append(hexChars.charAt(i&15));
1394      return buf.toString();
1395    }
1396
1397    // Private Methods -------------------------------------------------------
1398
// Mark TreeItem and all parents for retention.
1399
private void retainHierarchy(TreeItem ti)
1400    {
1401        if (!ti.isFixed())
1402        {
1403            ti.setOutName(ti.getInName());
1404            ti.setFromScript();
1405        }
1406        if (ti.parent != null)
1407        {
1408            retainHierarchy(ti.parent);
1409        }
1410    }
1411
1412    /** Walk the whole tree taking action once only on each package level, class, method and field. */
1413    public void walkTree(TreeAction ta)
1414    {
1415        walkTree(ta, root);
1416    }
1417
1418    // Walk the tree which has TreeItem as its root taking action once only on each
1419
// package level, class, method and field.
1420
private void walkTree(TreeAction ta, TreeItem ti)
1421    {
1422        if (ti instanceof Pk)
1423        {
1424            Enumeration JavaDoc packageEnum = ((Pk)ti).getPackageEnum();
1425            ta.packageAction((Pk)ti);
1426            while (packageEnum.hasMoreElements())
1427            {
1428                walkTree(ta, (TreeItem)packageEnum.nextElement());
1429            }
1430        }
1431        if (ti instanceof PkCl)
1432        {
1433            Enumeration JavaDoc classEnum = ((PkCl)ti).getClassEnum();
1434            while (classEnum.hasMoreElements())
1435            {
1436                walkTree(ta, (TreeItem)classEnum.nextElement());
1437            }
1438        }
1439        if (ti instanceof Cl)
1440        {
1441            Enumeration JavaDoc fieldEnum = ((Cl)ti).getFieldEnum();
1442            Enumeration JavaDoc methodEnum = ((Cl)ti).getMethodEnum();
1443            ta.classAction((Cl)ti);
1444            while (fieldEnum.hasMoreElements())
1445            {
1446                ta.fieldAction((Fd)fieldEnum.nextElement());
1447            }
1448            while (methodEnum.hasMoreElements())
1449            {
1450                ta.methodAction((Md)methodEnum.nextElement());
1451            }
1452        }
1453    }
1454    
1455    /** Getter for property replaceClassNameStrings.
1456     * @return Value of property replaceClassNameStrings.
1457     *
1458     */

1459    public boolean isReplaceClassNameStrings()
1460    {
1461      return this.replaceClassNameStrings;
1462    }
1463    
1464    /** Setter for property replaceClassNameStrings.
1465     * @param replaceClassNameStrings New value of property replaceClassNameStrings.
1466     *
1467     */

1468    public void setReplaceClassNameStrings(boolean replaceClassNameStrings)
1469    {
1470      this.replaceClassNameStrings = replaceClassNameStrings;
1471    }
1472    
1473    /** Getter for property pedantic.
1474     * @return Value of property pedantic.
1475     *
1476     */

1477    public boolean isPedantic()
1478    {
1479      return this.pedantic;
1480    }
1481    
1482    /** Setter for property pedantic.
1483     * @param pedantic New value of property pedantic.
1484     *
1485     */

1486    public void setPedantic(boolean pedantic)
1487    {
1488      this.pedantic = pedantic;
1489    }
1490
1491  public void retainSourceFileAttributeMap(String JavaDoc name, String JavaDoc obfName) {
1492    for (Enumeration JavaDoc clEnum = getClEnum(name); clEnum.hasMoreElements(); )
1493    {
1494      Cl classItem = (Cl)clEnum.nextElement();
1495      classItem.setSourceFileMapping(obfName);
1496      classItem.getAttributesToKeep().add(ClassConstants.ATTR_SourceFile);
1497    }
1498  }
1499
1500  public void retainLineNumberTable(String JavaDoc name, final LineNumberTableMapper lineNumberTableMapper) {
1501    for (Enumeration JavaDoc clEnum = getClEnum(name); clEnum.hasMoreElements(); )
1502    {
1503      Cl classItem = (Cl)clEnum.nextElement();
1504      classItem.setLineNumberTableMapper(lineNumberTableMapper);
1505      classItem.getAttributesToKeep().add(ClassConstants.ATTR_LineNumberTable);
1506    }
1507  }
1508
1509  public void retainAttributeForClass(String JavaDoc className, String JavaDoc attributeDescriptor) {
1510    for (Enumeration JavaDoc clEnum = getClEnum(className); clEnum.hasMoreElements(); )
1511    {
1512      Cl classItem = (Cl)clEnum.nextElement();
1513      final Set JavaDoc set = classItem.getAttributesToKeep();
1514      set.add(attributeDescriptor);
1515    }
1516  }
1517
1518  public void retainPackage(String JavaDoc packageName) {
1519    retainHierarchy(getPk(packageName));
1520  }
1521}
1522
1523
1524
Popular Tags