Source Code Cross Referenced for ClassTree.java in  » Development » RetroGuard » COM » rl » obf » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Development » RetroGuard » COM.rl.obf 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* ===========================================================================
0002:         * $RCSfile: ClassTree.java,v $
0003:         * ===========================================================================
0004:         *
0005:         * RetroGuard -- an obfuscation package for Java classfiles.
0006:         *
0007:         * Copyright (c) 1998-2006 Mark Welsh (markw@retrologic.com)
0008:         *
0009:         * This program can be redistributed and/or modified under the terms of the 
0010:         * Version 2 of the GNU General Public License as published by the Free 
0011:         * Software Foundation.
0012:         *
0013:         * This program is distributed in the hope that it will be useful,
0014:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
0016:         * GNU General Public License for more details.
0017:         *
0018:         */
0019:
0020:        package COM.rl.obf;
0021:
0022:        import java.io.*;
0023:        import java.lang.reflect.*;
0024:        import java.util.*;
0025:        import COM.rl.obf.classfile.*;
0026:
0027:        /**
0028:         * Tree structure of package levels, classes, methods and fields used for obfuscation.
0029:         *
0030:         * @author      Mark Welsh
0031:         */
0032:        public class ClassTree implements  NameMapper {
0033:            // Constants -------------------------------------------------------------
0034:            public static final char PACKAGE_LEVEL = '/';
0035:            public static final char CLASS_LEVEL = '$';
0036:            public static final char METHOD_FIELD_LEVEL = '/';
0037:            private static final String LOG_PRE_UNOBFUSCATED = "# Names reserved from obfuscation:";
0038:            private static final String LOG_PRE_OBFUSCATED = "# Obfuscated name mappings (some of these may be unchanged due to polymorphism constraints):";
0039:            private static final String LOG_FREQUENCY_TABLE = "# Obfuscated name overloading frequency:";
0040:            private static final String LOG_DANGER_HEADER1 = "# WARNING - Reflection methods are called which may unavoidably break in the";
0041:            private static final String LOG_DANGER_HEADER2 = "# obfuscated version at runtime. Please review your source code to ensure";
0042:            private static final String LOG_DANGER_HEADER3 = "# these methods do not act on classes in the obfuscated Jar file.";
0043:
0044:            // Fields ----------------------------------------------------------------
0045:            private Vector retainAttrs = new Vector(); // List of attributes to retain
0046:            private Pk root = null; // Root package in database (Java default package)
0047:
0048:            // Class methods ---------------------------------------------------------
0049:            /** Return a fully qualified name broken into package/class segments. */
0050:            public static Enumeration getNameEnum(String name) throws Exception {
0051:                Vector vec = new Vector();
0052:                String nameOrig = name;
0053:                while (name != null && !name.equals("")) {
0054:                    int posP = name.indexOf(PACKAGE_LEVEL);
0055:                    int posC = name.indexOf(CLASS_LEVEL);
0056:                    SimpleName simpleName = null;
0057:                    if (posP == -1 && posC == -1) {
0058:                        simpleName = new SimpleName(name).setAsClass();
0059:                        name = "";
0060:                    }
0061:                    if (posP == -1 && posC != -1) {
0062:                        simpleName = new SimpleName(name.substring(0, posC))
0063:                                .setAsClass();
0064:                        name = name.substring(posC + 1, name.length());
0065:                    }
0066:                    if (posP != -1 && posC == -1) {
0067:                        simpleName = new SimpleName(name.substring(0, posP))
0068:                                .setAsPackage();
0069:                        name = name.substring(posP + 1, name.length());
0070:                    }
0071:                    if (posP != -1 && posC != -1) {
0072:                        if (posP < posC) {
0073:                            simpleName = new SimpleName(name.substring(0, posP))
0074:                                    .setAsPackage();
0075:                            name = name.substring(posP + 1, name.length());
0076:                        } else {
0077:                            throw new IOException(
0078:                                    "Invalid fully qualified name (a): "
0079:                                            + nameOrig);
0080:                        }
0081:                    }
0082:                    vec.addElement(simpleName);
0083:                }
0084:                return vec.elements();
0085:            }
0086:
0087:            // Instance Methods ------------------------------------------------------
0088:            /** Ctor. */
0089:            public ClassTree() {
0090:                root = Pk.createRoot(this );
0091:            }
0092:
0093:            /** Return the root node. */
0094:            public Pk getRoot() {
0095:                return root;
0096:            }
0097:
0098:            /** Update the path of the passed filename, if that path corresponds to a package. */
0099:            public String getOutName(String inName) {
0100:                try {
0101:                    TreeItem ti = root;
0102:                    StringBuffer sb = new StringBuffer();
0103:                    for (Enumeration nameEnum = getNameEnum(inName); nameEnum
0104:                            .hasMoreElements();) {
0105:                        SimpleName simpleName = (SimpleName) nameEnum
0106:                                .nextElement();
0107:                        String name = simpleName.getName();
0108:                        if (simpleName.isAsPackage()) {
0109:                            if (ti != null) {
0110:                                ti = ((Pk) ti).getPackage(name);
0111:                                if (ti != null) {
0112:                                    String repackageName = ((Pk) ti)
0113:                                            .getRepackageName();
0114:                                    if (repackageName != null) {
0115:                                        sb = new StringBuffer(repackageName);
0116:                                    } else {
0117:                                        sb.append(ti.getOutName());
0118:                                    }
0119:                                } else {
0120:                                    sb.append(name);
0121:                                }
0122:                            } else {
0123:                                sb.append(name);
0124:                            }
0125:                            sb.append(PACKAGE_LEVEL);
0126:                        } else if (simpleName.isAsClass()) {
0127:                            sb.append(name);
0128:                            return sb.toString();
0129:                        } else {
0130:                            throw new Exception(
0131:                                    "Internal error: illegal package/class name tag");
0132:                        }
0133:                    }
0134:                } catch (Exception e) {
0135:                    // Just drop through and return the original name
0136:                }
0137:                return inName;
0138:            }
0139:
0140:            /** Add a classfile's package, class, method and field entries to database. */
0141:            public void addClassFile(ClassFile cf) throws Exception {
0142:                addClassFile(cf, false);
0143:            }
0144:
0145:            /** Add a classfile's package, class, method and field entries to database. */
0146:            public void addClassFile(ClassFile cf, boolean enableTrim)
0147:                    throws Exception {
0148:                // Add the fully qualified class name
0149:                TreeItem ti = root;
0150:                for (Enumeration nameEnum = getNameEnum(cf.getName()); nameEnum
0151:                        .hasMoreElements();) {
0152:                    SimpleName simpleName = (SimpleName) nameEnum.nextElement();
0153:                    String name = simpleName.getName();
0154:                    if (simpleName.isAsPackage()) {
0155:                        ti = ((Pk) ti).addPackage(name);
0156:                    } else if (simpleName.isAsClass()) {
0157:                        // If this is an inner class, just add placeholder classes up the tree
0158:                        if (nameEnum.hasMoreElements()) {
0159:                            ti = ((PkCl) ti).addPlaceholderClass(name);
0160:                        } else {
0161:                            ti = ((PkCl) ti).addClass(name, cf.getSuper(), cf
0162:                                    .getInterfaces(), cf.getModifiers());
0163:                        }
0164:                    } else {
0165:                        throw new Exception(
0166:                                "Internal error: illegal package/class name tag");
0167:                    }
0168:                }
0169:
0170:                // We must have a class before adding methods and fields
0171:                if (ti instanceof  Cl) {
0172:                    Cl cl = (Cl) ti;
0173:
0174:                    // Add the class's methods to the database
0175:                    for (int i = 0; i < cf.getMethodCount(); i++) {
0176:                        Md md = cl.addMethod(cf, cf.getMethod(i), enableTrim);
0177:                    }
0178:
0179:                    // Add the class's fields to the database
0180:                    for (int i = 0; i < cf.getFieldCount(); i++) {
0181:                        Fd fd = cl.addField(cf, cf.getField(i), enableTrim);
0182:                    }
0183:
0184:                    // Construct class's reference list
0185:                    cl.findRefs(cf);
0186:
0187:                    // Add warnings about class
0188:                    cl.setWarnings(cf);
0189:                } else {
0190:                    throw new Exception("Inconsistent class file.");
0191:                }
0192:            }
0193:
0194:            /** Mark a class/interface type to suppress warnings from it. */
0195:            public void noWarnClass(String name) throws Exception {
0196:                // Mark the class (or classes, if this is a wildcarded specifier)
0197:                for (Enumeration clEnum = getClEnum(name); clEnum
0198:                        .hasMoreElements();) {
0199:                    Cl cl = (Cl) clEnum.nextElement();
0200:                    cl.setNoWarn();
0201:                }
0202:            }
0203:
0204:            /** Write any non-suppressed warnings to the log. */
0205:            public void logWarnings(PrintWriter log) throws Exception {
0206:                final Vector hasWarnings = new Vector();
0207:                walkTree(new TreeAction() {
0208:                    public void classAction(Cl cl) throws Exception {
0209:                        if (cl.hasWarnings())
0210:                            hasWarnings.addElement(Boolean.valueOf(true));
0211:                    }
0212:                });
0213:                if (hasWarnings.size() > 0) {
0214:                    log.println("#");
0215:                    log.println(LOG_DANGER_HEADER1);
0216:                    log.println(LOG_DANGER_HEADER2);
0217:                    log.println(LOG_DANGER_HEADER3);
0218:                    final PrintWriter flog = log;
0219:                    walkTree(new TreeAction() {
0220:                        public void classAction(Cl cl) throws Exception {
0221:                            cl.logWarnings(flog);
0222:                        }
0223:                    });
0224:                }
0225:            }
0226:
0227:            /** Mark an attribute type for retention. */
0228:            public void retainAttribute(String name) throws Exception {
0229:                retainAttrs.addElement(name);
0230:            }
0231:
0232:            /** Mark a class/interface type (and possibly methods and fields defined in class) for retention. */
0233:            public void retainClass(String name, boolean retainToPublic,
0234:                    boolean retainToProtected, boolean retainPubProtOnly,
0235:                    boolean retainFieldsOnly, boolean retainMethodsOnly,
0236:                    String extendsName, boolean invert, boolean notrimOnly, // TODO - use notrimOnly
0237:                    int accessMask, int accessSetting) throws Exception {
0238:                // Mark the class (or classes, if this is a wildcarded specifier)
0239:                for (Enumeration clEnum = getClEnum(name); clEnum
0240:                        .hasMoreElements();) {
0241:                    Cl cl = (Cl) clEnum.nextElement();
0242:                    if ((extendsName == null || cl
0243:                            .hasAsSuperOrInterface(extendsName))
0244:                            && cl.modifiersMatchMask(accessMask, accessSetting)) {
0245:                        retainHierarchy(cl, invert);
0246:                        if (retainToPublic || retainToProtected
0247:                                || retainPubProtOnly) {
0248:                            // Retain methods if requested
0249:                            if (!retainFieldsOnly) {
0250:                                for (Enumeration enm = cl.getMethodEnum(); enm
0251:                                        .hasMoreElements();) {
0252:                                    Md md = (Md) enm.nextElement();
0253:                                    if ((retainToPublic && Modifier.isPublic(md
0254:                                            .getModifiers()))
0255:                                            || (retainToProtected && !Modifier
0256:                                                    .isPrivate(md
0257:                                                            .getModifiers()))
0258:                                            || (retainPubProtOnly && (Modifier
0259:                                                    .isPublic(md.getModifiers()) || Modifier
0260:                                                    .isProtected(md
0261:                                                            .getModifiers())))) {
0262:                                        if (invert) {
0263:                                            md.setOutName(null);
0264:                                            md.clearFromScript();
0265:                                        } else {
0266:                                            md.setOutName(md.getInName());
0267:                                            md.setFromScript();
0268:                                        }
0269:                                    }
0270:                                }
0271:                            }
0272:
0273:                            // Retain fields if requested
0274:                            if (!retainMethodsOnly) {
0275:                                for (Enumeration enm = cl.getFieldEnum(); enm
0276:                                        .hasMoreElements();) {
0277:                                    Fd fd = (Fd) enm.nextElement();
0278:                                    if ((retainToPublic && Modifier.isPublic(fd
0279:                                            .getModifiers()))
0280:                                            || (retainToProtected && !Modifier
0281:                                                    .isPrivate(fd
0282:                                                            .getModifiers()))
0283:                                            || (retainPubProtOnly && (Modifier
0284:                                                    .isPublic(fd.getModifiers()) || Modifier
0285:                                                    .isProtected(fd
0286:                                                            .getModifiers())))) {
0287:                                        if (invert) {
0288:                                            fd.setOutName(null);
0289:                                            fd.clearFromScript();
0290:                                        } else {
0291:                                            fd.setOutName(fd.getInName());
0292:                                            fd.setFromScript();
0293:                                        }
0294:                                    }
0295:                                }
0296:                            }
0297:                        }
0298:                    }
0299:                }
0300:            }
0301:
0302:            /** Mark a method type for retention. */
0303:            public void retainMethod(String name, String descriptor,
0304:                    boolean retainAndClass, String extendsName, boolean invert,
0305:                    boolean notrimOnly, // TODO - use notrimOnly
0306:                    int accessMask, int accessSetting) throws Exception {
0307:                for (Enumeration enm = getMdEnum(name, descriptor); enm
0308:                        .hasMoreElements();) {
0309:                    Md md = (Md) enm.nextElement();
0310:                    Cl this Cl = (Cl) md.getParent();
0311:                    if ((extendsName == null || this Cl
0312:                            .hasAsSuperOrInterface(extendsName))
0313:                            && md.modifiersMatchMask(accessMask, accessSetting)) {
0314:                        if (invert) {
0315:                            md.setOutName(null);
0316:                            md.clearFromScript();
0317:                        } else {
0318:                            md.setOutName(md.getInName());
0319:                            md.setFromScript();
0320:                        }
0321:                        if (retainAndClass) {
0322:                            retainHierarchy(this Cl, invert);
0323:                        }
0324:                    }
0325:                }
0326:            }
0327:
0328:            /** Mark a field type for retention. */
0329:            public void retainField(String name, String descriptor,
0330:                    boolean retainAndClass, String extendsName, boolean invert,
0331:                    boolean notrimOnly, // TODO - use notrimOnly
0332:                    int accessMask, int accessSetting) throws Exception {
0333:                for (Enumeration enm = getFdEnum(name, descriptor); enm
0334:                        .hasMoreElements();) {
0335:                    Fd fd = (Fd) enm.nextElement();
0336:                    Cl this Cl = (Cl) fd.getParent();
0337:                    if ((extendsName == null || this Cl
0338:                            .hasAsSuperOrInterface(extendsName))
0339:                            && fd.modifiersMatchMask(accessMask, accessSetting)) {
0340:                        if (invert) {
0341:                            fd.setOutName(null);
0342:                            fd.clearFromScript();
0343:                        } else {
0344:                            fd.setOutName(fd.getInName());
0345:                            fd.setFromScript();
0346:                        }
0347:                        if (retainAndClass) {
0348:                            retainHierarchy(this Cl, invert);
0349:                        }
0350:                    }
0351:                }
0352:            }
0353:
0354:            /** Mark a package for retention, and specify its new name. */
0355:            public void retainPackageMap(String name, String obfName)
0356:                    throws Exception {
0357:                retainItemMap(getPk(name), obfName);
0358:            }
0359:
0360:            /** Mark a package for repackaging under this new name. */
0361:            public void retainRepackageMap(String name, String obfName)
0362:                    throws Exception {
0363:                Pk pk = getPk(name);
0364:                if (!pk.isFixed()) {
0365:                    pk.setRepackageName(obfName);
0366:                    pk.setOutName(pk.getInName());
0367:                }
0368:            }
0369:
0370:            /** Mark a class/interface type for retention, and specify its new name. */
0371:            public void retainClassMap(String name, String obfName)
0372:                    throws Exception {
0373:                retainItemMap(getCl(name), obfName);
0374:            }
0375:
0376:            /** Mark a method type for retention, and specify its new name. */
0377:            public void retainMethodMap(String name, String descriptor,
0378:                    String obfName) throws Exception {
0379:                retainItemMap(getMd(name, descriptor), obfName);
0380:            }
0381:
0382:            /** Mark a field type for retention, and specify its new name. */
0383:            public void retainFieldMap(String name, String obfName)
0384:                    throws Exception {
0385:                retainItemMap(getFd(name), obfName);
0386:            }
0387:
0388:            // Mark an item for retention, and specify its new name.
0389:            private void retainItemMap(TreeItem item, String obfName)
0390:                    throws Exception {
0391:                if (!item.isFixed()) {
0392:                    item.setOutName(obfName);
0393:                    item.setFromScriptMap();
0394:                }
0395:            }
0396:
0397:            /** Traverse the class tree, generating obfuscated names within each namespace. */
0398:            public void generateNames(boolean enableRepackage) throws Exception {
0399:                // Repackage first, if requested 
0400:                // (need TreeItem.isFixed set properly, so must be done first)
0401:                if (enableRepackage) {
0402:                    // Exclude package names already fixed at the root level
0403:                    String[] noObfNames = getRootPackageNames();
0404:                    final NameMaker nm = new KeywordNameMaker(noObfNames,
0405:                            false, true);
0406:                    // Generate single-level package names, unique across jar
0407:                    walkTree(new TreeAction() {
0408:                        public void packageAction(Pk pk) throws Exception {
0409:                            pk.repackageName(nm);
0410:                        }
0411:                    });
0412:                }
0413:                // Now rename everything in the traditional way (no repackaging)
0414:                walkTree(new TreeAction() {
0415:                    public void packageAction(Pk pk) throws Exception {
0416:                        pk.generateNames();
0417:                    }
0418:
0419:                    public void classAction(Cl cl) throws Exception {
0420:                        cl.generateNames();
0421:                    }
0422:                });
0423:            }
0424:
0425:            // Return list of currently fixed root package names
0426:            private String[] getRootPackageNames() throws Exception {
0427:                Vector vec = new Vector();
0428:                for (Enumeration enm = root.getPackageEnum(); enm
0429:                        .hasMoreElements();) {
0430:                    Pk pk = (Pk) enm.nextElement();
0431:                    if (pk.isFixed()) {
0432:                        vec.addElement(pk.getOutName());
0433:                    }
0434:                }
0435:                String[] noObfNames = new String[vec.size()];
0436:                for (int i = 0; i < noObfNames.length; i++) {
0437:                    noObfNames[i] = (String) vec.elementAt(i);
0438:                }
0439:                return noObfNames;
0440:            }
0441:
0442:            /** Resolve the polymorphic dependencies of each class. */
0443:            public void resolveClasses() throws Exception {
0444:                walkTree(new TreeAction() {
0445:                    public void classAction(Cl cl) throws Exception {
0446:                        cl.resetResolve();
0447:                    }
0448:                });
0449:                walkTree(new TreeAction() {
0450:                    public void classAction(Cl cl) throws Exception {
0451:                        cl.setupNameListDowns();
0452:                    }
0453:                });
0454:                Cl.nameSpace = 0;
0455:                walkTree(new TreeAction() {
0456:                    public void classAction(Cl cl) throws Exception {
0457:                        cl.resolveOptimally();
0458:                    }
0459:                });
0460:            }
0461:
0462:            /** Return a list of attributes marked to keep. */
0463:            public String[] getAttrsToKeep() throws Exception {
0464:                String[] attrs = new String[retainAttrs.size()];
0465:                for (int i = 0; i < attrs.length; i++) {
0466:                    attrs[i] = (String) retainAttrs.elementAt(i);
0467:                }
0468:                return attrs;
0469:            }
0470:
0471:            /** Get classes in tree from the fully qualified name 
0472:                (can be wildcarded). */
0473:            public Enumeration getClEnum(String fullName) throws Exception {
0474:                final Vector vec = new Vector();
0475:                // Wildcard? then return list of all matching classes (including inner)
0476:                if (fullName.indexOf('*') != -1) {
0477:                    // Old !a/b/* wildcard syntax, for backward compatibility
0478:                    // (acts as if every * becomes a ** in new-style match)
0479:                    if (fullName.indexOf('!') == 0) {
0480:                        final String fName = fullName.substring(1);
0481:                        walkTree(new TreeAction() {
0482:                            public void classAction(Cl cl) throws Exception {
0483:                                if (cl.isOldStyleMatch(fName)) {
0484:                                    vec.addElement(cl);
0485:                                }
0486:                            }
0487:                        });
0488:                    }
0489:                    // New a/b/** wildcard syntax
0490:                    else {
0491:                        final String fName = fullName;
0492:                        walkTree(new TreeAction() {
0493:                            public void classAction(Cl cl) throws Exception {
0494:                                if (cl.isWildcardMatch(fName)) {
0495:                                    vec.addElement(cl);
0496:                                }
0497:                            }
0498:                        });
0499:                    }
0500:                } else {
0501:                    // Single class
0502:                    Cl cl = getCl(fullName);
0503:                    if (cl != null) {
0504:                        vec.addElement(cl);
0505:                    }
0506:                }
0507:                return vec.elements();
0508:            }
0509:
0510:            /** Get methods in tree from the fully qualified, and possibly
0511:                wildcarded, name. */
0512:            public Enumeration getMdEnum(String fullName, String descriptor)
0513:                    throws Exception {
0514:                final Vector vec = new Vector();
0515:                final String fDesc = descriptor;
0516:                // Wildcard? then return list of all matching methods
0517:                if (fullName.indexOf('*') != -1
0518:                        || descriptor.indexOf('*') != -1) {
0519:                    // Old !a/b/* wildcard syntax, for backward compatibility
0520:                    // (acts as if every * becomes a ** in new-style match)
0521:                    if (fullName.indexOf('!') == 0) {
0522:                        final String fName = fullName.substring(1);
0523:                        walkTree(new TreeAction() {
0524:                            public void methodAction(Md md) throws Exception {
0525:                                if (md.isOldStyleMatch(fName, fDesc)) {
0526:                                    vec.addElement(md);
0527:                                }
0528:                            }
0529:                        });
0530:                    }
0531:                    // New a/b/** wildcard syntax
0532:                    else {
0533:                        final String fName = fullName;
0534:                        walkTree(new TreeAction() {
0535:                            public void methodAction(Md md) throws Exception {
0536:                                if (md.isWildcardMatch(fName, fDesc)) {
0537:                                    vec.addElement(md);
0538:                                }
0539:                            }
0540:                        });
0541:                    }
0542:                } else {
0543:                    Md md = getMd(fullName, descriptor);
0544:                    if (md != null) {
0545:                        vec.addElement(md);
0546:                    }
0547:                }
0548:                return vec.elements();
0549:            }
0550:
0551:            /** Get fields in tree from the fully qualified, and possibly
0552:                wildcarded, name. */
0553:            public Enumeration getFdEnum(String fullName, String descriptor)
0554:                    throws Exception {
0555:                final Vector vec = new Vector();
0556:                // Wildcard? then return list of all matching methods
0557:                if (fullName.indexOf('*') != -1) {
0558:                    // Old !a/b/* wildcard syntax, for backward compatibility
0559:                    // (acts as if every * becomes a ** in new-style match)
0560:                    if (fullName.indexOf('!') == 0) {
0561:                        final String fName = fullName.substring(1);
0562:                        walkTree(new TreeAction() {
0563:                            public void fieldAction(Fd fd) throws Exception {
0564:                                if (fd.isOldStyleMatch(fName)) {
0565:                                    vec.addElement(fd);
0566:                                }
0567:                            }
0568:                        });
0569:                    }
0570:                    // New a/b/** wildcard syntax
0571:                    else {
0572:                        final String fName = fullName;
0573:                        final String fDesc = descriptor;
0574:                        walkTree(new TreeAction() {
0575:                            public void fieldAction(Fd fd) throws Exception {
0576:                                if (fd.isWildcardMatch(fName, fDesc)) {
0577:                                    vec.addElement(fd);
0578:                                }
0579:                            }
0580:                        });
0581:                    }
0582:                } else {
0583:                    Fd fd = getFd(fullName);
0584:                    if (fd != null) {
0585:                        vec.addElement(fd);
0586:                    }
0587:                }
0588:                return vec.elements();
0589:            }
0590:
0591:            /** Get class in tree from the fully qualified name, returning null if name not found. */
0592:            public Cl getCl(String fullName) throws Exception {
0593:                TreeItem ti = root;
0594:                for (Enumeration nameEnum = getNameEnum(fullName); nameEnum
0595:                        .hasMoreElements();) {
0596:                    SimpleName simpleName = (SimpleName) nameEnum.nextElement();
0597:                    String name = simpleName.getName();
0598:                    if (simpleName.isAsPackage()) {
0599:                        ti = ((Pk) ti).getPackage(name);
0600:                    } else if (simpleName.isAsClass()) {
0601:                        ti = ((PkCl) ti).getClass(name);
0602:                    } else {
0603:                        throw new Exception(
0604:                                "Internal error: illegal package/class name tag");
0605:                    }
0606:
0607:                    // If the name is not in the database, return null
0608:                    if (ti == null) {
0609:                        return null;
0610:                    }
0611:                }
0612:
0613:                // It is an error if we do not end up with a class or interface
0614:                if (!(ti instanceof  Cl)) {
0615:                    // 15Jul2005 - this exception is being over-sensitive with fullName of null (should never get here) so safely return null instead
0616:                    //throw new Exception("Inconsistent class or interface name: " + fullName);
0617:                    return null;
0618:                }
0619:                return (Cl) ti;
0620:            }
0621:
0622:            /** Get package in tree from the fully qualified name, returning null if name not found. */
0623:            public Pk getPk(String fullName) throws Exception {
0624:                TreeItem ti = root;
0625:                for (Enumeration nameEnum = getNameEnum(fullName); nameEnum
0626:                        .hasMoreElements();) {
0627:                    SimpleName simpleName = (SimpleName) nameEnum.nextElement();
0628:                    String name = simpleName.getName();
0629:                    ti = ((Pk) ti).getPackage(name);
0630:
0631:                    // If the name is not in the database, return null
0632:                    if (ti == null) {
0633:                        return null;
0634:                    }
0635:                    // It is an error if we do not end up with a package
0636:                    if (!(ti instanceof  Pk)) {
0637:                        throw new Exception("Inconsistent package.");
0638:                    }
0639:                }
0640:                return (Pk) ti;
0641:            }
0642:
0643:            /** Get method in tree from the fully qualified name. */
0644:            public Md getMd(String fullName, String descriptor)
0645:                    throws Exception {
0646:                // Split into class and method names
0647:                int pos = fullName.lastIndexOf(METHOD_FIELD_LEVEL);
0648:                Cl cl = getCl(fullName.substring(0, pos));
0649:                return cl.getMethod(fullName.substring(pos + 1), descriptor);
0650:            }
0651:
0652:            /** Get field in tree from the fully qualified name. */
0653:            public Fd getFd(String fullName) throws Exception {
0654:                // Split into class and field names
0655:                int pos = fullName.lastIndexOf(METHOD_FIELD_LEVEL);
0656:                Cl cl = getCl(fullName.substring(0, pos));
0657:                return cl.getField(fullName.substring(pos + 1));
0658:            }
0659:
0660:            /** Mapping for fully qualified class name.
0661:             *  @see NameMapper#mapClass */
0662:            public String mapClass(String className) throws Exception {
0663:                // Check for array -- requires special handling
0664:                if (className.length() > 0 && className.charAt(0) == '[') {
0665:                    StringBuffer newName = new StringBuffer();
0666:                    int i = 0;
0667:                    while (i < className.length()) {
0668:                        char ch = className.charAt(i++);
0669:                        switch (ch) {
0670:                        case '[':
0671:                        case ';':
0672:                            newName.append(ch);
0673:                            break;
0674:
0675:                        case 'L':
0676:                            newName.append(ch);
0677:                            int pos = className.indexOf(';', i);
0678:                            if (pos < 0) {
0679:                                throw new Exception(
0680:                                        "Invalid class name encountered: "
0681:                                                + className);
0682:                            }
0683:                            newName
0684:                                    .append(mapClass(className
0685:                                            .substring(i, pos)));
0686:                            i = pos;
0687:                            break;
0688:
0689:                        default:
0690:                            return className;
0691:                        }
0692:                    }
0693:                    return newName.toString();
0694:                } else {
0695:                    Cl cl = getCl(className);
0696:                    return cl != null ? cl.getFullOutName() : className;
0697:                }
0698:            }
0699:
0700:            /** Mapping for method name, of fully qualified class.
0701:             *  @see NameMapper#mapMethod */
0702:            public String mapMethod(String className, String methodName,
0703:                    String descriptor) throws Exception {
0704:                String outName = methodName;
0705:                if (!methodName.equals("<init>")) {
0706:                    Stack s = new Stack();
0707:                    Cl nextCl = getCl(className);
0708:                    if (nextCl != null) {
0709:                        s.push(nextCl);
0710:                    }
0711:                    while (!s.empty()) {
0712:                        Cl cl = (Cl) s.pop();
0713:                        Md md = cl.getMethod(methodName, descriptor);
0714:                        if (md != null) {
0715:                            outName = md.getOutName();
0716:                            break;
0717:                        } else {
0718:                            nextCl = cl.getSuperCl();
0719:                            if (nextCl != null) {
0720:                                s.push(nextCl);
0721:                            }
0722:                            Enumeration enm = cl.getSuperInterfaces();
0723:                            while (enm.hasMoreElements()) {
0724:                                nextCl = (Cl) enm.nextElement();
0725:                                if (nextCl != null) {
0726:                                    s.push(nextCl);
0727:                                }
0728:                            }
0729:                        }
0730:                    }
0731:                }
0732:                return outName;
0733:            }
0734:
0735:            /** Mapping for field name, of fully qualified class.
0736:             *  @see NameMapper#mapField */
0737:            public String mapField(String className, String fieldName)
0738:                    throws Exception {
0739:                String outName = fieldName;
0740:                if (!fieldName.equals("<init>")) {
0741:                    Stack s = new Stack();
0742:                    Cl nextCl = getCl(className);
0743:                    if (nextCl != null) {
0744:                        s.push(nextCl);
0745:                    }
0746:                    while (!s.empty()) {
0747:                        Cl cl = (Cl) s.pop();
0748:                        Fd fd = cl.getField(fieldName);
0749:                        if (fd != null) {
0750:                            outName = fd.getOutName();
0751:                            break;
0752:                        } else {
0753:                            nextCl = cl.getSuperCl();
0754:                            if (nextCl != null) {
0755:                                s.push(nextCl);
0756:                            }
0757:                            Enumeration enm = cl.getSuperInterfaces();
0758:                            while (enm.hasMoreElements()) {
0759:                                nextCl = (Cl) enm.nextElement();
0760:                                if (nextCl != null) {
0761:                                    s.push(nextCl);
0762:                                }
0763:                            }
0764:                        }
0765:                    }
0766:                }
0767:                return outName;
0768:            }
0769:
0770:            /** Mapping for generic type signature.
0771:             *  @see NameMapper#mapSignature */
0772:            public String mapSignature(String signature) throws Exception {
0773:                // NOTE - not currently parsed and mapped; reserve identifiers
0774:                //     appearing in type signatures for reflective methods to work.
0775:                return signature;
0776:            }
0777:
0778:            /** Mapping for descriptor of field or method.
0779:             *  @see NameMapper#mapDescriptor */
0780:            public String mapDescriptor(String descriptor) throws Exception {
0781:                // Pass everything through unchanged, except for the String between
0782:                // 'L' and ';' -- this is passed through mapClass(String)
0783:                StringBuffer newDesc = new StringBuffer();
0784:                int i = 0;
0785:                while (i < descriptor.length()) {
0786:                    char ch = descriptor.charAt(i++);
0787:                    switch (ch) {
0788:                    case '[':
0789:                    case 'B':
0790:                    case 'C':
0791:                    case 'D':
0792:                    case 'F':
0793:                    case 'I':
0794:                    case 'J':
0795:                    case 'S':
0796:                    case 'Z':
0797:                    case 'V':
0798:                    case '(':
0799:                    case ')':
0800:                    case ';':
0801:                        newDesc.append(ch);
0802:                        break;
0803:
0804:                    case 'L':
0805:                        newDesc.append(ch);
0806:                        int pos = descriptor.indexOf(';', i);
0807:                        if (pos < 0) {
0808:                            throw new Exception(
0809:                                    "Invalid descriptor string encountered.");
0810:                        }
0811:                        newDesc.append(mapClass(descriptor.substring(i, pos)));
0812:                        i = pos;
0813:                        break;
0814:
0815:                    default:
0816:                        throw new Exception(
0817:                                "Invalid descriptor string encountered.");
0818:                    }
0819:                }
0820:                return newDesc.toString();
0821:            }
0822:
0823:            /** Dump the content of the class tree to the specified file (used for logging). */
0824:            public void dump(final PrintWriter log) throws Exception {
0825:                log.println("#");
0826:                log.println(LOG_FREQUENCY_TABLE);
0827:                dumpFrequencyCount(log);
0828:                log.println("#");
0829:                log.println(LOG_PRE_UNOBFUSCATED);
0830:                log.println("#");
0831:                walkTree(new TreeAction() {
0832:                    public void classAction(Cl cl) {
0833:                        if (cl.isFromScript()) {
0834:                            log.println(".class " + cl.getFullInName());
0835:                            if (cl.isTrimmed()) {
0836:                                log
0837:                                        .println("# ERROR: incorrectly trimmed class "
0838:                                                + cl.getFullInName());
0839:                            }
0840:                        }
0841:                    }
0842:
0843:                    public void methodAction(Md md) {
0844:                        if (md.isFromScript()) {
0845:                            log.println(".method " + md.getFullInName() + " "
0846:                                    + md.getDescriptor());
0847:                            if (md.isTrimmed()) {
0848:                                log
0849:                                        .println("# ERROR: incorrectly trimmed method "
0850:                                                + md.getFullInName()
0851:                                                + " "
0852:                                                + md.getDescriptor());
0853:                            }
0854:                        }
0855:                    }
0856:
0857:                    public void fieldAction(Fd fd) {
0858:                        if (fd.isFromScript()) {
0859:                            log.println(".field " + fd.getFullInName() + " "
0860:                                    + fd.getDescriptor());
0861:                            if (fd.isTrimmed()) {
0862:                                log
0863:                                        .println("# ERROR: incorrectly trimmed field "
0864:                                                + fd.getFullInName()
0865:                                                + " "
0866:                                                + fd.getDescriptor());
0867:                            }
0868:                        }
0869:                    }
0870:
0871:                    public void packageAction(Pk pk) {
0872:                        // No action
0873:                    }
0874:                });
0875:                log.println("#");
0876:                log.println("#");
0877:                log.println(LOG_PRE_OBFUSCATED);
0878:                log.println("#");
0879:                walkTree(new TreeAction() {
0880:                    public void classAction(Cl cl) {
0881:                        if (!cl.isFromScript()) {
0882:                            if (cl.isTrimmed()) {
0883:                                log.println("# trimmed class "
0884:                                        + cl.getFullInName());
0885:                            } else {
0886:                                log.println(".class_map " + cl.getFullInName()
0887:                                        + " " + cl.getOutName());
0888:                            }
0889:                        }
0890:                    }
0891:
0892:                    public void methodAction(Md md) {
0893:                        if (!md.isFromScript()) {
0894:                            if (!md.getParent().isTrimmed()) {
0895:                                if (md.isTrimmed()) {
0896:                                    log.println("# trimmed method "
0897:                                            + md.getFullInName() + " "
0898:                                            + md.getDescriptor());
0899:                                } else {
0900:                                    log.println(".method_map "
0901:                                            + md.getFullInName() + " "
0902:                                            + md.getDescriptor() + " "
0903:                                            + md.getOutName());
0904:                                }
0905:                            }
0906:                        }
0907:                    }
0908:
0909:                    public void fieldAction(Fd fd) {
0910:                        if (!fd.isFromScript()) {
0911:                            if (!fd.getParent().isTrimmed()) {
0912:                                if (fd.isTrimmed()) {
0913:                                    log.println("# trimmed field "
0914:                                            + fd.getFullInName() + " "
0915:                                            + fd.getDescriptor());
0916:                                } else {
0917:                                    log.println(".field_map "
0918:                                            + fd.getFullInName() + " "
0919:                                            + fd.getOutName());
0920:                                }
0921:                            }
0922:                        }
0923:                    }
0924:
0925:                    public void packageAction(Pk pk) {
0926:                        if (!pk.isFromScript()
0927:                                && pk.getFullInName().length() > 0) {
0928:                            if (pk.getRepackageName() != null) {
0929:                                log.println(".repackage_map "
0930:                                        + pk.getFullInName() + " "
0931:                                        + pk.getRepackageName());
0932:                            } else {
0933:                                log.println(".package_map "
0934:                                        + pk.getFullInName() + " "
0935:                                        + pk.getOutName());
0936:                            }
0937:                        }
0938:                    }
0939:                });
0940:            }
0941:
0942:            private void dumpFrequencyCount(PrintWriter log) {
0943:                // Compute total use count
0944:                int totalUseCount = 0;
0945:                for (Enumeration useCountEnum = NameMaker.getUseCounts(); useCountEnum
0946:                        .hasMoreElements();) {
0947:                    totalUseCount += ((Integer) useCountEnum.nextElement())
0948:                            .intValue() + 1;
0949:                }
0950:
0951:                // Log the individual use counts for names
0952:                if (totalUseCount != 0) {
0953:                    int sumPercent = 0;
0954:                    int sumUseCount = 0;
0955:                    Vector sort = new Vector();
0956:                    for (Enumeration nameEnum = NameMaker.getNames(), useCountEnum = NameMaker
0957:                            .getUseCounts(); nameEnum.hasMoreElements();) {
0958:                        String name = (String) nameEnum.nextElement();
0959:                        int useCount = ((Integer) useCountEnum.nextElement())
0960:                                .intValue() + 1;
0961:                        int percent = 100 * useCount / totalUseCount;
0962:                        if (percent != 0) {
0963:                            sort.addElement(new SortElement(name, useCount));
0964:                            sumUseCount += useCount;
0965:                            sumPercent += percent;
0966:                        }
0967:                    }
0968:                    while (sort.size() != 0) {
0969:                        SortElement se = null;
0970:                        int largestUseCount = 0;
0971:                        for (Enumeration enm = sort.elements(); enm
0972:                                .hasMoreElements();) {
0973:                            SortElement this Se = (SortElement) enm
0974:                                    .nextElement();
0975:                            if (this Se.useCount >= largestUseCount) {
0976:                                se = this Se;
0977:                                largestUseCount = se.useCount;
0978:                            }
0979:                        }
0980:                        sort.removeElement(se);
0981:                        log.println("#  '"
0982:                                + se.name
0983:                                + "'   \tused "
0984:                                + se.useCount
0985:                                + " times\t("
0986:                                + Integer.toString(100 * se.useCount
0987:                                        / totalUseCount) + "%)");
0988:                    }
0989:
0990:                    // Log the remainder percentage
0991:                    log
0992:                            .println("#  Other names (each used in <1% of mappings) used a total of "
0993:                                    + Integer.toString(totalUseCount
0994:                                            - sumUseCount)
0995:                                    + " times ("
0996:                                    + Integer.toString(100 - sumPercent) + "%)");
0997:                    log.println("#");
0998:                }
0999:            }
1000:
1001:            class SortElement {
1002:                int useCount;
1003:                String name;
1004:
1005:                SortElement(String name, int useCount) {
1006:                    this .useCount = useCount;
1007:                    this .name = name;
1008:                }
1009:            }
1010:
1011:            // Private Methods -------------------------------------------------------
1012:            // Mark TreeItem and all parents for retention.
1013:            private void retainHierarchy(TreeItem ti, boolean invert)
1014:                    throws Exception {
1015:                if (invert) {
1016:                    // error to force package level obfuscation
1017:                    if (!(ti instanceof  Pk)) {
1018:                        ti.setOutName(null);
1019:                        ti.clearFromScript();
1020:                    }
1021:                } else {
1022:                    if (!ti.isFixed()) {
1023:                        ti.setOutName(ti.getInName());
1024:                        ti.setFromScript();
1025:                    }
1026:                }
1027:                if (ti.parent != null) {
1028:                    retainHierarchy(ti.parent, invert);
1029:                }
1030:            }
1031:
1032:            /** Walk the whole tree taking action once only on each package level, class, method and field. */
1033:            public void walkTree(TreeAction ta) throws Exception {
1034:                walkTree(ta, root);
1035:            }
1036:
1037:            // Walk the tree which has TreeItem as its root taking action once only on each
1038:            // package level, class, method and field.
1039:            private void walkTree(TreeAction ta, TreeItem ti) throws Exception {
1040:                if (ti instanceof  Pk) {
1041:                    Enumeration packageEnum = ((Pk) ti).getPackageEnum();
1042:                    ta.packageAction((Pk) ti);
1043:                    while (packageEnum.hasMoreElements()) {
1044:                        walkTree(ta, (TreeItem) packageEnum.nextElement());
1045:                    }
1046:                }
1047:                if (ti instanceof  PkCl) {
1048:                    Enumeration classEnum = ((PkCl) ti).getClassEnum();
1049:                    while (classEnum.hasMoreElements()) {
1050:                        walkTree(ta, (TreeItem) classEnum.nextElement());
1051:                    }
1052:                }
1053:                if (ti instanceof  Cl) {
1054:                    Enumeration fieldEnum = ((Cl) ti).getFieldEnum();
1055:                    Enumeration methodEnum = ((Cl) ti).getMethodEnum();
1056:                    ta.classAction((Cl) ti);
1057:                    while (fieldEnum.hasMoreElements()) {
1058:                        ta.fieldAction((Fd) fieldEnum.nextElement());
1059:                    }
1060:                    while (methodEnum.hasMoreElements()) {
1061:                        ta.methodAction((Md) methodEnum.nextElement());
1062:                    }
1063:                }
1064:            }
1065:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.