KickJava   Java API By Example, From Geeks To Geeks.

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


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 java.io.*;
30 import java.lang.reflect.*;
31 import java.util.*;
32 import com.yworks.yguard.obf.classfile.*;
33
34 /**
35  * Tree item representing a class or interface.
36  *
37  * @author Mark Welsh
38  */

39 public class Cl extends PkCl implements NameListUp, NameListDown
40 {
41   private boolean sourceFileMappingSet;
42
43   public Set getAttributesToKeep() {
44         return attributesToKeep;
45     }
46
47     public interface ClassResolver {
48       Class JavaDoc resolve(String JavaDoc className) throws ClassNotFoundException JavaDoc;
49     }
50     
51     private static final class DefaultClassResolver implements ClassResolver{
52       public Class JavaDoc resolve(String JavaDoc className) throws ClassNotFoundException JavaDoc
53       {
54         return Class.forName(className);
55       }
56     }
57     
58     private static boolean pedantic = false;
59   
60     // Constants -------------------------------------------------------------
61
private static ClassResolver resolver;
62
63     static {
64       resolver = new DefaultClassResolver();
65     }
66     
67     public static ClassResolver getClassResolver(){
68       return resolver;
69     }
70     
71     public static void setPedantic(boolean val){
72       pedantic = val;
73     }
74     
75     public static void setClassResolver(ClassResolver res){
76       if (res != null){
77         resolver = res;
78       } else {
79         resolver = new DefaultClassResolver();
80       }
81     }
82
83     // Fields ----------------------------------------------------------------
84
private Hashtable mds = new Hashtable(); // Owns a list of methods
85
private Hashtable fds = new Hashtable(); // Owns a list of fields
86
private boolean isResolved = false; // Has the class been resolved already?
87
private boolean isScanned = false; // Has the class been scanned already?
88
private String JavaDoc superClass; // Our superclass name
89
private String JavaDoc[] superInterfaces; // Names of implemented interfaces
90
private boolean isInnerClass; // Is this an inner class?
91
private String JavaDoc sourceFileMapping;
92     private int classFileAccess;
93     private LineNumberTableMapper lineNumberTableMapper;
94     private Vector nameListUps = new Vector(); // NameListUp interfaces for super-class/interfaces
95
private Vector nameListDowns = new Vector(); // NameListDown interfaces for derived class/interfaces
96
public static int nameSpace = 0;
97     private static NameMaker methodNameMaker;
98     private static NameMaker fieldNameMaker;
99     private Map innerClassModifiers = new HashMap();
100     private Set attributesToKeep = new HashSet();
101 // private boolean isPublic = true;
102

103     // Class Methods ---------------------------------------------------------
104

105
106     // Instance Methods ------------------------------------------------------
107
/** Ctor. */
108     public Cl(TreeItem parent, boolean isInnerClass, String JavaDoc name, String JavaDoc superClass, String JavaDoc[] superInterfaces, int modifiers)
109     {
110         super(parent, name);
111         this.superClass = superClass;
112         this.superInterfaces = superInterfaces;
113         this.isInnerClass = isInnerClass;
114         this.access = modifiers;
115         if (parent == null || name.equals(""))
116         {
117             System.err.println("Internal error: class must have parent and name");
118         }
119         if (parent instanceof Cl)
120         {
121             sep = ClassFile.SEP_INNER;
122         }
123
124         // Do not obfuscate anonymous inner classes
125
if (isInnerClass && Character.isDigit(name.charAt(0)))
126         {
127             setOutName(getInName());
128         }
129     }
130     
131     void setClassFileAccess(int classFileAccess){
132       this.classFileAccess = classFileAccess;
133     }
134
135     public LineNumberTableMapper getLineNumberTableMapper() {
136       return lineNumberTableMapper;
137     }
138
139     public void setLineNumberTableMapper(LineNumberTableMapper lineNumberTableMapper) {
140       this.lineNumberTableMapper = lineNumberTableMapper;
141     }
142
143     public String JavaDoc getSourceFileMapping() {
144       return sourceFileMapping;
145     }
146
147     public void setSourceFileMapping(String JavaDoc sourceFileMapping) {
148       this.sourceFileMappingSet = true;
149       this.sourceFileMapping = sourceFileMapping;
150     }
151
152     public boolean isSourceFileMappingSet(){
153       return sourceFileMappingSet;
154     }
155
156     public String JavaDoc getSuperClass(){
157       return this.superClass;
158     }
159     
160     public String JavaDoc[] getInterfaces(){
161       return this.superInterfaces;
162     }
163     
164     public void setInnerClassModifiers(Map map){
165       this.innerClassModifiers.putAll(map);
166     }
167     
168     public int getInnerClassModifier(String JavaDoc fqn){
169       Integer JavaDoc i = (Integer JavaDoc) innerClassModifiers.get(fqn);
170       if (i == null){
171         return Modifier.PRIVATE;
172       } else {
173         return i.intValue();
174       }
175     }
176     
177     /** Is this an inner class? */
178     public boolean isInnerClass() {return isInnerClass;}
179
180     /** Get a method by name. */
181     public Md getMethod(String JavaDoc name, String JavaDoc descriptor) {return (Md)mds.get(name + descriptor);}
182
183     /** Get a field by name. */
184     public Fd getField(String JavaDoc name) {return (Fd)fds.get(name);}
185
186     /** Get an Enumeration of methods. */
187     public Enumeration getMethodEnum() {return mds.elements();}
188
189     /** Get an Enumeration of fields. */
190     public Enumeration getFieldEnum() {return fds.elements();}
191
192     /** Is this class's name a match to the wildcard pattern? */
193     public boolean isWildcardMatch(String JavaDoc pattern) {
194         return isMatch(pattern, getFullInName());
195     }
196
197     /** Is this class's name a non-recursive match to the wildcard pattern? */
198     public boolean isNRWildcardMatch(String JavaDoc pattern) {
199         return isNRMatch(pattern, getFullInName());
200     }
201
202     /** Does this class have the specified class in its super chain? */
203     public boolean hasAsSuper(String JavaDoc queryName) throws ClassNotFoundException JavaDoc
204     {
205         // Special case: we are java/lang/Object
206
if (superClass == null) return false;
207
208         try
209         {
210             if (superClass.equals(queryName))
211             {
212                 return true;
213             }
214             else
215             {
216                 Cl superClassItem = classTree.getCl(superClass);
217                 if (superClassItem != null)
218                 {
219                     return superClassItem.hasAsSuper(queryName);
220                 }
221                 else
222                 {
223                     Class JavaDoc extSuper = resolver.resolve(ClassFile.translate(superClass));
224                     while (extSuper != null)
225                     {
226                         if (extSuper.getName().equals(ClassFile.translate(queryName)))
227                         {
228                             return true;
229                         }
230                         extSuper = extSuper.getSuperclass();
231                     }
232                     return false;
233                 }
234             }
235         }
236         catch (ClassNotFoundException JavaDoc cnfe)
237         {
238           if (pedantic){
239             throw cnfe;
240           } else {
241             return false;
242           }
243         }
244     }
245
246     /** Add an inner class. */
247     public Cl addClass(String JavaDoc name, String JavaDoc superName, String JavaDoc[] interfaceNames, int modifiers)
248     {
249         return addClass(true, name, superName, interfaceNames, modifiers);
250     }
251
252     /** Add an inner class, used when copying inner classes from a placeholder. */
253     public Cl addClass(Cl cl)
254     {
255         cls.put(cl.getInName(), cl);
256         return cl;
257     }
258
259     /** Add a placeholder class. */
260     public Cl addPlaceholderClass(String JavaDoc name)
261     {
262         return addPlaceholderClass(true, name);
263     }
264
265     /** Add a method. */
266     public Md addMethod(boolean isSynthetic, String JavaDoc name, String JavaDoc descriptor, int access)
267     {
268         // Exclude the <init> and <clinit> methods
269
if (name.charAt(0) == '<')
270         {
271             return null;
272         }
273         Md md = getMethod(name, descriptor);
274         if (md == null)
275         {
276             md = new Md(this, isSynthetic, name, descriptor, access);
277             mds.put(name + descriptor, md);
278         }
279         // Exclude the public ... valueOf(String) and values() methods of the Enum classes.
280
final int PublicStatic = ClassConstants.ACC_PUBLIC | ClassConstants.ACC_STATIC;
281         if ((this.classFileAccess & ClassConstants.ACC_ENUM) == ClassConstants.ACC_ENUM &&
282             ((access & PublicStatic) == PublicStatic)){
283           final String JavaDoc desc = "(Ljava/lang/String;)L" + getFullInName() + ';';
284           if ("valueOf".equals(name) && desc.equals(descriptor)){
285             md.setOutName(name);
286           } else if ("values".equals(name) && descriptor.equals("()[L" + getFullInName() + ';')){
287             md.setOutName(name);
288           }
289         }
290         return md;
291     }
292
293     /** Add a field. */
294     public Fd addField(boolean isSynthetic, String JavaDoc name, String JavaDoc descriptor, int access)
295     {
296         Fd fd = getField(name);
297         if (fd == null)
298         {
299             fd = new Fd(this, isSynthetic, name, descriptor, access);
300             fds.put(name, fd);
301         }
302         return fd;
303     }
304
305     /** Prepare for resolve of a class entry by resetting flags. */
306     public void resetResolve()
307     {
308         isScanned = false;
309         isResolved = false;
310         nameListDowns.removeAllElements();
311     }
312
313     /** Set up reverse list of reserved names prior to resolving classes. */
314     public void setupNameListDowns()
315     {
316         // Special case: we are java/lang/Object
317
if (superClass == null) return;
318
319         // Add this class as a NameListDown to the super and each interface, if they are in the JAR
320
Cl superClassItem = classTree.getCl(superClass);
321         if (superClassItem != null)
322         {
323             superClassItem.nameListDowns.addElement(this);
324         }
325         for (int i = 0; i < superInterfaces.length; i++)
326         {
327             Cl interfaceItem = classTree.getCl(superInterfaces[i]);
328             if (interfaceItem != null)
329             {
330                 interfaceItem.nameListDowns.addElement(this);
331             }
332         }
333     }
334
335     /**
336      * Resolve a class entry - set obfuscation permissions based on super class and interfaces.
337      * Overload method and field names maximally.
338      */

339     public void resolveOptimally() throws ClassNotFoundException JavaDoc
340     {
341         // Already processed, then do nothing
342

343         if (!isResolved)
344         {
345             // Get lists of method and field names in inheritance namespace
346
Vector methods = new Vector();
347             Vector fields = new Vector();
348             scanNameSpaceExcept(null, methods, fields);
349             String JavaDoc[] methodNames = new String JavaDoc[methods.size()];
350             for (int i = 0; i < methodNames.length; i++)
351             {
352                 methodNames[i] = (String JavaDoc)methods.elementAt(i);
353             }
354             String JavaDoc[] fieldNames = new String JavaDoc[fields.size()];
355             for (int i = 0; i < fieldNames.length; i++)
356             {
357                 fieldNames[i] = (String JavaDoc)fields.elementAt(i);
358             }
359
360             NameMakerFactory nmf = NameMakerFactory.getInstance();
361
362             // Create new name-makers for the namespace
363
methodNameMaker = nmf.getMethodNameMaker(methodNames, getFullInName());
364             fieldNameMaker = nmf.getFieldNameMaker(fieldNames, getFullInName());
365
366             // Resolve a full name space
367
resolveNameSpaceExcept(null);
368
369             // and move to next
370
nameSpace++;
371         }
372     }
373
374     // Get lists of method and field names in inheritance namespace
375
private void scanNameSpaceExcept(Cl ignoreCl, Vector methods,
376                                      Vector fields) throws ClassNotFoundException JavaDoc
377     {
378 // System.out.println("Scan: "+getInName());
379

380         // Special case: we are java/lang/Object
381
if (superClass == null) return;
382
383         // Traverse one step in each direction in name space, scanning
384
if (!isScanned)
385         {
386             // First step up to super classes, scanning them
387
Cl superCl = classTree.getCl(superClass);
388             if (superCl != null) // internal to JAR
389
{
390                 if (superCl != ignoreCl)
391                 {
392                     superCl.scanNameSpaceExcept(this, methods, fields);
393                 }
394             }
395             else // external to JAR
396
{
397               scanExtSupers(superClass, methods, fields);
398             }
399             for (int i = 0; i < superInterfaces.length; i++)
400             {
401                 Cl interfaceItem = classTree.getCl(superInterfaces[i]);
402                 if (interfaceItem != null)
403                 {
404                   if (interfaceItem != ignoreCl){
405                     interfaceItem.scanNameSpaceExcept(this, methods, fields);
406                   }
407                 } else { // external to JAR
408
scanExtSupers(superInterfaces[i], methods, fields);
409                 }
410             }
411
412             // Next, scan ourself
413
if (!isScanned)
414             {
415                 scanThis(methods, fields);
416
417                 // Signal class has been scanned
418
isScanned = true;
419             }
420
421             // Finally step down to derived classes, resolving them
422
for (Enumeration clEnum = nameListDowns.elements(); clEnum.hasMoreElements(); )
423             {
424                 Cl cl = (Cl)clEnum.nextElement();
425                 if (cl != ignoreCl)
426                 {
427                     cl.scanNameSpaceExcept(this, methods, fields);
428                 }
429             }
430         }
431     }
432
433
434     // Get lists of method and field names in inheritance namespace
435
private void scanExtSupers(String JavaDoc name, Vector methods,
436                                Vector fields) throws ClassNotFoundException JavaDoc
437     {
438       try {
439         Class JavaDoc extClass = resolver.resolve(ClassFile.translate(name));
440         scanExtSupers(extClass, methods, fields);
441       } catch(ClassNotFoundException JavaDoc cnfe)
442       {
443         if (pedantic){
444           throw cnfe;
445         } else {
446           Logger.getInstance().warningToLogfile("Unresolved external dependency: "+Conversion.toJavaClass(name)+" not found!");
447           Logger.getInstance().setUnresolved();
448         }
449       }
450     }
451
452     // Get lists of method and field names in inheritance namespace
453
private void scanExtSupers(Class JavaDoc extClass, Vector methods,
454                                Vector fields) throws ClassNotFoundException JavaDoc
455     {
456       // Get public methods and fields from supers and interfaces up the tree
457
Method[] allPubMethods = extClass.getMethods();
458       if (allPubMethods != null) {
459           for (int i = 0; i < allPubMethods.length; i++) {
460               String JavaDoc methodName = allPubMethods[i].getName();
461               if (methods.indexOf(methodName) == -1) {
462                   methods.addElement(methodName);
463               }
464           }
465       }
466       Field[] allPubFields = extClass.getFields();
467       if (allPubFields != null) {
468           for (int i = 0; i < allPubFields.length; i++) {
469               String JavaDoc fieldName = allPubFields[i].getName();
470               if (fields.indexOf(fieldName) == -1) {
471                   fields.addElement(fieldName);
472               }
473           }
474       }
475       
476       // Go up the super hierarchy, adding all non-public methods/fields
477
while (extClass != null) {
478           Method[] allClassMethods = extClass.getDeclaredMethods();
479           if (allClassMethods != null) {
480               for (int i = 0; i < allClassMethods.length; i++) {
481                   if (!Modifier.isPublic(allClassMethods[i].getModifiers())) {
482                       String JavaDoc methodName = allClassMethods[i].getName();
483                       if (methods.indexOf(methodName) == -1) {
484                           methods.addElement(methodName);
485                       }
486                   }
487               }
488           }
489           Field[] allClassFields = extClass.getDeclaredFields();
490           if (allClassFields != null) {
491               for (int i = 0; i < allClassFields.length; i++) {
492                   if (!Modifier.isPublic(allClassFields[i].getModifiers())) {
493                       String JavaDoc fieldName = allClassFields[i].getName();
494                       if (fields.indexOf(fieldName) == -1) {
495                           fields.addElement(fieldName);
496                       }
497                   }
498               }
499           }
500           extClass = extClass.getSuperclass();
501       }
502     }
503
504     // Add method and field names from this class to the lists
505
private void scanThis(Vector methods, Vector fields)
506     {
507         for (Enumeration mdEnum = mds.elements(); mdEnum.hasMoreElements(); )
508         {
509             Md md = (Md)mdEnum.nextElement();
510             if (md.isFixed())
511             {
512                 String JavaDoc name = md.getOutName();
513                 if (methods.indexOf(name) == -1)
514                 {
515                     methods.addElement(name);
516                 }
517             }
518         }
519         for (Enumeration fdEnum = fds.elements(); fdEnum.hasMoreElements(); )
520         {
521             Fd fd = (Fd)fdEnum.nextElement();
522             if (fd.isFixed())
523             {
524                 String JavaDoc name = fd.getOutName();
525                 if (fields.indexOf(name) == -1)
526                 {
527                     fields.addElement(name);
528                 }
529             }
530         }
531     }
532
533     // Resolve an entire inheritance name space optimally.
534
private void resolveNameSpaceExcept(Cl ignoreCl) throws ClassNotFoundException JavaDoc
535     {
536         // Special case: we are java/lang/Object
537
if (superClass == null) return;
538
539         // Traverse one step in each direction in name space, resolving
540
if (!isResolved)
541         {
542             // First step up to super classes, resolving them, since we depend on them
543
Cl superCl = classTree.getCl(superClass);
544             if (superCl != null && superCl != ignoreCl)
545             {
546                 superCl.resolveNameSpaceExcept(this);
547             }
548             for (int i = 0; i < superInterfaces.length; i++)
549             {
550                 Cl interfaceItem = classTree.getCl(superInterfaces[i]);
551                 if (interfaceItem != null && interfaceItem != ignoreCl)
552                 {
553                     interfaceItem.resolveNameSpaceExcept(this);
554                 }
555             }
556
557             // Next, resolve ourself
558
if (!isResolved)
559             {
560 // System.out.println("Resolve: "+getInName());
561
// System.out.println("fds: "+fds);
562
resolveThis();
563
564                 // Signal class has been processed
565
isResolved = true;
566             }
567
568             // Finally step down to derived classes, resolving them
569
for (Enumeration clEnum = nameListDowns.elements(); clEnum.hasMoreElements(); )
570             {
571                 Cl cl = (Cl)clEnum.nextElement();
572                 if (cl != ignoreCl)
573                 {
574                     cl.resolveNameSpaceExcept(this);
575                 }
576             }
577         }
578     }
579
580     // For each super interface and the super class, if it is outside DB, use reflection
581
// to merge its list of public/protected methods/fields --
582
// while for those in the DB, resolve to get the name-mapping lists
583
private void resolveThis() throws ClassNotFoundException JavaDoc
584     {
585         // Special case: we are java/lang/Object
586
if (superClass == null) return;
587
588         Cl superClassItem = classTree.getCl(superClass);
589         nameListUps.addElement(superClassItem != null ?
590                                (NameListUp)superClassItem :
591                                getExtNameListUp(superClass));
592         for (int i = 0; i < superInterfaces.length; i++)
593         {
594             Cl interfaceItem = classTree.getCl(superInterfaces[i]);
595             nameListUps.addElement(interfaceItem != null ?
596                                    (NameListUp)interfaceItem :
597                                    getExtNameListUp(superInterfaces[i]));
598         }
599
600         // Run through each method/field in this class checking for reservations and
601
// obfuscating accordingly
602
nextMethod:
603         for (Enumeration mdEnum = mds.elements(); mdEnum.hasMoreElements(); )
604         {
605             Md md = (Md)mdEnum.nextElement();
606           if (!md.isFixed()) {
607             //muellese: private should never make any problems
608
if (!Modifier.isPrivate(md.getModifiers())) {
609               // Check for name reservation via derived classes
610
for (Enumeration nlEnum = nameListDowns.elements(); nlEnum.hasMoreElements();) {
611                 String JavaDoc theOutName = ((NameListDown) nlEnum.nextElement()).getMethodObfNameDown(this, md.getInName(),
612                     md.getDescriptor());
613                 if (theOutName != null) {
614                   md.setOutName(theOutName);
615                   continue nextMethod;
616                 }
617               }
618               // Check for name reservation via super classes
619
for (Enumeration nlEnum = nameListUps.elements(); nlEnum.hasMoreElements();) {
620                 String JavaDoc theOutName = ((NameListUp) nlEnum.nextElement()).getMethodOutNameUp(md.getInName(),
621                     md.getDescriptor());
622                 if (theOutName != null) {
623                   md.setOutName(theOutName);
624                   continue nextMethod;
625                 }
626               }
627             }
628             // If no other restrictions, obfuscate it
629
md.setOutName(methodNameMaker.nextName(md.getDescriptor()));
630           } else {
631             if (Modifier.isNative(md.access)) {
632               // native method, check if hierarchy is fixed, too, otherwise - this will break JNI calls
633
if (!md.getParent().getFullOutName().equals(md.getParent().getFullInName())) {
634                 Logger.getInstance().warning(
635                     "Method " + md.getOutName() + " is native but " + md.getParent().getFullInName() + " is not kept/exposed.");
636               }
637             }
638           }
639         }
640         nextField:
641         for (Enumeration fdEnum = fds.elements(); fdEnum.hasMoreElements(); )
642         {
643             Fd fd = (Fd)fdEnum.nextElement();
644             if (!fd.isFixed())
645             {
646                 //muellese: private should never make any problems
647
if (!Modifier.isPrivate(fd.getModifiers())){
648                   // Check for name reservation via derived classes
649
for (Enumeration nlEnum = nameListDowns.elements(); nlEnum.hasMoreElements(); )
650                   {
651                       String JavaDoc theOutName = ((NameListDown)nlEnum.nextElement()).getFieldObfNameDown(this, fd.getInName());
652                       if (theOutName != null)
653                       {
654                           fd.setOutName(theOutName);
655                           continue nextField;
656                       }
657                   }
658                   // Check for name reservation via super classes
659
for (Enumeration nlEnum = nameListUps.elements(); nlEnum.hasMoreElements(); )
660                   {
661                       String JavaDoc superOutName = ((NameListUp)nlEnum.nextElement()).getFieldOutNameUp(fd.getInName());
662                       if (superOutName != null)
663                       {
664                           fd.setOutName(superOutName);
665                           continue nextField;
666                       }
667                   }
668                 }
669                 // If no other restrictions, obfuscate it
670
fd.setOutName(fieldNameMaker.nextName(null));
671             }
672         }
673     }
674
675     /** Get output method name from list, or null if no mapping exists. */
676     public String JavaDoc getMethodOutNameUp(String JavaDoc name, String JavaDoc descriptor) throws ClassNotFoundException JavaDoc
677     {
678         // Check supers
679
for (Enumeration enumeration = nameListUps.elements(); enumeration.hasMoreElements(); )
680         {
681             String JavaDoc superOutName = ((NameListUp)enumeration.nextElement()).getMethodOutNameUp(name, descriptor);
682             if (superOutName != null)
683             {
684                 return superOutName;
685             }
686         }
687
688         // Check self
689
Md md = getMethod(name, descriptor);
690         if (md != null && !Modifier.isPrivate(md.access))
691         {
692             return md.getOutName();
693         }
694         else
695         {
696             return null;
697         }
698     }
699
700     /** Get obfuscated method name from list, or null if no mapping exists. */
701     public String JavaDoc getMethodObfNameUp(String JavaDoc name, String JavaDoc descriptor) throws ClassNotFoundException JavaDoc
702     {
703         // Check supers
704
for (Enumeration enumeration = nameListUps.elements(); enumeration.hasMoreElements(); )
705         {
706             String JavaDoc superObfName = ((NameListUp)enumeration.nextElement()).getMethodObfNameUp(name, descriptor);
707             if (superObfName != null)
708             {
709                 return superObfName;
710             }
711         }
712
713         // Check self
714
Md md = getMethod(name, descriptor);
715         if (md != null && !Modifier.isPrivate(md.access))
716         {
717             return md.getObfName();
718         }
719         else
720         {
721             return null;
722         }
723     }
724
725     /** Get output field name from list, or null if no mapping exists. */
726     public String JavaDoc getFieldOutNameUp(String JavaDoc name) throws ClassNotFoundException JavaDoc
727     {
728         // Check supers
729
for (Enumeration enumeration = nameListUps.elements(); enumeration.hasMoreElements(); )
730         {
731             String JavaDoc superOutName = ((NameListUp)enumeration.nextElement()).getFieldOutNameUp(name);
732             if (superOutName != null)
733             {
734                 return superOutName;
735             }
736         }
737
738         // Check self
739
Fd fd = getField(name);
740         if (fd != null && !Modifier.isPrivate(fd.access))
741         {
742             return fd.getOutName();
743         }
744         else
745         {
746             return null;
747         }
748     }
749
750     /** Get obfuscated field name from list, or null if no mapping exists. */
751     public String JavaDoc getFieldObfNameUp(String JavaDoc name) throws ClassNotFoundException JavaDoc
752     {
753         // Check supers
754
for (Enumeration enumeration = nameListUps.elements(); enumeration.hasMoreElements(); )
755         {
756             String JavaDoc superObfName = ((NameListUp)enumeration.nextElement()).getFieldObfNameUp(name);
757             if (superObfName != null)
758             {
759                 return superObfName;
760             }
761         }
762
763         // Check self
764
Fd fd = getField(name);
765         if (fd != null && !Modifier.isPrivate(fd.access))
766         {
767             return fd.getObfName();
768         }
769         else
770         {
771             return null;
772         }
773     }
774
775     /** Is the method reserved because of its reservation down the class hierarchy? */
776     public String JavaDoc getMethodObfNameDown(Cl caller, String JavaDoc name, String JavaDoc descriptor) throws ClassNotFoundException JavaDoc
777     {
778         // Check ourself for an explicit 'do not obfuscate'
779
Md md = getMethod(name, descriptor);
780         if (md != null && md.isFixed())
781         {
782             return md.getOutName();
783         }
784
785         // Check our supers, except for our caller (special case if we are java/lang/Object)
786
String JavaDoc theObfName = null;
787         if (superClass != null)
788         {
789             Cl superClassItem = classTree.getCl(superClass);
790             if (superClassItem != caller)
791             {
792                 NameListUp nl = superClassItem != null ? (NameListUp)superClassItem : getExtNameListUp(superClass);
793                 theObfName = nl.getMethodObfNameUp(name, descriptor);
794                 if (theObfName != null)
795                 {
796                     return theObfName;
797                 }
798             }
799             for (int i = 0; i < superInterfaces.length; i++)
800             {
801                 Cl interfaceItem = classTree.getCl(superInterfaces[i]);
802                 if (interfaceItem != caller)
803                 {
804                     NameListUp nl = interfaceItem != null ? (NameListUp)interfaceItem : getExtNameListUp(superInterfaces[i]);
805                     theObfName = nl.getMethodObfNameUp(name, descriptor);
806                     if (theObfName != null)
807                     {
808                         return theObfName;
809                     }
810                 }
811             }
812         }
813
814         // Check our derived classes
815
for (Enumeration enumeration = nameListDowns.elements(); enumeration.hasMoreElements(); )
816         {
817             theObfName = ((NameListDown)enumeration.nextElement()).getMethodObfNameDown(this, name, descriptor);
818             if (theObfName != null)
819             {
820                 return theObfName;
821             }
822         }
823
824         // No reservation found
825
return null;
826     }
827
828     /** Is the field reserved because of its reservation down the class hierarchy? */
829     public String JavaDoc getFieldObfNameDown(Cl caller, String JavaDoc name) throws ClassNotFoundException JavaDoc
830     {
831         // Check ourself for an explicit 'do not obfuscate'
832
Fd fd = getField(name);
833         if (fd != null && fd.isFixed())
834         {
835             return fd.getOutName();
836         }
837
838         // Check our supers, except for our caller (special case if we are java/lang/Object)
839
String JavaDoc theObfName = null;
840         if (superClass != null)
841         {
842             Cl superClassItem = classTree.getCl(superClass);
843             if (superClassItem != caller)
844             {
845                 NameListUp nl = superClassItem != null ? (NameListUp)superClassItem : getExtNameListUp(superClass);
846                 theObfName = nl.getFieldObfNameUp(name);
847                 if (theObfName != null)
848                 {
849                     return theObfName;
850                 }
851             }
852             for (int i = 0; i < superInterfaces.length; i++)
853             {
854                 Cl interfaceItem = classTree.getCl(superInterfaces[i]);
855                 if (interfaceItem != caller)
856                 {
857                     NameListUp nl = interfaceItem != null ? (NameListUp)interfaceItem : getExtNameListUp(superInterfaces[i]);
858                     theObfName = nl.getFieldObfNameUp(name);
859                     if (theObfName != null)
860                     {
861                         return theObfName;
862                     }
863                 }
864             }
865         }
866
867         // Check our derived classes
868
for (Enumeration enumeration = nameListDowns.elements(); enumeration.hasMoreElements(); )
869         {
870             theObfName = ((NameListDown)enumeration.nextElement()).getFieldObfNameDown(this, name);
871             if (theObfName != null)
872             {
873                 return theObfName;
874             }
875         }
876
877         // No reservation found
878
return null;
879     }
880
881     // Construct, or retrieve from cache, the NameListUp object for an external class/interface
882
private static Hashtable extNameListUpCache = new Hashtable();
883     private NameListUp getExtNameListUp(String JavaDoc name) throws ClassNotFoundException JavaDoc
884     {
885         NameListUp nl = (NameListUp)extNameListUpCache.get(name);
886         if (nl == null)
887         {
888             nl = new ExtNameListUp(name);
889             extNameListUpCache.put(name, nl);
890         }
891         return nl;
892     }
893
894     // NameListUp for class/interface not in the database.
895
class ExtNameListUp implements NameListUp
896     {
897         // Class's fully qualified name
898
private Class JavaDoc extClass;
899         private Method[] methods = null;
900
901         // Ctor.
902
public ExtNameListUp(String JavaDoc name) throws ClassNotFoundException JavaDoc
903         {
904           try
905           {
906             extClass = resolver.resolve(ClassFile.translate(name));
907           }
908           catch (ClassNotFoundException JavaDoc cnfe)
909           {
910             if (pedantic){
911               throw cnfe;
912             } else {
913               Logger.getInstance().warningToLogfile("Unresolved external dependency: "+Conversion.toJavaClass(name)+" not found!");
914               Logger.getInstance().setUnresolved();
915             }
916           }
917         }
918
919         // Ctor.
920
public ExtNameListUp(Class JavaDoc extClass)
921         {
922             this.extClass = extClass;
923         }
924
925         // Get obfuscated method name from list, or null if no mapping exists.
926
public String JavaDoc getMethodObfNameUp(String JavaDoc name, String JavaDoc descriptor)
927         {
928             return getMethodOutNameUp(name, descriptor);
929         }
930
931         // Get obfuscated method name from list, or null if no mapping exists.
932
public String JavaDoc getMethodOutNameUp(String JavaDoc name, String JavaDoc descriptor)
933         {
934           //RW
935
if(extClass == null) return name;
936           
937             // Get list of public/protected methods
938
if (methods == null)
939             {
940                 methods = getAllDeclaredMethods(extClass);
941                 Vector pruned = new Vector();
942                 for (int i = 0; i < methods.length; i++)
943                 {
944                     int modifiers = methods[i].getModifiers();
945                     if (!Modifier.isPrivate(modifiers))
946                     {
947                         pruned.addElement(methods[i]);
948                     }
949                 }
950                 methods = new Method[pruned.size()];
951                 for (int i = 0; i < methods.length; i++)
952                 {
953                     methods[i] = (Method)pruned.elementAt(i);
954                 }
955             }
956
957             // Check each public/protected class method against the named one
958
nextMethod:
959             for (int i = 0; i < methods.length; i++)
960             {
961                 if (name.equals(methods[i].getName()))
962                 {
963                     String JavaDoc[] paramAndReturnNames = ClassFile.parseDescriptor(descriptor);
964                     Class JavaDoc[] paramTypes = methods[i].getParameterTypes();
965                     Class JavaDoc returnType = methods[i].getReturnType();
966                     if (paramAndReturnNames.length == paramTypes.length + 1)
967                     {
968                         for (int j = 0; j < paramAndReturnNames.length - 1; j++)
969                         {
970                             if (!paramAndReturnNames[j].equals(paramTypes[j].getName()))
971                             {
972                                 continue nextMethod;
973                             }
974                         }
975                         String JavaDoc returnName = returnType.getName();
976                         if (!paramAndReturnNames[paramAndReturnNames.length - 1].equals(returnName))
977                         {
978                             continue nextMethod;
979                         }
980
981                         // We have a match, and so the derived class method name must be made to match
982
return name;
983                     }
984                 }
985             }
986
987             // Method is not present
988
return null;
989         }
990
991         // Get obfuscated field name from list, or null if no mapping exists.
992
public String JavaDoc getFieldObfNameUp(String JavaDoc name)
993         {
994             return getFieldOutNameUp(name);
995         }
996
997         // Get obfuscated field name from list, or null if no mapping exists.
998
public String JavaDoc getFieldOutNameUp(String JavaDoc name)
999         {
1000          if(extClass == null) return name;
1001            // Use reflection to check class for field
1002
Field field = getAllDeclaredField(extClass, name);
1003            if (field != null)
1004            {
1005                // Field must be public or protected
1006
int modifiers = field.getModifiers();
1007                if (!Modifier.isPrivate(modifiers))
1008                {
1009                    return name;
1010                }
1011            }
1012
1013            // Field is not present
1014
return null;
1015        }
1016
1017        // Get all methods (from supers too) regardless of access level
1018
private Method[] getAllDeclaredMethods(Class JavaDoc theClass)
1019        {
1020            Vector ma = new Vector();
1021            int length = 0;
1022
1023            // Get the public methods from all supers and interfaces up the tree
1024
Method[] allPubMethods = theClass.getMethods();
1025            ma.addElement(allPubMethods);
1026            length += allPubMethods.length;
1027
1028            // Go up the super hierarchy, getting arrays of all methods (some redundancy
1029
// here, but that's okay)
1030
while (theClass != null)
1031            {
1032                Method[] methods = theClass.getDeclaredMethods();
1033                ma.addElement(methods);
1034                length += methods.length;
1035                theClass = theClass.getSuperclass();
1036            }
1037
1038            // Merge the arrays
1039
Method[] allMethods = new Method[length];
1040            int pos = 0;
1041            for (Enumeration enumeration = ma.elements(); enumeration.hasMoreElements(); )
1042            {
1043                Method[] methods = (Method[])enumeration.nextElement();
1044                System.arraycopy(methods, 0, allMethods, pos, methods.length);
1045                pos += methods.length;
1046            }
1047            return allMethods;
1048        }
1049
1050        // Get a specified field (from supers and interfaces too) regardless of access level
1051
private Field getAllDeclaredField(Class JavaDoc theClass, String JavaDoc name)
1052        {
1053            Class JavaDoc origClass = theClass;
1054
1055            // Check for field in supers
1056
while (theClass != null)
1057            {
1058                Field field = null;
1059                try
1060                {
1061                    field = theClass.getDeclaredField(name);
1062                }
1063                catch (Exception JavaDoc e)
1064                {
1065                    field = null;
1066                }
1067                if (field != null)
1068                {
1069                    return field;
1070                }
1071                theClass = theClass.getSuperclass();
1072            }
1073
1074            // Check for public field in supers and interfaces (some redundancy here,
1075
// but that's okay)
1076
try
1077            {
1078                return origClass.getField(name);
1079            }
1080            catch (SecurityException JavaDoc nsfe)
1081            {
1082                return null;
1083            }
1084            catch (NoSuchFieldException JavaDoc nsfe)
1085            {
1086                return null;
1087            }
1088        }
1089    }
1090}
1091
1092
Popular Tags