KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > javaguard > Cl


1 /**
2  * JavaGuard -- an obfuscation package for Java classfiles.
3  *
4  * Copyright (c) 1999 Mark Welsh (markw@retrologic.com)
5  * Copyright (c) 2002 Thorsten Heit (theit@gmx.de)
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 theit@gmx.de.
22  *
23  *
24  * $Id: Cl.java,v 1.4 2002/05/11 18:55:54 glurk Exp $
25  */

26 package net.sf.javaguard;
27
28 import java.lang.reflect.*;
29 import java.util.*;
30 import net.sf.javaguard.classfile.ClassConstants;
31 import net.sf.javaguard.log.*;
32
33
34 /** Tree item representing a class or an interface.
35  *
36  * @author <a HREF="mailto:markw@retrologic.com">Mark Welsh</a>
37  * @author <a HREF="mailto:theit@gmx.de">Thorsten Heit</a>
38  */

39 public class Cl extends PkCl implements NameListUp, NameListDown {
40   // Fields ----------------------------------------------------------------
41
private Map mds = new TreeMap(); // Owns a list of methods
42
private Map fds = new TreeMap(); // Owns a list of fields
43
private boolean isResolved = false; // Has the class been resolved already?
44
private boolean isScanned = false; // Has the class been scanned already?
45
private String JavaDoc superClass; // Our superclass name
46
private String JavaDoc[] superInterfaces; // Names of implemented interfaces
47
private boolean isInnerClass; // Is this an inner class?
48
private Vector nameListUps = new Vector(); // NameListUp interfaces for super-class/interfaces
49
private Vector nameListDowns = new Vector(); // NameListDown interfaces for derived class/interfaces
50
public static int nameSpace = 0;
51   private static NameMaker methodNameMaker;
52   private static NameMaker fieldNameMaker;
53   
54   
55   /** Holds whether the class implements java.io.Serializable or not. */
56   private boolean isSerializableClass;
57   /** Holds whether the class implements java.rmi.Remote or not. */
58   private boolean isRemoteClass;
59   
60   /** Holds the screen logger. */
61   private FileLogger logger;
62   
63   
64   
65   
66   /** Creates a new class element.
67    * @param parent the parent element of the class
68    * @param isInnerClass true if the class element specifies an inner class;
69    * false else
70    * @param name the name of the class
71    * @param superClass the name of the super class
72    * @param superInterfaces an array containing the directly implemented
73    * interfaces
74    */

75   public Cl(TreeItem parent, boolean isInnerClass, String JavaDoc name, String JavaDoc superClass, String JavaDoc[] superInterfaces) {
76     super(parent, name);
77     this.superClass = superClass;
78     this.superInterfaces = superInterfaces;
79     this.isInnerClass = isInnerClass;
80     if (parent == null || name.equals("")) {
81       throw new InternalError JavaDoc("Internal error: class must have parent and name");
82     }
83     if (parent instanceof Cl) {
84       setSeparator(ClassConstants.SEP_INNER);
85     }
86     
87     setSerializable(false);
88     setRemoteClass(false);
89     
90     // Do not obfuscate anonymous inner classes
91
if (isInnerClass && Character.isDigit(name.charAt(0))) {
92       setOutName(getInName());
93     }
94     
95     logger = FileLogger.getInstance();
96   }
97   
98   
99   /** Is this an inner class? */
100   public boolean isInnerClass() {
101     return isInnerClass;
102   }
103   
104   
105   /** Get a method by name. */
106   public Md getMethod(String JavaDoc name, String JavaDoc descriptor) {
107     return (Md) mds.get(name + descriptor);
108   }
109   
110   
111   /** Get a field by name. */
112   public Fd getField(String JavaDoc name) {
113     return (Fd) fds.get(name);
114   }
115   
116   
117   /** Get an iterator for all available methods.
118    * @return iterator for the methods
119    */

120   public Iterator getMethodIterator() {
121     return mds.values().iterator();
122   }
123   
124   
125   /** Get an iterator for all available fields.
126    * @return iterator for the fields
127    */

128   public Iterator getFieldIterator() {
129     return fds.values().iterator();
130   }
131   
132   
133   /** Does this class have the specified class in its super chain? */
134   public boolean hasAsSuper(String JavaDoc queryName) {
135     // Special case: we are java/lang/Object
136
if (superClass == null) return false;
137     
138     try {
139       if (superClass.equals(queryName)) {
140         return true;
141       } else {
142         Cl superClassItem = getClassTree().getCl(superClass);
143         if (superClassItem != null) {
144           return superClassItem.hasAsSuper(queryName);
145         } else {
146           Class JavaDoc extSuper = Class.forName(Tools.translate(superClass), false, getClass().getClassLoader());
147           while (extSuper != null) {
148             if (extSuper.getName().equals(Tools.translate(queryName))) {
149               return true;
150             }
151             extSuper = extSuper.getSuperclass();
152           }
153           return false;
154         }
155       }
156     } catch (Exception JavaDoc e) {
157       return false;
158     }
159   }
160   
161   
162   /** Add an inner class. */
163   public Cl addClass(String JavaDoc name, String JavaDoc superName, String JavaDoc[] interfaceNames) {
164     return addClass(name, true, superName, interfaceNames);
165   }
166   
167   
168   /** Add an inner class, used when copying inner classes from a placeholder. */
169   public Cl addClass(Cl cl) {
170     cls.put(cl.getInName(), cl);
171     return cl;
172   }
173   
174   
175   /** Add a placeholder class. */
176   public Cl addPlaceholderClass(String JavaDoc name) {
177     return addPlaceholderClass(name, true);
178   }
179   
180   
181   /** Add a method. */
182   public Md addMethod(boolean isSynthetic, String JavaDoc name, String JavaDoc descriptor, int access) {
183     // Exclude the <init> and <clinit> methods
184
if (name.charAt(0) == '<') {
185       return null;
186     }
187     Md md = getMethod(name, descriptor);
188     if (md == null) {
189       md = new Md(this, isSynthetic, name, descriptor, access);
190       mds.put(name + descriptor, md);
191     }
192     return md;
193   }
194   
195   
196   /** Add a field. */
197   public Fd addField(boolean isSynthetic, String JavaDoc name, String JavaDoc descriptor, int access) {
198     Fd fd = getField(name);
199     if (fd == null) {
200       fd = new Fd(this, isSynthetic, name, descriptor, access);
201       fds.put(name, fd);
202     }
203     return fd;
204   }
205   
206   
207   /** Prepare for resolve of a class entry by resetting flags. */
208   public void resetResolve() {
209     isScanned = false;
210     isResolved = false;
211     nameListDowns.removeAllElements();
212   }
213   
214   /** Set up reverse list of reserved names prior to resolving classes. */
215   public void setupNameListDowns() {
216     // Special case: we are java/lang/Object
217
if (superClass == null) return;
218     
219     // Add this class as a NameListDown to the super and each interface, if they are in the JAR
220
Cl superClassItem = getClassTree().getCl(superClass);
221     if (superClassItem != null) {
222       superClassItem.nameListDowns.addElement(this);
223     }
224     for (int i = 0; i < superInterfaces.length; i++) {
225       Cl interfaceItem = getClassTree().getCl(superInterfaces[i]);
226       if (interfaceItem != null) {
227         interfaceItem.nameListDowns.addElement(this);
228       }
229     }
230   }
231   
232   
233   /**
234    * Resolve a class entry - set obfuscation permissions based on super class and interfaces.
235    * Overload method and field names maximally.
236    */

237   public void resolveOptimally() {
238     // Already processed, then do nothing
239
if (!isResolved) {
240       // Get lists of method and field names in inheritance namespace
241
Vector methods = new Vector();
242       Vector fields = new Vector();
243       scanNameSpaceExcept(null, methods, fields);
244       String JavaDoc[] methodNames = new String JavaDoc[methods.size()];
245       for (int i = 0; i < methodNames.length; i++) {
246         methodNames[i] = (String JavaDoc)methods.elementAt(i);
247       }
248       String JavaDoc[] fieldNames = new String JavaDoc[fields.size()];
249       for (int i = 0; i < fieldNames.length; i++) {
250         fieldNames[i] = (String JavaDoc)fields.elementAt(i);
251       }
252       
253       // Create new name-makers for the namespace
254
methodNameMaker = new KeywordNameMaker(methodNames);
255       fieldNameMaker = new KeywordNameMaker(fieldNames);
256       
257       // Resolve a full name space
258
resolveNameSpaceExcept(null);
259       
260       // and move to next
261
nameSpace++;
262     }
263   }
264   
265   
266   // Get lists of method and field names in inheritance namespace
267
private void scanNameSpaceExcept(Cl ignoreCl, Vector methods, Vector fields) {
268     // Special case: we are java/lang/Object
269
if (superClass == null) return;
270     
271     // Traverse one step in each direction in name space, scanning
272
if (!isScanned) {
273       // First step up to super classes, scanning them
274
Cl superCl = getClassTree().getCl(superClass);
275       if (superCl != null) // internal to JAR
276
{
277         if (superCl != ignoreCl) {
278           superCl.scanNameSpaceExcept(this, methods, fields);
279         }
280       }
281       else // external to JAR
282
{
283         scanExtSupers(superClass, methods, fields);
284       }
285       for (int i = 0; i < superInterfaces.length; i++) {
286         Cl interfaceItem = getClassTree().getCl(superInterfaces[i]);
287         if (interfaceItem != null && interfaceItem != ignoreCl) {
288           interfaceItem.scanNameSpaceExcept(this, methods, fields);
289         }
290       }
291       
292       // Next, scan ourself
293
if (!isScanned) {
294         scanThis(methods, fields);
295         
296         // Signal class has been scanned
297
isScanned = true;
298       }
299       
300       // Finally step down to derived classes, resolving them
301
for (Iterator iter = nameListDowns.iterator(); iter.hasNext(); ) {
302         Cl cl = (Cl) iter.next();
303         if (cl != ignoreCl) {
304           cl.scanNameSpaceExcept(this, methods, fields);
305         }
306       }
307     }
308   }
309   
310   // Get lists of method and field names in inheritance namespace
311
private void scanExtSupers(String JavaDoc name, Vector methods, Vector fields) {
312     Class JavaDoc extClass = null;
313     try {
314       extClass = Class.forName(Tools.translate(name), false, getClass().getClassLoader());
315     } catch (ClassNotFoundException JavaDoc ex) {
316       return;
317     }
318     // Get public methods and fields from supers and interfaces up the tree
319
Method[] allPubMethods = extClass.getMethods();
320     if (allPubMethods != null) {
321       for (int i = 0; i < allPubMethods.length; i++) {
322         String JavaDoc methodName = allPubMethods[i].getName();
323         if (methods.indexOf(methodName) == -1) {
324           methods.addElement(methodName);
325         }
326       }
327     }
328     Field[] allPubFields = extClass.getFields();
329     if (allPubFields != null) {
330       for (int i = 0; i < allPubFields.length; i++) {
331         String JavaDoc fieldName = allPubFields[i].getName();
332         if (fields.indexOf(fieldName) == -1) {
333           fields.addElement(fieldName);
334         }
335       }
336     }
337     // Go up the super hierarchy, adding all non-public methods/fields
338
while (extClass != null) {
339       Method[] allClassMethods = extClass.getDeclaredMethods();
340       if (allClassMethods != null) {
341         for (int i = 0; i < allClassMethods.length; i++) {
342           if (!Modifier.isPublic(allClassMethods[i].getModifiers())) {
343             String JavaDoc methodName = allClassMethods[i].getName();
344             if (methods.indexOf(methodName) == -1) {
345               methods.addElement(methodName);
346             }
347           }
348         }
349       }
350       Field[] allClassFields = extClass.getDeclaredFields();
351       if (allClassFields != null) {
352         for (int i = 0; i < allClassFields.length; i++) {
353           if (!Modifier.isPublic(allClassFields[i].getModifiers())) {
354             String JavaDoc fieldName = allClassFields[i].getName();
355             if (fields.indexOf(fieldName) == -1) {
356               fields.addElement(fieldName);
357             }
358           }
359         }
360       }
361       extClass = extClass.getSuperclass();
362     }
363   }
364   
365   
366   // Add method and field names from this class to the lists
367
private void scanThis(Vector methods, Vector fields) {
368     for (Iterator mdEnum = getMethodIterator(); mdEnum.hasNext(); ) {
369       Md md = (Md) mdEnum.next();
370       if (md.isFixed()) {
371         String JavaDoc name = md.getOutName();
372         if (methods.indexOf(name) == -1) {
373           methods.addElement(name);
374         }
375       }
376     }
377     for (Iterator fdEnum = getFieldIterator(); fdEnum.hasNext(); ) {
378       Fd fd = (Fd) fdEnum.next();
379       if (fd.isFixed()) {
380         String JavaDoc name = fd.getOutName();
381         if (fields.indexOf(name) == -1) {
382           fields.addElement(name);
383         }
384       }
385     }
386   }
387   
388   
389   // Resolve an entire inheritance name space optimally.
390
private void resolveNameSpaceExcept(Cl ignoreCl) {
391     // Special case: we are java/lang/Object
392
if (superClass == null) return;
393     
394     // Traverse one step in each direction in name space, resolving
395
if (!isResolved) {
396       // First step up to super classes, resolving them, since we depend on them
397
Cl superCl = getClassTree().getCl(superClass);
398       if (superCl != null && superCl != ignoreCl) {
399         superCl.resolveNameSpaceExcept(this);
400       }
401       for (int i = 0; i < superInterfaces.length; i++) {
402         Cl interfaceItem = getClassTree().getCl(superInterfaces[i]);
403         if (interfaceItem != null && interfaceItem != ignoreCl) {
404           interfaceItem.resolveNameSpaceExcept(this);
405         }
406       }
407       
408       // Next, resolve ourself
409
if (!isResolved) {
410         resolveThis();
411         
412         // Signal class has been processed
413
isResolved = true;
414       }
415       
416       // Finally step down to derived classes, resolving them
417
for (Iterator iter = nameListDowns.iterator(); iter.hasNext(); ) {
418         Cl cl = (Cl) iter.next();
419         if (cl != ignoreCl) {
420           cl.resolveNameSpaceExcept(this);
421         }
422       }
423     }
424   }
425   
426   
427   
428   // For each super interface and the super class, if it is outside DB, use reflection
429
// to merge its list of public/protected methods/fields --
430
// while for those in the DB, resolve to get the name-mapping lists
431
private void resolveThis() {
432     // Special case: we are java/lang/Object
433
if (superClass == null) return;
434     
435     Cl superClassItem = getClassTree().getCl(superClass);
436     nameListUps.addElement(superClassItem != null
437     ? (NameListUp)superClassItem
438     : getExtNameListUp(superClass));
439     
440     for (int i = 0; i < superInterfaces.length; i++) {
441       Cl interfaceItem = getClassTree().getCl(superInterfaces[i]);
442       nameListUps.addElement(interfaceItem != null
443       ? (NameListUp)interfaceItem
444       : getExtNameListUp(superInterfaces[i]));
445     }
446     
447     // Run through each method/field in this class checking for reservations and
448
// obfuscating accordingly
449
nextMethod:
450       for (Iterator mdIter = getMethodIterator(); mdIter.hasNext(); ) {
451         Md md = (Md) mdIter.next();
452         if (!md.isFixed()) {
453           // Check for name reservation via derived classes
454
for (Iterator nlIter = nameListDowns.iterator(); nlIter.hasNext(); ) {
455             String JavaDoc theOutName = ((NameListDown) nlIter.next()).getMethodObfNameDown(this, md.getInName(), md.getDescriptor());
456             if (theOutName != null) {
457               md.setOutName(theOutName);
458               continue nextMethod;
459             }
460           }
461           // Check for name reservation via super classes
462
for (Iterator nlIter = nameListUps.iterator(); nlIter.hasNext(); ) {
463             NameListUp nlu = (NameListUp) nlIter.next();
464             if (null != nlu) {
465               String JavaDoc theOutName = nlu.getMethodOutNameUp(md.getInName(), md.getDescriptor());
466               if (theOutName != null) {
467                 md.setOutName(theOutName);
468                 continue nextMethod;
469               }
470             } else {
471               logger.addWarning("# Warning: name list contains null pointer (check your classpath settings)!");
472               logger.addWarning("# method: " + md.getFullInName() + " / " + md.getDescriptor());
473               logger.addWarning("# in: Cl.resolveThis()");
474             }
475           }
476           // If no other restrictions, obfuscate it
477
md.setOutName(methodNameMaker.nextName(md.getDescriptor()));
478         }
479       }
480       
481       nextField:
482         for (Iterator fdIter = getFieldIterator(); fdIter.hasNext(); ) {
483           Fd fd = (Fd) fdIter.next();
484           if (!fd.isFixed()) {
485             // Check for name reservation via derived classes
486
for (Iterator nlIter = nameListDowns.iterator(); nlIter.hasNext(); ) {
487               String JavaDoc theOutName = ((NameListDown) nlIter.next()).getFieldObfNameDown(this, fd.getInName());
488               if (theOutName != null) {
489                 fd.setOutName(theOutName);
490                 continue nextField;
491               }
492             }
493             // Check for name reservation via super classes
494
for (Iterator nlIter = nameListUps.iterator(); nlIter.hasNext(); ) {
495               NameListUp nlu = (NameListUp) nlIter.next();
496               if (null != nlu) {
497                 String JavaDoc superOutName = nlu.getFieldOutNameUp(fd.getInName());
498                 if (superOutName != null) {
499                   fd.setOutName(superOutName);
500                   continue nextField;
501                 }
502               } else {
503                 logger.addWarning("# Warning: name list contains null pointer (check your classpath settings)!");
504                 logger.addWarning("# field: " + fd.getFullInName() + " / " + fd.getDescriptor());
505                 logger.addWarning("# in: Cl.resolveThis()");
506               }
507             }
508             // If no other restrictions, obfuscate it
509
fd.setOutName(fieldNameMaker.nextName(null));
510           }
511         }
512   }
513   
514   
515   /** Get output method name from list, or null if no mapping exists. */
516   public String JavaDoc getMethodOutNameUp(String JavaDoc name, String JavaDoc descriptor) {
517     // Check supers
518
for (Iterator iter = nameListUps.iterator(); iter.hasNext(); ) {
519       NameListUp nlu = (NameListUp) iter.next();
520       if (null != nlu) {
521         String JavaDoc superOutName = nlu.getMethodOutNameUp(name, descriptor);
522         if (superOutName != null) {
523           return superOutName;
524         }
525       } else {
526         logger.addWarning("# Warning: Cannot lookup output method name (check your classpath settings)!");
527         logger.addWarning("# method: " + getFullInName() + " / " + name + " / " + descriptor);
528       }
529     }
530     
531     // Check self
532
Md md = getMethod(name, descriptor);
533     if (md != null && !Modifier.isPrivate(md.getModifiers())) {
534       return md.getOutName();
535     }
536     else {
537       return null;
538     }
539   }
540   
541   
542   /** Get obfuscated method name from list, or null if no mapping exists. */
543   public String JavaDoc getMethodObfNameUp(String JavaDoc name, String JavaDoc descriptor) {
544     // Check supers
545
for (Iterator iter = nameListUps.iterator(); iter.hasNext(); ) {
546       NameListUp nlu = (NameListUp) iter.next();
547       if (null != nlu) {
548         String JavaDoc superObfName = nlu.getMethodObfNameUp(name, descriptor);
549         if (superObfName != null) {
550           return superObfName;
551         }
552       } else {
553         logger.addWarning("# Warning: Cannot lookup obfuscated method name (check your classpath settings)!");
554         logger.addWarning("# method: " + getFullInName() + " / " + name + " / " + descriptor);
555       }
556     }
557     
558     // Check self
559
Md md = getMethod(name, descriptor);
560     if (md != null && !Modifier.isPrivate(md.getModifiers())) {
561       return md.getObfName();
562     }
563     else {
564       return null;
565     }
566   }
567   
568   
569   /** Get output field name from list, or null if no mapping exists. */
570   public String JavaDoc getFieldOutNameUp(String JavaDoc name) {
571     // Check supers
572
for (Iterator iter = nameListUps.iterator(); iter.hasNext(); ) {
573       NameListUp nlu = (NameListUp) iter.next();
574       if (null != nlu) {
575         String JavaDoc superOutName = nlu.getFieldOutNameUp(name);
576         if (superOutName != null) {
577           return superOutName;
578         }
579       } else {
580         logger.addWarning("# Warning: Cannot lookup output field name (check your classpath settings)!");
581         logger.addWarning("# field: " + getFullInName() + " / " + name);
582       }
583     }
584     
585     // Check self
586
Fd fd = getField(name);
587     if (fd != null && !Modifier.isPrivate(fd.getModifiers())) {
588       return fd.getOutName();
589     }
590     else {
591       return null;
592     }
593   }
594   
595   
596   /** Get obfuscated field name from list, or null if no mapping exists. */
597   public String JavaDoc getFieldObfNameUp(String JavaDoc name) {
598     // Check supers
599
for (Iterator iter = nameListUps.iterator(); iter.hasNext(); ) {
600       NameListUp nlu = (NameListUp) iter.next();
601       if (null != nlu) {
602         String JavaDoc superObfName = nlu.getFieldObfNameUp(name);
603         if (superObfName != null) {
604           return superObfName;
605         }
606       } else {
607         logger.addWarning("# Warning: Cannot lookup obfuscated field name (check your classpath settings)!");
608         logger.addWarning("# field: " + getFullInName() + " / " + name);
609       }
610     }
611     
612     // Check self
613
Fd fd = getField(name);
614     if (fd != null && !Modifier.isPrivate(fd.getModifiers())) {
615       return fd.getObfName();
616     }
617     else {
618       return null;
619     }
620   }
621   
622   
623   /** Is the method reserved because of its reservation down the class hierarchy? */
624   public String JavaDoc getMethodObfNameDown(Cl caller, String JavaDoc name, String JavaDoc descriptor) {
625     // Check ourself for an explicit 'do not obfuscate'
626
Md md = getMethod(name, descriptor);
627     if (md != null && md.isFixed()) {
628       return md.getOutName();
629     }
630     
631     // Check our supers, except for our caller (special case if we are java/lang/Object)
632
String JavaDoc theObfName = null;
633     if (superClass != null) {
634       Cl superClassItem = getClassTree().getCl(superClass);
635       if (superClassItem != caller) {
636         NameListUp nl = superClassItem != null ? (NameListUp)superClassItem : getExtNameListUp(superClass);
637         if (null != nl) {
638           theObfName = nl.getMethodObfNameUp(name, descriptor);
639           if (theObfName != null) {
640             return theObfName;
641           }
642         } else {
643           logger.addWarning("# Warning: Cannot lookup method in super class (check your classpath settings)!");
644           logger.addWarning("# Cl: " + caller.getFullInName() + " / " + name + " / " + descriptor);
645         }
646       }
647       for (int i = 0; i < superInterfaces.length; i++) {
648         Cl interfaceItem = getClassTree().getCl(superInterfaces[i]);
649         if (interfaceItem != caller) {
650           NameListUp nl = interfaceItem != null ? (NameListUp)interfaceItem : getExtNameListUp(superInterfaces[i]);
651           if (null != nl) {
652             theObfName = nl.getMethodObfNameUp(name, descriptor);
653             if (theObfName != null) {
654               return theObfName;
655             }
656           } else {
657             logger.addWarning("# Warning: Cannot lookup method in interfaces (check your classpath settings)!");
658             logger.addWarning("# Cl: " + caller.getFullInName() + " / " + name + " / " + descriptor);
659           }
660         }
661       }
662     }
663     
664     // Check our derived classes
665
for (Iterator iter = nameListDowns.iterator(); iter.hasNext(); ) {
666       theObfName = ((NameListDown) iter.next()).getMethodObfNameDown(this, name, descriptor);
667       if (theObfName != null) {
668         return theObfName;
669       }
670     }
671     
672     // No reservation found
673
return null;
674   }
675   
676   
677   /** Is the field reserved because of its reservation down the class hierarchy? */
678   public String JavaDoc getFieldObfNameDown(Cl caller, String JavaDoc name) {
679     // Check ourself for an explicit 'do not obfuscate'
680
Fd fd = getField(name);
681     if (fd != null && fd.isFixed()) {
682       return fd.getOutName();
683     }
684     
685     // Check our supers, except for our caller (special case if we are java/lang/Object)
686
String JavaDoc theObfName = null;
687     if (superClass != null) {
688       Cl superClassItem = getClassTree().getCl(superClass);
689       if (superClassItem != caller) {
690         NameListUp nl = superClassItem != null ? (NameListUp)superClassItem : getExtNameListUp(superClass);
691         if (nl != null) {
692           theObfName = nl.getFieldObfNameUp(name);
693           if (theObfName != null) {
694             return theObfName;
695           }
696         } else {
697           logger.addWarning("# Warning: Cannot lookup field in super class (check your classpath settings)!");
698           logger.addWarning("# Cl: " + caller.getFullInName() + " / " + name);
699         }
700       }
701       for (int i = 0; i < superInterfaces.length; i++) {
702         Cl interfaceItem = getClassTree().getCl(superInterfaces[i]);
703         if (interfaceItem != caller) {
704           NameListUp nl = interfaceItem != null ? (NameListUp)interfaceItem : getExtNameListUp(superInterfaces[i]);
705           if (null != nl) {
706             theObfName = nl.getFieldObfNameUp(name);
707             if (theObfName != null) {
708               return theObfName;
709             }
710           } else {
711             logger.addWarning("# Warning: Cannot lookup field in interfaces (check your classpath settings)!");
712             logger.addWarning("# Cl: " + caller.getFullInName() + " / " + name);
713           }
714         }
715       }
716     }
717     
718     // Check our derived classes
719
for (Iterator iter = nameListDowns.iterator(); iter.hasNext(); ) {
720       theObfName = ((NameListDown) iter.next()).getFieldObfNameDown(this, name);
721       if (theObfName != null) {
722         return theObfName;
723       }
724     }
725     
726     // No reservation found
727
return null;
728   }
729   
730   
731   // Construct, or retrieve from cache, the NameListUp object for an external class/interface
732
private static Hashtable extNameListUpCache = new Hashtable();
733   
734   private NameListUp getExtNameListUp(String JavaDoc name) {
735     NameListUp nl = (NameListUp)extNameListUpCache.get(name);
736     if (nl == null) {
737       try {
738         nl = new ExtNameListUp(name);
739         extNameListUpCache.put(name, nl);
740       } catch (ClassNotFoundException JavaDoc cnfex) {
741         nl = null;
742       }
743     }
744     return nl;
745   }
746   
747   // NameListUp for class/interface not in the database.
748
class ExtNameListUp implements NameListUp {
749     // Class's fully qualified name
750
private Class JavaDoc extClass;
751     private Method[] methods = null;
752     
753     // Ctor.
754
public ExtNameListUp(String JavaDoc name)
755     throws ClassNotFoundException JavaDoc {
756       extClass = Class.forName(Tools.translate(name), false, getClass().getClassLoader());
757     }
758     
759     
760     // Ctor.
761
public ExtNameListUp(Class JavaDoc extClass) {
762       this.extClass = extClass;
763     }
764     
765     
766     // Get obfuscated method name from list, or null if no mapping exists.
767
public String JavaDoc getMethodObfNameUp(String JavaDoc name, String JavaDoc descriptor) {
768       return getMethodOutNameUp(name, descriptor);
769     }
770     
771     
772     // Get obfuscated method name from list, or null if no mapping exists.
773
public String JavaDoc getMethodOutNameUp(String JavaDoc name, String JavaDoc descriptor) {
774       // Get list of public/protected methods
775
if (methods == null) {
776         methods = getAllDeclaredMethods(extClass);
777         Vector pruned = new Vector();
778         for (int i = 0; i < methods.length; i++) {
779           int modifiers = methods[i].getModifiers();
780           if (!Modifier.isPrivate(modifiers)) {
781             pruned.addElement(methods[i]);
782           }
783         }
784         methods = new Method[pruned.size()];
785         for (int i = 0; i < methods.length; i++) {
786           methods[i] = (Method)pruned.elementAt(i);
787         }
788       }
789       
790       // Check each public/protected class method against the named one
791
nextMethod:
792         for (int i = 0; i < methods.length; i++) {
793           if (name.equals(methods[i].getName())) {
794             String JavaDoc[] paramAndReturnNames = Tools.parseDescriptor(descriptor);
795             Class JavaDoc[] paramTypes = methods[i].getParameterTypes();
796             Class JavaDoc returnType = methods[i].getReturnType();
797             if (paramAndReturnNames.length == paramTypes.length + 1) {
798               for (int j = 0; j < paramAndReturnNames.length - 1; j++) {
799                 if (!paramAndReturnNames[j].equals(paramTypes[j].getName())) {
800                   continue nextMethod;
801                 }
802               }
803               String JavaDoc returnName = returnType.getName();
804               if (!paramAndReturnNames[paramAndReturnNames.length - 1].equals(returnName)) {
805                 continue nextMethod;
806               }
807               
808               // We have a match, and so the derived class method name must be made to match
809
return name;
810             }
811           }
812         }
813         
814         // Method is not present
815
return null;
816     }
817     
818     
819     // Get obfuscated field name from list, or null if no mapping exists.
820
public String JavaDoc getFieldObfNameUp(String JavaDoc name) {
821       return getFieldOutNameUp(name);
822     }
823     
824     
825     // Get obfuscated field name from list, or null if no mapping exists.
826
public String JavaDoc getFieldOutNameUp(String JavaDoc name) {
827       // Use reflection to check class for field
828
Field field = getAllDeclaredField(extClass, name);
829       if (field != null) {
830         // Field must be public or protected
831
int modifiers = field.getModifiers();
832         if (!Modifier.isPrivate(modifiers)) {
833           return name;
834         }
835       }
836       
837       // Field is not present
838
return null;
839     }
840     
841     
842     // Get all methods (from supers too) regardless of access level
843
private Method[] getAllDeclaredMethods(Class JavaDoc theClass) {
844       Vector ma = new Vector();
845       int length = 0;
846       
847       // Get the public methods from all supers and interfaces up the tree
848
Method[] allPubMethods = theClass.getMethods();
849       ma.addElement(allPubMethods);
850       length += allPubMethods.length;
851       
852       // Go up the super hierarchy, getting arrays of all methods (some redundancy
853
// here, but that's okay)
854
while (theClass != null) {
855         Method[] methods = theClass.getDeclaredMethods();
856         ma.addElement(methods);
857         length += methods.length;
858         theClass = theClass.getSuperclass();
859       }
860       
861       // Merge the arrays
862
Method[] allMethods = new Method[length];
863       int pos = 0;
864       for (Iterator iter = ma.iterator(); iter.hasNext(); ) {
865         Method[] methods = (Method[]) iter.next();
866         System.arraycopy(methods, 0, allMethods, pos, methods.length);
867         pos += methods.length;
868       }
869       return allMethods;
870     }
871     
872     
873     // Get a specified field (from supers and interfaces too) regardless of access level
874
private Field getAllDeclaredField(Class JavaDoc theClass, String JavaDoc name) {
875       Class JavaDoc origClass = theClass;
876       
877       // Check for field in supers
878
while (theClass != null) {
879         Field field = null;
880         try {
881           field = theClass.getDeclaredField(name);
882         } catch (Exception JavaDoc e) {
883           field = null;
884         }
885         if (field != null) {
886           return field;
887         }
888         theClass = theClass.getSuperclass();
889       }
890       
891       // Check for public field in supers and interfaces (some redundancy here,
892
// but that's okay)
893
try {
894         return origClass.getField(name);
895       } catch (Exception JavaDoc e) {
896         return null;
897       }
898     }
899   }
900   
901   
902   
903   
904   /** Sets whether the class implements the Serializable interface.
905    * @param serializable true if the class implements java.io.Serializable;
906    * false else
907    * @see #isSerializable
908    */

909   public void setSerializable(boolean serializable) {
910     this.isSerializableClass = serializable;
911   }
912   
913   
914   /** Returns whether the class implements java.io.Serializable and the
915    * obfuscator respects serializable fields and methods.
916    * @return true if the class implements java.io.Serializable; false else
917    * @see #setSerializable
918    */

919   public boolean isSerializable() {
920     return isSerializableClass;
921   }
922   
923   
924   
925   
926   /** Sets whether the class implements the Remote interface.
927    * @param rmic true if the class implements java.rmi.Remote; false else
928    * @see #isRemoteClass
929    */

930   public void setRemoteClass(boolean rmic) {
931     this.isRemoteClass = rmic;
932   }
933   
934   
935   /** Returns whether the class implements java.rmi.Remote and the obfuscator
936    * respects such classes.
937    * @return true if the class implements java.rmi.Remote; false else
938    * @see #setRemoteClass
939    */

940   public boolean isRemoteClass() {
941     return isRemoteClass;
942   }
943   
944   
945   
946   
947   /** Check whether the class is assigned a new class or package name during
948    * the obfuscation.
949    * @return true if the class name or the package name is changed; false else
950    */

951   public boolean isBeingObfuscated() {
952     TreeItem ti = this;
953     while (null != ti) {
954       if (!ti.getInName().equals(ti.getOutName())) {
955         return true;
956       }
957       ti = ti.getParent();
958     }
959     return false;
960   }
961   
962   
963   
964   
965   /** Return the list of implemented interfaces.
966    * @return array with implemented super interfaces
967    */

968   public String JavaDoc[] getSuperInterfaces() {
969     return superInterfaces;
970   }
971   
972   
973   
974   
975   /** Return the name of the super class of the current element.
976    * @return name of the super class
977    */

978   public String JavaDoc getSuperclass() {
979     return superClass;
980   }
981 }
982
Popular Tags